ada: Reject illegal array aggregates as per AI22-0106.

Implement the new legality rules of AI22-0106 which (as discussed in the AI)
are needed to disallow constructs whose semantics would otherwise be poorly
defined.

gcc/ada/

	* sem_aggr.adb (Resolve_Array_Aggregate): Implement the two new
	legality rules of AI11-0106. Add code to avoid cascading error
	messages.
This commit is contained in:
Steve Baird 2024-08-19 14:58:38 -07:00 committed by Marc Poulhiès
parent b776b08b71
commit e083e72866

View File

@ -301,7 +301,7 @@ package body Sem_Aggr is
-- In addition this step analyzes and resolves each discrete_choice,
-- making sure that its type is the type of the corresponding Index.
-- If we are not at the lowest array aggregate level (in the case of
-- multi-dimensional aggregates) then invoke Resolve_Array_Aggregate
-- multidimensional aggregates) then invoke Resolve_Array_Aggregate
-- recursively on each component expression. Otherwise, resolve the
-- bottom level component expressions against the expected component
-- type ONLY IF the component corresponds to a single discrete choice
@ -314,7 +314,7 @@ package body Sem_Aggr is
-- 3. For positional aggregates:
--
-- (A) Loop over the component expressions either recursively invoking
-- Resolve_Array_Aggregate on each of these for multi-dimensional
-- Resolve_Array_Aggregate on each of these for multidimensional
-- array aggregates or resolving the bottom level component
-- expressions against the expected component type.
--
@ -1596,6 +1596,8 @@ package body Sem_Aggr is
Nb_Choices : Nat := 0;
-- Contains the overall number of named choices in this sub-aggregate
Saved_SED : constant Nat := Serious_Errors_Detected;
function Add (Val : Uint; To : Node_Id) return Node_Id;
-- Creates a new expression node where Val is added to expression To.
-- Tries to constant fold whenever possible. To must be an already
@ -1968,7 +1970,7 @@ package body Sem_Aggr is
Nxt_Ind_Constr : constant Node_Id := Next_Index (Index_Constr);
-- Index is the current index corresponding to the expression
Resolution_OK : Boolean := True;
Resolution_OK : Boolean := True;
-- Set to False if resolution of the expression failed
begin
@ -2038,6 +2040,9 @@ package body Sem_Aggr is
Resolution_OK := Resolve_Array_Aggregate
(Expr, Nxt_Ind, Nxt_Ind_Constr, Component_Typ, Others_Allowed);
if Resolution_OK = Failure then
return Failure;
end if;
else
-- If it's "... => <>", nothing to resolve
@ -2135,10 +2140,10 @@ package body Sem_Aggr is
-- Local variables
Choice : Node_Id;
Dummy : Boolean;
Scop : Entity_Id;
Expr : constant Node_Id := Expression (N);
Choice : Node_Id;
Resolution_OK : Boolean;
Scop : Entity_Id;
Expr : constant Node_Id := Expression (N);
-- Start of processing for Resolve_Iterated_Component_Association
@ -2208,7 +2213,11 @@ package body Sem_Aggr is
-- rewritting as a loop with a new index variable; when not
-- generating code we leave the analyzed expression as it is.
Dummy := Resolve_Aggr_Expr (Expr, Single_Elmt => False);
Resolution_OK := Resolve_Aggr_Expr (Expr, Single_Elmt => False);
if not Resolution_OK then
return;
end if;
if Operating_Mode /= Check_Semantics then
Remove_References (Expr);
@ -2610,6 +2619,14 @@ package body Sem_Aggr is
if Nkind (Assoc) = N_Iterated_Component_Association
and then Present (Iterator_Specification (Assoc))
then
if Number_Dimensions (Etype (N)) /= 1 then
Error_Msg_N ("iterated_component_association with an" &
" iterator_specification not allowed for" &
" multidimensional array aggregate",
Assoc);
return Failure;
end if;
-- All other component associations must have an iterator spec.
Next (Assoc);
@ -2931,16 +2948,75 @@ package body Sem_Aggr is
Get_Index_Bounds (Choice, Low, High);
end if;
if (Dynamic_Or_Null_Range (Low, High)
or else (Nkind (Choice) = N_Subtype_Indication
and then
Dynamic_Or_Null_Range (S_Low, S_High)))
and then Nb_Choices /= 1
if Dynamic_Or_Null_Range (Low, High)
or else (Nkind (Choice) = N_Subtype_Indication
and then Dynamic_Or_Null_Range (S_Low, S_High))
then
Error_Msg_N
("dynamic or empty choice in aggregate "
& "must be the only choice", Choice);
return Failure;
if Nb_Choices /= 1 then
Error_Msg_N
("dynamic or empty choice in aggregate "
& "must be the only choice", Choice);
return Failure;
elsif Number_Dimensions (Etype (N)) > 1 then
declare
function Check_Bound_Subexpression
(Exp : Node_Id) return Traverse_Result;
-- A bound expression for a subaggregate of an
-- array aggregate is not permitted to reference
-- a loop iteration variable defined in an earlier
-- dimension of the same enclosing aggregate, as
-- in (for X in 1 .. 3 => (1 .. X + 2 => ...)) .
-- Always returns OK.
--------------------------------
-- Check_Bound_Subexpression --
--------------------------------
function Check_Bound_Subexpression
(Exp : Node_Id) return Traverse_Result
is
Scope_Parent : Node_Id;
begin
if Nkind (Exp) /= N_Identifier
or else not Present (Entity (Exp))
or else not Present (Scope (Entity (Exp)))
or else Ekind (Scope (Entity (Exp))) /= E_Loop
then
return OK;
end if;
Scope_Parent := Parent (Scope (Entity (Exp)));
if Nkind (Scope_Parent) = N_Aggregate
-- We want to know whether the aggregate
-- where this loop var is defined is
-- "the same" aggregate as N, where "the
-- same" means looking through subaggregates.
-- To do this, we compare Etypes of the two.
--
-- ??? There may be very obscure cases
-- involving allocators where this is too
-- strict and will generate a spurious error.
and then Etype (Scope_Parent) = Etype (N)
then
Error_Msg_N ("bound expression for a "
& "subaggregate of an array aggregate must "
& "not refer to an index parameter of an "
& "earlier dimension", Exp);
end if;
return OK;
end Check_Bound_Subexpression;
procedure Check_Bound_Expression is new
Traverse_Proc (Check_Bound_Subexpression);
begin
Check_Bound_Expression (Low);
Check_Bound_Expression (High);
end;
end if;
end if;
if not (All_Composite_Constraints_Static (Low)
@ -3706,6 +3782,10 @@ package body Sem_Aggr is
Analyze_Dimension_Array_Aggregate (N, Component_Typ);
if Serious_Errors_Detected /= Saved_SED then
return Failure;
end if;
return Success;
end Resolve_Array_Aggregate;