@@ -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.
@@ -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
@@ -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
@@ -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)
From: Eric Botcazou <ebotcazou@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(-)