if Nkind (Call_Node) = N_Function_Call
and then Needs_Finalization (Etype (Call_Node))
+ and then not Is_Build_In_Place_Function_Call (Call_Node)
+ and then (No (First_Formal (Subp))
+ or else not
+ Is_Concurrent_Record_Type (Etype (First_Formal (Subp))))
then
- if not Is_Build_In_Place_Function_Call (Call_Node)
- and then
- (No (First_Formal (Subp))
- or else
- not Is_Concurrent_Record_Type (Etype (First_Formal (Subp))))
- then
- Expand_Ctrl_Function_Call
- (Call_Node, Needs_Secondary_Stack (Etype (Call_Node)));
-
- -- Build-in-place function calls which appear in anonymous contexts
- -- need a transient scope to ensure the proper finalization of the
- -- intermediate result after its use.
-
- elsif Is_Build_In_Place_Function_Call (Call_Node)
- and then Nkind (Parent (Unqual_Conv (Call_Node))) in
- N_Attribute_Reference
- | N_Function_Call
- | N_Indexed_Component
- | N_Object_Renaming_Declaration
- | N_Procedure_Call_Statement
- | N_Selected_Component
- | N_Slice
- and then
- (Ekind (Current_Scope) /= E_Loop
- or else Nkind (Parent (Call_Node)) /= N_Function_Call
- or else not
- Is_Build_In_Place_Function_Call (Parent (Call_Node)))
- then
- Establish_Transient_Scope
- (Call_Node, Needs_Secondary_Stack (Etype (Call_Node)));
- end if;
+ Expand_Ctrl_Function_Call
+ (Call_Node, Needs_Secondary_Stack (Etype (Call_Node)));
-- Functions returning noncontrolled objects that may be subject to
-- user-defined indexing also need special attention. The problem
Loc : constant Source_Ptr := Sloc (Function_Call);
Func_Call : constant Node_Id := Unqual_Conv (Function_Call);
Function_Id : Entity_Id;
+ Known_Size : Boolean;
+ Needs_Fin : Boolean;
Result_Subt : Entity_Id;
begin
Warn_BIP (Func_Call);
Result_Subt := Etype (Function_Id);
+ Known_Size := Caller_Known_Size (Func_Call, Result_Subt);
+ Needs_Fin := Needs_Finalization (Result_Subt);
-- If the build-in-place function returns a controlled object, then the
- -- object needs to be finalized immediately after the context. Since
- -- this case produces a transient scope, the servicing finalizer needs
- -- to name the returned object.
+ -- object needs to be finalized immediately after the context is exited,
+ -- which requires the creation of a transient scope and a named object.
-- If the build-in-place function returns a definite subtype, then an
-- object also needs to be created and an access value designating it
-- the expander using the appropriate mechanism in Make_Build_In_Place_
-- Call_In_Object_Declaration.
- if Needs_Finalization (Result_Subt)
- or else Caller_Known_Size (Func_Call, Result_Subt)
- then
+ if Needs_Fin or else Known_Size then
+ if Needs_Fin then
+ Establish_Transient_Scope
+ (Func_Call, Manage_Sec_Stack => not Known_Size);
+ end if;
+
declare
Temp_Id : constant Entity_Id := Make_Temporary (Loc, 'R');
Temp_Decl : constant Node_Id :=
Add_Access_Actual_To_Build_In_Place_Call
(Func_Call, Function_Id, Empty);
+ Establish_Transient_Scope (Func_Call, Manage_Sec_Stack => True);
+
-- Mark the call as processed as a build-in-place call
Set_Is_Expanded_Build_In_Place_Call (Func_Call);
Set_Do_Range_Check (Expression (A));
end if;
- -- If the actual is a function call that returns a limited
- -- unconstrained object that needs finalization, create a
- -- transient scope for it, so that it can receive the proper
- -- finalization list.
-
- elsif Expander_Active
- and then Nkind (A) = N_Function_Call
- and then Is_Limited_Record (Etype (F))
- and then not Is_Constrained (Etype (F))
- and then (Needs_Finalization (Etype (F))
- or else Has_Task (Etype (F)))
- then
- Establish_Transient_Scope (A, Manage_Sec_Stack => False);
- Resolve (A, Etype (F));
-
-- A small optimization: if one of the actuals is a concatenation
-- create a block around a procedure call to recover stack space.
-- This alleviates stack usage when several procedure calls in
-- b) Subprograms that are ignored ghost entities do not return anything
- -- c) Calls to a build-in-place function, since such functions may
- -- allocate their result directly in a target object, and cases where
- -- the result does get allocated in the secondary stack are checked for
- -- within the specialized Exp_Ch6 procedures for expanding those
+ -- c) Calls to a build-in-place function, since such functions allocate
+ -- their result directly in the target object or on the secondary stack,
+ -- and cases where the target object needs to be created and destroyed
+ -- on exit to the context, or the secondary stack is used, are checked
+ -- for within the specialized Exp_Ch6 procedures for expanding those
-- build-in-place calls.
-- d) Calls to inlinable expression functions do not use the secondary