------------------
procedure Mark_Context (Inst_Decl : Node_Id; Gen_Decl : Node_Id) is
- Inst_CU : constant Unit_Number_Type := Get_Code_Unit (Inst_Decl);
+ Loc : constant Source_Ptr := Sloc (Inst_Decl);
+ Inst_CU : constant Unit_Number_Type := Get_Code_Unit (Inst_Decl);
+
+ -- Note that we use Get_Code_Unit to determine the position of the
+ -- instantiation, because it may itself appear within another instance
+ -- and we need to mark the context of the enclosing unit, not that of
+ -- the unit that contains the generic.
+
Gen_CU : constant Unit_Number_Type := Get_Source_Unit (Gen_Decl);
Inst : Entity_Id;
Clause : Node_Id;
+ Scop : Entity_Id;
+
+ procedure Add_Implicit_With (CU : Unit_Number_Type);
+ -- If a generic is instantiated in the direct or indirect context of
+ -- the current unit, but there is no with_clause for it in the current
+ -- context, add a with_clause for it to indicate that the body of the
+ -- generic should be examined before the current unit.
+
+ procedure Add_Implicit_With (CU : Unit_Number_Type) is
+ Withn : constant Node_Id :=
+ Make_With_Clause (Loc,
+ Name => New_Occurrence_Of (Cunit_Entity (CU), Loc));
+ begin
+ Set_Implicit_With (Withn);
+ Set_Library_Unit (Withn, Cunit (CU));
+ Set_Withed_Body (Withn, Cunit (CU));
+ Append (Withn, Context_Items (Cunit (Inst_CU)));
+ end Add_Implicit_With;
begin
- -- Note that we use Get_Code_Unit to determine the position of the
- -- instantiation, because it may itself appear within another instance
- -- and we need to mark the context of the enclosing unit, not that of
- -- the unit that contains the corresponding generic.
+ -- This is only relevant when compiling for CodePeer. In what follows,
+ -- C is the current unit containing the instance body, and G is the
+ -- generic unit in that instance.
+
+ if not CodePeer_Mode then
+ return;
+ end if;
+
+ -- If G is itself declared within an instance, indicate that the generic
+ -- body of that instance is also needed by C. This must be done
+ -- recursively.
+
+ Scop := Scope (Defining_Entity (Gen_Decl));
+
+ while Is_Generic_Instance (Scop)
+ and then Ekind (Scop) = E_Package
+ loop
+ Mark_Context
+ (Inst_Decl,
+ Unit_Declaration_Node (Generic_Parent (Parent (Scop))));
+ Scop := Scope (Scop);
+ end loop;
+
+ -- Add references to other generic units in the context of G, because
+ -- they may be instantiated within G, and their bodies needed by C.
+
+ Clause := First (Context_Items (Cunit (Gen_CU)));
+
+ while Present (Clause) loop
+ if Nkind (Clause) = N_With_Clause
+ and then
+ Nkind (Unit (Library_Unit (Clause)))
+ = N_Generic_Package_Declaration
+ then
+ Add_Implicit_With (Get_Source_Unit (Library_Unit (Clause)));
+ end if;
+
+ Next (Clause);
+ end loop;
+
+ -- Now indicate that the body of G is needed by C
Clause := First (Context_Items (Cunit (Inst_CU)));
while Present (Clause) loop
Next (Clause);
end loop;
- -- If the with-clause for the generic unit was not found, it must
- -- appear in some ancestor of the current unit.
+ -- If the with-clause for G is not in the context of C, it may appear in
+ -- some ancestor of C.
Inst := Cunit_Entity (Inst_CU);
while Is_Child_Unit (Inst) loop
First (Context_Items (Parent (Unit_Declaration_Node (Inst))));
while Present (Clause) loop
if Nkind (Clause) = N_With_Clause
- and then Library_Unit (Clause) = Cunit (Gen_CU)
+ and then Library_Unit (Clause) = Cunit (Gen_CU)
then
Set_Withed_Body (Clause, Cunit (Gen_CU));
return;
Next (Clause);
end loop;
end loop;
+
+ -- If not found, G comes from an instance elsewhere in the context. Make
+ -- the dependence explicit in the context of C.
+
+ Add_Implicit_With (Gen_CU);
end Mark_Context;
---------------------
-- instantiations are available, we must analyze them, to ensure that
-- the public symbols generated are the same when the unit is compiled
-- to generate code, and when it is compiled in the context of a unit
- -- that needs a particular nested instance. This process is applied
- -- to both package and subprogram instances.
+ -- that needs a particular nested instance. This process is applied to
+ -- both package and subprogram instances.
--------------------------------
-- Collect_Previous_Instances --
-- enclosing body. Because the generic body we need may use
-- global entities declared in the enclosing package (including
-- aggregates) it is in general necessary to compile this body
- -- with expansion enabled. The exception is if we are within a
- -- generic package, in which case the usual generic rule
- -- applies.
+ -- with expansion enabled, except if we are within a generic
+ -- package, in which case the usual generic rule applies.
declare
Exp_Status : Boolean := True;