From 7617b83242b19efa2216eb817befb53b75a6794c Mon Sep 17 00:00:00 2001 From: Eric Botcazou <ebotcazou@adacore.com> Date: Tue, 5 Nov 2024 15:46:45 +0100 Subject: [PATCH] ada: Further cleanup in expansion of array aggregates in allocators This mainly decouples the handling of the allocator case from that of the assignment case in Expand_Array_Aggregate and also makes Must_Slide a bit more forgiving. gcc/ada/ChangeLog: * exp_aggr.adb (In_Place_Assign_OK): Remove handling of allocators and call Must_Slide instead of implementing the check manually. (Convert_To_Assignments): Adjust outdated comment. (Expand_Array_Aggregate): Move handling of allocator case to STEP 3 and call Must_Slide directly for it. (Must_Slide): Replace tests based on Is_OK_Static_Expression with tests based on Compile_Time_Known_Value. --- gcc/ada/exp_aggr.adb | 182 ++++++++++++++----------------------------- 1 file changed, 58 insertions(+), 124 deletions(-) diff --git a/gcc/ada/exp_aggr.adb b/gcc/ada/exp_aggr.adb index eabbc6a0df50..65ef081109b3 100644 --- a/gcc/ada/exp_aggr.adb +++ b/gcc/ada/exp_aggr.adb @@ -3997,10 +3997,6 @@ package body Exp_Aggr is -- Local variables - Aggr_In : Node_Id; - Aggr_Bounds : Range_Nodes; - Obj_In : Node_Id; - Obj_Bounds : Range_Nodes; Parent_Kind : Node_Kind; Parent_Node : Node_Id; @@ -4025,86 +4021,15 @@ package body Exp_Aggr is -- assignment in place unless the bounds of the aggregate are -- statically equal to those of the target. - -- If the aggregate is given by an others choice, the bounds are - -- derived from the left-hand side, and the assignment is safe if - -- the expression is. - if Is_Array - and then Present (Component_Associations (N)) - and then not Is_Others_Aggregate (N) + and then Must_Slide (N, Etype (Name (Parent_Node)), Etype (N)) then - Aggr_In := First_Index (Etype (N)); - - -- Context is an assignment - - if Parent_Kind = N_Assignment_Statement then - Obj_In := First_Index (Etype (Name (Parent_Node))); - - -- Context is an allocator. Check the bounds of the aggregate against - -- those of the designated type, except in the case where the type is - -- unconstrained (and then we can directly return true, see below). - - else pragma Assert (Parent_Kind = N_Allocator); - declare - Desig_Typ : constant Entity_Id := - Designated_Type (Etype (Parent_Node)); - begin - if not Is_Constrained (Desig_Typ) then - return True; - end if; - - Obj_In := First_Index (Desig_Typ); - end; - end if; - - while Present (Aggr_In) loop - Aggr_Bounds := Get_Index_Bounds (Aggr_In); - Obj_Bounds := Get_Index_Bounds (Obj_In); - - -- We require static bounds for the target and a static matching - -- of low bound for the aggregate. - - if not Compile_Time_Known_Value (Obj_Bounds.First) - or else not Compile_Time_Known_Value (Obj_Bounds.Last) - or else not Compile_Time_Known_Value (Aggr_Bounds.First) - or else Expr_Value (Aggr_Bounds.First) /= - Expr_Value (Obj_Bounds.First) - then - return False; - - -- For an assignment statement we require static matching of - -- bounds. Ditto for an allocator whose qualified expression - -- is a constrained type. If the expression in the allocator - -- is an unconstrained array, we accept an upper bound that - -- is not static, to allow for nonstatic expressions of the - -- base type. Clearly there are further possibilities (with - -- diminishing returns) for safely building arrays in place - -- here. - - elsif Parent_Kind = N_Assignment_Statement - or else Is_Constrained (Etype (Parent_Node)) - then - if not Compile_Time_Known_Value (Aggr_Bounds.Last) - or else Expr_Value (Aggr_Bounds.Last) /= - Expr_Value (Obj_Bounds.Last) - then - return False; - end if; - end if; - - Next_Index (Aggr_In); - Next_Index (Obj_In); - end loop; + return False; end if; - -- Now check the component values themselves, except for an allocator - -- for which the target is newly allocated memory. + -- Now check the component values themselves - if Parent_Kind = N_Allocator then - return True; - else - return Safe_Aggregate (N); - end if; + return Safe_Aggregate (N); end In_Place_Assign_OK; ---------------------------- @@ -4227,16 +4152,8 @@ package body Exp_Aggr is or else (Nkind (Parent_Node) = N_Assignment_Statement and then Inside_Init_Proc) - -- (Ada 2005) An inherently limited type in a return statement, which - -- will be handled in a build-in-place fashion, and may be rewritten - -- as an extended return and have its own finalization machinery. - -- In the case of a simple return, the aggregate needs to be delayed - -- until the scope for the return statement has been created, so - -- that any finalization chain will be associated with that scope. - -- For extended returns, we delay expansion to avoid the creation - -- of an unwanted transient scope that could result in premature - -- finalization of the return object (which is built in place - -- within the caller's scope). + -- Simple return statement, which will be handled in a build-in-place + -- fashion and will ultimately be rewritten as an extended return. or else Is_Build_In_Place_Aggregate_Return (Parent_Node) then @@ -6109,9 +6026,8 @@ package body Exp_Aggr is -- STEP 3 - -- Delay expansion for nested aggregates: it will be taken care of when - -- the parent aggregate is expanded, excluding container aggregates as - -- these are transformed into subprogram calls later. + -- Set the Expansion_Delayed flag in the cases where the transformation + -- will be done top down from above. Parent_Node := Parent (N); Parent_Kind := Nkind (Parent_Node); @@ -6121,17 +6037,48 @@ package body Exp_Aggr is Parent_Kind := Nkind (Parent_Node); end if; - if (Parent_Kind = N_Component_Association + if + -- Internal aggregates (transformed when expanding the parent), + -- excluding container aggregates as these are transformed into + -- subprogram calls later. So far aggregates with self-references + -- are not supported if they appear in a conditional expression. + + (Parent_Kind = N_Component_Association and then not Is_Container_Aggregate (Parent (Parent_Node))) - or else (Parent_Kind in N_Aggregate | N_Extension_Aggregate - and then not Is_Container_Aggregate (Parent_Node)) - or else (Parent_Kind = N_Object_Declaration - and then (Needs_Finalization (Typ) - or else Is_Special_Return_Object - (Defining_Identifier (Parent_Node)))) - or else (Parent_Kind = N_Assignment_Statement - and then Inside_Init_Proc) - or else Is_Build_In_Place_Aggregate_Return (Parent_Node) + + or else (Parent_Kind in N_Aggregate | N_Extension_Aggregate + and then not Is_Container_Aggregate (Parent_Node)) + + -- Allocator (see Convert_Aggr_In_Allocator) + + or else (Nkind (Parent_Node) = N_Allocator + and then (Is_Limited_Type (Typ) + or else Needs_Finalization (Typ) + or else (not Is_Bit_Packed_Array (Typ) + and then not + Must_Slide + (N, + Designated_Type + (Etype (Parent_Node)), + Typ)))) + + -- Object declaration (see Convert_Aggr_In_Object_Decl) + + or else (Parent_Kind = N_Object_Declaration + and then (Needs_Finalization (Typ) + or else Is_Special_Return_Object + (Defining_Identifier (Parent_Node)))) + + -- Safe assignment (see Convert_Aggr_In_Assignment). So far only the + -- assignments in init procs are taken into account. + + or else (Parent_Kind = N_Assignment_Statement + and then Inside_Init_Proc) + + -- Simple return statement, which will be handled in a build-in-place + -- fashion and will ultimately be rewritten as an extended return. + + or else Is_Build_In_Place_Aggregate_Return (Parent_Node) then Set_Expansion_Delayed (N, not Static_Array_Aggregate (N)); return; @@ -6150,11 +6097,6 @@ package body Exp_Aggr is -- create a temporary. A full analysis for safety of in-place assignment -- is delicate. - -- For allocators we assign to the designated object in place if the - -- aggregate meets the same conditions as other in-place assignments. - -- In this case the aggregate may not come from source but was created - -- for default initialization, e.g. with Initialize_Scalars. - if Requires_Transient_Scope (Typ) then Establish_Transient_Scope (N, Manage_Sec_Stack => False); end if; @@ -6176,9 +6118,6 @@ package body Exp_Aggr is Maybe_In_Place_OK := In_Place_Assign_OK (N, Get_Base_Object (Name (Parent_Node))); - elsif Parent_Kind = N_Allocator then - Maybe_In_Place_OK := In_Place_Assign_OK (N); - else Maybe_In_Place_OK := False; end if; @@ -6234,10 +6173,6 @@ package body Exp_Aggr is Set_Etype (Tmp, Typ); end if; - elsif Maybe_In_Place_OK and then Parent_Kind = N_Allocator then - Set_Expansion_Delayed (N); - return; - -- In the remaining cases the aggregate appears in the RHS of an -- assignment, which may be part of the expansion of an object -- declaration. If the aggregate is an actual in a call, itself @@ -9519,17 +9454,16 @@ package body Exp_Aggr is Typ_Bounds := Get_Index_Bounds (Typ_Index); Obj_Bounds := Get_Index_Bounds (Obj_Index); - if not Is_OK_Static_Expression (Typ_Bounds.First) or else - not Is_OK_Static_Expression (Obj_Bounds.First) or else - not Is_OK_Static_Expression (Typ_Bounds.Last) or else - not Is_OK_Static_Expression (Obj_Bounds.Last) - then - return True; + -- We require static bounds and their static matching - elsif Expr_Value (Typ_Bounds.First) - /= Expr_Value (Obj_Bounds.First) - or else Expr_Value (Typ_Bounds.Last) - /= Expr_Value (Obj_Bounds.Last) + if not Compile_Time_Known_Value (Typ_Bounds.First) + or else not Compile_Time_Known_Value (Obj_Bounds.First) + or else not Compile_Time_Known_Value (Typ_Bounds.Last) + or else not Compile_Time_Known_Value (Obj_Bounds.Last) + or else Expr_Value (Typ_Bounds.First) /= + Expr_Value (Obj_Bounds.First) + or else Expr_Value (Typ_Bounds.Last) /= + Expr_Value (Obj_Bounds.Last) then return True; end if; -- GitLab