[Ada] Ongoing work for AI12-0212: container aggregates
Add legality checks for indexed aggregates with component associations. RN 4.3.5 (28/5 - 30/5) specifies validity rules for indexed aggregates, intended to simplify implementation as well as the computation of the expected size of an indexed aggregate, such for an aggregaate of a vector type. Tested on x86_64-pc-linux-gnu, committed on trunk gcc/ada/ * sem_aggr.adb (Resolve_Indexed_Aggregate): For indexed aggregates with component associations verify that if there is more than one component association then all the choices are static, that the set of choices define a continuous sequence of values, and that if loop specfications appear, they do not include iterator filters or key expressions.diff --git a/gcc/ada/sem_aggr.adb b/gcc/ada/sem_aggr.adb --- a/gcc/ada/sem_aggr.adb +++ b/gcc/ada/sem_aggr.adb @@ -2980,9 +2980,12 @@ package body Sem_Aggr is Index_Type : constant Entity_Id := Etype (Next_Formal (Container)); Comp_Type : constant Entity_Id := Etype (Next_Formal (Next_Formal (Container))); -Comp : Node_Id; -Choice : Node_Id; +Comp: Node_Id; +Choice : Node_Id; +Num_Choices : Nat := 0; +Hi_Val : Uint; +Lo_Val : Uint; begin if Present (Expressions (N)) then Comp := First (Expressions (N)); @@ -2999,7 +3002,7 @@ package body Sem_Aggr is return; end if; - Comp := First (Expressions (N)); + Comp := First (Component_Associations (N)); while Present (Comp) loop if Nkind (Comp) = N_Component_Association then @@ -3007,6 +3010,7 @@ package body Sem_Aggr is while Present (Choice) loop Analyze_And_Resolve (Choice, Index_Type); +Num_Choices := Num_Choices + 1; Next (Choice); end loop; @@ -3018,10 +3022,107 @@ package body Sem_Aggr is then Resolve_Iterated_Association (Comp, Index_Type, Comp_Type); + Num_Choices := Num_Choices + 1; end if; Next (Comp); end loop; + + -- The component associations in an indexed aggregate + -- must denote a contiguous set of static values. We + -- build a table of values/ranges and sort it, as is done + -- elsewhere for case statements and array aggregates. + -- If the aggregate has a single iterated association it + -- is allowed to be nonstatic and there is nothing to check. + + if Num_Choices > 1 then + declare + Table : Case_Table_Type (1 .. Num_Choices); + No_Choice : Pos := 1; + Lo, Hi: Node_Id; + + -- Traverse aggregate to determine size of needed table. + -- Verify that bounds are static and that loops have no + -- filters or key expressions. + + begin + Comp := First (Component_Associations (N)); + while Present (Comp) loop +if Nkind (Comp) = N_Iterated_Element_Association then + if Present + (Loop_Parameter_Specification (Comp)) + then + if Present (Iterator_Filter +(Loop_Parameter_Specification (Comp))) + then + Error_Msg_N + ("iterator filter not allowed " & + "in indexed aggregate", Comp); + return; + + elsif Present (Key_Expression +(Loop_Parameter_Specification (Comp))) + then + Error_Msg_N + ("key expression not allowed " & + "in indexed aggregate", Comp); + return; + end if; + end if; +else + Choice := First (Choices (Comp)); + + while Present (Choice) loop + Get_Index_Bounds (Choice, Lo, Hi); + Table (No_Choice).Choice := Choice; + Table (No_Choice).Lo := Lo; + Table (No_Choice).Hi := Hi; + + -- Verify staticness of value or range + +
[Ada] Ongoing work for AI12-0212: container aggregates
This patch refines the handling of container aggregates with non-static sizes given with iterated component associations and iterated element associations. When necessary we construct an expression to be evaluated dynamically to guide the allocation of the container, prior to inserting elements. Tested on x86_64-pc-linux-gnu, committed on trunk gcc/ada/ * exp_aggr.adb (Build_Siz_Exp): new function, subsidiary of Expand_Container_Aggregate, to create an expression to be used in the dynamic allocation of a container with a single container element association. (Add_Range): Handle static bounds of ranges over enumerations. (Expand_Container_Aggregate): Add declaration for size expression when needed, and use it in container object declaration for container.diff --git a/gcc/ada/exp_aggr.adb b/gcc/ada/exp_aggr.adb --- a/gcc/ada/exp_aggr.adb +++ b/gcc/ada/exp_aggr.adb @@ -6982,11 +6982,24 @@ package body Exp_Aggr is Init_Stat : Node_Id; Siz : Int; + -- The following are used when the size of the aggregate is not + -- static and requires a dynamic evaluation. + Siz_Decl : Node_Id; + Siz_Exp: Node_Id := Empty; + Count_Type : Entity_Id; + function Aggregate_Size return Int; -- Compute number of entries in aggregate, including choices - -- that cover a range, as well as iterated constructs. + -- that cover a range or subtype, as well as iterated constructs. -- Return -1 if the size is not known statically, in which case - -- we allocate a default size for the aggregate. + -- allocate a default size for the aggregate, or build an expression + -- to estimate the size dynamically. + + function Build_Siz_Exp (Comp : Node_Id) return Int; + -- When the aggregate contains a single Iterated_Component_Association + -- or Element_Association with non-static bounds, build an expression + -- to be used as the allocated size of the container. This may be an + -- overestimate if a filter is present, but is a safe approximation. procedure Expand_Iterated_Component (Comp : Node_Id); -- Handle iterated_component_association and iterated_Element @@ -7005,34 +7018,54 @@ package body Exp_Aggr is Siz : Int := 0; procedure Add_Range_Size; - -- Compute size of component association given by - -- range or subtype name. + -- Compute number of components specified by a component association + -- given by a range or subtype name. + + + -- Add_Range_Size -- + procedure Add_Range_Size is begin +-- The bounds of the discrete range are integers or enumeration +-- literals + if Nkind (Lo) = N_Integer_Literal then Siz := Siz + UI_To_Int (Intval (Hi)) - - UI_To_Int (Intval (Lo)) + 1; + - UI_To_Int (Intval (Lo)) + 1; +else + Siz := Siz + UI_To_Int (Enumeration_Pos (Hi)) + - UI_To_Int (Enumeration_Pos (Lo)) + 1; end if; end Add_Range_Size; begin + -- Aggregate is either all positional or all named. + if Present (Expressions (N)) then Siz := List_Length (Expressions (N)); end if; if Present (Component_Associations (N)) then Comp := First (Component_Associations (N)); - --- If the component is an Iterated_Element_Association --- it includes an iterator or a loop parameter, possibly --- with a filter, so we do not attempt to compute its --- size. Room for future optimization ??? - -if Nkind (Comp) = N_Iterated_Element_Association then - return -1; +-- If there is a single component association it can be +-- an iterated component with dynamic bounds or an element +-- iterator over an iterable object. If it is an array +-- we can use the attribute Length to get its size; +-- for a predefined container the function Length plays +-- the same role. There is no available mechanism for +-- user-defined containers. For now we treat all of these +-- as dynamic. + +if List_Length (Component_Associations (N)) = 1 + and then Nkind (Comp) in N_Iterated_Component_Association | + N_Iterated_Element_Association +then + return Build_Siz_Exp (Comp); end if; +-- Otherwise all associations must specify static sizes. + while Present (Comp) loop Choice := First (Choice_List (Comp)); @@ -7042,26 +7075,14 @@ package body Exp_Aggr is
[Ada] Ongoing work for AI12-0212 : container aggregates
This patch adds support for indexed aggregates with both positional components and component associations that include multiple choices and range specifications. For indexed aggregates the expansion uses a separate pass, as suggested in AI12-0212, to compute the size of the resulting object and preallocate that size before expanding the aggregate into individual indexed assignments. Tested on x86_64-pc-linux-gnu, committed on trunk gcc/ada/ * sem_aggr.adb (Resolve_Container_Aggregate): Add semantic checks for indexed aggregates, including component associations and iterated component associations. * exp_aggr.adb (Expand_Iterated_Component): New subprogram, subsidiary of Expand_Container_Aggreggate, used for positional, named, and indexed aggregates. (Aggregate_Size): New subprogram to precompute the size of an indexed aggregate prior to call to allocate it. (Expand_Range_Component): New subprogram so generate loop for a component association given by a range or a subtype name in an indexed aggregate.diff --git a/gcc/ada/exp_aggr.adb b/gcc/ada/exp_aggr.adb --- a/gcc/ada/exp_aggr.adb +++ b/gcc/ada/exp_aggr.adb @@ -6878,8 +6878,6 @@ package body Exp_Aggr is New_Indexed_Subp: Node_Id := Empty; Assign_Indexed_Subp : Node_Id := Empty; - procedure Expand_Iterated_Component (Comp : Node_Id); - Aggr_Code : constant List_Id := New_List; Temp : constant Entity_Id := Make_Temporary (Loc, 'C', N); @@ -6887,6 +6885,12 @@ package body Exp_Aggr is Decl : Node_Id; Init_Stat : Node_Id; + procedure Expand_Iterated_Component (Comp : Node_Id); + -- Handle iterated_component_association and iterated_Element + -- association by generating a loop over the specified range, + -- given either by a loop parameter specification or an iterator + -- specification. + --- -- Expand_Iterated_Component -- --- @@ -6946,6 +6950,7 @@ package body Exp_Aggr is Iteration_Scheme => L_Iteration_Scheme, Statements => Stats); Append (Loop_Stat, Aggr_Code); + end Expand_Iterated_Component; begin @@ -6968,11 +6973,16 @@ package body Exp_Aggr is Name => New_Occurrence_Of (Temp, Loc), Expression => New_Occurrence_Of (Entity (Empty_Subp), Loc)); end if; + Append (Init_Stat, Aggr_Code); - -- First case: positional aggregate + --- + -- Positional aggregate -- + --- - if Present (Add_Unnamed_Subp) then + if Present (Add_Unnamed_Subp) +and then No (Assign_Indexed_Subp) + then if Present (Expressions (N)) then declare Insert : constant Entity_Id := Entity (Add_Unnamed_Subp); @@ -6993,7 +7003,7 @@ package body Exp_Aggr is end; end if; - -- iterated component associations may be present. + -- Iterated component associations may also be present. Comp := First (Component_Associations (N)); while Present (Comp) loop @@ -7001,6 +7011,10 @@ package body Exp_Aggr is Next (Comp); end loop; + - + -- Named_Aggregate -- + - + elsif Present (Add_Named_Subp) then declare Insert : constant Entity_Id := Entity (Add_Named_Subp); @@ -7034,6 +7048,235 @@ package body Exp_Aggr is Next (Comp); end loop; end; + + --- + -- Indexed_Aggregate -- + --- + + elsif Present (Assign_Indexed_Subp) then + declare +Insert : constant Entity_Id := Entity (Assign_Indexed_Subp); +Index_Type : constant Entity_Id := + Etype (Next_Formal (First_Formal (Insert))); + +function Aggregate_Size return Int; +-- Compute number of entries in aggregate, including choices +-- that cover a range, as well as iterated constructs. + +function Expand_Range_Component + (Rng : Node_Id; + Expr : Node_Id) return Node_Id; +-- Transform a component assoication with a range into an +-- explicit loop. If the choice is a subtype name, it is +-- rewritten as a range with the corresponding bounds, which +-- are known to be static. + +Comp : Node_Id; +Index : Node_Id; +Pos: Int := 0; +Stat : Node_Id; +Key: Node_Id; +Size : Int := 0; + +- +-- Expand_Raange_Component -- +- + +function
[Ada] Ongoing work for AI12-0212: container aggregates
This patch modifies the parser to recognize iterated_element_associations, which may include a key_exprewsion to be used in a named aggregate such as a map. The new syntactic node N_Iterated_Element_Association is recognized throughout the compiler. The patch also extends the analysis and expansion of positional and named aggregates that include iterated_element_associations, (for now without key_expressions). Tested on x86_64-pc-linux-gnu, committed on trunk gcc/ada/ * par-ch4.adb (P_Iterated_Component_Association): Extended to recognzize the similar Iterated_Element_Association. This node is only generated when an explicit Key_Expression is given. Otherwise the distinction between the two iterated forms is done during semantic analysis. * sinfo.ads: New node N_Iterated_Element_Association, for Ada202x container aggregates. New field Key_Expression. * sinfo.adb: Subprograms for new node and newn field. * sem_aggr.adb (Resolve_Iterated_Component_Association): Handle the case where the Iteration_Scheme is an Iterator_Specification. * exp_aggr.adb (Wxpand_Iterated_Component): Handle a component with an Iterated_Component_Association, generate proper loop using given Iterator_Specification. * exp_util.adb (Insert_Axtions): Handle new node as other aggregate components. * sem.adb, sprint.adb: Handle new node. * tbuild.adb (Make_Implicit_Loop_Statement): Handle properly a loop with an Iterator_ specification.diff --git a/gcc/ada/exp_aggr.adb b/gcc/ada/exp_aggr.adb --- a/gcc/ada/exp_aggr.adb +++ b/gcc/ada/exp_aggr.adb @@ -6914,13 +6914,20 @@ package body Exp_Aggr is Stats : List_Id; begin - L_Range := Relocate_Node (First (Discrete_Choices (Comp))); - L_Iteration_Scheme := - Make_Iteration_Scheme (Loc, - Loop_Parameter_Specification => - Make_Loop_Parameter_Specification (Loc, - Defining_Identifier => Loop_Id, - Discrete_Subtype_Definition => L_Range)); + if Present (Iterator_Specification (Comp)) then +L_Iteration_Scheme := + Make_Iteration_Scheme (Loc, +Iterator_Specification => Iterator_Specification (Comp)); + + else +L_Range := Relocate_Node (First (Discrete_Choices (Comp))); +L_Iteration_Scheme := + Make_Iteration_Scheme (Loc, +Loop_Parameter_Specification => + Make_Loop_Parameter_Specification (Loc, +Defining_Identifier => Loop_Id, +Discrete_Subtype_Definition => L_Range)); + end if; -- Build insertion statement. For a positional aggregate, only the -- expression is needed. For a named aggregate, the loop variable, diff --git a/gcc/ada/exp_util.adb b/gcc/ada/exp_util.adb --- a/gcc/ada/exp_util.adb +++ b/gcc/ada/exp_util.adb @@ -7346,6 +7346,7 @@ package body Exp_Util is when N_Component_Association | N_Iterated_Component_Association + | N_Iterated_Element_Association => if Nkind (Parent (P)) = N_Aggregate and then Present (Loop_Actions (P)) diff --git a/gcc/ada/par-ch4.adb b/gcc/ada/par-ch4.adb --- a/gcc/ada/par-ch4.adb +++ b/gcc/ada/par-ch4.adb @@ -3407,6 +3407,8 @@ package body Ch4 is function P_Iterated_Component_Association return Node_Id is Assoc_Node : Node_Id; Id : Node_Id; + Iter_Spec : Node_Id; + Loop_Spec : Node_Id; State : Saved_Scan_State; -- Start of processing for P_Iterated_Component_Association @@ -3423,6 +3425,9 @@ package body Ch4 is -- if E is a subtype indication this is a loop parameter spec, -- while if E a name it is an iterator_specification, and the -- disambiguation takes place during semantic analysis. + -- In addition, if "use" is present after the specification, + -- this is an Iterated_Element_Association that carries a + -- key_expression, and we generate the appropriate node. Id := P_Defining_Identifier; Assoc_Node := @@ -3432,6 +3437,22 @@ package body Ch4 is Set_Defining_Identifier (Assoc_Node, Id); T_In; Set_Discrete_Choices (Assoc_Node, P_Discrete_Choice_List); + + if Token = Tok_Use then + +-- Key-expression is present, rewrite node as an +-- iterated_Element_Awwoiation. + +Scan; -- past USE +Loop_Spec := + New_Node (N_Loop_Parameter_Specification, Prev_Token_Ptr); +Set_Defining_Identifier (Loop_Spec, Id); +Set_Discrete_Subtype_Definition (Loop_Spec, + First (Discrete_Choices (Assoc_Node))); +Set_Loop_Parameter_Specification (Assoc_Node, Loop_Spec);