OSDN Git Service

2011-12-05 Bob Duff <duff@adacore.com>
[pf3gnuchains/gcc-fork.git] / gcc / ada / sem_ch12.adb
index 9da8614..2a431f8 100644 (file)
@@ -29,6 +29,7 @@ with Einfo;    use Einfo;
 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;
@@ -399,6 +400,13 @@ package body Sem_Ch12 is
    --  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;
@@ -443,6 +451,12 @@ package body Sem_Ch12 is
    --  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;
@@ -465,9 +479,11 @@ package body Sem_Ch12 is
       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.
@@ -556,6 +572,18 @@ package body Sem_Ch12 is
    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;
@@ -709,6 +737,9 @@ package body Sem_Ch12 is
    --  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.
@@ -884,7 +915,6 @@ package body Sem_Ch12 is
       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;
@@ -1573,12 +1603,14 @@ package body Sem_Ch12 is
      (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;
@@ -1719,7 +1751,8 @@ package body Sem_Ch12 is
       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);
@@ -1768,7 +1801,7 @@ package body Sem_Ch12 is
       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
@@ -1987,7 +2020,8 @@ package body Sem_Ch12 is
       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.
@@ -2035,6 +2069,10 @@ package body Sem_Ch12 is
       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
@@ -2120,9 +2158,11 @@ package body Sem_Ch12 is
 
                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;
 
@@ -2259,6 +2299,7 @@ package body Sem_Ch12 is
             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;
@@ -2332,6 +2373,7 @@ package body Sem_Ch12 is
       end;
 
       End_Package_Scope (Formal);
+      Restore_Hidden_Primitives (Vis_Prims_List);
 
       if Parent_Installed then
          Remove_Parent;
@@ -2410,9 +2452,9 @@ package body Sem_Ch12 is
    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);
@@ -3127,6 +3169,12 @@ package body Sem_Ch12 is
          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
@@ -3304,9 +3352,11 @@ package body Sem_Ch12 is
 
          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);
@@ -3692,6 +3742,7 @@ package body Sem_Ch12 is
 
          Check_Formal_Packages (Act_Decl_Id);
 
+         Restore_Hidden_Primitives (Vis_Prims_List);
          Restore_Private_Views (Act_Decl_Id);
 
          Inherit_Context (Gen_Decl, N);
@@ -4273,6 +4324,12 @@ package body Sem_Ch12 is
          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
@@ -4372,6 +4429,7 @@ package body Sem_Ch12 is
             Error_Msg_NE
               ("circular Instantiation: & instantiated in &!", N, Gen_Unit);
             Circularity_Detected := True;
+            Restore_Hidden_Primitives (Vis_Prims_List);
             goto Leave;
          end if;
 
@@ -4398,9 +4456,11 @@ package body Sem_Ch12 is
 
          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.
@@ -4550,6 +4610,7 @@ package body Sem_Ch12 is
             Remove_Parent;
          end if;
 
+         Restore_Hidden_Primitives (Vis_Prims_List);
          Restore_Env;
          Env_Installed := False;
          Generic_Renamings.Set_Last (0);
@@ -5015,6 +5076,18 @@ package body Sem_Ch12 is
             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));
@@ -5852,6 +5925,49 @@ package body Sem_Ch12 is
       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 --
    --------------------------
@@ -6669,6 +6785,103 @@ package body Sem_Ch12 is
       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 --
    ----------------------
@@ -6735,11 +6948,6 @@ package body Sem_Ch12 is
       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
@@ -6750,91 +6958,6 @@ package body Sem_Ch12 is
       --  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 --
       --------------------
@@ -6880,19 +7003,6 @@ package body Sem_Ch12 is
          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
@@ -7243,6 +7353,7 @@ package body Sem_Ch12 is
 
          elsif Nkind_In (Nod, N_Subprogram_Body,
                               N_Package_Body,
+                              N_Package_Declaration,
                               N_Task_Body,
                               N_Protected_Body,
                               N_Block_Statement)
@@ -7385,12 +7496,89 @@ package body Sem_Ch12 is
       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).
 
@@ -7407,9 +7595,9 @@ package body Sem_Ch12 is
          --  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
@@ -7418,7 +7606,9 @@ package body Sem_Ch12 is
              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);
@@ -7432,6 +7622,7 @@ package body Sem_Ch12 is
          --  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;
@@ -7889,6 +8080,140 @@ package body Sem_Ch12 is
       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 --
    --------------------------------
@@ -9061,6 +9386,10 @@ package body Sem_Ch12 is
       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);
 
@@ -9130,6 +9459,29 @@ package body Sem_Ch12 is
          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.
@@ -9222,6 +9574,7 @@ package body Sem_Ch12 is
             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
@@ -12042,9 +12395,11 @@ package body Sem_Ch12 is
       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
@@ -12922,6 +13277,19 @@ package body Sem_Ch12 is
       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 --
    -----------------------------