aboutsummaryrefslogtreecommitdiff
path: root/gcc/ada/sem_ch6.adb
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/ada/sem_ch6.adb')
-rw-r--r--gcc/ada/sem_ch6.adb877
1 files changed, 792 insertions, 85 deletions
diff --git a/gcc/ada/sem_ch6.adb b/gcc/ada/sem_ch6.adb
index 48dcf8e..709f625 100644
--- a/gcc/ada/sem_ch6.adb
+++ b/gcc/ada/sem_ch6.adb
@@ -3864,9 +3864,14 @@ package body Sem_Ch6 is
Spec_Id := Build_Internal_Protected_Declaration (N);
end if;
- -- If a separate spec is present, then deal with freezing issues
+ -- Separate spec is not present
- if Present (Spec_Id) then
+ if No (Spec_Id) then
+ Create_Extra_Formals (Body_Id);
+
+ -- Separate spec is present; deal with freezing issues
+
+ else
Spec_Decl := Unit_Declaration_Node (Spec_Id);
Verify_Overriding_Indicator;
@@ -3882,6 +3887,8 @@ package body Sem_Ch6 is
and then not Has_BIP_Formals (Spec_Id)
then
Create_Extra_Formals (Spec_Id);
+ pragma Assert (not Expander_Active
+ or else Extra_Formals_Known (Spec_Id));
Compute_Returns_By_Ref (Spec_Id);
end if;
@@ -8564,14 +8571,13 @@ package body Sem_Ch6 is
-- without coordinating with CodePeer, which makes use of these to
-- provide better messages.
+ -- A and B denote extra formals for unchecked unions equality. See
+ -- exp_ch3.Build_Variant_Record_Equality.
-- O denotes the Constrained bit.
-- L denotes the accessibility level.
-- BIP_xxx denotes an extra formal for a build-in-place function. See
-- the full list in exp_ch6.BIP_Formal_Kind.
- function Has_Extra_Formals (E : Entity_Id) return Boolean;
- -- Determines if E has its extra formals
-
function Might_Need_BIP_Task_Actuals (E : Entity_Id) return Boolean;
-- Determines if E is a function or an access to a function returning a
-- limited tagged type object. On dispatching primitives this predicate
@@ -8610,14 +8616,6 @@ package body Sem_Ch6 is
EF : Entity_Id;
begin
- -- A little optimization. Never generate an extra formal for the
- -- _init operand of an initialization procedure, since it could
- -- never be used.
-
- if Chars (Formal) = Name_uInit then
- return Empty;
- end if;
-
EF := Make_Defining_Identifier (Sloc (Assoc_Entity),
Chars => New_External_Name (Chars (Assoc_Entity),
Suffix => Suffix));
@@ -8643,25 +8641,22 @@ package body Sem_Ch6 is
return EF;
end Add_Extra_Formal;
- -----------------------
- -- Has_Extra_Formals --
- -----------------------
-
- function Has_Extra_Formals (E : Entity_Id) return Boolean is
- begin
- return Present (Extra_Formals (E))
- or else
- (Ekind (E) = E_Function
- and then Present (Extra_Accessibility_Of_Result (E)));
- end Has_Extra_Formals;
-
---------------------------------
-- Might_Need_BIP_Task_Actuals --
---------------------------------
function Might_Need_BIP_Task_Actuals (E : Entity_Id) return Boolean is
Subp_Id : Entity_Id;
- Func_Typ : Entity_Id;
+ Original : Entity_Id;
+ Root : Entity_Id;
+
+ function Has_No_Task_Parts_Enabled (E : Entity_Id) return Boolean
+ is (Has_Enabled_Aspect (E, Aspect_No_Task_Parts));
+
+ function Collect_Ancestors_With_No_Task_Parts is new
+ Collect_Types_In_Hierarchy (Predicate => Has_No_Task_Parts_Enabled);
+
+ -- Start of processing for Might_Need_BIP_Task_Actuals
begin
if Global_No_Tasking or else No_Run_Time_Mode then
@@ -8689,21 +8684,29 @@ package body Sem_Ch6 is
then
Subp_Id := Protected_Body_Subprogram (E);
- else
+ -- For access-to-subprogram types we look at the return type of the
+ -- subprogram type itself, as it cannot be overridden or inherited.
+
+ elsif Ekind (E) = E_Subprogram_Type then
Subp_Id := E;
- end if;
- -- We check the root type of the return type since the same
- -- decision must be taken for all descendants overriding a
- -- dispatching operation.
+ -- Otherwise, we need to return the same value we would return for
+ -- the original corresponding operation of the root of the aliased
+ -- chain.
+
+ else
+ Subp_Id := Original_Corresponding_Operation (Ultimate_Alias (E));
+ end if;
- Func_Typ := Root_Type (Underlying_Type (Etype (Subp_Id)));
+ Original := Underlying_Type (Etype (Subp_Id));
+ Root := Underlying_Type (Root_Type (Original));
return Ekind (Subp_Id) in E_Function | E_Subprogram_Type
- and then not Has_Foreign_Convention (Func_Typ)
- and then Is_Tagged_Type (Func_Typ)
- and then Is_Limited_Type (Func_Typ)
- and then not Has_Aspect (Func_Typ, Aspect_No_Task_Parts);
+ and then Is_Inherently_Limited_Type (Original)
+ and then not Has_Foreign_Convention (Root)
+ and then Is_Tagged_Type (Root)
+ and then Is_Empty_Elmt_List
+ (Collect_Ancestors_With_No_Task_Parts (Original));
end Might_Need_BIP_Task_Actuals;
-------------------------------------
@@ -8792,10 +8795,12 @@ package body Sem_Ch6 is
-- we have no direct way to climb to the corresponding parent
-- subprogram but this internal entity has the extra formals
-- (if any) required for the purpose of checking the extra
- -- formals of Subp_Id.
+ -- formals of Subp_Id because its extra formals are shared
+ -- with its parent subprogram (see Sem_Ch3.Derive_Subprogram).
else
pragma Assert (not Comes_From_Source (Ovr_E));
+ Freeze_Extra_Formals (Ovr_E);
end if;
-- Use as our reference entity the ultimate renaming of the
@@ -8818,10 +8823,14 @@ package body Sem_Ch6 is
-- Local variables
- Formal_Type : Entity_Id;
- May_Have_Alias : Boolean;
+ use Deferred_Extra_Formals_Support;
+
+ Can_Be_Deferred : constant Boolean :=
+ not Is_Unsupported_Extra_Formals_Entity (E);
Alias_Formal : Entity_Id := Empty;
Alias_Subp : Entity_Id := Empty;
+ Formal_Type : Entity_Id;
+ May_Have_Alias : Boolean;
Parent_Formal : Entity_Id := Empty;
Parent_Subp : Entity_Id := Empty;
Ref_E : Entity_Id;
@@ -8832,10 +8841,18 @@ package body Sem_Ch6 is
pragma Assert (Is_Subprogram_Or_Entry (E)
or else Ekind (E) in E_Subprogram_Type);
+ -- No action needed if extra formals were already handled. This
+ -- situation may arise because of a previous call to create the
+ -- extra formals, and also for subprogram types created as part
+ -- of dispatching calls (see Expand_Dispatching_Call).
+
+ if Extra_Formals_Known (E) then
+ return;
+
-- We never generate extra formals if expansion is not active because we
-- don't need them unless we are generating code.
- if not Expander_Active then
+ elsif not Expander_Active then
return;
-- Enumeration literals have no extra formal; this case occurs when
@@ -8844,25 +8861,38 @@ package body Sem_Ch6 is
elsif Ekind (E) = E_Function
and then Ekind (Ultimate_Alias (E)) = E_Enumeration_Literal
then
+ Freeze_Extra_Formals (E);
return;
- -- Extra formals of Initialization procedures are added by the function
- -- Exp_Ch3.Init_Formals
+ -- Extra formals of init procs are added by Exp_Ch3.Init_Formals and
+ -- Set_CPP_Constructors when they are built, but we must handle here
+ -- aliased init procs.
elsif Is_Init_Proc (E) then
+ pragma Assert (Present (Alias (E)));
+ pragma Assert (Extra_Formals_Known (Ultimate_Alias (E)));
+ Freeze_Extra_Formals (E);
return;
-- No need to generate extra formals in thunks whose target has no extra
-- formals, but we can have two of them chained (interface and stack).
- elsif Is_Thunk (E) and then No (Extra_Formals (Thunk_Target (E))) then
+ elsif Is_Thunk (E)
+ and then Extra_Formals_Known (Thunk_Target (E))
+ and then No (Extra_Formals (Thunk_Target (E)))
+ then
+ Freeze_Extra_Formals (E);
return;
- -- If Extra_Formals were already created, don't do it again. This
- -- situation may arise for subprogram types created as part of
- -- dispatching calls (see Expand_Dispatching_Call).
+ -- Handle alias of unchecked union equality with frozen extra formals
- elsif Has_Extra_Formals (E) then
+ elsif Is_Overloadable (E)
+ and then Present (Alias (E))
+ and then Extra_Formals_Known (Ultimate_Alias (E))
+ and then Is_Unchecked_Union_Equality (Ultimate_Alias (E))
+ then
+ Set_Extra_Formals (E, Extra_Formals (Ultimate_Alias (E)));
+ Freeze_Extra_Formals (E);
return;
-- Extra formals of renamings of generic actual subprograms and
@@ -8880,6 +8910,8 @@ package body Sem_Ch6 is
= Is_Generic_Instance (Ultimate_Alias (E)));
Create_Extra_Formals (Ultimate_Alias (E));
+ pragma Assert (not Expander_Active
+ or else Extra_Formals_Known (Ultimate_Alias (E)));
-- Share the extra formals
@@ -8891,17 +8923,72 @@ package body Sem_Ch6 is
end if;
pragma Assert (Extra_Formals_OK (E));
+ Freeze_Extra_Formals (E);
return;
end if;
- -- Locate the last formal; required by Add_Extra_Formal.
+ -- Check if the addition of the extra formals must be deferred
Formal := First_Formal (E);
while Present (Formal) loop
- Last_Extra := Formal;
+ if No (Underlying_Type (Etype (Formal)))
+ and then Can_Be_Deferred
+ then
+ Register_Deferred_Extra_Formals_Entity (E);
+ return;
+ end if;
+
Next_Formal (Formal);
end loop;
+ if Ekind (E) in E_Function
+ | E_Subprogram_Type
+ and then No (Underlying_Type (Etype (E)))
+ and then Can_Be_Deferred
+ then
+ Register_Deferred_Extra_Formals_Entity (E);
+ return;
+ end if;
+
+ -- Here we start adding the extra formals
+
+ -- We we know that either the underlying type of all the formals and
+ -- returned results of E are known, or this is an special case where
+ -- some underlying type is still not available.
+
+ -- In the former case, we can already mark functions that return their
+ -- result by reference; in the latter case, we can mark them only if the
+ -- underlying return type is available (and it will be marked later).
+
+ if not Is_Unsupported_Extra_Formals_Entity (E)
+ or else (Ekind (E) in E_Function | E_Subprogram_Type
+ and then Present (Underlying_Type (Etype (E))))
+ then
+ Compute_Returns_By_Ref (E);
+ end if;
+
+ -- Locate the last formal (required by Add_Extra_Formal)
+
+ if Present (First_Formal (E))
+ and then Is_Unchecked_Union (Etype (First_Formal (E)))
+ and then Present (Extra_Formals (E))
+ and then Has_Suffix (Extra_Formals (E), 'A')
+ then
+ -- An unchecked union equality has two extra formals per discriminant
+
+ First_Extra := Extra_Formals (E);
+ Last_Extra := First_Extra;
+ while Present (Last_Extra) loop
+ pragma Assert (Has_Suffix (Last_Extra, 'A'));
+ Last_Extra := Extra_Formal (Last_Extra);
+
+ pragma Assert (Has_Suffix (Last_Extra, 'B'));
+ Last_Extra := Extra_Formal (Last_Extra);
+ end loop;
+ else
+ Last_Extra := Last_Formal (E);
+ end if;
+
-- We rely on three entities to ensure consistency of extra formals of
-- entity E:
--
@@ -8961,6 +9048,7 @@ package body Sem_Ch6 is
or else (Present (Alias_Subp)
and then Has_Foreign_Convention (Alias_Subp))
then
+ Freeze_Extra_Formals (E);
return;
end if;
@@ -9039,14 +9127,44 @@ package body Sem_Ch6 is
-- Here we establish our priority for deciding on the extra
-- formals: 1) Parent primitive 2) Aliased primitive 3) Identity
- if Present (Parent_Formal) then
- Formal_Type := Etype (Parent_Formal);
+ -- Common case: the underlying type of all the formals is known
+ -- to be available.
+
+ if Can_Be_Deferred then
+ if Present (Parent_Formal) then
+ Formal_Type := Underlying_Type (Etype (Parent_Formal));
+ elsif Present (Alias_Formal) then
+ Formal_Type := Underlying_Type (Etype (Alias_Formal));
+ else
+ Formal_Type := Underlying_Type (Etype (Formal));
+ end if;
+
+ pragma Assert (Present (Formal_Type));
- elsif Present (Alias_Formal) then
- Formal_Type := Etype (Alias_Formal);
+ -- Special case: The underlying type of some formal is not available.
+ -- We use the underlying type when present. More work needed here???
else
- Formal_Type := Etype (Formal);
+ if Present (Parent_Formal) then
+ Formal_Type := Etype (Parent_Formal);
+
+ if Present (Underlying_Type (Formal_Type)) then
+ Formal_Type := Underlying_Type (Formal_Type);
+ end if;
+
+ elsif Present (Alias_Formal) then
+ Formal_Type := Etype (Alias_Formal);
+
+ if Present (Underlying_Type (Formal_Type)) then
+ Formal_Type := Underlying_Type (Formal_Type);
+ end if;
+ else
+ Formal_Type := Etype (Formal);
+
+ if Present (Underlying_Type (Formal_Type)) then
+ Formal_Type := Underlying_Type (Formal_Type);
+ end if;
+ end if;
end if;
-- Create extra formal for supporting the attribute 'Constrained.
@@ -9093,12 +9211,13 @@ package body Sem_Ch6 is
and then (Is_Definite_Subtype (Formal_Type)
or else Is_Mutably_Tagged_Type (Formal_Type))
and then (Ada_Version < Ada_2012
- or else No (Underlying_Type (Formal_Type))
+ or else
+ (not Can_Be_Deferred
+ and then No (Underlying_Type (Formal_Type)))
or else not
(Is_Limited_Type (Formal_Type)
and then
- Is_Tagged_Type
- (Underlying_Type (Formal_Type))))
+ Is_Tagged_Type (Formal_Type)))
then
Set_Extra_Constrained
(Formal, Add_Extra_Formal (Formal, Standard_Boolean, E, "O"));
@@ -9337,6 +9456,8 @@ package body Sem_Ch6 is
Set_Extra_Formals (Alias (E), Extra_Formals (E));
end if;
+ Freeze_Extra_Formals (E);
+
pragma Assert (No (Alias_Subp)
or else Extra_Formals_Match_OK (E, Alias_Subp));
@@ -9651,6 +9772,19 @@ package body Sem_Ch6 is
return False;
end if;
+ -- Extra formals (A and B) of Unchecked_Unions (see Build_Variant_
+ -- Record_Equality)
+
+ elsif Has_Suffix (Formal_1, 'A') then
+ if not Has_Suffix (Formal_2, 'A') then
+ return False;
+ end if;
+
+ elsif Has_Suffix (Formal_1, 'B') then
+ if not Has_Suffix (Formal_2, 'B') then
+ return False;
+ end if;
+
elsif BIP_Suffix_Kind (Formal_1) /= BIP_Suffix_Kind (Formal_2) then
return False;
end if;
@@ -10003,6 +10137,16 @@ package body Sem_Ch6 is
return Empty;
end Find_Corresponding_Spec;
+ --------------------------
+ -- Freeze_Extra_Formals --
+ --------------------------
+
+ procedure Freeze_Extra_Formals (E : Entity_Id) is
+ begin
+ pragma Assert (not Extra_Formals_Known (E));
+ Set_Extra_Formals_Known (E);
+ end Freeze_Extra_Formals;
+
----------------------
-- Fully_Conformant --
----------------------
@@ -10622,6 +10766,10 @@ package body Sem_Ch6 is
Formal : Entity_Id := First_Formal_With_Extras (E);
begin
+ -- It makes no sense to perform this check if the extra formals
+ -- have not been added.
+ pragma Assert (Extra_Formals_Known (E));
+
while Present (Formal) loop
if Is_Build_In_Place_Entity (Formal) then
return True;
@@ -12133,36 +12281,51 @@ package body Sem_Ch6 is
and then Present (Find_Dispatching_Type (Alias (S)))
and then Is_Interface (Find_Dispatching_Type (Alias (S)))
then
- -- For private types, when the full-view is processed we propagate to
- -- the full view the non-overridden entities whose attribute "alias"
- -- references an interface primitive. These entities were added by
- -- Derive_Subprograms to ensure that interface primitives are
- -- covered.
-
- -- Inside_Freeze_Actions is non zero when S corresponds with an
- -- internal entity that links an interface primitive with its
- -- covering primitive through attribute Interface_Alias (see
- -- Add_Internal_Interface_Entities).
-
- if Inside_Freezing_Actions = 0
- and then Is_Package_Or_Generic_Package (Current_Scope)
- and then In_Private_Part (Current_Scope)
- and then Parent_Kind (E) = N_Private_Extension_Declaration
- and then Nkind (Parent (S)) = N_Full_Type_Declaration
- and then Full_View (Defining_Identifier (Parent (E)))
- = Defining_Identifier (Parent (S))
- and then Alias (E) = Alias (S)
- then
- Check_Operation_From_Private_View (S, E);
- Set_Is_Dispatching_Operation (S);
+ declare
+ Private_Operation_Exported_By_Visible_Part : constant Boolean :=
+ Is_Package_Or_Generic_Package (Current_Scope)
+ and then In_Private_Part (Current_Scope)
+ and then Parent_Kind (E) = N_Private_Extension_Declaration
+ and then Nkind (Parent (S)) = N_Full_Type_Declaration
+ and then Full_View (Defining_Identifier (Parent (E)))
+ = Defining_Identifier (Parent (S));
+
+ begin
+ -- For private types, when the full view is processed we propagate
+ -- to the full view the nonoverridden entities whose attribute
+ -- "alias" references an interface primitive. These entities were
+ -- added by Derive_Subprograms to ensure that interface primitives
+ -- are covered.
+
+ -- Inside_Freeze_Actions is nonzero when S corresponds to an
+ -- internal entity that links an interface primitive with its
+ -- covering primitive through attribute Interface_Alias (see
+ -- Add_Internal_Interface_Entities).
+
+ if Inside_Freezing_Actions = 0
+ and then Private_Operation_Exported_By_Visible_Part
+ and then Alias (E) = Alias (S)
+ then
+ Check_Operation_From_Private_View (S, E);
+ Set_Is_Dispatching_Operation (S);
- -- Common case
+ -- Common case
- else
- Enter_Overloaded_Entity (S);
- Check_Dispatching_Operation (S, Empty);
- Check_For_Primitive_Subprogram (Is_Primitive_Subp);
- end if;
+ else
+ Enter_Overloaded_Entity (S);
+ Check_Dispatching_Operation (S, Empty);
+ Check_For_Primitive_Subprogram (Is_Primitive_Subp);
+ end if;
+
+ if Private_Operation_Exported_By_Visible_Part
+ and then Type_Conformant (E, S)
+ then
+ -- Record the actual inherited subprogram that's being
+ -- overridden.
+
+ Set_Overridden_Inherited_Operation (S, E);
+ end if;
+ end;
return;
end if;
@@ -12601,6 +12764,26 @@ package body Sem_Ch6 is
and then not Is_Dispatch_Table_Wrapper (S)))
then
Set_Overridden_Operation (S, Alias (E));
+
+ -- Record the actual inherited subprogram that's being
+ -- overridden. In the case where a subprogram declared
+ -- in a private part overrides an inherited subprogram
+ -- that itself is also declared in the private part,
+ -- and that subprogram in turns overrides a subprogram
+ -- declared in a package visible part (inherited via
+ -- a private extension), we record the visible subprogram
+ -- as the overridden one, so that we can determine
+ -- visibility properly for prefixed calls to the
+ -- subprogram made from outside the package. (See
+ -- Try_Primitive_Operation in Sem_Ch4.)
+
+ if Present (Overridden_Inherited_Operation (E)) then
+ Set_Overridden_Inherited_Operation
+ (S, Overridden_Inherited_Operation (E));
+ else
+ Set_Overridden_Inherited_Operation (S, E);
+ end if;
+
Inherit_Subprogram_Contract (S, Alias (E));
Set_Is_Ada_2022_Only (S, Is_Ada_2022_Only (Alias (E)));
@@ -12760,6 +12943,530 @@ package body Sem_Ch6 is
end if;
end New_Overloaded_Entity;
+ ------------------------------------
+ -- Deferred_Extra_Formals_Support --
+ ------------------------------------
+
+ package body Deferred_Extra_Formals_Support is
+ Calls_List : Elist_Id := No_Elist;
+ Calls_Scope_List : Elist_Id := No_Elist;
+ -- Calls to subprograms or entries with some unknown underlying type
+ -- in their parameters or result type, and the scope where each call
+ -- is performed.
+
+ Entities_List : Elist_Id := No_Elist;
+ -- Subprograms, entries, and subprogram types with some unknown
+ -- underlying type in their formals or result type.
+
+ Types_List : Elist_Id := No_Elist;
+ -- Types with no underlying type
+
+ function Underlying_Types_Available (E : Entity_Id) return Boolean;
+ -- Determines if the underlying type of all the formals and result
+ -- type of the given subprogram, subprogram type, or entry are
+ -- available.
+
+ -------------------------------
+ -- Add_Deferred_Extra_Params --
+ -------------------------------
+
+ procedure Add_Deferred_Extra_Params (Typ : Entity_Id) is
+
+ procedure Check_Registered_Calls;
+ -- Check all the registered calls; for each registered call that
+ -- has the underlying type of all the parameters and result types
+ -- of the called entity available, call Create_Extra_Actuals, and
+ -- unregister the call.
+
+ procedure Check_Registered_Entities;
+ -- Check all the registered entities (subprograms, entries and
+ -- subprogram types); for each registered entity E that has all
+ -- its underlying types available, call Create_Extra_Formals,
+ -- and unregister E.
+
+ ----------------------------
+ -- Check_Registered_Calls --
+ ----------------------------
+
+ procedure Check_Registered_Calls is
+
+ function Get_Relocated_Function_Call (N : Node_Id) return Node_Id;
+ -- Given a node N that references a function call that has been
+ -- relocated to remove possible side effects of the call (see
+ -- Remove_Side_Effects) or to wrap the call in a transient scope
+ -- (see Wrap_Transient_Expression), search and return the function
+ -- call. Notice that this function does not use the Original_Node
+ -- field of N; it searchs for the actual call associated with N
+ -- in the expanded code (since we need to add to such call its
+ -- missing extra actuals).
+
+ ---------------------------------
+ -- Get_Relocated_Function_Call --
+ ---------------------------------
+
+ function Get_Relocated_Function_Call (N : Node_Id) return Node_Id
+ is
+ Current_Node : Node_Id;
+ Decl : Node_Id;
+ Id : Entity_Id;
+
+ begin
+ Current_Node := N;
+
+ while Nkind (Current_Node) /= N_Function_Call loop
+ case Nkind (Current_Node) is
+ when N_Identifier =>
+ Id := Entity (Current_Node);
+ Decl := Parent (Id);
+
+ if Nkind (Decl) = N_Object_Renaming_Declaration then
+ Current_Node := Name (Decl);
+
+ else
+ pragma Assert (Nkind (Decl) = N_Object_Declaration);
+
+ if Present (Expression (Decl)) then
+ Current_Node := Expression (Decl);
+
+ elsif Present (BIP_Initialization_Call (Id)) then
+ Decl := BIP_Initialization_Call (Id);
+ pragma Assert (Present (Expression (Decl)));
+ Current_Node := Expression (Decl);
+
+ elsif Present (Related_Expression (Id)) then
+ Current_Node := Related_Expression (Id);
+
+ else
+ pragma Assert (False);
+ raise Program_Error;
+ end if;
+ end if;
+
+ when N_Explicit_Dereference | N_Reference =>
+ Current_Node := Prefix (Current_Node);
+
+ when others =>
+ pragma Assert (False);
+ raise Program_Error;
+ end case;
+ end loop;
+
+ return Current_Node;
+ end Get_Relocated_Function_Call;
+
+ -- Local variables
+
+ Call_Node : Node_Id;
+ Call_Id : Entity_Id;
+ Elmt_Call : Elmt_Id;
+ Elmt_Scope : Elmt_Id;
+ Remove_Call : Boolean;
+ Scop_Id : Entity_Id;
+
+ -- Start of processing for Check_Registered_Calls
+
+ begin
+ -- Perform a single traversal of both lists simultaneously,
+ -- since they have the same number of elements with a 1-to-1
+ -- relationship.
+
+ Elmt_Scope := First_Elmt (Calls_Scope_List);
+ Elmt_Call := First_Elmt (Calls_List);
+
+ while Present (Elmt_Scope) loop
+ Scop_Id := Node (Elmt_Scope);
+ Remove_Call := False;
+
+ -- Check the enclosing scope of the call: if the underlying
+ -- type of some formal or return type of the enclosing scope
+ -- of this call is not available then we must skip processing
+ -- this call.
+
+ if Underlying_Types_Available (Scop_Id) then
+ Call_Node := Node (Elmt_Call);
+
+ if Nkind (Call_Node) in N_Entry_Call_Statement
+ | N_Function_Call
+ | N_Procedure_Call_Statement
+ then
+ Call_Id := Get_Called_Entity (Call_Node);
+
+ -- Handle expanded function calls that could have side
+ -- effects.
+
+ else
+ pragma Assert
+ (Nkind (Original_Node (Call_Node)) = N_Function_Call);
+
+ Call_Node := Get_Relocated_Function_Call (Call_Node);
+ Call_Id := Get_Called_Entity (Call_Node);
+ end if;
+
+ -- If the underlying types of all the formal and return
+ -- types of this called entity are available then create
+ -- its extra actuals and remove it from the list of
+ -- registered calls.
+
+ if Underlying_Types_Available (Call_Id) then
+
+ -- Given that the call is placed in the body of an
+ -- internally built subprogram, ensure that the extra
+ -- formals of the enclosing scope are available before
+ -- adding the extra actuals of this call.
+
+ Create_Extra_Formals (Scop_Id);
+ Create_Extra_Formals (Call_Id);
+
+ pragma Assert (Extra_Formals_Known (Scop_Id));
+ pragma Assert (Extra_Formals_Known (Call_Id));
+
+ -- Mark functions that return a result by reference
+
+ Compute_Returns_By_Ref (Scop_Id);
+ Compute_Returns_By_Ref (Call_Id);
+
+ Push_Scope (Scop_Id);
+ Create_Extra_Actuals (Call_Node);
+ Pop_Scope;
+
+ Remove_Call := True;
+ end if;
+ end if;
+
+ -- In order to safely remove these elements from their
+ -- containing lists, remember these elements before moving
+ -- to the next list elements.
+
+ if Remove_Call then
+ declare
+ Removed_Call : constant Elmt_Id := Elmt_Call;
+ Removed_Scope : constant Elmt_Id := Elmt_Scope;
+
+ begin
+ Next_Elmt (Elmt_Scope);
+ Next_Elmt (Elmt_Call);
+
+ Remove_Elmt (Calls_List, Removed_Call);
+ Remove_Elmt (Calls_Scope_List, Removed_Scope);
+ end;
+ else
+ Next_Elmt (Elmt_Scope);
+ Next_Elmt (Elmt_Call);
+ end if;
+
+ end loop;
+ end Check_Registered_Calls;
+
+ -------------------------------
+ -- Check_Registered_Entities --
+ -------------------------------
+
+ procedure Check_Registered_Entities is
+ Elmt : Elmt_Id;
+ Found_Elmt : Elmt_Id;
+ Id : Entity_Id;
+
+ begin
+ Elmt := First_Elmt (Entities_List);
+
+ while Present (Elmt) loop
+ Id := Node (Elmt);
+
+ -- If the underlying type of some formal or return type of this
+ -- entity is not available then skip this element.
+
+ if not Underlying_Types_Available (Id) then
+ Next_Elmt (Elmt);
+
+ -- Otherwise, create its extra formals and remove it from the
+ -- list of entities that require adding the extra formals.
+
+ else
+ -- In order to safely remove this element from the list,
+ -- temporarily remember this element, and move to the next
+ -- element.
+
+ Found_Elmt := Elmt;
+ Next_Elmt (Elmt);
+
+ -- Create the extra formals, and mark functions that return
+ -- by reference (not be done before if the underying return
+ -- type was previously unknown).
+
+ Create_Extra_Formals (Id);
+ Compute_Returns_By_Ref (Id);
+
+ Remove_Elmt (Entities_List, Found_Elmt);
+
+ -- For deferred entries and entry families, the expansion of
+ -- their entry declaration was deferred, and must be done
+ -- now (after adding their extra formals).
+
+ if Ekind (Id) in E_Entry | E_Entry_Family then
+ Expand_N_Entry_Declaration (Parent (Id),
+ Was_Deferred => True);
+ end if;
+ end if;
+ end loop;
+ end Check_Registered_Entities;
+
+ -- Start of processing for Add_Deferred_Extra_Params
+
+ begin
+ pragma Assert (Present (Underlying_Type (Typ)));
+
+ if Present (Entities_List) then
+ Check_Registered_Entities;
+ end if;
+
+ if Present (Calls_List) then
+ Check_Registered_Calls;
+ end if;
+
+ Remove (Types_List, Typ);
+ end Add_Deferred_Extra_Params;
+
+ --------------------------------
+ -- Has_Deferred_Extra_Formals --
+ --------------------------------
+
+ function Has_Deferred_Extra_Formals (Typ : Entity_Id) return Boolean is
+ begin
+ return Contains (Types_List, Typ);
+ end Has_Deferred_Extra_Formals;
+
+ --------------------------------------
+ -- Is_Deferred_Extra_Formals_Entity --
+ --------------------------------------
+
+ function Is_Deferred_Extra_Formals_Entity
+ (Id : Entity_Id) return Boolean is
+ begin
+ return Contains (Entities_List, Id);
+ end Is_Deferred_Extra_Formals_Entity;
+
+ ---------------------------------------
+ -- Is_Unsupported_Extra_Actuals_Call --
+ ---------------------------------------
+
+ -- Similarly to Is_Unsupported_Extra_Formals_Entity, we cannot
+ -- determine if the extra formals are needed when the underlying
+ -- type of some formal or result type is not available, and we are
+ -- compiling the body of a subprogram or package. However, for calls
+ -- we must also handle internal calls generated by the compiler as
+ -- part of compiling a package spec. For example, internal calls
+ -- performed in thunks of secondary dispatch table entries.
+ --
+ -- Example
+ -- -------
+ -- package P is
+ -- type T is tagged null record;
+ -- end;
+ --
+ -- limited with P;
+ -- package Q is
+ -- type Iface is interface;
+ -- procedure Prim (Self : Iface; Current : P.T) is abstract;
+ -- end;
+ --
+ -- limited with P;
+ -- with Q;
+ -- package R is
+ -- type Root is tagged null record;
+ -- type DT is new Root and Q.Iface with null record;
+ --
+ -- procedure Prim (Self : DT; Current : P.T);
+ -- end;
+ --
+ -- The initialization of the secondary dispatch table of tagged type
+ -- DT has an internally generated thunk that displaces the pointer to
+ -- the object and calls the primitive Prim (and the underlying type
+ -- of type T is not available).
+
+ function Is_Unsupported_Extra_Actuals_Call
+ (Call_Node : Node_Id; Id : Entity_Id) return Boolean
+ is
+ Comp_Unit : constant Entity_Id :=
+ Cunit_Entity (Get_Source_Unit (Call_Node));
+ begin
+ return not Underlying_Types_Available (Id)
+ and then Is_Compilation_Unit (Comp_Unit)
+ and then Ekind (Comp_Unit) in E_Package
+ | E_Package_Body
+ | E_Subprogram_Body;
+ end Is_Unsupported_Extra_Actuals_Call;
+
+ -----------------------------------------
+ -- Is_Unsupported_Extra_Formals_Entity --
+ -----------------------------------------
+
+ -- We cannot determine if the extra formals are needed when the
+ -- underlying type of some formal or result type is not available,
+ -- and we are compiling the body of a subprogram or package. The
+ -- scenery for this case is a package spec that has a limited_with_
+ -- clause on unit Q, and its body has no regular with-clause on Q
+ -- (AI05-0151-1/08).
+
+ function Is_Unsupported_Extra_Formals_Entity
+ (Id : Entity_Id) return Boolean
+ is
+ Comp_Unit : constant Entity_Id :=
+ Cunit_Entity (Get_Source_Unit (Id));
+ begin
+ return not Underlying_Types_Available (Id)
+ and then Is_Compilation_Unit (Comp_Unit)
+ and then Ekind (Comp_Unit) in E_Package_Body
+ | E_Subprogram_Body;
+ end Is_Unsupported_Extra_Formals_Entity;
+
+ --------------------------------------------
+ -- Register_Deferred_Extra_Formals_Entity --
+ --------------------------------------------
+
+ procedure Register_Deferred_Extra_Formals_Entity (Id : Entity_Id) is
+
+ procedure Register_Type (Typ : Entity_Id);
+ -- Register the given type in Types_List; for types visible though
+ -- limited_with_clauses, register their non-limited view.
+
+ -------------------
+ -- Register_Type --
+ -------------------
+
+ procedure Register_Type (Typ : Entity_Id) is
+ begin
+ -- Handle entities visible through limited_with_clauses
+
+ if Has_Non_Limited_View (Typ) then
+ Append_Unique_Elmt (Non_Limited_View (Typ), Types_List);
+ else
+ Append_Unique_Elmt (Typ, Types_List);
+ end if;
+ end Register_Type;
+
+ -- Local variables
+
+ Formal : Entity_Id;
+
+ -- Start of processing for Register_Deferred_Extra_Formals_Entity
+
+ begin
+ pragma Assert (Is_Subprogram_Or_Entry (Id)
+ or else Ekind (Id) in E_Subprogram_Type);
+
+ if not Is_Deferred_Extra_Formals_Entity (Id) then
+ if No (Types_List) then
+ Types_List := New_Elmt_List;
+ end if;
+
+ if No (Entities_List) then
+ Entities_List := New_Elmt_List;
+ end if;
+
+ -- Register all the types of the subprogram profile that are not
+ -- fully known.
+
+ Formal := First_Formal (Id);
+ while Present (Formal) loop
+
+ if No (Underlying_Type (Etype (Formal))) then
+ Register_Type (Etype (Formal));
+ end if;
+
+ Next_Formal (Formal);
+ end loop;
+
+ if Ekind (Id) in E_Function | E_Subprogram_Type
+ and then No (Underlying_Type (Etype (Id)))
+ then
+ Register_Type (Etype (Id));
+ end if;
+
+ -- Register this subprogram
+
+ Append_Elmt (Id, Entities_List);
+ end if;
+ end Register_Deferred_Extra_Formals_Entity;
+
+ ------------------------------------------
+ -- Register_Deferred_Extra_Formals_Call --
+ ------------------------------------------
+
+ procedure Register_Deferred_Extra_Formals_Call
+ (Call_Node : Node_Id;
+ Scope_Id : Entity_Id) is
+ begin
+ pragma Assert (Nkind (Call_Node) in N_Subprogram_Call
+ | N_Entry_Call_Statement);
+ if No (Calls_List) then
+ Calls_List := New_Elmt_List;
+ Calls_Scope_List := New_Elmt_List;
+ end if;
+
+ -- Avoid registering any call twice; this may occur in dispatching
+ -- calls with deferred extra actuals because Expand_Call_Helper
+ -- registers the call and invokes Expand_Dispatching_Call (which
+ -- tries again to register the expanded call).
+
+ if not Contains (Calls_List, Call_Node) then
+ Append_Elmt (Call_Node, Calls_List);
+ Append_Elmt (Scope_Id, Calls_Scope_List);
+ end if;
+ end Register_Deferred_Extra_Formals_Call;
+
+ --------------------------------
+ -- Underlying_Types_Available --
+ --------------------------------
+
+ function Underlying_Types_Available (E : Entity_Id) return Boolean is
+ Formal : Entity_Id;
+ Formal_Typ : Entity_Id;
+ Func_Typ : Entity_Id;
+
+ begin
+ -- If the extra formals are available, then the nonlimited view
+ -- of all the types referenced in the profile are available.
+
+ if Extra_Formals_Known (E) then
+ return True;
+ end if;
+
+ -- Check the return type
+
+ if Ekind (E) in E_Function | E_Subprogram_Type then
+ Func_Typ := Etype (E);
+
+ if Has_Non_Limited_View (Func_Typ) then
+ Func_Typ := Non_Limited_View (Func_Typ);
+ end if;
+
+ if No (Underlying_Type (Func_Typ)) then
+ return False;
+ end if;
+ end if;
+
+ -- Check the type of the formals
+
+ Formal := First_Formal (E);
+ while Present (Formal) loop
+ Formal_Typ := Etype (Formal);
+
+ if Has_Non_Limited_View (Formal_Typ) then
+ Formal_Typ := Non_Limited_View (Formal_Typ);
+ end if;
+
+ if No (Underlying_Type (Formal_Typ)) then
+ return False;
+ end if;
+
+ Next_Formal (Formal);
+ end loop;
+
+ return True;
+ end Underlying_Types_Available;
+
+ end Deferred_Extra_Formals_Support;
+
---------------------
-- Process_Formals --
---------------------