From: Eric Botcazou <ebotca...@adacore.com> It is implemented for container aggregates that are used to initialize an object, as specified by RM 7.6(17.2/3-17.3/3) for immutably limited types and types that need finalization, but for all types like other aggregates.
gcc/ada/ChangeLog: * exp_aggr.adb (Expand_Delta_Array_Aggregate): Move declaration. (Expand_Delta_Record_Aggregate): Likewise. (Expand_Container_Aggregate): Likewise. Move implementation to Build_Container_Aggr_Code. Implement built-in-place expansion for object declarations and allocators. (Build_Container_Aggr_Code): New function containing most of the code of the original Expand_Container_Aggregate. Do not build a temporary for the size calculation. Minor formatting tweaks. (Expand_N_Aggregate): Add comment. * exp_ch4.adb (Expand_Allocator_Expression): Detect the case of a container aggregate as qualified expression. Do not apply the predicate check on entry in this case and rewrite the allocator. * exp_ch7.adb (Build_Finalizer.Process_Object_Declaration): Deal with Last_Aggregate_Assignment first to compute the attachment point (as already done in Attach_Object_To_Master_Node). Tested on x86_64-pc-linux-gnu, committed on master. --- gcc/ada/exp_aggr.adb | 387 ++++++++++++++++++++++++++++--------------- gcc/ada/exp_ch4.adb | 32 +++- gcc/ada/exp_ch7.adb | 14 +- 3 files changed, 285 insertions(+), 148 deletions(-) diff --git a/gcc/ada/exp_aggr.adb b/gcc/ada/exp_aggr.adb index c94a6b9d581..cadbe7881f0 100644 --- a/gcc/ada/exp_aggr.adb +++ b/gcc/ada/exp_aggr.adb @@ -94,10 +94,6 @@ package body Exp_Aggr is type Case_Table_Type is array (Nat range <>) of Case_Bounds; -- Table type used by Check_Case_Choices procedure - procedure Expand_Delta_Array_Aggregate (N : Node_Id; Deltas : List_Id); - procedure Expand_Delta_Record_Aggregate (N : Node_Id; Deltas : List_Id); - procedure Expand_Container_Aggregate (N : Node_Id); - function Get_Base_Object (N : Node_Id) return Entity_Id; -- Return the base object, i.e. the outermost prefix object, that N refers -- to statically, or Empty if it cannot be determined. The assumption is @@ -181,7 +177,7 @@ package body Exp_Aggr is Typ : Entity_Id; Lhs : Node_Id) return List_Id; -- N is an N_Aggregate or an N_Extension_Aggregate. Typ is the type of the - -- aggregate. Target is an expression containing the location on which the + -- aggregate. Lhs is an expression containing the location on which the -- component by component assignments will take place. Returns the list of -- assignments plus all other adjustments needed for tagged and controlled -- types. @@ -191,6 +187,9 @@ package body Exp_Aggr is -- component by component. N is an N_Aggregate or N_Extension_Aggregate. -- Typ is the type of the record aggregate. + procedure Expand_Delta_Record_Aggregate (N : Node_Id; Deltas : List_Id); + -- This is the top level procedure for delta record aggregate expansion + procedure Expand_Record_Aggregate (N : Node_Id; Orig_Tag : Node_Id := Empty; @@ -232,6 +231,23 @@ package body Exp_Aggr is -- functions of the parent type, and when applying a stream attribute to -- an object of the derived type. + --------------------------------------------------------- + -- Local Subprograms for Container Aggregate Expansion -- + --------------------------------------------------------- + + procedure Expand_Container_Aggregate (N : Node_Id); + -- This is the top-level routine for container aggregate expansion + + function Build_Container_Aggr_Code + (N : Node_Id; + Typ : Entity_Id; + Lhs : Node_Id; + Init : out Node_Id) return List_Id; + -- N is an N_Aggregate for a container type Typ. Lhs is an expression + -- containing the location of the anonymous object, which may be built + -- in place. Returns the function call used to initialize the anonymous + -- object in Init and the list of statements needed to build N. + ----------------------------------------------------- -- Local Subprograms for Array Aggregate Expansion -- ----------------------------------------------------- @@ -299,9 +315,12 @@ package body Exp_Aggr is -- these are cases we handle in there. procedure Expand_Array_Aggregate (N : Node_Id); - -- This is the top-level routine to perform array aggregate expansion. + -- This is the top-level routine for array aggregate expansion. -- N is the N_Aggregate node to be expanded. + procedure Expand_Delta_Array_Aggregate (N : Node_Id; Deltas : List_Id); + -- This is the top-level routine for delta array aggregate expansion + function Is_Two_Dim_Packed_Array (Typ : Entity_Id) return Boolean; -- For 2D packed array aggregates with constant bounds and constant scalar -- components, it is preferable to pack the inner aggregates because the @@ -6499,6 +6518,7 @@ package body Exp_Aggr is procedure Expand_N_Aggregate (N : Node_Id) is T : constant Entity_Id := Etype (N); + begin -- Record aggregate case @@ -6508,6 +6528,8 @@ package body Exp_Aggr is then Expand_Record_Aggregate (N); + -- Container aggregate case + elsif Has_Aspect (T, Aspect_Aggregate) then Expand_Container_Aggregate (N); @@ -6612,41 +6634,34 @@ package body Exp_Aggr is return; end Expand_N_Aggregate; - -------------------------------- - -- Expand_Container_Aggregate -- - -------------------------------- + ------------------------------- + -- Build_Container_Aggr_Code -- + ------------------------------- - procedure Expand_Container_Aggregate (N : Node_Id) is - Loc : constant Source_Ptr := Sloc (N); - Typ : constant Entity_Id := Etype (N); - Asp : constant Node_Id := Find_Value_Of_Aspect (Typ, Aspect_Aggregate); + function Build_Container_Aggr_Code + (N : Node_Id; + Typ : Entity_Id; + Lhs : Node_Id; + Init : out Node_Id) return List_Id + is + Loc : constant Source_Ptr := Sloc (N); + Aggr_Code : constant List_Id := New_List; + Asp : constant Node_Id := + Find_Value_Of_Aspect (Typ, Aspect_Aggregate); Empty_Subp : Node_Id := Empty; Add_Named_Subp : Node_Id := Empty; Add_Unnamed_Subp : Node_Id := Empty; New_Indexed_Subp : Node_Id := Empty; Assign_Indexed_Subp : Node_Id := Empty; + -- Identifiers for the subprograms referenced in the aggregate - Aggr_Code : constant List_Id := New_List; - Temp : constant Entity_Id := Make_Temporary (Loc, 'C', N); - - Comp : Node_Id; - Init_Stat : Node_Id; - - -- 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; - + Choice_Lo : Node_Id := Empty; + Choice_Hi : Node_Id := Empty; -- These variables are used to determine the smallest and largest -- choice values. Choice_Lo and Choice_Hi are passed to the New_Indexed -- function, for allocating an indexed aggregate object. - Choice_Lo : Node_Id := Empty; - Choice_Hi : Node_Id := Empty; - - Is_Indexed_Aggregate : Boolean := False; - function Aggregate_Size return Node_Id; -- Compute number of entries in aggregate, including choices -- that cover a range or subtype, as well as iterated constructs. @@ -6658,7 +6673,7 @@ package body Exp_Aggr is -- happens this function returns an empty node. In that case we will -- later just allocate a default size for the aggregate. - function Build_Siz_Exp (Comp : Node_Id) return Node_Id; + function Build_Size_Expr (Comp : Node_Id) return Node_Id; -- 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 @@ -6673,7 +6688,7 @@ package body Exp_Aggr is -- given either by a loop parameter specification or an iterator -- specification. - function Expand_Range_Component + function Expand_Range_Component (Rng : Node_Id; Expr : Node_Id; Insert_Op : Entity_Id) return Node_Id; @@ -6693,8 +6708,6 @@ package body Exp_Aggr is Comp_Siz_Exp : Node_Id; Siz_Exp : Node_Id; - -- Start of processing for Aggregate_Size - begin -- Aggregate is either all positional or all named @@ -6705,7 +6718,7 @@ package body Exp_Aggr is Comp := First (Component_Associations (N)); while Present (Comp) loop - Comp_Siz_Exp := Build_Siz_Exp (Comp); + Comp_Siz_Exp := Build_Size_Expr (Comp); if No (Comp_Siz_Exp) then @@ -6714,6 +6727,7 @@ package body Exp_Aggr is -- should use the default value instead. return Empty; + else if Is_Static_Expression (Siz_Exp) and then Is_Static_Expression (Comp_Siz_Exp) @@ -6724,6 +6738,7 @@ package body Exp_Aggr is To_Int (Siz_Exp) + To_Int (Comp_Siz_Exp)); Set_Is_Static_Expression (Siz_Exp); + else Siz_Exp := Make_Op_Add (Sloc (Comp), Left_Opnd => Siz_Exp, @@ -6738,11 +6753,11 @@ package body Exp_Aggr is return Siz_Exp; end Aggregate_Size; - ------------------- - -- Build_Siz_Exp -- - ------------------- + --------------------- + -- Build_Size_Expr -- + --------------------- - function Build_Siz_Exp (Comp : Node_Id) return Node_Id is + function Build_Size_Expr (Comp : Node_Id) return Node_Id is Lo, Hi : Node_Id; It : Node_Id; Siz_Exp : Node_Id := Empty; @@ -6754,9 +6769,11 @@ package body Exp_Aggr is -- Update the Choice_Lo and Choice_Hi variables with the smallest -- and largest possible node values. - procedure Update_Choices (Lo : Node_Id; Hi : Node_Id) is - -- Local variables + -------------------- + -- Update_Choices -- + -------------------- + procedure Update_Choices (Lo : Node_Id; Hi : Node_Id) is Range_Int_Lo : constant Int := To_Int (Lo); Range_Int_Hi : constant Int := To_Int (Hi); @@ -6776,7 +6793,7 @@ package body Exp_Aggr is end if; end Update_Choices; - -- Start of processing for Build_Siz_Exp + -- Start of processing for Build_Size_Expr begin if Nkind (Comp) = N_Range then @@ -6797,6 +6814,7 @@ package body Exp_Aggr is Set_Is_Static_Expression (Siz_Exp); return Siz_Exp; + else -- Capture the nonstatic bounds, for later use in passing on -- the call to New_Indexed. @@ -6833,7 +6851,7 @@ package body Exp_Aggr is Siz_Exp : Node_Id := Empty; begin while Present (Idx_N) loop - Temp_Siz_Exp := Build_Siz_Exp (Idx_N); + Temp_Siz_Exp := Build_Size_Expr (Idx_N); pragma Assert (Present (Temp_Siz_Exp)); @@ -6866,8 +6884,9 @@ package body Exp_Aggr is end if; return Empty; + else - return Build_Siz_Exp (First (Discrete_Choices (Comp))); + return Build_Size_Expr (First (Discrete_Choices (Comp))); end if; elsif Nkind (Comp) = N_Component_Association then @@ -6878,7 +6897,7 @@ package body Exp_Aggr is if Nkind (Choice) = N_Range then - Temp_Siz_Exp := Build_Siz_Exp (Choice); + Temp_Siz_Exp := Build_Size_Expr (Choice); -- Choice is subtype_mark; add range based on its bounds @@ -6893,7 +6912,7 @@ package body Exp_Aggr is New_Copy_Tree (Lo), New_Copy_Tree (Hi))); - Temp_Siz_Exp := Build_Siz_Exp (Choice); + Temp_Siz_Exp := Build_Size_Expr (Choice); -- Choice is a single discrete value @@ -6935,6 +6954,7 @@ package body Exp_Aggr is end loop; return Siz_Exp; + elsif Nkind (Comp) = N_Iterated_Element_Association then return Empty; @@ -6945,14 +6965,14 @@ package body Exp_Aggr is else return Empty; end if; - end Build_Siz_Exp; + end Build_Size_Expr; ------------------------------- -- Expand_Iterated_Component -- ------------------------------- procedure Expand_Iterated_Component (Comp : Node_Id) is - Expr : constant Node_Id := Expression (Comp); + Expr : constant Node_Id := Expression (Comp); Key_Expr : Node_Id := Empty; Loop_Id : Entity_Id; @@ -6998,8 +7018,8 @@ package body Exp_Aggr is (Loop_Parameter_Specification (L_Iteration_Scheme), Loop_Id); end if; - else + else -- Iterated_Component_Association. if Present (Iterator_Specification (Comp)) then @@ -7047,20 +7067,21 @@ package body Exp_Aggr is (Make_Procedure_Call_Statement (Loc, Name => New_Occurrence_Of (Entity (Add_Unnamed_Subp), Loc), Parameter_Associations => - New_List (New_Occurrence_Of (Temp, Loc), + New_List (New_Copy_Tree (Lhs), New_Copy_Tree (Expr)))); + else -- Named or indexed aggregate, for which a key is present, -- possibly with a specified key_expression. if Present (Key_Expr) then - Params := New_List (New_Occurrence_Of (Temp, Loc), - New_Copy_Tree (Key_Expr), - New_Copy_Tree (Expr)); + Params := New_List (New_Copy_Tree (Lhs), + New_Copy_Tree (Key_Expr), + New_Copy_Tree (Expr)); else - Params := New_List (New_Occurrence_Of (Temp, Loc), - New_Occurrence_Of (Loop_Id, Loc), - New_Copy_Tree (Expr)); + Params := New_List (New_Copy_Tree (Lhs), + New_Occurrence_Of (Loop_Id, Loc), + New_Copy_Tree (Expr)); end if; Stats := New_List @@ -7074,8 +7095,8 @@ package body Exp_Aggr is Identifier => Empty, Iteration_Scheme => L_Iteration_Scheme, Statements => Stats); - Append (Loop_Stat, Aggr_Code); + Append (Loop_Stat, Aggr_Code); end Expand_Iterated_Component; ---------------------------- @@ -7087,8 +7108,7 @@ package body Exp_Aggr is Expr : Node_Id; Insert_Op : Entity_Id) return Node_Id is - Loop_Id : constant Entity_Id := - Make_Temporary (Loc, 'T'); + Loop_Id : constant Entity_Id := Make_Temporary (Loc, 'T'); L_Iteration_Scheme : Node_Id; Stats : List_Id; @@ -7106,11 +7126,11 @@ package body Exp_Aggr is Name => New_Occurrence_Of (Insert_Op, Loc), Parameter_Associations => - New_List (New_Occurrence_Of (Temp, Loc), + New_List (New_Copy_Tree (Lhs), New_Occurrence_Of (Loop_Id, Loc), New_Copy_Tree (Expr)))); - return Make_Implicit_Loop_Statement + return Make_Implicit_Loop_Statement (Node => N, Identifier => Empty, Iteration_Scheme => L_Iteration_Scheme, @@ -7121,43 +7141,52 @@ package body Exp_Aggr is -- To_Int -- ------------ + -- The bounds of the discrete range are integers or enumeration literals + function To_Int (Expr : N_Subexpr_Id) return Int is begin - -- The bounds of the discrete range are integers or enumeration - -- literals return UI_To_Int ((if Nkind (Expr) = N_Integer_Literal then Intval (Expr) - else Enumeration_Pos (Expr))); + else Enumeration_Pos (Expr))); end To_Int; - -- Start of processing for Expand_Container_Aggregate + -- Local variables + + Is_Indexed_Aggregate : Boolean; + -- True if the aggregate is indexed as per RM 4.3.5(25/5) + + -- Start of processing for Build_Container_Aggr_Code begin Parse_Aspect_Aggregate (Asp, Empty_Subp, Add_Named_Subp, Add_Unnamed_Subp, New_Indexed_Subp, Assign_Indexed_Subp); - -- Determine whether this is an indexed aggregate (see RM 4.3.5(25/5)) + -- Determine whether this is an indexed aggregate Is_Indexed_Aggregate := Sem_Aggr.Is_Indexed_Aggregate (N, Add_Unnamed_Subp, New_Indexed_Subp); - -- The constructor for bounded containers is a function with - -- a parameter that sets the size of the container. If the - -- size cannot be determined statically we use a default value - -- or a dynamic expression. - - Siz_Exp := Aggregate_Size; + -- Build the function call that initializes the anonymous object declare - Count_Type : Entity_Id := Standard_Natural; - Default : Node_Id := Empty; Empty_First_Formal : constant Entity_Id := - First_Formal (Entity (Empty_Subp)); - Param_List : List_Id; + First_Formal (Entity (Empty_Subp)); + + Count_Type : Entity_Id; + Default : Node_Id; + Param_List : List_Id; + Siz_Exp : Node_Id; begin + -- The constructor for bounded containers is a function with + -- a parameter that sets the size of the container. If the + -- size cannot be determined statically we use a default value + -- or a dynamic expression. + + Siz_Exp := Aggregate_Size; + -- If aggregate size is not static, we use the default value of the -- Empty operation's formal parameter for the allocation. We assume -- that this (implementation-dependent) value is static, even though @@ -7166,6 +7195,10 @@ package body Exp_Aggr is if Present (Empty_First_Formal) then Default := Default_Value (Empty_First_Formal); Count_Type := Etype (Empty_First_Formal); + + else + Default := Empty; + Count_Type := Standard_Natural; end if; -- Create an object initialized by the aggregate's determined size @@ -7174,32 +7207,21 @@ package body Exp_Aggr is -- and the default otherwise. if Present (Siz_Exp) then - Siz_Exp := Make_Type_Conversion (Loc, - Subtype_Mark => - New_Occurrence_Of (Count_Type, Loc), - Expression => Siz_Exp); + Siz_Exp := + Make_Type_Conversion (Loc, + Subtype_Mark => New_Occurrence_Of (Count_Type, Loc), + Expression => Siz_Exp); elsif Present (Default) then - Siz_Exp := Make_Integer_Literal (Loc, - UI_To_Int (Intval (Default))); + Siz_Exp := New_Copy_Tree (Default); -- If the length isn't known and there's not a default, then use -- zero for the initial container length. else - Siz_Exp := Make_Type_Conversion (Loc, - Subtype_Mark => - New_Occurrence_Of (Count_Type, Loc), - Expression => Make_Integer_Literal (Loc, 0)); + Siz_Exp := Make_Integer_Literal (Loc, 0); end if; - Siz_Decl := Make_Object_Declaration (Loc, - Defining_Identifier => Make_Temporary (Loc, 'S', N), - Object_Definition => - New_Occurrence_Of (Count_Type, Loc), - Expression => Siz_Exp); - Append (Siz_Decl, Aggr_Code); - -- In the case of an indexed aggregate, the aggregate is allocated -- with the New_Indexed operation, passing the bounds. @@ -7223,10 +7245,7 @@ package body Exp_Aggr is Left_Opnd => Make_Type_Conversion (Loc, Subtype_Mark => New_Occurrence_Of (Index_Type, Loc), - Expression => - New_Occurrence_Of - (Defining_Identifier (Siz_Decl), - Loc)), + Expression => Siz_Exp), Right_Opnd => Make_Integer_Literal (Loc, 1))); else @@ -7234,40 +7253,28 @@ package body Exp_Aggr is Choice_Hi := New_Copy_Tree (Choice_Hi); end if; - Init_Stat := - Make_Object_Declaration (Loc, - Defining_Identifier => Temp, - Object_Definition => New_Occurrence_Of (Typ, Loc), - Expression => Make_Function_Call (Loc, - Name => - New_Occurrence_Of (Entity (New_Indexed_Subp), Loc), - Parameter_Associations => - New_List (Choice_Lo, Choice_Hi))); + Init := + Make_Function_Call (Loc, + Name => New_Occurrence_Of (Entity (New_Indexed_Subp), Loc), + Parameter_Associations => New_List (Choice_Lo, Choice_Hi)); end; -- Otherwise we generate a call to the Empty function, passing the - -- determined number of elements as saved in Siz_Decl if the function - -- has a formal parameter, and otherwise making a parameterless call. + -- determined number of elements Siz_Exp if the function has a formal + -- parameter, and otherwise making a parameterless call. else if Present (Empty_First_Formal) then - Param_List := - New_List - (New_Occurrence_Of (Defining_Identifier (Siz_Decl), Loc)); + Param_List := New_List (Siz_Exp); else Param_List := No_List; end if; - Init_Stat := - Make_Object_Declaration (Loc, - Defining_Identifier => Temp, - Object_Definition => New_Occurrence_Of (Typ, Loc), - Expression => Make_Function_Call (Loc, - Name => New_Occurrence_Of (Entity (Empty_Subp), Loc), - Parameter_Associations => Param_List)); + Init := + Make_Function_Call (Loc, + Name => New_Occurrence_Of (Entity (Empty_Subp), Loc), + Parameter_Associations => Param_List); end if; - - Append (Init_Stat, Aggr_Code); end; -- Report warning on infinite recursion if an empty container aggregate @@ -7361,12 +7368,12 @@ package body Exp_Aggr is end if; Param_List := - New_List (New_Occurrence_Of (Temp, Loc), + New_List (New_Copy_Tree (Lhs), New_Occurrence_Of (Key_Index, Loc), New_Copy_Tree (Comp)); else Param_List := - New_List (New_Occurrence_Of (Temp, Loc), + New_List (New_Copy_Tree (Lhs), New_Copy_Tree (Comp)); end if; @@ -7382,15 +7389,20 @@ package body Exp_Aggr is -- such as sets may include iterated component associations. elsif not Is_Indexed_Aggregate then - Comp := First (Component_Associations (N)); - while Present (Comp) loop - if Nkind (Comp) = N_Iterated_Component_Association - or else Nkind (Comp) = N_Iterated_Element_Association - then - Expand_Iterated_Component (Comp); - end if; - Next (Comp); - end loop; + declare + Comp : Node_Id; + + begin + Comp := First (Component_Associations (N)); + while Present (Comp) loop + if Nkind (Comp) = N_Iterated_Component_Association + or else Nkind (Comp) = N_Iterated_Element_Association + then + Expand_Iterated_Component (Comp); + end if; + Next (Comp); + end loop; + end; end if; --------------------- @@ -7400,8 +7412,11 @@ package body Exp_Aggr is elsif Present (Add_Named_Subp) then declare Insert : constant Entity_Id := Entity (Add_Named_Subp); - Stat : Node_Id; - Key : Node_Id; + + Comp : Node_Id; + Key : Node_Id; + Stat : Node_Id; + begin Comp := First (Component_Associations (N)); @@ -7429,7 +7444,7 @@ package body Exp_Aggr is Stat := Make_Procedure_Call_Statement (Loc, Name => New_Occurrence_Of (Insert, Loc), Parameter_Associations => - New_List (New_Occurrence_Of (Temp, Loc), + New_List (New_Copy_Tree (Lhs), New_Copy_Tree (Key), New_Copy_Tree (Expression (Comp)))); end if; @@ -7498,7 +7513,7 @@ package body Exp_Aggr is Stat := Make_Procedure_Call_Statement (Loc, Name => New_Occurrence_Of (Insert, Loc), Parameter_Associations => - New_List (New_Occurrence_Of (Temp, Loc), + New_List (New_Copy_Tree (Lhs), New_Copy_Tree (Key), New_Copy_Tree (Expression (Comp)))); end if; @@ -7527,9 +7542,107 @@ package body Exp_Aggr is end; end if; - Insert_Actions (N, Aggr_Code); - Rewrite (N, New_Occurrence_Of (Temp, Loc)); - Analyze_And_Resolve (N, Typ); + return Aggr_Code; + end Build_Container_Aggr_Code; + + -------------------------------- + -- Expand_Container_Aggregate -- + -------------------------------- + + procedure Expand_Container_Aggregate (N : Node_Id) is + Loc : constant Source_Ptr := Sloc (N); + Typ : constant Entity_Id := Etype (N); + + Aggr_Code : List_Id; + Init : Node_Id; + Lhs : Node_Id; + Obj_Id : Entity_Id; + Par : Node_Id; + + begin + Par := Parent (N); + while Nkind (Par) = N_Qualified_Expression loop + Par := Parent (Par); + end loop; + + -- If the aggregate is the initialization expression of an object + -- declaration, we always build the aggregate in place, although + -- this is required only for immutably limited types and types + -- that need finalization, see RM 7.6(17.2/3-17.3/3). + + if Nkind (Par) = N_Object_Declaration then + Obj_Id := Defining_Identifier (Par); + Lhs := New_Occurrence_Of (Obj_Id, Loc); + Set_Assignment_OK (Lhs); + Aggr_Code := Build_Container_Aggr_Code (N, Typ, Lhs, Init); + + -- Save the last assignment statement associated with the aggregate + -- when building a controlled object. This reference is utilized by + -- the finalization machinery when marking an object as successfully + -- initialized. + + if Needs_Finalization (Typ) then + Mutate_Ekind (Obj_Id, E_Variable); + Set_Last_Aggregate_Assignment (Obj_Id, Last (Aggr_Code)); + end if; + + -- If a transient scope has been created around the declaration, we + -- need to attach the code to it so that the finalization actions of + -- the declaration will be inserted after it. Otherwise, we directly + -- insert it after the declaration and it will be analyzed only once + -- the declaration is processed. + + if Scope_Is_Transient and then Par = Node_To_Be_Wrapped then + Insert_Actions_After (Par, Aggr_Code); + else + Insert_List_After (Par, Aggr_Code); + end if; + + Rewrite (N, Init); + Analyze_And_Resolve (N, Typ); + + -- Likewise if the aggregate is the qualified expression of an allocator + -- but, in this case, we wait until after Expand_Allocator_Expression + -- rewrites the allocator as the initialization expression of an object + -- declaration to have the left hand side. + + elsif Nkind (Par) = N_Allocator then + if Nkind (Parent (Par)) = N_Object_Declaration + and then not Comes_From_Source (Defining_Identifier (Parent (Par))) + then + Obj_Id := Defining_Identifier (Parent (Par)); + Lhs := + Make_Explicit_Dereference (Loc, + Prefix => New_Occurrence_Of (Obj_Id, Loc)); + Set_Assignment_OK (Lhs); + Aggr_Code := Build_Container_Aggr_Code (N, Typ, Lhs, Init); + + Insert_Actions_After (Parent (Par), Aggr_Code); + + Rewrite (N, Init); + Analyze_And_Resolve (N, Typ); + end if; + + -- Otherwise we create a temporary for the anonymous object and replace + -- the aggregate with the temporary. + + else + Obj_Id := Make_Temporary (Loc, 'A', N); + Lhs := New_Occurrence_Of (Obj_Id, Loc); + Set_Assignment_OK (Lhs); + + Aggr_Code := Build_Container_Aggr_Code (N, Typ, Lhs, Init); + Prepend_To (Aggr_Code, + Make_Object_Declaration (Loc, + Defining_Identifier => Obj_Id, + Object_Definition => New_Occurrence_Of (Typ, Loc), + Expression => Init)); + + Insert_Actions (N, Aggr_Code); + + Rewrite (N, Lhs); + Analyze_And_Resolve (N, Typ); + end if; end Expand_Container_Aggregate; ------------------------------ diff --git a/gcc/ada/exp_ch4.adb b/gcc/ada/exp_ch4.adb index 3817997c836..381c9f8fb3d 100644 --- a/gcc/ada/exp_ch4.adb +++ b/gcc/ada/exp_ch4.adb @@ -657,6 +657,7 @@ package body Exp_Ch4 is Adj_Call : Node_Id; Aggr_In_Place : Boolean; + Container_Aggr : Boolean; Delayed_Cond_Expr : Boolean; Node : Node_Id; Temp : Entity_Id; @@ -668,6 +669,8 @@ package body Exp_Ch4 is TagR : Node_Id := Empty; -- Target reference for tag assignment + -- Start of processing for Expand_Allocator_Expression + begin -- Handle call to C++ constructor @@ -689,14 +692,19 @@ package body Exp_Ch4 is Aggr_In_Place := Is_Delayed_Aggregate (Exp); Delayed_Cond_Expr := Is_Delayed_Conditional_Expression (Exp); + Container_Aggr := Nkind (Exp) = N_Aggregate + and then Has_Aspect (T, Aspect_Aggregate); -- If the expression is an aggregate to be built in place, then we need -- to delay applying predicate checks, because this would result in the -- creation of a temporary, which is illegal for limited types and just -- inefficient in the other cases. Likewise for a conditional expression - -- whose expansion has been delayed. + -- whose expansion has been delayed and for container aggregates. - if not Aggr_In_Place and then not Delayed_Cond_Expr then + if not Aggr_In_Place + and then not Delayed_Cond_Expr + and then not Container_Aggr + then Apply_Predicate_Check (Exp, T); end if; @@ -759,9 +767,26 @@ package body Exp_Ch4 is return; end if; + -- An allocator with a container aggregate as qualified expression must + -- be rewritten into the form expected by Expand_Container_Aggregate. + + if Container_Aggr then + Temp := Make_Temporary (Loc, 'P', N); + Temp_Decl := + Make_Object_Declaration (Loc, + Defining_Identifier => Temp, + Object_Definition => New_Occurrence_Of (PtrT, Loc), + Expression => Relocate_Node (N)); + + Set_Analyzed (Exp, False); + Insert_Action (N, Temp_Decl); + Rewrite (N, New_Occurrence_Of (Temp, Loc)); + Analyze_And_Resolve (N, PtrT); + Apply_Predicate_Check (N, T, Deref => True); + -- Case of tagged type or type requiring finalization - if Is_Tagged_Type (T) or else Needs_Finalization (T) then + elsif Is_Tagged_Type (T) or else Needs_Finalization (T) then -- Ada 2005 (AI-318-02): If the initialization expression is a call -- to a build-in-place function, then access to the allocated object @@ -1072,7 +1097,6 @@ package body Exp_Ch4 is Build_Allocate_Deallocate_Proc (Declaration_Node (Temp), Mark => N); Rewrite (N, New_Occurrence_Of (Temp, Loc)); Analyze_And_Resolve (N, PtrT); - Apply_Predicate_Check (N, T, Deref => True); elsif Is_Access_Type (T) and then Can_Never_Be_Null (T) then diff --git a/gcc/ada/exp_ch7.adb b/gcc/ada/exp_ch7.adb index f40371347fd..5db9659c1bd 100644 --- a/gcc/ada/exp_ch7.adb +++ b/gcc/ada/exp_ch7.adb @@ -2781,18 +2781,18 @@ package body Exp_Ch7 is if Ekind (Obj_Id) in E_Constant | E_Variable then - -- The object is initialized by a build-in-place function call. - -- The Master_Node insertion point is after the function call. - - if Present (BIP_Initialization_Call (Obj_Id)) then - Master_Node_Ins := BIP_Initialization_Call (Obj_Id); - -- The object is initialized by an aggregate. The Master_Node -- insertion point is after the last aggregate assignment. - elsif Present (Last_Aggregate_Assignment (Obj_Id)) then + if Present (Last_Aggregate_Assignment (Obj_Id)) then Master_Node_Ins := Last_Aggregate_Assignment (Obj_Id); + -- The object is initialized by a build-in-place function call. + -- The Master_Node insertion point is after the function call. + + elsif Present (BIP_Initialization_Call (Obj_Id)) then + Master_Node_Ins := BIP_Initialization_Call (Obj_Id); + -- In other cases the Master_Node is inserted after the last call -- to either [Deep_]Initialize or the type-specific init proc. -- 2.43.0