summaryrefslogtreecommitdiff
path: root/gcc/ada/exp_ch6.adb
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/ada/exp_ch6.adb')
-rw-r--r--gcc/ada/exp_ch6.adb945
1 files changed, 754 insertions, 191 deletions
diff --git a/gcc/ada/exp_ch6.adb b/gcc/ada/exp_ch6.adb
index 75746422125..8955e5d9174 100644
--- a/gcc/ada/exp_ch6.adb
+++ b/gcc/ada/exp_ch6.adb
@@ -29,6 +29,7 @@ with Debug; use Debug;
with Einfo; use Einfo;
with Errout; use Errout;
with Elists; use Elists;
+with Exp_Aggr; use Exp_Aggr;
with Exp_Atag; use Exp_Atag;
with Exp_Ch2; use Exp_Ch2;
with Exp_Ch3; use Exp_Ch3;
@@ -103,21 +104,16 @@ package body Exp_Ch6 is
-- present, then use it, otherwise pass a literal corresponding to the
-- Alloc_Form parameter (which must not be Unspecified in that case).
- procedure Add_Extra_Actual_To_Call
- (Subprogram_Call : Node_Id;
- Extra_Formal : Entity_Id;
- Extra_Actual : Node_Id);
- -- Adds Extra_Actual as a named parameter association for the formal
- -- Extra_Formal in Subprogram_Call.
-
procedure Add_Finalization_Master_Actual_To_Build_In_Place_Call
- (Func_Call : Node_Id;
- Func_Id : Entity_Id;
- Ptr_Typ : Entity_Id := Empty);
+ (Func_Call : Node_Id;
+ Func_Id : Entity_Id;
+ Ptr_Typ : Entity_Id := Empty;
+ Master_Exp : Node_Id := Empty);
-- Ada 2005 (AI-318-02): If the result type of a build-in-place call needs
-- finalization actions, add an actual parameter which is a pointer to the
- -- finalization master of the caller. If Ptr_Typ is left Empty, this will
- -- result in an automatic "null" value for the actual.
+ -- finalization master of the caller. If Master_Exp is not Empty, then that
+ -- will be passed as the actual. Otherwise, if Ptr_Typ is left Empty, this
+ -- will result in an automatic "null" value for the actual.
procedure Add_Task_Actuals_To_Build_In_Place_Call
(Function_Call : Node_Id;
@@ -177,7 +173,7 @@ package body Exp_Ch6 is
procedure Expand_Non_Function_Return (N : Node_Id);
-- Called by Expand_N_Simple_Return_Statement in case we're returning from
-- a procedure body, entry body, accept statement, or extended return
- -- statement. Note that all non-function returns are simple return
+ -- statement. Note that all non-function returns are simple return
-- statements.
function Expand_Protected_Object_Reference
@@ -193,6 +189,11 @@ package body Exp_Ch6 is
-- reference to the object itself, and the call becomes a call to the
-- corresponding protected subprogram.
+ function Has_Unconstrained_Access_Discriminants
+ (Subtyp : Entity_Id) return Boolean;
+ -- Returns True if the given subtype is unconstrained and has one
+ -- or more access discriminants.
+
procedure Expand_Simple_Function_Return (N : Node_Id);
-- Expand simple return from function. In the case where we are returning
-- from a function body this is called by Expand_N_Simple_Return_Statement.
@@ -311,9 +312,10 @@ package body Exp_Ch6 is
-----------------------------------------------------------
procedure Add_Finalization_Master_Actual_To_Build_In_Place_Call
- (Func_Call : Node_Id;
- Func_Id : Entity_Id;
- Ptr_Typ : Entity_Id := Empty)
+ (Func_Call : Node_Id;
+ Func_Id : Entity_Id;
+ Ptr_Typ : Entity_Id := Empty;
+ Master_Exp : Node_Id := Empty)
is
begin
if not Needs_BIP_Finalization_Master (Func_Id) then
@@ -329,9 +331,16 @@ package body Exp_Ch6 is
Desig_Typ : Entity_Id;
begin
+ -- If there is a finalization master actual, such as the implicit
+ -- finalization master of an enclosing build-in-place function,
+ -- then this must be added as an extra actual of the call.
+
+ if Present (Master_Exp) then
+ Actual := Master_Exp;
+
-- Case where the context does not require an actual master
- if No (Ptr_Typ) then
+ elsif No (Ptr_Typ) then
Actual := Make_Null (Loc);
else
@@ -459,7 +468,7 @@ package body Exp_Ch6 is
begin
-- No such extra parameters are needed if there are no tasks
- if not Has_Task (Etype (Function_Id)) then
+ if not Has_Task (Available_View (Etype (Function_Id))) then
return;
end if;
@@ -467,6 +476,12 @@ package body Exp_Ch6 is
if Restriction_Active (No_Task_Hierarchy) then
Actual := New_Occurrence_Of (RTE (RE_Library_Task_Level), Loc);
+
+ -- In the case where we use the master associated with an access type,
+ -- the actual is an entity and requires an explicit reference.
+
+ elsif Nkind (Actual) = N_Defining_Identifier then
+ Actual := New_Reference_To (Actual, Loc);
end if;
-- The master
@@ -483,8 +498,7 @@ package body Exp_Ch6 is
-- Build the parameter association for the new actual and add it to
-- the end of the function's actuals.
- Add_Extra_Actual_To_Call
- (Function_Call, Master_Formal, Actual);
+ Add_Extra_Actual_To_Call (Function_Call, Master_Formal, Actual);
end;
-- The activation chain
@@ -496,8 +510,8 @@ package body Exp_Ch6 is
begin
-- Locate implicit activation chain parameter in the called function
- Activation_Chain_Formal := Build_In_Place_Formal
- (Function_Id, BIP_Activation_Chain);
+ Activation_Chain_Formal :=
+ Build_In_Place_Formal (Function_Id, BIP_Activation_Chain);
-- Create the actual which is a pointer to the current activation
-- chain
@@ -552,6 +566,16 @@ package body Exp_Ch6 is
-- Maybe it would be better for each implicit formal of a build-in-place
-- function to have a flag or a Uint attribute to identify it. ???
+ -- The return type in the function declaration may have been a limited
+ -- view, and the extra formals for the function were not generated at
+ -- that point. At the point of call the full view must be available and
+ -- the extra formals can be created.
+
+ if No (Extra_Formal) then
+ Create_Extra_Formals (Func);
+ Extra_Formal := Extra_Formals (Func);
+ end if;
+
loop
pragma Assert (Present (Extra_Formal));
exit when
@@ -1823,8 +1847,10 @@ package body Exp_Ch6 is
if No (Prev) then
if No (Parameter_Associations (Call_Node)) then
Set_Parameter_Associations (Call_Node, New_List);
- Append (Insert_Param, Parameter_Associations (Call_Node));
end if;
+
+ Append (Insert_Param, Parameter_Associations (Call_Node));
+
else
Insert_After (Prev, Insert_Param);
end if;
@@ -2725,6 +2751,120 @@ package body Exp_Ch6 is
Next_Formal (Formal);
end loop;
+ -- If we are calling an Ada2012 function which needs to have the
+ -- "accessibility level determined by the point of call" (AI05-0234)
+ -- passed in to it, then pass it in.
+
+ if Ekind_In (Subp, E_Function, E_Operator, E_Subprogram_Type)
+ and then
+ Present (Extra_Accessibility_Of_Result (Ultimate_Alias (Subp)))
+ then
+ declare
+ Ancestor : Node_Id := Parent (Call_Node);
+ Level : Node_Id := Empty;
+ Defer : Boolean := False;
+
+ begin
+ -- Unimplemented: if Subp returns an anonymous access type, then
+
+ -- a) if the call is the operand of an explict conversion, then
+ -- the target type of the conversion (a named access type)
+ -- determines the accessibility level pass in;
+
+ -- b) if the call defines an access discriminant of an object
+ -- (e.g., the discriminant of an object being created by an
+ -- allocator, or the discriminant of a function result),
+ -- then the accessibility level to pass in is that of the
+ -- discriminated object being initialized).
+
+ -- ???
+
+ while Nkind (Ancestor) = N_Qualified_Expression
+ loop
+ Ancestor := Parent (Ancestor);
+ end loop;
+
+ case Nkind (Ancestor) is
+ when N_Allocator =>
+
+ -- At this point, we'd like to assign
+
+ -- Level := Dynamic_Accessibility_Level (Ancestor);
+
+ -- but Etype of Ancestor may not have been set yet,
+ -- so that doesn't work.
+
+ -- Handle this later in Expand_Allocator_Expression.
+
+ Defer := True;
+
+ when N_Object_Declaration | N_Object_Renaming_Declaration =>
+ declare
+ Def_Id : constant Entity_Id :=
+ Defining_Identifier (Ancestor);
+
+ begin
+ if Is_Return_Object (Def_Id) then
+ if Present (Extra_Accessibility_Of_Result
+ (Return_Applies_To (Scope (Def_Id))))
+ then
+ -- Pass along value that was passed in if the
+ -- routine we are returning from also has an
+ -- Accessibility_Of_Result formal.
+
+ Level :=
+ New_Occurrence_Of
+ (Extra_Accessibility_Of_Result
+ (Return_Applies_To (Scope (Def_Id))), Loc);
+ end if;
+ else
+ Level :=
+ Make_Integer_Literal (Loc,
+ Intval => Object_Access_Level (Def_Id));
+ end if;
+ end;
+
+ when N_Simple_Return_Statement =>
+ if Present (Extra_Accessibility_Of_Result
+ (Return_Applies_To
+ (Return_Statement_Entity (Ancestor))))
+ then
+ -- Pass along value that was passed in if the routine
+ -- we are returning from also has an
+ -- Accessibility_Of_Result formal.
+
+ Level :=
+ New_Occurrence_Of
+ (Extra_Accessibility_Of_Result
+ (Return_Applies_To
+ (Return_Statement_Entity (Ancestor))), Loc);
+ end if;
+
+ when others =>
+ null;
+ end case;
+
+ if not Defer then
+ if not Present (Level) then
+
+ -- The "innermost master that evaluates the function call".
+
+ -- ??? - Should we use Integer'Last here instead in order
+ -- to deal with (some of) the problems associated with
+ -- calls to subps whose enclosing scope is unknown (e.g.,
+ -- Anon_Access_To_Subp_Param.all)?
+
+ Level := Make_Integer_Literal (Loc,
+ Scope_Depth (Current_Scope) + 1);
+ end if;
+
+ Add_Extra_Actual
+ (Level,
+ Extra_Accessibility_Of_Result (Ultimate_Alias (Subp)));
+ end if;
+ end;
+ end if;
+
-- If we are expanding a rhs of an assignment we need to check if tag
-- propagation is needed. You might expect this processing to be in
-- Analyze_Assignment but has to be done earlier (bottom-up) because the
@@ -3600,8 +3740,15 @@ package body Exp_Ch6 is
New_A : Node_Id;
Num_Ret : Int := 0;
Ret_Type : Entity_Id;
- Targ : Node_Id;
- Targ1 : Node_Id;
+
+ Targ : Node_Id;
+ -- The target of the call. If context is an assignment statement then
+ -- this is the left-hand side of the assignment. else it is a temporary
+ -- to which the return value is assigned prior to rewriting the call.
+
+ Targ1 : Node_Id;
+ -- A separate target used when the return type is unconstrained
+
Temp : Entity_Id;
Temp_Typ : Entity_Id;
@@ -3609,8 +3756,8 @@ package body Exp_Ch6 is
-- Entity in declaration in an extended_return_statement
Is_Unc : constant Boolean :=
- Is_Array_Type (Etype (Subp))
- and then not Is_Constrained (Etype (Subp));
+ Is_Array_Type (Etype (Subp))
+ and then not Is_Constrained (Etype (Subp));
-- If the type returned by the function is unconstrained and the call
-- can be inlined, special processing is required.
@@ -3701,6 +3848,7 @@ package body Exp_Ch6 is
Rewrite (N, New_Copy (A));
end if;
end if;
+
return Skip;
elsif Is_Entity_Name (N)
@@ -3751,8 +3899,8 @@ package body Exp_Ch6 is
if Nkind_In (Expression (N), N_Aggregate, N_Null) then
Ret :=
Make_Qualified_Expression (Sloc (N),
- Subtype_Mark => New_Occurrence_Of (Ret_Type, Sloc (N)),
- Expression => Relocate_Node (Expression (N)));
+ Subtype_Mark => New_Occurrence_Of (Ret_Type, Sloc (N)),
+ Expression => Relocate_Node (Expression (N)));
else
Ret :=
Unchecked_Convert_To
@@ -3762,12 +3910,12 @@ package body Exp_Ch6 is
if Nkind (Targ) = N_Defining_Identifier then
Rewrite (N,
Make_Assignment_Statement (Loc,
- Name => New_Occurrence_Of (Targ, Loc),
+ Name => New_Occurrence_Of (Targ, Loc),
Expression => Ret));
else
Rewrite (N,
Make_Assignment_Statement (Loc,
- Name => New_Copy (Targ),
+ Name => New_Copy (Targ),
Expression => Ret));
end if;
@@ -3775,19 +3923,17 @@ package body Exp_Ch6 is
if Present (Exit_Lab) then
Insert_After (N,
- Make_Goto_Statement (Loc,
- Name => New_Copy (Lab_Id)));
+ Make_Goto_Statement (Loc, Name => New_Copy (Lab_Id)));
end if;
end if;
return OK;
- elsif Nkind (N) = N_Extended_Return_Statement then
-
- -- An extended return becomes a block whose first statement is
- -- the assignment of the initial expression of the return object
- -- to the target of the call itself.
+ -- An extended return becomes a block whose first statement is the
+ -- assignment of the initial expression of the return object to the
+ -- target of the call itself.
+ elsif Nkind (N) = N_Extended_Return_Statement then
declare
Return_Decl : constant Entity_Id :=
First (Return_Object_Declarations (N));
@@ -3800,12 +3946,12 @@ package body Exp_Ch6 is
if Nkind (Targ) = N_Defining_Identifier then
Assign :=
Make_Assignment_Statement (Loc,
- Name => New_Occurrence_Of (Targ, Loc),
+ Name => New_Occurrence_Of (Targ, Loc),
Expression => Expression (Return_Decl));
else
Assign :=
Make_Assignment_Statement (Loc,
- Name => New_Copy (Targ),
+ Name => New_Copy (Targ),
Expression => Expression (Return_Decl));
end if;
@@ -3871,7 +4017,6 @@ package body Exp_Ch6 is
and then Nkind (Fst) = N_Assignment_Statement
and then No (Next (Fst))
then
-
-- The function call may have been rewritten as the temporary
-- that holds the result of the call, in which case remove the
-- now useless declaration.
@@ -3891,12 +4036,20 @@ package body Exp_Ch6 is
Insert_After (Parent (Entity (N)), Blk);
+ -- If the context is an assignment, and the left-hand side is free of
+ -- side-effects, the replacement is also safe.
+ -- Can this be generalized further???
+
elsif Nkind (Parent (N)) = N_Assignment_Statement
and then
(Is_Entity_Name (Name (Parent (N)))
- or else
- (Nkind (Name (Parent (N))) = N_Explicit_Dereference
- and then Is_Entity_Name (Prefix (Name (Parent (N))))))
+ or else
+ (Nkind (Name (Parent (N))) = N_Explicit_Dereference
+ and then Is_Entity_Name (Prefix (Name (Parent (N)))))
+
+ or else
+ (Nkind (Name (Parent (N))) = N_Selected_Component
+ and then Is_Entity_Name (Prefix (Name (Parent (N))))))
then
-- Replace assignment with the block
@@ -3932,6 +4085,7 @@ package body Exp_Ch6 is
procedure Rewrite_Procedure_Call (N : Node_Id; Blk : Node_Id) is
HSS : constant Node_Id := Handled_Statement_Sequence (Blk);
+
begin
-- If there is a transient scope for N, this will be the scope of the
-- actions for N, and the statements in Blk need to be within this
@@ -4013,7 +4167,6 @@ package body Exp_Ch6 is
-- Start of processing for Expand_Inlined_Call
begin
-
-- Check for an illegal attempt to inline a recursive procedure. If the
-- subprogram has parameters this is detected when trying to supply a
-- binding for parameters that already have one. For parameterless
@@ -4061,22 +4214,27 @@ package body Exp_Ch6 is
Set_Declarations (Blk, New_List);
end if;
- -- For the unconstrained case, capture the name of the local
- -- variable that holds the result. This must be the first declaration
- -- in the block, because its bounds cannot depend on local variables.
- -- Otherwise there is no way to declare the result outside of the
- -- block. Needless to say, in general the bounds will depend on the
- -- actuals in the call.
+ -- For the unconstrained case, capture the name of the local variable
+ -- that holds the result. This must be the first declaration in the
+ -- block, because its bounds cannot depend on local variables. Otherwise
+ -- there is no way to declare the result outside of the block. Needless
+ -- to say, in general the bounds will depend on the actuals in the call.
+
+ -- If the context is an assignment statement, as is the case for the
+ -- expansion of an extended return, the left-hand side provides bounds
+ -- even if the return type is unconstrained.
if Is_Unc then
- Targ1 := Defining_Identifier (First (Declarations (Blk)));
+ if Nkind (Parent (N)) /= N_Assignment_Statement then
+ Targ1 := Defining_Identifier (First (Declarations (Blk)));
+ else
+ Targ1 := Name (Parent (N));
+ end if;
end if;
-- If this is a derived function, establish the proper return type
- if Present (Orig_Subp)
- and then Orig_Subp /= Subp
- then
+ if Present (Orig_Subp) and then Orig_Subp /= Subp then
Ret_Type := Etype (Orig_Subp);
else
Ret_Type := Etype (Subp);
@@ -4101,8 +4259,7 @@ package body Exp_Ch6 is
if Is_Class_Wide_Type (Etype (F))
or else (Is_Access_Type (Etype (F))
- and then
- Is_Class_Wide_Type (Designated_Type (Etype (F))))
+ and then Is_Class_Wide_Type (Designated_Type (Etype (F))))
then
Temp_Typ := Etype (F);
@@ -4110,7 +4267,6 @@ package body Exp_Ch6 is
and then Etype (F) /= Base_Type (Etype (F))
then
Temp_Typ := Etype (F);
-
else
Temp_Typ := Etype (A);
end if;
@@ -4136,13 +4292,13 @@ package body Exp_Ch6 is
or else
(Nkind_In (A, N_Real_Literal,
- N_Integer_Literal,
- N_Character_Literal)
- and then not Address_Taken (F))
+ N_Integer_Literal,
+ N_Character_Literal)
+ and then not Address_Taken (F))
then
if Etype (F) /= Etype (A) then
Set_Renamed_Object
- (F, Unchecked_Convert_To (Etype (F), Relocate_Node (A)));
+ (F, Unchecked_Convert_To (Etype (F), Relocate_Node (A)));
else
Set_Renamed_Object (F, A);
end if;
@@ -4188,9 +4344,9 @@ package body Exp_Ch6 is
if Ekind (F) = E_In_Parameter
and then not Is_By_Reference_Type (Etype (A))
and then
- (not Is_Array_Type (Etype (A))
- or else not Is_Object_Reference (A)
- or else Is_Bit_Packed_Array (Etype (A)))
+ (not Is_Array_Type (Etype (A))
+ or else not Is_Object_Reference (A)
+ or else Is_Bit_Packed_Array (Etype (A)))
then
Decl :=
Make_Object_Declaration (Loc,
@@ -4232,6 +4388,12 @@ package body Exp_Ch6 is
then
Targ := Name (Parent (N));
+ elsif Nkind (Parent (N)) = N_Assignment_Statement
+ and then Nkind (Name (Parent (N))) = N_Selected_Component
+ and then Is_Entity_Name (Prefix (Name (Parent (N))))
+ then
+ Targ := New_Copy_Tree (Name (Parent (N)));
+
elsif Nkind (Parent (N)) = N_Object_Declaration
and then Is_Limited_Type (Etype (Subp))
then
@@ -4248,11 +4410,13 @@ package body Exp_Ch6 is
-- eventually be possible to remove that temporary and use the
-- result variable directly.
- if Is_Unc then
+ if Is_Unc
+ and then Nkind (Parent (N)) /= N_Assignment_Statement
+ then
Decl :=
Make_Object_Declaration (Loc,
Defining_Identifier => Temp,
- Object_Definition =>
+ Object_Definition =>
New_Copy_Tree (Object_Definition (Parent (Targ1))));
Replace_Formals (Decl);
@@ -4261,8 +4425,7 @@ package body Exp_Ch6 is
Decl :=
Make_Object_Declaration (Loc,
Defining_Identifier => Temp,
- Object_Definition =>
- New_Occurrence_Of (Ret_Type, Loc));
+ Object_Definition => New_Occurrence_Of (Ret_Type, Loc));
Set_Etype (Temp, Ret_Type);
end if;
@@ -4282,9 +4445,7 @@ package body Exp_Ch6 is
Replace_Formals (Blk);
Set_Parent (Blk, N);
- if not Comes_From_Source (Subp)
- or else Is_Predef
- then
+ if not Comes_From_Source (Subp) or else Is_Predef then
Reset_Slocs (Blk);
end if;
@@ -4296,7 +4457,7 @@ package body Exp_Ch6 is
if Num_Ret = 1
and then
Nkind (Last (Statements (Handled_Statement_Sequence (Blk)))) =
- N_Goto_Statement
+ N_Goto_Statement
then
Remove (Last (Statements (Handled_Statement_Sequence (Blk))));
else
@@ -4334,6 +4495,7 @@ package body Exp_Ch6 is
if Ekind (Subp) = E_Procedure then
Rewrite_Procedure_Call (N, Blk);
+
else
Rewrite_Function_Call (N, Blk);
@@ -4489,10 +4651,10 @@ package body Exp_Ch6 is
Build_In_Place_Formal
(Func_Id, BIP_Finalization_Master);
Stmts : constant List_Id := New_List;
-
- Local_Id : Entity_Id;
- Pool_Id : Entity_Id;
- Ptr_Typ : Entity_Id;
+ Desig_Typ : Entity_Id;
+ Local_Id : Entity_Id;
+ Pool_Id : Entity_Id;
+ Ptr_Typ : Entity_Id;
begin
-- Generate:
@@ -4522,8 +4684,19 @@ package body Exp_Ch6 is
-- of the temporary. Otherwise the secondary stack allocation
-- will fail.
+ Desig_Typ := Ret_Typ;
+
+ -- Ensure that the build-in-place machinery uses a fat pointer
+ -- when allocating an unconstrained array on the heap. In this
+ -- case the result object type is a constrained array type even
+ -- though the function type is unconstrained.
+
+ if Ekind (Desig_Typ) = E_Array_Subtype then
+ Desig_Typ := Base_Type (Desig_Typ);
+ end if;
+
-- Generate:
- -- type Ptr_Typ is access Ret_Typ;
+ -- type Ptr_Typ is access Desig_Typ;
Ptr_Typ := Make_Temporary (Loc, 'P');
@@ -4533,7 +4706,7 @@ package body Exp_Ch6 is
Type_Definition =>
Make_Access_To_Object_Definition (Loc,
Subtype_Indication =>
- New_Reference_To (Ret_Typ, Loc))));
+ New_Reference_To (Desig_Typ, Loc))));
-- Perform minor decoration in order to set the master and the
-- storage pool attributes.
@@ -4543,7 +4716,6 @@ package body Exp_Ch6 is
Set_Associated_Storage_Pool (Ptr_Typ, Pool_Id);
-- Create the temporary, generate:
- --
-- Local_Id : Ptr_Typ;
Local_Id := Make_Temporary (Loc, 'T');
@@ -4555,7 +4727,6 @@ package body Exp_Ch6 is
New_Reference_To (Ptr_Typ, Loc)));
-- Allocate the object, generate:
- --
-- Local_Id := <Alloc_Expr>;
Append_To (Stmts,
@@ -4603,7 +4774,6 @@ package body Exp_Ch6 is
end;
-- For all other cases, generate:
- --
-- Temp_Id := <Alloc_Expr>;
else
@@ -4619,38 +4789,29 @@ package body Exp_Ch6 is
---------------------------
function Move_Activation_Chain return Node_Id is
- Chain_Formal : constant Entity_Id :=
- Build_In_Place_Formal
- (Par_Func, BIP_Activation_Chain);
- To : constant Node_Id :=
- New_Reference_To (Chain_Formal, Loc);
- Master_Formal : constant Entity_Id :=
- Build_In_Place_Formal (Par_Func, BIP_Master);
- New_Master : constant Node_Id :=
- New_Reference_To (Master_Formal, Loc);
-
- Chain_Id : Entity_Id;
- From : Node_Id;
-
begin
- Chain_Id := First_Entity (Return_Statement_Entity (N));
- while Chars (Chain_Id) /= Name_uChain loop
- Chain_Id := Next_Entity (Chain_Id);
- end loop;
-
- From :=
- Make_Attribute_Reference (Loc,
- Prefix =>
- New_Reference_To (Chain_Id, Loc),
- Attribute_Name => Name_Unrestricted_Access);
- -- ??? Not clear why "Make_Identifier (Loc, Name_uChain)" doesn't
- -- work, instead of "New_Reference_To (Chain_Id, Loc)" above.
-
return
Make_Procedure_Call_Statement (Loc,
Name =>
New_Reference_To (RTE (RE_Move_Activation_Chain), Loc),
- Parameter_Associations => New_List (From, To, New_Master));
+
+ Parameter_Associations => New_List (
+
+ -- Source chain
+
+ Make_Attribute_Reference (Loc,
+ Prefix => Make_Identifier (Loc, Name_uChain),
+ Attribute_Name => Name_Unrestricted_Access),
+
+ -- Destination chain
+
+ New_Reference_To
+ (Build_In_Place_Formal (Par_Func, BIP_Activation_Chain), Loc),
+
+ -- New master
+
+ New_Reference_To
+ (Build_In_Place_Formal (Par_Func, BIP_Master), Loc)));
end Move_Activation_Chain;
-- Start of processing for Expand_N_Extended_Return_Statement
@@ -4682,6 +4843,7 @@ package body Exp_Ch6 is
-- Recover the function body
Func_Bod := Unit_Declaration_Node (Par_Func);
+
if Nkind (Func_Bod) = N_Subprogram_Declaration then
Func_Bod := Parent (Parent (Corresponding_Body (Func_Bod)));
end if;
@@ -4743,6 +4905,15 @@ package body Exp_Ch6 is
if Is_Build_In_Place
and then Has_Task (Etype (Par_Func))
then
+ -- The return expression is an aggregate for a complex type which
+ -- contains tasks. This particular case is left unexpanded since
+ -- the regular expansion would insert all temporaries and
+ -- initialization code in the wrong block.
+
+ if Nkind (Exp) = N_Aggregate then
+ Expand_N_Aggregate (Exp);
+ end if;
+
Append_To (Stmts, Move_Activation_Chain);
end if;
@@ -4794,12 +4965,12 @@ package body Exp_Ch6 is
Set_Identifier
(Result, New_Occurrence_Of (Return_Statement_Entity (N), Loc));
- -- If the object decl was already rewritten as a renaming, then
- -- we don't want to do the object allocation and transformation of
- -- of the return object declaration to a renaming. This case occurs
+ -- If the object decl was already rewritten as a renaming, then we
+ -- don't want to do the object allocation and transformation of of
+ -- the return object declaration to a renaming. This case occurs
-- when the return object is initialized by a call to another
- -- build-in-place function, and that function is responsible for the
- -- allocation of the return object.
+ -- build-in-place function, and that function is responsible for
+ -- the allocation of the return object.
if Is_Build_In_Place
and then Nkind (Ret_Obj_Decl) = N_Object_Renaming_Declaration
@@ -5083,9 +5254,9 @@ package body Exp_Ch6 is
-- The allocator is returned on the secondary stack,
-- so indicate that the function return, as well as
-- the block that encloses the allocator, must not
- -- release it. The flags must be set now because the
- -- decision to use the secondary stack is done very
- -- late in the course of expanding the return
+ -- release it. The flags must be set now because
+ -- the decision to use the secondary stack is done
+ -- very late in the course of expanding the return
-- statement, past the point where these flags are
-- normally set.
@@ -5162,10 +5333,10 @@ package body Exp_Ch6 is
-- If a separate initialization assignment was created
-- earlier, append that following the assignment of the
-- implicit access formal to the access object, to ensure
- -- that the return object is initialized in that case.
- -- In this situation, the target of the assignment must
- -- be rewritten to denote a dereference of the access to
- -- the return object passed in by the caller.
+ -- that the return object is initialized in that case. In
+ -- this situation, the target of the assignment must be
+ -- rewritten to denote a dereference of the access to the
+ -- return object passed in by the caller.
if Present (Init_Assignment) then
Rewrite (Name (Init_Assignment),
@@ -5813,10 +5984,10 @@ package body Exp_Ch6 is
Pop_Scope;
end if;
- -- Ada 2005 (AI-348): Generate body for a null procedure.
- -- In most cases this is superfluous because calls to it
- -- will be automatically inlined, but we definitely need
- -- the body if preconditions for the procedure are present.
+ -- Ada 2005 (AI-348): Generate body for a null procedure. In most
+ -- cases this is superfluous because calls to it will be automatically
+ -- inlined, but we definitely need the body if preconditions for the
+ -- procedure are present.
elsif Nkind (Specification (N)) = N_Procedure_Specification
and then Null_Present (Specification (N))
@@ -5854,11 +6025,11 @@ package body Exp_Ch6 is
begin
-- Call _Postconditions procedure if procedure with active
- -- postconditions. Here, we use the Postcondition_Proc attribute, which
- -- is needed for implicitly-generated returns. Functions never
- -- have implicitly-generated returns, and there's no room for
- -- Postcondition_Proc in E_Function, so we look up the identifier
- -- Name_uPostconditions for function returns (see
+ -- postconditions. Here, we use the Postcondition_Proc attribute,
+ -- which is needed for implicitly-generated returns. Functions
+ -- never have implicitly-generated returns, and there's no
+ -- room for Postcondition_Proc in E_Function, so we look up the
+ -- identifier Name_uPostconditions for function returns (see
-- Expand_Simple_Function_Return).
if Ekind (Scope_Id) = E_Procedure
@@ -6063,13 +6234,13 @@ package body Exp_Ch6 is
Rec : Node_Id;
begin
- -- If the protected object is not an enclosing scope, this is an
- -- inter-object function call. Inter-object procedure calls are expanded
- -- by Exp_Ch9.Build_Simple_Entry_Call. The call is intra-object only if
- -- the subprogram being called is in the protected body being compiled,
- -- and if the protected object in the call is statically the enclosing
- -- type. The object may be an component of some other data structure, in
- -- which case this must be handled as an inter-object call.
+ -- If the protected object is not an enclosing scope, this is an inter-
+ -- object function call. Inter-object procedure calls are expanded by
+ -- Exp_Ch9.Build_Simple_Entry_Call. The call is intra-object only if the
+ -- subprogram being called is in the protected body being compiled, and
+ -- if the protected object in the call is statically the enclosing type.
+ -- The object may be an component of some other data structure, in which
+ -- case this must be handled as an inter-object call.
if not In_Open_Scopes (Scop)
or else not Is_Entity_Name (Name (N))
@@ -6119,12 +6290,38 @@ package body Exp_Ch6 is
end if;
end Expand_Protected_Subprogram_Call;
+ --------------------------------------------
+ -- Has_Unconstrained_Access_Discriminants --
+ --------------------------------------------
+
+ function Has_Unconstrained_Access_Discriminants
+ (Subtyp : Entity_Id) return Boolean
+ is
+ Discr : Entity_Id;
+
+ begin
+ if Has_Discriminants (Subtyp)
+ and then not Is_Constrained (Subtyp)
+ then
+ Discr := First_Discriminant (Subtyp);
+ while Present (Discr) loop
+ if Ekind (Etype (Discr)) = E_Anonymous_Access_Type then
+ return True;
+ end if;
+
+ Next_Discriminant (Discr);
+ end loop;
+ end if;
+
+ return False;
+ end Has_Unconstrained_Access_Discriminants;
+
-----------------------------------
-- Expand_Simple_Function_Return --
-----------------------------------
- -- The "simple" comes from the syntax rule simple_return_statement.
- -- The semantics are not at all simple!
+ -- The "simple" comes from the syntax rule simple_return_statement. The
+ -- semantics are not at all simple!
procedure Expand_Simple_Function_Return (N : Node_Id) is
Loc : constant Source_Ptr := Sloc (N);
@@ -6145,12 +6342,12 @@ package body Exp_Ch6 is
-- The type of the expression (not necessarily the same as R_Type)
Subtype_Ind : Node_Id;
- -- If the result type of the function is class-wide and the
- -- expression has a specific type, then we use the expression's
- -- type as the type of the return object. In cases where the
- -- expression is an aggregate that is built in place, this avoids
- -- the need for an expensive conversion of the return object to
- -- the specific type on assignments to the individual components.
+ -- If the result type of the function is class-wide and the expression
+ -- has a specific type, then we use the expression's type as the type of
+ -- the return object. In cases where the expression is an aggregate that
+ -- is built in place, this avoids the need for an expensive conversion
+ -- of the return object to the specific type on assignments to the
+ -- individual components.
begin
if Is_Class_Wide_Type (R_Type)
@@ -6314,13 +6511,13 @@ package body Exp_Ch6 is
-- Optimize the case where the result is a function call. In this
-- case either the result is already on the secondary stack, or is
-- already being returned with the stack pointer depressed and no
- -- further processing is required except to set the By_Ref flag to
- -- ensure that gigi does not attempt an extra unnecessary copy.
+ -- further processing is required except to set the By_Ref flag
+ -- to ensure that gigi does not attempt an extra unnecessary copy.
-- (actually not just unnecessary but harmfully wrong in the case
-- of a controlled type, where gigi does not know how to do a copy).
- -- To make up for a gcc 2.8.1 deficiency (???), we perform
- -- the copy for array types if the constrained status of the
- -- target type is different from that of the expression.
+ -- To make up for a gcc 2.8.1 deficiency (???), we perform the copy
+ -- for array types if the constrained status of the target type is
+ -- different from that of the expression.
if Requires_Transient_Scope (Exptyp)
and then
@@ -6414,12 +6611,12 @@ package body Exp_Ch6 is
end if;
end if;
- -- Implement the rules of 6.5(8-10), which require a tag check in the
- -- case of a limited tagged return type, and tag reassignment for
+ -- Implement the rules of 6.5(8-10), which require a tag check in
+ -- the case of a limited tagged return type, and tag reassignment for
-- nonlimited tagged results. These actions are needed when the return
-- type is a specific tagged type and the result expression is a
- -- conversion or a formal parameter, because in that case the tag of the
- -- expression might differ from the tag of the specific result type.
+ -- conversion or a formal parameter, because in that case the tag of
+ -- the expression might differ from the tag of the specific result type.
if Is_Tagged_Type (Utyp)
and then not Is_Class_Wide_Type (Utyp)
@@ -6428,8 +6625,8 @@ package body Exp_Ch6 is
or else (Is_Entity_Name (Exp)
and then Ekind (Entity (Exp)) in Formal_Kind))
then
- -- When the return type is limited, perform a check that the
- -- tag of the result is the same as the tag of the return type.
+ -- When the return type is limited, perform a check that the tag of
+ -- the result is the same as the tag of the return type.
if Is_Limited_Type (R_Type) then
Insert_Action (Exp,
@@ -6449,8 +6646,8 @@ package body Exp_Ch6 is
-- If the result type is a specific nonlimited tagged type, then we
-- have to ensure that the tag of the result is that of the result
- -- type. This is handled by making a copy of the expression in the
- -- case where it might have a different tag, namely when the
+ -- type. This is handled by making a copy of the expression in
+ -- the case where it might have a different tag, namely when the
-- expression is a conversion or a formal parameter. We create a new
-- object of the result type and initialize it from the expression,
-- which will implicitly force the tag to be set appropriately.
@@ -6509,8 +6706,8 @@ package body Exp_Ch6 is
begin
-- Ada 2005 (AI-251): In class-wide interface objects we displace
- -- "this" to reference the base of the object --- required to get
- -- access to the TSD of the object.
+ -- "this" to reference the base of the object. This is required to
+ -- get access to the TSD of the object.
if Is_Class_Wide_Type (Etype (Exp))
and then Is_Interface (Etype (Exp))
@@ -6563,20 +6760,237 @@ package body Exp_Ch6 is
Make_Op_Ne (Loc,
Left_Opnd => Duplicate_Subexpr (Exp),
Right_Opnd => Make_Null (Loc)),
+
Right_Opnd => Make_Op_Ne (Loc,
Left_Opnd =>
Make_Selected_Component (Loc,
Prefix => Duplicate_Subexpr (Exp),
Selector_Name => Make_Identifier (Loc, Name_uTag)),
+
Right_Opnd =>
Make_Attribute_Reference (Loc,
Prefix =>
New_Occurrence_Of (Designated_Type (R_Type), Loc),
Attribute_Name => Name_Tag))),
+
Reason => CE_Tag_Check_Failed),
Suppress => All_Checks);
end if;
+ -- AI05-0234: RM 6.5(21/3). Check access discriminants to
+ -- ensure that the function result does not outlive an
+ -- object designated by one of it discriminants.
+
+ if Present (Extra_Accessibility_Of_Result (Scope_Id))
+ and then Has_Unconstrained_Access_Discriminants (R_Type)
+ then
+ declare
+ Discrim_Source : Node_Id;
+
+ procedure Check_Against_Result_Level (Level : Node_Id);
+ -- Check the given accessibility level against the level
+ -- determined by the point of call. (AI05-0234).
+
+ --------------------------------
+ -- Check_Against_Result_Level --
+ --------------------------------
+
+ procedure Check_Against_Result_Level (Level : Node_Id) is
+ begin
+ Insert_Action (N,
+ Make_Raise_Program_Error (Loc,
+ Condition =>
+ Make_Op_Gt (Loc,
+ Left_Opnd => Level,
+ Right_Opnd =>
+ New_Occurrence_Of
+ (Extra_Accessibility_Of_Result (Scope_Id), Loc)),
+ Reason => PE_Accessibility_Check_Failed));
+ end Check_Against_Result_Level;
+
+ begin
+ Discrim_Source := Exp;
+ while Nkind (Discrim_Source) = N_Qualified_Expression loop
+ Discrim_Source := Expression (Discrim_Source);
+ end loop;
+
+ if Nkind (Discrim_Source) = N_Identifier
+ and then Is_Return_Object (Entity (Discrim_Source))
+ then
+ Discrim_Source := Entity (Discrim_Source);
+
+ if Is_Constrained (Etype (Discrim_Source)) then
+ Discrim_Source := Etype (Discrim_Source);
+ else
+ Discrim_Source := Expression (Parent (Discrim_Source));
+ end if;
+
+ elsif Nkind (Discrim_Source) = N_Identifier
+ and then Nkind_In (Original_Node (Discrim_Source),
+ N_Aggregate, N_Extension_Aggregate)
+ then
+ Discrim_Source := Original_Node (Discrim_Source);
+
+ elsif Nkind (Discrim_Source) = N_Explicit_Dereference and then
+ Nkind (Original_Node (Discrim_Source)) = N_Function_Call
+ then
+ Discrim_Source := Original_Node (Discrim_Source);
+ end if;
+
+ while Nkind_In (Discrim_Source, N_Qualified_Expression,
+ N_Type_Conversion,
+ N_Unchecked_Type_Conversion)
+ loop
+ Discrim_Source := Expression (Discrim_Source);
+ end loop;
+
+ case Nkind (Discrim_Source) is
+ when N_Defining_Identifier =>
+
+ pragma Assert (Is_Composite_Type (Discrim_Source)
+ and then Has_Discriminants (Discrim_Source)
+ and then Is_Constrained (Discrim_Source));
+
+ declare
+ Discrim : Entity_Id :=
+ First_Discriminant (Base_Type (R_Type));
+ Disc_Elmt : Elmt_Id :=
+ First_Elmt (Discriminant_Constraint
+ (Discrim_Source));
+ begin
+ loop
+ if Ekind (Etype (Discrim)) =
+ E_Anonymous_Access_Type
+ then
+ Check_Against_Result_Level
+ (Dynamic_Accessibility_Level (Node (Disc_Elmt)));
+ end if;
+
+ Next_Elmt (Disc_Elmt);
+ Next_Discriminant (Discrim);
+ exit when not Present (Discrim);
+ end loop;
+ end;
+
+ when N_Aggregate | N_Extension_Aggregate =>
+
+ -- Unimplemented: extension aggregate case where discrims
+ -- come from ancestor part, not extension part.
+
+ declare
+ Discrim : Entity_Id :=
+ First_Discriminant (Base_Type (R_Type));
+
+ Disc_Exp : Node_Id := Empty;
+
+ Positionals_Exhausted
+ : Boolean := not Present (Expressions
+ (Discrim_Source));
+
+ function Associated_Expr
+ (Comp_Id : Entity_Id;
+ Associations : List_Id) return Node_Id;
+
+ -- Given a component and a component associations list,
+ -- locate the expression for that component; returns
+ -- Empty if no such expression is found.
+
+ ---------------------
+ -- Associated_Expr --
+ ---------------------
+
+ function Associated_Expr
+ (Comp_Id : Entity_Id;
+ Associations : List_Id) return Node_Id
+ is
+ Assoc : Node_Id;
+ Choice : Node_Id;
+
+ begin
+ -- Simple linear search seems ok here
+
+ Assoc := First (Associations);
+ while Present (Assoc) loop
+ Choice := First (Choices (Assoc));
+ while Present (Choice) loop
+ if (Nkind (Choice) = N_Identifier
+ and then Chars (Choice) = Chars (Comp_Id))
+ or else (Nkind (Choice) = N_Others_Choice)
+ then
+ return Expression (Assoc);
+ end if;
+
+ Next (Choice);
+ end loop;
+
+ Next (Assoc);
+ end loop;
+
+ return Empty;
+ end Associated_Expr;
+
+ -- Start of processing for Expand_Simple_Function_Return
+
+ begin
+ if not Positionals_Exhausted then
+ Disc_Exp := First (Expressions (Discrim_Source));
+ end if;
+
+ loop
+ if Positionals_Exhausted then
+ Disc_Exp :=
+ Associated_Expr
+ (Discrim,
+ Component_Associations (Discrim_Source));
+ end if;
+
+ if Ekind (Etype (Discrim)) =
+ E_Anonymous_Access_Type
+ then
+ Check_Against_Result_Level
+ (Dynamic_Accessibility_Level (Disc_Exp));
+ end if;
+
+ Next_Discriminant (Discrim);
+ exit when not Present (Discrim);
+
+ if not Positionals_Exhausted then
+ Next (Disc_Exp);
+ Positionals_Exhausted := not Present (Disc_Exp);
+ end if;
+ end loop;
+ end;
+
+ when N_Function_Call =>
+
+ -- No check needed (check performed by callee)
+
+ null;
+
+ when others =>
+
+ declare
+ Level : constant Node_Id :=
+ Make_Integer_Literal (Loc,
+ Object_Access_Level (Discrim_Source));
+
+ begin
+ -- Unimplemented: check for name prefix that includes
+ -- a dereference of an access value with a dynamic
+ -- accessibility level (e.g., an access param or a
+ -- saooaaat) and use dynamic level in that case. For
+ -- example:
+ -- return Access_Param.all(Some_Index).Some_Component;
+ -- ???
+
+ Set_Etype (Level, Standard_Natural);
+ Check_Against_Result_Level (Level);
+ end;
+
+ end case;
+ end;
+ end if;
+
-- If we are returning an object that may not be bit-aligned, then copy
-- the value into a temporary first. This copy may need to expand to a
-- loop of component operations.
@@ -6794,8 +7208,8 @@ package body Exp_Ch6 is
-- Step past qualification or unchecked conversion (the latter can occur
-- in cases of calls to 'Input).
- if Nkind_In
- (Exp_Node, N_Qualified_Expression, N_Unchecked_Type_Conversion)
+ if Nkind_In (Exp_Node, N_Qualified_Expression,
+ N_Unchecked_Type_Conversion)
then
Exp_Node := Expression (N);
end if;
@@ -6804,19 +7218,22 @@ package body Exp_Ch6 is
return False;
else
- if Is_Entity_Name (Name (Exp_Node)) then
+ -- In Alfa mode, build-in-place calls are not expanded, so that we
+ -- may end up with a call that is neither resolved to an entity, nor
+ -- an indirect call.
+
+ if Alfa_Mode then
+ return False;
+
+ elsif Is_Entity_Name (Name (Exp_Node)) then
Function_Id := Entity (Name (Exp_Node));
+ -- In the case of an explicitly dereferenced call, use the subprogram
+ -- type generated for the dereference.
+
elsif Nkind (Name (Exp_Node)) = N_Explicit_Dereference then
Function_Id := Etype (Name (Exp_Node));
- -- In Alfa mode, protected subprogram calls are not expanded, so that
- -- we may end up with a call that is neither resolved to an entity,
- -- nor an indirect call.
-
- elsif Alfa_Mode then
- return False;
-
else
raise Program_Error;
end if;
@@ -6877,9 +7294,9 @@ package body Exp_Ch6 is
Thunk_Code,
Build_Set_Predefined_Prim_Op_Address (Loc,
- Tag_Node =>
+ Tag_Node =>
New_Reference_To (Node (Next_Elmt (Iface_DT_Ptr)), Loc),
- Position => DT_Position (Prim),
+ Position => DT_Position (Prim),
Address_Node =>
Unchecked_Convert_To (RTE (RE_Prim_Ptr),
Make_Attribute_Reference (Loc,
@@ -6887,11 +7304,11 @@ package body Exp_Ch6 is
Attribute_Name => Name_Unrestricted_Access))),
Build_Set_Predefined_Prim_Op_Address (Loc,
- Tag_Node =>
+ Tag_Node =>
New_Reference_To
(Node (Next_Elmt (Next_Elmt (Next_Elmt (Iface_DT_Ptr)))),
Loc),
- Position => DT_Position (Prim),
+ Position => DT_Position (Prim),
Address_Node =>
Unchecked_Convert_To (RTE (RE_Prim_Ptr),
Make_Attribute_Reference (Loc,
@@ -6904,13 +7321,12 @@ package body Exp_Ch6 is
Next_Elmt (Iface_DT_Ptr);
pragma Assert (Has_Thunks (Node (Iface_DT_Ptr)));
- -- Skip the tag of the no-thunks dispatch table
+ -- Skip tag of the no-thunks dispatch table
Next_Elmt (Iface_DT_Ptr);
pragma Assert (not Has_Thunks (Node (Iface_DT_Ptr)));
- -- Skip the tag of the predefined primitives no-thunks dispatch
- -- table.
+ -- Skip tag of predefined primitives no-thunks dispatch table
Next_Elmt (Iface_DT_Ptr);
pragma Assert (not Has_Thunks (Node (Iface_DT_Ptr)));
@@ -6962,8 +7378,8 @@ package body Exp_Ch6 is
-- slots.
elsif Is_Imported (Subp)
- and then (Convention (Subp) = Convention_CPP
- or else Convention (Subp) = Convention_C)
+ and then (Convention (Subp) = Convention_CPP
+ or else Convention (Subp) = Convention_C)
then
null;
@@ -7072,11 +7488,11 @@ package body Exp_Ch6 is
(Allocator : Node_Id;
Function_Call : Node_Id)
is
+ Acc_Type : constant Entity_Id := Etype (Allocator);
Loc : Source_Ptr;
Func_Call : Node_Id := Function_Call;
Function_Id : Entity_Id;
Result_Subt : Entity_Id;
- Acc_Type : constant Entity_Id := Etype (Allocator);
New_Allocator : Node_Id;
Return_Obj_Access : Entity_Id;
@@ -7115,7 +7531,14 @@ package body Exp_Ch6 is
raise Program_Error;
end if;
- Result_Subt := Etype (Function_Id);
+ Result_Subt := Available_View (Etype (Function_Id));
+
+ -- Check whether return type includes tasks. This may not have been done
+ -- previously, if the type was a limited view.
+
+ if Has_Task (Result_Subt) then
+ Build_Activation_Chain_Entity (Allocator);
+ end if;
-- When the result subtype is constrained, the return object must be
-- allocated on the caller side, and access to it is passed to the
@@ -7235,10 +7658,14 @@ package body Exp_Ch6 is
then
null;
- -- Do not generate the call to Make_Set_Finalize_Address for
- -- CodePeer compilations because Finalize_Address is never built.
+ -- Do not generate the call to Set_Finalize_Address in Alfa mode
+ -- because it is not necessary and results in unwanted expansion.
+ -- This expansion is also not carried out in CodePeer mode because
+ -- Finalize_Address is never built.
- elsif not CodePeer_Mode then
+ elsif not Alfa_Mode
+ and then not CodePeer_Mode
+ then
Insert_Action (Allocator,
Make_Set_Finalize_Address_Call (Loc,
Typ => Etype (Function_Id),
@@ -7561,7 +7988,9 @@ package body Exp_Ch6 is
Ptr_Typ_Decl : Node_Id;
Def_Id : Entity_Id;
New_Expr : Node_Id;
- Enclosing_Func : Entity_Id;
+ Enclosing_Func : constant Entity_Id :=
+ Enclosing_Subprogram (Obj_Def_Id);
+ Fmaster_Actual : Node_Id := Empty;
Pass_Caller_Acc : Boolean := False;
begin
@@ -7613,8 +8042,6 @@ package body Exp_Ch6 is
if Is_Return_Object (Defining_Identifier (Object_Decl)) then
Pass_Caller_Acc := True;
- Enclosing_Func := Enclosing_Subprogram (Obj_Def_Id);
-
-- When the enclosing function has a BIP_Alloc_Form formal then we
-- pass it along to the callee (such as when the enclosing function
-- has an unconstrained or tagged result type).
@@ -7636,6 +8063,13 @@ package body Exp_Ch6 is
(Func_Call, Function_Id, Alloc_Form => Caller_Allocation);
end if;
+ if Needs_BIP_Finalization_Master (Enclosing_Func) then
+ Fmaster_Actual :=
+ New_Reference_To
+ (Build_In_Place_Formal
+ (Enclosing_Func, BIP_Finalization_Master), Loc);
+ end if;
+
-- Retrieve the BIPacc formal from the enclosing function and convert
-- it to the access type of the callee's BIP_Object_Access formal.
@@ -7686,14 +8120,18 @@ package body Exp_Ch6 is
Establish_Transient_Scope (Object_Decl, Sec_Stack => True);
end if;
+ -- Pass along any finalization master actual, which is needed in the
+ -- case where the called function initializes a return object of an
+ -- enclosing build-in-place function.
+
Add_Finalization_Master_Actual_To_Build_In_Place_Call
- (Func_Call, Function_Id);
+ (Func_Call => Func_Call,
+ Func_Id => Function_Id,
+ Master_Exp => Fmaster_Actual);
if Nkind (Parent (Object_Decl)) = N_Extended_Return_Statement
and then Has_Task (Result_Subt)
then
- Enclosing_Func := Enclosing_Subprogram (Obj_Def_Id);
-
-- Here we're passing along the master that was passed in to this
-- function.
@@ -7853,7 +8291,6 @@ package body Exp_Ch6 is
is
pragma Assert (Is_Build_In_Place_Function (Func_Id));
Func_Typ : constant Entity_Id := Underlying_Type (Etype (Func_Id));
-
begin
return
not Restriction_Active (No_Finalization)
@@ -7871,4 +8308,130 @@ package body Exp_Ch6 is
return not Is_Constrained (Func_Typ) or else Is_Tagged_Type (Func_Typ);
end Needs_BIP_Alloc_Form;
+ --------------------------------------
+ -- Needs_Result_Accessibility_Level --
+ --------------------------------------
+
+ function Needs_Result_Accessibility_Level
+ (Func_Id : Entity_Id) return Boolean
+ is
+ Func_Typ : constant Entity_Id := Underlying_Type (Etype (Func_Id));
+
+ function Has_Unconstrained_Access_Discriminant_Component
+ (Comp_Typ : Entity_Id) return Boolean;
+ -- Returns True if any component of the type has an unconstrained access
+ -- discriminant.
+
+ -----------------------------------------------------
+ -- Has_Unconstrained_Access_Discriminant_Component --
+ -----------------------------------------------------
+
+ function Has_Unconstrained_Access_Discriminant_Component
+ (Comp_Typ : Entity_Id) return Boolean
+ is
+ begin
+ if not Is_Limited_Type (Comp_Typ) then
+ return False;
+
+ -- Only limited types can have access discriminants with
+ -- defaults.
+
+ elsif Has_Unconstrained_Access_Discriminants (Comp_Typ) then
+ return True;
+
+ elsif Is_Array_Type (Comp_Typ) then
+ return Has_Unconstrained_Access_Discriminant_Component
+ (Underlying_Type (Component_Type (Comp_Typ)));
+
+ elsif Is_Record_Type (Comp_Typ) then
+ declare
+ Comp : Entity_Id;
+
+ begin
+ Comp := First_Component (Comp_Typ);
+ while Present (Comp) loop
+ if Has_Unconstrained_Access_Discriminant_Component
+ (Underlying_Type (Etype (Comp)))
+ then
+ return True;
+ end if;
+
+ Next_Component (Comp);
+ end loop;
+ end;
+ end if;
+
+ return False;
+ end Has_Unconstrained_Access_Discriminant_Component;
+
+ Feature_Disabled : constant Boolean := True;
+ -- Temporary
+
+ -- Start of processing for Needs_Result_Accessibility_Level
+
+ begin
+ -- False if completion unavailable (how does this happen???)
+
+ if not Present (Func_Typ) then
+ return False;
+
+ elsif Feature_Disabled then
+ return False;
+
+ -- False if not a function, also handle enum-lit renames case
+
+ elsif Func_Typ = Standard_Void_Type
+ or else Is_Scalar_Type (Func_Typ)
+ then
+ return False;
+
+ -- Handle a corner case, a cross-dialect subp renaming. For example,
+ -- an Ada2012 renaming of an Ada05 subprogram. This can occur when a
+ -- non-Ada2012 unit references predefined runtime units.
+
+ elsif Present (Alias (Func_Id)) then
+
+ -- Unimplemented: a cross-dialect subp renaming which does not set
+ -- the Alias attribute (e.g., a rename of a dereference of an access
+ -- to subprogram value). ???
+
+ return Present (Extra_Accessibility_Of_Result (Alias (Func_Id)));
+
+ -- Remaining cases require Ada 2012 mode
+
+ elsif Ada_Version < Ada_2012 then
+ return False;
+
+ elsif Ekind (Func_Typ) = E_Anonymous_Access_Type
+ or else Is_Tagged_Type (Func_Typ)
+ then
+ -- In the case of, say, a null tagged record result type, the need
+ -- for this extra parameter might not be obvious. This function
+ -- returns True for all tagged types for compatibility reasons.
+ -- A function with, say, a tagged null controlling result type might
+ -- be overridden by a primitive of an extension having an access
+ -- discriminant and the overrider and overridden must have compatible
+ -- calling conventions (including implicitly declared parameters).
+ -- Similarly, values of one access-to-subprogram type might designate
+ -- both a primitive subprogram of a given type and a function
+ -- which is, for example, not a primitive subprogram of any type.
+ -- Again, this requires calling convention compatibility.
+ -- It might be possible to solve these issues by introducing
+ -- wrappers, but that is not the approach that was chosen.
+
+ return True;
+
+ elsif Has_Unconstrained_Access_Discriminants (Func_Typ) then
+ return True;
+
+ elsif Has_Unconstrained_Access_Discriminant_Component (Func_Typ) then
+ return True;
+
+ -- False for all other cases
+
+ else
+ return False;
+ end if;
+ end Needs_Result_Accessibility_Level;
+
end Exp_Ch6;