-- 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:
+ --
+ -- function Make_Lim_Ctrl return Lim_Ctrl is
+ -- begin
+ -- return Result : Lim_Ctrl := raise Program_Error do
+ -- null;
+ -- end return;
+ -- end Make_Lim_Ctrl;
+ --
+ -- Obj : Lim_Ctrl_Ptr := new Lim_Ctrl'(Make_Lim_Ctrl);
+ --
+ -- Even though the size of limited controlled type Lim_Ctrl is known,
+ -- allocating Obj at the caller side will chain Obj on Lim_Ctrl_Ptr's
+ -- finalization collection. The subsequent call to Make_Lim_Ctrl will
+ -- fail during the initialization actions for Result, which means that
+ -- Result (and Obj by extension) should not be finalized. However Obj
+ -- will be finalized when access type Lim_Ctrl_Ptr goes out of scope
+ -- since it is already attached on the its finalization collection.
+
if Needs_BIP_Alloc_Form (Function_Id) then
Temp_Init := Empty;
end if;
end;
- -- Add implicit actuals for the BIP formal parameters, if any
+ -- When the function has a controlling result, an allocation-form
+ -- parameter must be passed indicating that the caller is allocating
+ -- the result object. This is needed because such a function can be
+ -- called as a dispatching operation and must be treated similarly
+ -- to functions with unconstrained result subtypes.
Add_Unconstrained_Actuals_To_Build_In_Place_Call
(Func_Call,
Add_Access_Actual_To_Build_In_Place_Call
(Func_Call, Function_Id, Return_Obj_Actual);
- -- If the allocation is done in the caller, create a custom Allocate
- -- procedure if need be.
-
- if not Needs_BIP_Alloc_Form (Function_Id) then
- Build_Allocate_Deallocate_Proc
- (Declaration_Node (Return_Obj_Access), Mark => Allocator);
- end if;
-
-- Finally, replace the allocator node with a reference to the temp
Rewrite (Allocator, New_Occurrence_Of (Return_Obj_Access, Loc));
-- ensure that the heap allocation can properly chain the object
-- and later finalize it when the library unit goes out of scope.
- if Needs_BIP_Collection (Function_Id) then
+ if Needs_BIP_Collection (Func_Call) then
Build_Finalization_Collection
(Typ => Ptr_Typ,
For_Lib_Level => True,
Typ : constant Entity_Id := Underlying_Type (Etype (Func_Id));
begin
- -- No need for BIP_Collection if allocation is always done in the caller
-
- if not Needs_BIP_Alloc_Form (Func_Id) then
- return False;
- end if;
-
-- A formal for the finalization collection is needed for build-in-place
-- functions whose result type needs finalization or is a tagged type.
-- Tagged primitive build-in-place functions need such a formal because
Typ : constant Entity_Id := Underlying_Type (Etype (Func_Id));
begin
+ -- See Make_Build_In_Place_Call_In_Allocator for the rationale
+
+ if Needs_BIP_Collection (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
-- BIP_Alloc_Form parameter (see type BIP_Formal_Kind).
function Needs_BIP_Collection (Func_Id : Entity_Id) return Boolean;
- -- Ada 2005 (AI-318-02): Return True if the function needs an implicit
- -- BIP_Collection parameter (see type BIP_Formal_Kind).
+ -- Ada 2005 (AI-318-02): Return True if the result subtype of function
+ -- Func_Id might need finalization actions. This includes build-in-place
+ -- functions with tagged result types, since they can be invoked via
+ -- dispatching calls, and descendant types may require finalization.
function Needs_BIP_Task_Actuals (Func_Id : Entity_Id) return Boolean;
-- Return True if the function returns an object of a type that has tasks.
-- We mark the secondary stack if it is used in this construct, and
-- we're not returning a function result on the secondary stack, except
- -- that a build-in-place function that only conditionally returns on
- -- the secondary stack will also need a mark. A run-time test for doing
- -- the release call is needed in the case where the build-in-place
- -- function has a BIP_Alloc_Form parameter (see Create_Finalizer).
+ -- that a build-in-place function that might or might not return on the
+ -- secondary stack always needs a mark. A run-time test is required in
+ -- the case where the build-in-place function has a BIP_Alloc extra
+ -- parameter (see Create_Finalizer).
Needs_Sec_Stack_Mark : constant Boolean :=
- Uses_Sec_Stack (Scop)
- and then
- (not Sec_Stack_Needed_For_Return (Scop)
- or else
- (Is_Build_In_Place_Function (Scop)
- and then Needs_BIP_Alloc_Form (Scop)));
+ (Uses_Sec_Stack (Scop)
+ and then
+ not Sec_Stack_Needed_For_Return (Scop))
+ or else
+ (Is_Build_In_Place_Function (Scop)
+ and then Needs_BIP_Alloc_Form (Scop));
Needs_Custom_Cleanup : constant Boolean :=
Nkind (N) = N_Block_Statement