From: Eric Botcazou <ebotca...@adacore.com>

The resolution made some time ago had been that a dynamic allocation for
a limited type that needs finalization with a function call as expression
always needs to be done in the called function, even if the limited type
has a known size.  But the fix implementing this resolution was dropped
inadvertently at some point.

The change also contains a small tweak for Expand_N_Object_Declaration
and a small related cleanup in the finalization machinery.

gcc/ada/

        * exp_ch3.adb (Expand_N_Object_Declaration): In the case of a
        return object of a BIP function that needs finalization, save
        the assignment statement made to initialize it, if any.
        * exp_ch6.ads (BIP_Formal_Kind): Adjust description.
        * exp_ch6.adb (Make_Build_In_Place_Call_In_Allocator): Make a
        couple of adjustments to the commentary.
        (Needs_BIP_Alloc_Form): Also return true if the function needs
        a BIP_Finalization_Master parameter.
        * exp_ch7.adb (Build_BIP_Cleanup_Stmts): Remove now always true
        test on Needs_BIP_Alloc_Form.
        (Attach_Object_To_Master_Node): Remove duplication in comment.

Tested on x86_64-pc-linux-gnu, committed on master.

---
 gcc/ada/exp_ch3.adb |  8 +++++
 gcc/ada/exp_ch6.adb | 34 ++++++++++----------
 gcc/ada/exp_ch6.ads | 22 +++++++------
 gcc/ada/exp_ch7.adb | 75 ++++++++++++++++-----------------------------
 4 files changed, 64 insertions(+), 75 deletions(-)

diff --git a/gcc/ada/exp_ch3.adb b/gcc/ada/exp_ch3.adb
index f934dbfddaa..4ebc7b977e9 100644
--- a/gcc/ada/exp_ch3.adb
+++ b/gcc/ada/exp_ch3.adb
@@ -8746,6 +8746,14 @@ package body Exp_Ch3 is
             Initialize_Return_Object
               (Tag_Assign, Adj_Call, Expr_Q, Init_Stmt, Init_After);
 
+            --  Save the assignment statement when returning a controlled
+            --  object. This reference is used later by the finalization
+            --  machinery to mark the object as successfully initialized.
+
+            if Present (Init_Stmt) and then Needs_Finalization (Typ) then
+               Set_Last_Aggregate_Assignment (Def_Id, Init_Stmt);
+            end if;
+
             --  Replace the return object declaration with a renaming of a
             --  dereference of the access value designating the return object.
 
diff --git a/gcc/ada/exp_ch6.adb b/gcc/ada/exp_ch6.adb
index a89c9af0bb2..9e1844aa08e 100644
--- a/gcc/ada/exp_ch6.adb
+++ b/gcc/ada/exp_ch6.adb
@@ -158,9 +158,9 @@ package body Exp_Ch6 is
       Alloc_Form     : BIP_Allocation_Form := Unspecified;
       Alloc_Form_Exp : Node_Id             := Empty;
       Pool_Actual    : Node_Id             := Make_Null (No_Location));
-   --  Ada 2005 (AI-318-02): Add the actuals needed for a build-in-place
-   --  function call that returns a caller-unknown-size result (BIP_Alloc_Form
-   --  and BIP_Storage_Pool). If Alloc_Form_Exp is present, then use it,
+   --  Ada 2005 (AI-318-02): If the result type of a build-in-place call needs
+   --  them, add the actuals parameters BIP_Alloc_Form and BIP_Storage_Pool.
+   --  If Alloc_Form_Exp is present, then pass it for the first parameter,
    --  otherwise pass a literal corresponding to the Alloc_Form parameter
    --  (which must not be Unspecified in that case). Pool_Actual is the
    --  parameter to pass to BIP_Storage_Pool.
@@ -8328,9 +8328,11 @@ package body Exp_Ch6 is
       Set_Can_Never_Be_Null (Acc_Type, False);
       --  It gets initialized to null, so we can't have that
 
-      --  When the result subtype is constrained, the return object is created
-      --  on the caller side, and access to it is passed to the function. This
-      --  optimization is disabled when the result subtype needs finalization
+      --  When the result subtype is returned on the secondary stack or is
+      --  tagged, the called function itself must perform the allocation of
+      --  the return object, so we pass parameters indicating that.
+
+      --  But that's also the case when the result subtype needs finalization
       --  actions because the caller side allocation may result in undesirable
       --  finalization. Consider the following example:
       --
@@ -8351,11 +8353,6 @@ package body Exp_Ch6 is
       --  will be finalized when access type Lim_Ctrl_Ptr goes out of scope
       --  since it is already attached on the related finalization master.
 
-      --  Here and in related routines, we must examine the full view of the
-      --  type, because the view at the point of call may differ from the
-      --  one in the function body, and the expansion mechanism depends on
-      --  the characteristics of the full view.
-
       if Needs_BIP_Alloc_Form (Function_Id) then
          Temp_Init := Empty;
 
@@ -8386,6 +8383,10 @@ package body Exp_Ch6 is
 
          Return_Obj_Actual := Empty;
 
+      --  When the result subtype neither is returned on the secondary stack
+      --  nor is tagged, the return object is created on the caller side, and
+      --  access to it is passed to the function.
+
       else
          --  Replace the initialized allocator of form "new T'(Func (...))"
          --  with an uninitialized allocator of form "new T", where T is the
@@ -8428,11 +8429,6 @@ package body Exp_Ch6 is
            (Result_Subt,
             Make_Explicit_Dereference (Loc,
               Prefix => New_Occurrence_Of (Return_Obj_Access, Loc)));
-
-      --  When the result subtype is unconstrained, the function itself must
-      --  perform the allocation of the return object, so we pass parameters
-      --  indicating that.
-
       end if;
 
       --  Declare the temp object
@@ -9636,6 +9632,12 @@ package body Exp_Ch6 is
       Typ : constant Entity_Id := Underlying_Type (Etype (Func_Id));
 
    begin
+      --  See Make_Build_In_Place_Call_In_Allocator for the rationale
+
+      if Needs_BIP_Finalization_Master (Func_Id) then
+         return True;
+      end if;
+
       --  A formal giving the allocation method is needed for build-in-place
       --  functions whose result type is returned on the secondary stack or
       --  is a tagged type. Tagged primitive build-in-place functions need
diff --git a/gcc/ada/exp_ch6.ads b/gcc/ada/exp_ch6.ads
index 12a9ce3f1b8..79e4120cef1 100644
--- a/gcc/ada/exp_ch6.ads
+++ b/gcc/ada/exp_ch6.ads
@@ -47,8 +47,8 @@ package Exp_Ch6 is
    --  nodes (e.g. the filling of the corresponding Dispatch Table for
    --  Primitive Operations)
 
-   --  The following type defines the various forms of allocation used for the
-   --  results of build-in-place function calls.
+   --  Ada 2005 (AI-318-02): The following type defines the various forms of
+   --  allocation used for the result of build-in-place function calls.
 
    type BIP_Allocation_Form is
      (Unspecified,
@@ -57,22 +57,24 @@ package Exp_Ch6 is
       Global_Heap,
       User_Storage_Pool);
 
-   type BIP_Formal_Kind is
    --  Ada 2005 (AI-318-02): This type defines the kinds of implicit extra
    --  formals created for build-in-place functions. The order of these
    --  enumeration literals matches the order in which the formals are
    --  declared. See Sem_Ch6.Create_Extra_Formals.
 
+   type BIP_Formal_Kind is
      (BIP_Alloc_Form,
-      --  Present if result subtype is unconstrained or tagged. Indicates
-      --  whether the return object is allocated by the caller or callee, and
-      --  if the callee, whether to use the secondary stack or the heap. See
-      --  Create_Extra_Formals.
+      --  Present if result subtype is returned on the secondary stack or is
+      --  tagged: in this case, this indicates whether the return object is
+      --  allocated by the caller or callee, and if the callee, whether to
+      --  use the secondary stack, the global heap or a storage pool. Also
+      --  present if result type needs finalization.
 
       BIP_Storage_Pool,
-      --  Present if result subtype is unconstrained or tagged. If
-      --  BIP_Alloc_Form = User_Storage_Pool, this is a pointer to the pool
-      --  (of type access to Root_Storage_Pool'Class). Otherwise null.
+      --  Present if result subtype is returned on the secondary stack or is
+      --  tagged: in this case, if BIP_Alloc_Form = User_Storage_Pool, this
+      --  is a pointer to the pool (of type Root_Storage_Pool_Ptr); otherwise
+      --  this is null. Also present if result type needs finalization.
 
       BIP_Finalization_Master,
       --  Present if result type needs finalization. Pointer to caller's
diff --git a/gcc/ada/exp_ch7.adb b/gcc/ada/exp_ch7.adb
index e8dfdb02496..693d9b1c5a7 100644
--- a/gcc/ada/exp_ch7.adb
+++ b/gcc/ada/exp_ch7.adb
@@ -595,8 +595,9 @@ package body Exp_Ch7 is
       --    then
       --       declare
       --          type Ptr_Typ is access Fun_Typ;
-      --          for Ptr_Typ'Storage_Pool
-      --            use Base_Pool (BIPfinalizationmaster);
+      --          for Ptr_Typ'Storage_Pool use
+      --                Base_Pool (BIPfinalizationmaster.all).all;
+      --
       --       begin
       --          Free (Ptr_Typ (Obj_Addr));
       --       end;
@@ -612,10 +613,11 @@ package body Exp_Ch7 is
         (Func_Id  : Entity_Id;
          Obj_Addr : Node_Id) return Node_Id
       is
+         Alloc_Id   : constant Entity_Id :=
+           Build_In_Place_Formal (Func_Id, BIP_Alloc_Form);
          Decls      : constant List_Id := New_List;
          Fin_Mas_Id : constant Entity_Id :=
-                        Build_In_Place_Formal
-                          (Func_Id, BIP_Finalization_Master);
+           Build_In_Place_Formal (Func_Id, BIP_Finalization_Master);
          Func_Typ   : constant Entity_Id := Etype (Func_Id);
 
          Cond      : Node_Id;
@@ -700,38 +702,22 @@ package body Exp_Ch7 is
                  Statements => New_List (Free_Stmt)));
 
          --  Generate:
-         --    if BIPfinalizationmaster /= null then
-
-         Cond :=
-           Make_Op_Ne (Loc,
-             Left_Opnd  => New_Occurrence_Of (Fin_Mas_Id, Loc),
-             Right_Opnd => Make_Null (Loc));
-
-         --  For unconstrained or tagged results, escalate the condition to
-         --  include the allocation format. Generate:
-
          --    if BIPallocform > Secondary_Stack'Pos
          --      and then BIPfinalizationmaster /= null
          --    then
 
-         if Needs_BIP_Alloc_Form (Func_Id) then
-            declare
-               Alloc : constant Entity_Id :=
-                         Build_In_Place_Formal (Func_Id, BIP_Alloc_Form);
-            begin
-               Cond :=
-                 Make_And_Then (Loc,
-                   Left_Opnd  =>
-                     Make_Op_Gt (Loc,
-                       Left_Opnd  => New_Occurrence_Of (Alloc, Loc),
-                       Right_Opnd =>
-                         Make_Integer_Literal (Loc,
-                           UI_From_Int
-                             (BIP_Allocation_Form'Pos (Secondary_Stack)))),
-
-                   Right_Opnd => Cond);
-            end;
-         end if;
+         Cond :=
+           Make_And_Then (Loc,
+             Left_Opnd  =>
+               Make_Op_Gt (Loc,
+                 Left_Opnd  => New_Occurrence_Of (Alloc_Id, Loc),
+                 Right_Opnd =>
+                   Make_Integer_Literal (Loc,
+                     UI_From_Int (BIP_Allocation_Form'Pos (Secondary_Stack)))),
+             Right_Opnd =>
+               Make_Op_Ne (Loc,
+                 Left_Opnd  => New_Occurrence_Of (Fin_Mas_Id, Loc),
+                 Right_Opnd => Make_Null (Loc)));
 
          --  Generate:
          --    if <Cond> then
@@ -744,12 +730,16 @@ package body Exp_Ch7 is
              Then_Statements => New_List (Free_Blk));
       end Build_BIP_Cleanup_Stmts;
 
+      --  Local variables
+
       Fin_Id             : Entity_Id;
       Master_Node_Attach : Node_Id;
       Master_Node_Ins    : Node_Id;
       Obj_Ref            : Node_Id;
       Obj_Typ            : Entity_Id;
 
+      --  Start of processing for Attach_Object_To_Master_Node
+
    begin
       --  Finalize_Address is not generated in CodePeer mode because the
       --  body contains address arithmetic. So we don't want to generate
@@ -790,23 +780,10 @@ package body Exp_Ch7 is
          Obj_Typ := Available_View (Designated_Type (Obj_Typ));
       end if;
 
-      --  If we are dealing with a return object of a build-in-place
-      --  function, generate the following cleanup statements:
-
-      --    if BIPallocform > Secondary_Stack'Pos
-      --      and then BIPfinalizationmaster /= null
-      --    then
-      --       declare
-      --          type Ptr_Typ is access Obj_Typ;
-      --          for Ptr_Typ'Storage_Pool use
-      --                Base_Pool (BIPfinalizationmaster.all).all;
-      --       begin
-      --          Free (Ptr_Typ (Obj'Address));
-      --       end;
-      --    end if;
-
-      --  The generated code effectively detaches the temporary from the
-      --  caller finalization master and deallocates the object.
+      --  If we are dealing with a return object of a build-in-place function
+      --  and its allocation has been done in the function, we additionally
+      --  need to detach it from the caller's finalization master in order to
+      --  prevent double finalization.
 
       if Present (Func_Id)
         and then Is_Build_In_Place_Function (Func_Id)
-- 
2.43.2

Reply via email to