with Elists; use Elists;
with Errout; use Errout;
with Expander; use Expander;
+with Exp_Disp; use Exp_Disp;
with Fname; use Fname;
with Fname.UF; use Fname.UF;
with Freeze; use Freeze;
-- package cannot be inlined by the front-end because front-end inlining
-- requires a strict linear order of elaboration.
+ function Check_Hidden_Primitives (Assoc_List : List_Id) return Elist_Id;
+ -- Check if some association between formals and actuals requires to make
+ -- visible primitives of a tagged type, and make those primitives visible.
+ -- Return the list of primitives whose visibility is modified (to restore
+ -- their visibility later through Restore_Hidden_Primitives). If no
+ -- candidate is found then return No_Elist.
+
procedure Check_Hidden_Child_Unit
(N : Node_Id;
Gen_Unit : Entity_Id;
-- an instantiation in the source, or the internal instantiation that
-- corresponds to the actual for a formal package.
+ function Earlier (N1, N2 : Node_Id) return Boolean;
+ -- Yields True if N1 and N2 appear in the same compilation unit,
+ -- ignoring subunits, and if N1 is to the left of N2 in a left-to-right
+ -- traversal of the tree for the unit. Used to determine the placement
+ -- of freeze nodes for instance bodies that may depend on other instances.
+
function Find_Actual_Type
(Typ : Entity_Id;
Gen_Type : Entity_Id) return Entity_Id;
Inst : Node_Id) return Boolean;
-- True if the instantiation Inst and the given freeze_node F_Node appear
-- within the same declarative part, ignoring subunits, but with no inter-
- -- vening subprograms or concurrent units. If true, the freeze node
- -- of the instance can be placed after the freeze node of the parent,
- -- which it itself an instance.
+ -- vening subprograms or concurrent units. Used to find the proper plave
+ -- for the freeze node of an instance, when the generic is declared in a
+ -- previous instance. If predicate is true, the freeze node of the instance
+ -- can be placed after the freeze node of the previous instance, Otherwise
+ -- it has to be placed at the end of the current declarative part.
function In_Main_Context (E : Entity_Id) return Boolean;
-- Check whether an instantiation is in the context of the main unit.
procedure Remove_Parent (In_Body : Boolean := False);
-- Reverse effect after instantiation of child is complete
+ procedure Install_Hidden_Primitives
+ (Prims_List : in out Elist_Id;
+ Gen_T : Entity_Id;
+ Act_T : Entity_Id);
+ -- Remove suffix 'P' from hidden primitives of Act_T to match the
+ -- visibility of primitives of Gen_T. The list of primitives to which
+ -- the suffix is removed is added to Prims_List to restore them later.
+
+ procedure Restore_Hidden_Primitives (Prims_List : in out Elist_Id);
+ -- Restore suffix 'P' to primitives of Prims_List and leave Prims_List
+ -- set to No_Elist.
+
procedure Inline_Instance_Body
(N : Node_Id;
Gen_Unit : Entity_Id;
-- before installing parents of generics, that are not visible for the
-- actuals themselves.
+ function True_Parent (N : Node_Id) return Node_Id;
+ -- For a subunit, return parent of corresponding stub
+
procedure Valid_Default_Attribute (Nam : Entity_Id; Def : Node_Id);
-- Verify that an attribute that appears as the default for a formal
-- subprogram is a function or procedure with the correct profile.
Formals : List_Id;
F_Copy : List_Id) return List_Id
is
-
Actual_Types : constant Elist_Id := New_Elmt_List;
Assoc : constant List_Id := New_List;
Default_Actuals : constant Elist_Id := New_Elmt_List;
(T : Entity_Id;
Def : Node_Id)
is
- Loc : constant Source_Ptr := Sloc (Def);
- Base : constant Entity_Id :=
- New_Internal_Entity
- (E_Decimal_Fixed_Point_Type,
- Current_Scope,
- Sloc (Defining_Identifier (Parent (Def))), 'G');
+ Loc : constant Source_Ptr := Sloc (Def);
+
+ Base : constant Entity_Id :=
+ New_Internal_Entity
+ (E_Decimal_Fixed_Point_Type,
+ Current_Scope,
+ Sloc (Defining_Identifier (Parent (Def))), 'G');
+
Int_Base : constant Entity_Id := Standard_Integer;
Delta_Val : constant Ureal := Ureal_1;
Digs_Val : constant Uint := Uint_6;
Base : constant Entity_Id :=
New_Internal_Entity
(E_Floating_Point_Type, Current_Scope,
- Sloc (Defining_Identifier (Parent (Def))), 'G');
+ Sloc (Defining_Identifier (Parent (Def))), 'G');
+
begin
Enter_Name (T);
Set_Ekind (T, E_Enumeration_Subtype);
Base : constant Entity_Id :=
New_Internal_Entity
(E_Floating_Point_Type, Current_Scope,
- Sloc (Defining_Identifier (Parent (Def))), 'G');
+ Sloc (Defining_Identifier (Parent (Def))), 'G');
begin
-- The various semantic attributes are taken from the predefined type
Base : constant Entity_Id :=
New_Internal_Entity
(E_Ordinary_Fixed_Point_Type, Current_Scope,
- Sloc (Defining_Identifier (Parent (Def))), 'G');
+ Sloc (Defining_Identifier (Parent (Def))), 'G');
+
begin
-- The semantic attributes are set for completeness only, their values
-- will never be used, since all properties of the type are non-static.
Renaming_In_Par : Entity_Id;
Associations : Boolean := True;
+ Vis_Prims_List : Elist_Id := No_Elist;
+ -- List of primitives made temporarily visible in the instantiation
+ -- to match the visibility of the formal type
+
function Build_Local_Package return Node_Id;
-- The formal package is rewritten so that its parameters are replaced
-- with corresponding declarations. For parameters with bona fide
Decls :=
Analyze_Associations
- (Original_Node (N),
- Generic_Formal_Declarations (Act_Tree),
- Generic_Formal_Declarations (Gen_Decl));
+ (I_Node => Original_Node (N),
+ Formals => Generic_Formal_Declarations (Act_Tree),
+ F_Copy => Generic_Formal_Declarations (Gen_Decl));
+
+ Vis_Prims_List := Check_Hidden_Primitives (Decls);
end;
end if;
Enter_Name (Formal);
Set_Ekind (Formal, E_Variable);
Set_Etype (Formal, Any_Type);
+ Restore_Hidden_Primitives (Vis_Prims_List);
if Parent_Installed then
Remove_Parent;
end;
End_Package_Scope (Formal);
+ Restore_Hidden_Primitives (Vis_Prims_List);
if Parent_Installed then
Remove_Parent;
is
Base : constant Entity_Id :=
New_Internal_Entity
- (E_Signed_Integer_Type,
- Current_Scope,
- Sloc (Defining_Identifier (Parent (Def))), 'G');
+ (E_Signed_Integer_Type,
+ Current_Scope,
+ Sloc (Defining_Identifier (Parent (Def))), 'G');
begin
Enter_Name (T);
return False;
end Might_Inline_Subp;
+ -- Local declarations
+
+ Vis_Prims_List : Elist_Id := No_Elist;
+ -- List of primitives made temporarily visible in the instantiation
+ -- to match the visibility of the formal type
+
-- Start of processing for Analyze_Package_Instantiation
begin
Renaming_List :=
Analyze_Associations
- (N,
- Generic_Formal_Declarations (Act_Tree),
- Generic_Formal_Declarations (Gen_Decl));
+ (I_Node => N,
+ Formals => Generic_Formal_Declarations (Act_Tree),
+ F_Copy => Generic_Formal_Declarations (Gen_Decl));
+
+ Vis_Prims_List := Check_Hidden_Primitives (Renaming_List);
Set_Instance_Env (Gen_Unit, Act_Decl_Id);
Set_Defining_Unit_Name (Act_Spec, Act_Decl_Name);
Check_Formal_Packages (Act_Decl_Id);
+ Restore_Hidden_Primitives (Vis_Prims_List);
Restore_Private_Views (Act_Decl_Id);
Inherit_Context (Gen_Decl, N);
end if;
end Analyze_Instance_And_Renamings;
+ -- Local variables
+
+ Vis_Prims_List : Elist_Id := No_Elist;
+ -- List of primitives made temporarily visible in the instantiation
+ -- to match the visibility of the formal type
+
-- Start of processing for Analyze_Subprogram_Instantiation
begin
Error_Msg_NE
("circular Instantiation: & instantiated in &!", N, Gen_Unit);
Circularity_Detected := True;
+ Restore_Hidden_Primitives (Vis_Prims_List);
goto Leave;
end if;
Renaming_List :=
Analyze_Associations
- (N,
- Generic_Formal_Declarations (Act_Tree),
- Generic_Formal_Declarations (Gen_Decl));
+ (I_Node => N,
+ Formals => Generic_Formal_Declarations (Act_Tree),
+ F_Copy => Generic_Formal_Declarations (Gen_Decl));
+
+ Vis_Prims_List := Check_Hidden_Primitives (Renaming_List);
-- The subprogram itself cannot contain a nested instance, so the
-- current parent is left empty.
Remove_Parent;
end if;
+ Restore_Hidden_Primitives (Vis_Prims_List);
Restore_Env;
Env_Installed := False;
Generic_Renamings.Set_Last (0);
then
null;
+ -- If the formal package has an "others" box association that
+ -- covers this formal, there is no need for a check either.
+
+ elsif Nkind (Unit_Declaration_Node (E2)) in
+ N_Formal_Subprogram_Declaration
+ and then Box_Present (Unit_Declaration_Node (E2))
+ then
+ null;
+
+ -- Otherwise the actual in the formal and the actual in the
+ -- instantiation of the formal must match, up to renamings.
+
else
Check_Mismatch
(Ekind (E2) /= Ekind (E1) or else (Alias (E1)) /= Alias (E2));
end if;
end Check_Private_View;
+ -----------------------------
+ -- Check_Hidden_Primitives --
+ -----------------------------
+
+ function Check_Hidden_Primitives (Assoc_List : List_Id) return Elist_Id is
+ Actual : Node_Id;
+ Gen_T : Entity_Id;
+ Result : Elist_Id := No_Elist;
+
+ begin
+ if No (Assoc_List) then
+ return No_Elist;
+ end if;
+
+ -- Traverse the list of associations between formals and actuals
+ -- searching for renamings of tagged types
+
+ Actual := First (Assoc_List);
+ while Present (Actual) loop
+ if Nkind (Actual) = N_Subtype_Declaration then
+ Gen_T := Generic_Parent_Type (Actual);
+
+ if Present (Gen_T)
+ and then Is_Tagged_Type (Gen_T)
+ then
+ -- Traverse the list of primitives of the actual types
+ -- searching for hidden primitives that are visible in the
+ -- corresponding generic formal; leave them visible and
+ -- append them to Result to restore their decoration later.
+
+ Install_Hidden_Primitives
+ (Prims_List => Result,
+ Gen_T => Gen_T,
+ Act_T => Entity (Subtype_Indication (Actual)));
+ end if;
+ end if;
+
+ Next (Actual);
+ end loop;
+
+ return Result;
+ end Check_Hidden_Primitives;
+
--------------------------
-- Contains_Instance_Of --
--------------------------
Expander_Mode_Restore;
end End_Generic;
+ -------------
+ -- Earlier --
+ -------------
+
+ function Earlier (N1, N2 : Node_Id) return Boolean is
+ D1 : Integer := 0;
+ D2 : Integer := 0;
+ P1 : Node_Id := N1;
+ P2 : Node_Id := N2;
+
+ procedure Find_Depth (P : in out Node_Id; D : in out Integer);
+ -- Find distance from given node to enclosing compilation unit
+
+ ----------------
+ -- Find_Depth --
+ ----------------
+
+ procedure Find_Depth (P : in out Node_Id; D : in out Integer) is
+ begin
+ while Present (P)
+ and then Nkind (P) /= N_Compilation_Unit
+ loop
+ P := True_Parent (P);
+ D := D + 1;
+ end loop;
+ end Find_Depth;
+
+ -- Start of processing for Earlier
+
+ begin
+ Find_Depth (P1, D1);
+ Find_Depth (P2, D2);
+
+ if P1 /= P2 then
+ return False;
+ else
+ P1 := N1;
+ P2 := N2;
+ end if;
+
+ while D1 > D2 loop
+ P1 := True_Parent (P1);
+ D1 := D1 - 1;
+ end loop;
+
+ while D2 > D1 loop
+ P2 := True_Parent (P2);
+ D2 := D2 - 1;
+ end loop;
+
+ -- At this point P1 and P2 are at the same distance from the root.
+ -- We examine their parents until we find a common declarative list,
+ -- at which point we can establish their relative placement by
+ -- comparing their ultimate slocs. If we reach the root, N1 and N2
+ -- do not descend from the same declarative list (e.g. one is nested
+ -- in the declarative part and the other is in a block in the
+ -- statement part) and the earlier one is already frozen.
+
+ while not Is_List_Member (P1)
+ or else not Is_List_Member (P2)
+ or else List_Containing (P1) /= List_Containing (P2)
+ loop
+ P1 := True_Parent (P1);
+ P2 := True_Parent (P2);
+
+ if Nkind (Parent (P1)) = N_Subunit then
+ P1 := Corresponding_Stub (Parent (P1));
+ end if;
+
+ if Nkind (Parent (P2)) = N_Subunit then
+ P2 := Corresponding_Stub (Parent (P2));
+ end if;
+
+ if P1 = P2 then
+ return False;
+ end if;
+ end loop;
+
+ -- If the sloc positions are different the result is unambiguous. If
+ -- the slocs are identical, one of them must not come from source, which
+ -- is the case for freeze nodes, whose sloc is unrelated to the point
+ -- point at which they are inserted in the tree. The source node is the
+ -- earlier one in the tree.
+
+ if Top_Level_Location (Sloc (P1)) < Top_Level_Location (Sloc (P2)) then
+ return True;
+
+ elsif
+ Top_Level_Location (Sloc (P1)) > Top_Level_Location (Sloc (P2))
+ then
+ return False;
+
+ else
+ return Comes_From_Source (P1);
+ end if;
+ end Earlier;
+
----------------------
-- Find_Actual_Type --
----------------------
Enc_I : Node_Id;
F_Node : Node_Id;
- function Earlier (N1, N2 : Node_Id) return Boolean;
- -- Yields True if N1 and N2 appear in the same compilation unit,
- -- ignoring subunits, and if N1 is to the left of N2 in a left-to-right
- -- traversal of the tree for the unit.
-
function Enclosing_Body (N : Node_Id) return Node_Id;
-- Find innermost package body that encloses the given node, and which
-- is not a compilation unit. Freeze nodes for the instance, or for its
-- Find entity for given package body, and locate or create a freeze
-- node for it.
- function True_Parent (N : Node_Id) return Node_Id;
- -- For a subunit, return parent of corresponding stub
-
- -------------
- -- Earlier --
- -------------
-
- function Earlier (N1, N2 : Node_Id) return Boolean is
- D1 : Integer := 0;
- D2 : Integer := 0;
- P1 : Node_Id := N1;
- P2 : Node_Id := N2;
-
- procedure Find_Depth (P : in out Node_Id; D : in out Integer);
- -- Find distance from given node to enclosing compilation unit
-
- ----------------
- -- Find_Depth --
- ----------------
-
- procedure Find_Depth (P : in out Node_Id; D : in out Integer) is
- begin
- while Present (P)
- and then Nkind (P) /= N_Compilation_Unit
- loop
- P := True_Parent (P);
- D := D + 1;
- end loop;
- end Find_Depth;
-
- -- Start of processing for Earlier
-
- begin
- Find_Depth (P1, D1);
- Find_Depth (P2, D2);
-
- if P1 /= P2 then
- return False;
- else
- P1 := N1;
- P2 := N2;
- end if;
-
- while D1 > D2 loop
- P1 := True_Parent (P1);
- D1 := D1 - 1;
- end loop;
-
- while D2 > D1 loop
- P2 := True_Parent (P2);
- D2 := D2 - 1;
- end loop;
-
- -- At this point P1 and P2 are at the same distance from the root.
- -- We examine their parents until we find a common declarative list,
- -- at which point we can establish their relative placement by
- -- comparing their ultimate slocs. If we reach the root, N1 and N2
- -- do not descend from the same declarative list (e.g. one is nested
- -- in the declarative part and the other is in a block in the
- -- statement part) and the earlier one is already frozen.
-
- while not Is_List_Member (P1)
- or else not Is_List_Member (P2)
- or else List_Containing (P1) /= List_Containing (P2)
- loop
- P1 := True_Parent (P1);
- P2 := True_Parent (P2);
-
- if Nkind (Parent (P1)) = N_Subunit then
- P1 := Corresponding_Stub (Parent (P1));
- end if;
-
- if Nkind (Parent (P2)) = N_Subunit then
- P2 := Corresponding_Stub (Parent (P2));
- end if;
-
- if P1 = P2 then
- return False;
- end if;
- end loop;
-
- return
- Top_Level_Location (Sloc (P1)) < Top_Level_Location (Sloc (P2));
- end Earlier;
-
--------------------
-- Enclosing_Body --
--------------------
return Freeze_Node (Id);
end Package_Freeze_Node;
- -----------------
- -- True_Parent --
- -----------------
-
- function True_Parent (N : Node_Id) return Node_Id is
- begin
- if Nkind (Parent (N)) = N_Subunit then
- return Parent (Corresponding_Stub (Parent (N)));
- else
- return Parent (N);
- end if;
- end True_Parent;
-
-- Start of processing of Freeze_Subprogram_Body
begin
elsif Nkind_In (Nod, N_Subprogram_Body,
N_Package_Body,
+ N_Package_Declaration,
N_Task_Body,
N_Protected_Body,
N_Block_Statement)
Decls : List_Id;
Par_N : Node_Id;
+ function Previous_Instance (Gen : Entity_Id) return Entity_Id;
+ -- Find the local instance, if any, that declares the generic that is
+ -- being instantiated. If present, the freeze node for this instance
+ -- must follow the freeze node for the previous instance.
+
+ -----------------------
+ -- Previous_Instance --
+ -----------------------
+
+ function Previous_Instance (Gen : Entity_Id) return Entity_Id is
+ S : Entity_Id;
+ begin
+ S := Scope (Gen);
+ while Present (S)
+ and then S /= Standard_Standard
+ loop
+ if Is_Generic_Instance (S)
+ and then In_Same_Source_Unit (S, N)
+ then
+ return S;
+ end if;
+ S := Scope (S);
+ end loop;
+ return Empty;
+ end Previous_Instance;
+
begin
if not Is_List_Member (F_Node) then
Decls := List_Containing (N);
Par_N := Parent (Decls);
Decl := N;
+ -- If this is a package instance, check whether the generic is
+ -- declared in a previous instance and the current instance is
+ -- not within the previous one.
+
+ if Present (Generic_Parent (Parent (Inst)))
+ and then Is_In_Main_Unit (N)
+ then
+ declare
+ Par_I : constant Entity_Id :=
+ Previous_Instance (Generic_Parent (Parent (Inst)));
+ Scop : Entity_Id;
+
+ begin
+ if Present (Par_I)
+ and then Earlier (N, Freeze_Node (Par_I))
+ then
+ Scop := Scope (Inst);
+
+ -- If the current instance is within the one that contains
+ -- the generic, the freeze node for the current one must
+ -- appear in the current declarative part. Ditto, if the
+ -- current instance is within another package instance. In
+ -- both of these cases the freeze node of the previous
+ -- instance is not relevant.
+
+ while Present (Scop)
+ and then Scop /= Standard_Standard
+ loop
+ exit when Scop = Par_I
+ or else Is_Generic_Instance (Scop);
+ Scop := Scope (Scop);
+ end loop;
+
+ -- Previous instance encloses current instance
+
+ if Scop = Par_I then
+ null;
+
+ -- Current instance is within an unrelated instance
+
+ elsif Is_Generic_Instance (Scop) then
+ null;
+
+ else
+ Insert_After (Freeze_Node (Par_I), F_Node);
+ return;
+ end if;
+ end if;
+ end;
+ end if;
+
-- When the instantiation occurs in a package declaration, append the
-- freeze node to the private declarations (if any).
-- adhere to the general rule of a package or subprogram body causing
-- freezing of anything before it in the same declarative region. In
-- this case, the proper freeze point of a package instantiation is
- -- before the first source body which follows. This ensures that
- -- entities coming from the instance are already frozen and usable
- -- in source bodies.
+ -- before the first source body which follows, or before a stub.
+ -- This ensures that entities coming from the instance are already
+ -- frozen and usable in source bodies.
if Nkind (Par_N) /= N_Package_Declaration
and then Ekind (Inst) = E_Package
not In_Same_Source_Unit (Generic_Parent (Parent (Inst)), Inst)
then
while Present (Decl) loop
- if Nkind_In (Decl, N_Package_Body, N_Subprogram_Body)
+ if (Nkind (Decl) in N_Unit_Body
+ or else
+ Nkind (Decl) in N_Body_Stub)
and then Comes_From_Source (Decl)
then
Insert_Before (Decl, F_Node);
-- In a package declaration, or if no previous body, insert at end
-- of list.
+ Set_Sloc (F_Node, Sloc (Last (Decls)));
Insert_After (Last (Decls), F_Node);
end if;
end Insert_Freeze_Node_For_Instance;
end if;
end Install_Parent;
+ -------------------------------
+ -- Install_Hidden_Primitives --
+ -------------------------------
+
+ procedure Install_Hidden_Primitives
+ (Prims_List : in out Elist_Id;
+ Gen_T : Entity_Id;
+ Act_T : Entity_Id)
+ is
+ Elmt : Elmt_Id;
+ List : Elist_Id := No_Elist;
+ Prim_G_Elmt : Elmt_Id;
+ Prim_A_Elmt : Elmt_Id;
+ Prim_G : Node_Id;
+ Prim_A : Node_Id;
+
+ begin
+ -- No action needed in case of serious errors because we cannot trust
+ -- in the order of primitives
+
+ if Serious_Errors_Detected > 0 then
+ return;
+
+ -- No action possible if we don't have available the list of primitive
+ -- operations
+
+ elsif No (Gen_T)
+ or else not Is_Record_Type (Gen_T)
+ or else not Is_Tagged_Type (Gen_T)
+ or else not Is_Record_Type (Act_T)
+ or else not Is_Tagged_Type (Act_T)
+ then
+ return;
+
+ -- There is no need to handle interface types since their primitives
+ -- cannot be hidden
+
+ elsif Is_Interface (Gen_T) then
+ return;
+ end if;
+
+ Prim_G_Elmt := First_Elmt (Primitive_Operations (Gen_T));
+
+ if not Is_Class_Wide_Type (Act_T) then
+ Prim_A_Elmt := First_Elmt (Primitive_Operations (Act_T));
+ else
+ Prim_A_Elmt := First_Elmt (Primitive_Operations (Root_Type (Act_T)));
+ end if;
+
+ loop
+ -- Skip predefined primitives in the generic formal
+
+ while Present (Prim_G_Elmt)
+ and then Is_Predefined_Dispatching_Operation (Node (Prim_G_Elmt))
+ loop
+ Next_Elmt (Prim_G_Elmt);
+ end loop;
+
+ -- Skip predefined primitives in the generic actual
+
+ while Present (Prim_A_Elmt)
+ and then Is_Predefined_Dispatching_Operation (Node (Prim_A_Elmt))
+ loop
+ Next_Elmt (Prim_A_Elmt);
+ end loop;
+
+ exit when No (Prim_G_Elmt) or else No (Prim_A_Elmt);
+
+ Prim_G := Node (Prim_G_Elmt);
+ Prim_A := Node (Prim_A_Elmt);
+
+ -- There is no need to handle interface primitives because their
+ -- primitives are not hidden
+
+ exit when Present (Interface_Alias (Prim_G));
+
+ -- Here we install one hidden primitive
+
+ if Chars (Prim_G) /= Chars (Prim_A)
+ and then Has_Suffix (Prim_A, 'P')
+ and then Remove_Suffix (Prim_A, 'P') = Chars (Prim_G)
+ then
+ Set_Chars (Prim_A, Chars (Prim_G));
+
+ if List = No_Elist then
+ List := New_Elmt_List;
+ end if;
+
+ Append_Elmt (Prim_A, List);
+ end if;
+
+ Next_Elmt (Prim_A_Elmt);
+ Next_Elmt (Prim_G_Elmt);
+ end loop;
+
+ -- Append the elements to the list of temporarily visible primitives
+ -- avoiding duplicates.
+
+ if Present (List) then
+ if No (Prims_List) then
+ Prims_List := New_Elmt_List;
+ end if;
+
+ Elmt := First_Elmt (List);
+ while Present (Elmt) loop
+ Append_Unique_Elmt (Node (Elmt), Prims_List);
+ Next_Elmt (Elmt);
+ end loop;
+ end if;
+ end Install_Hidden_Primitives;
+
+ -------------------------------
+ -- Restore_Hidden_Primitives --
+ -------------------------------
+
+ procedure Restore_Hidden_Primitives (Prims_List : in out Elist_Id) is
+ Prim_Elmt : Elmt_Id;
+ Prim : Node_Id;
+
+ begin
+ if Prims_List /= No_Elist then
+ Prim_Elmt := First_Elmt (Prims_List);
+
+ while Present (Prim_Elmt) loop
+ Prim := Node (Prim_Elmt);
+ Set_Chars (Prim, Add_Suffix (Prim, 'P'));
+
+ Next_Elmt (Prim_Elmt);
+ end loop;
+
+ Prims_List := No_Elist;
+ end if;
+ end Restore_Hidden_Primitives;
+
--------------------------------
-- Instantiate_Formal_Package --
--------------------------------
Par_Ent : Entity_Id := Empty;
Par_Vis : Boolean := False;
+ Vis_Prims_List : Elist_Id := No_Elist;
+ -- List of primitives made temporarily visible in the instantiation
+ -- to match the visibility of the formal type
+
begin
Gen_Body_Id := Corresponding_Body (Gen_Decl);
Set_Corresponding_Spec (Act_Body, Act_Decl_Id);
Check_Generic_Actuals (Act_Decl_Id, False);
+ -- Install primitives hidden at the point of the instantiation but
+ -- visible when processing the generic formals
+
+ declare
+ E : Entity_Id;
+
+ begin
+ E := First_Entity (Act_Decl_Id);
+ while Present (E) loop
+ if Is_Type (E)
+ and then Is_Generic_Actual_Type (E)
+ and then Is_Tagged_Type (E)
+ then
+ Install_Hidden_Primitives
+ (Prims_List => Vis_Prims_List,
+ Gen_T => Generic_Parent_Type (Parent (E)),
+ Act_T => E);
+ end if;
+
+ Next_Entity (E);
+ end loop;
+ end;
+
-- If it is a child unit, make the parent instance (which is an
-- instance of the parent of the generic) visible. The parent
-- instance is the prefix of the name of the generic unit.
Set_Is_Immediately_Visible (Par_Ent, Par_Vis);
end if;
+ Restore_Hidden_Primitives (Vis_Prims_List);
Restore_Private_Views (Act_Decl_Id);
-- Remove the current unit from visibility if this is an instance
procedure Reset_Entity (N : Node_Id) is
procedure Set_Global_Type (N : Node_Id; N2 : Node_Id);
- -- If the type of N2 is global to the generic unit. Save the type in
- -- the generic node.
- -- What does this comment mean???
+ -- If the type of N2 is global to the generic unit, save the type in
+ -- the generic node. Just as we perform name capture for explicit
+ -- references within the generic, we must capture the global types
+ -- of local entities because they may participate in resolution in
+ -- the instance.
function Top_Ancestor (E : Entity_Id) return Entity_Id;
-- Find the ultimate ancestor of the current unit. If it is not a
end loop;
end Switch_View;
+ -----------------
+ -- True_Parent --
+ -----------------
+
+ function True_Parent (N : Node_Id) return Node_Id is
+ begin
+ if Nkind (Parent (N)) = N_Subunit then
+ return Parent (Corresponding_Stub (Parent (N)));
+ else
+ return Parent (N);
+ end if;
+ end True_Parent;
+
-----------------------------
-- Valid_Default_Attribute --
-----------------------------