]> gcc.gnu.org Git - gcc.git/blobdiff - gcc/ada/sem_ch10.adb
[Ada] Rename Ada 202* to Ada 2022
[gcc.git] / gcc / ada / sem_ch10.adb
index 180c025dfdbd234f5a496886b6392138ec2cb113..9ec584439b9f4a31fca102175cc2a12d479e20fc 100644 (file)
@@ -6,7 +6,7 @@
 --                                                                          --
 --                                 B o d y                                  --
 --                                                                          --
---          Copyright (C) 1992-2016, Free Software Foundation, Inc.         --
+--          Copyright (C) 1992-2021, Free Software Foundation, Inc.         --
 --                                                                          --
 -- GNAT is free software;  you can  redistribute it  and/or modify it under --
 -- terms of the  GNU General Public License as published  by the Free Soft- --
 --                                                                          --
 ------------------------------------------------------------------------------
 
-with Aspects;   use Aspects;
-with Atree;     use Atree;
-with Contracts; use Contracts;
-with Debug;     use Debug;
-with Einfo;     use Einfo;
-with Errout;    use Errout;
-with Exp_Util;  use Exp_Util;
-with Elists;    use Elists;
-with Fname;     use Fname;
-with Fname.UF;  use Fname.UF;
-with Freeze;    use Freeze;
-with Impunit;   use Impunit;
-with Inline;    use Inline;
-with Lib;       use Lib;
-with Lib.Load;  use Lib.Load;
-with Lib.Xref;  use Lib.Xref;
-with Namet;     use Namet;
-with Nlists;    use Nlists;
-with Nmake;     use Nmake;
-with Opt;       use Opt;
-with Output;    use Output;
-with Par_SCO;   use Par_SCO;
-with Restrict;  use Restrict;
-with Rident;    use Rident;
-with Rtsfind;   use Rtsfind;
-with Sem;       use Sem;
-with Sem_Aux;   use Sem_Aux;
-with Sem_Ch3;   use Sem_Ch3;
-with Sem_Ch6;   use Sem_Ch6;
-with Sem_Ch7;   use Sem_Ch7;
-with Sem_Ch8;   use Sem_Ch8;
-with Sem_Dist;  use Sem_Dist;
-with Sem_Prag;  use Sem_Prag;
-with Sem_Util;  use Sem_Util;
-with Sem_Warn;  use Sem_Warn;
-with Stand;     use Stand;
-with Sinfo;     use Sinfo;
-with Sinfo.CN;  use Sinfo.CN;
-with Sinput;    use Sinput;
-with Snames;    use Snames;
-with Style;     use Style;
-with Stylesw;   use Stylesw;
-with Tbuild;    use Tbuild;
-with Uname;     use Uname;
+with Aspects;        use Aspects;
+with Atree;          use Atree;
+with Contracts;      use Contracts;
+with Debug;          use Debug;
+with Einfo;          use Einfo;
+with Einfo.Entities; use Einfo.Entities;
+with Einfo.Utils;    use Einfo.Utils;
+with Errout;         use Errout;
+with Exp_Put_Image;
+with Exp_Util;       use Exp_Util;
+with Elists;         use Elists;
+with Fname;          use Fname;
+with Fname.UF;       use Fname.UF;
+with Freeze;         use Freeze;
+with Impunit;        use Impunit;
+with Inline;         use Inline;
+with Lib;            use Lib;
+with Lib.Load;       use Lib.Load;
+with Lib.Xref;       use Lib.Xref;
+with Namet;          use Namet;
+with Nlists;         use Nlists;
+with Nmake;          use Nmake;
+with Opt;            use Opt;
+with Output;         use Output;
+with Par_SCO;        use Par_SCO;
+with Restrict;       use Restrict;
+with Rident;         use Rident;
+with Rtsfind;        use Rtsfind;
+with Sem;            use Sem;
+with Sem_Aux;        use Sem_Aux;
+with Sem_Ch3;        use Sem_Ch3;
+with Sem_Ch6;        use Sem_Ch6;
+with Sem_Ch7;        use Sem_Ch7;
+with Sem_Ch8;        use Sem_Ch8;
+with Sem_Ch13;       use Sem_Ch13;
+with Sem_Dist;       use Sem_Dist;
+with Sem_Prag;       use Sem_Prag;
+with Sem_Util;       use Sem_Util;
+with Sem_Warn;       use Sem_Warn;
+with Stand;          use Stand;
+with Sinfo;          use Sinfo;
+with Sinfo.Nodes;    use Sinfo.Nodes;
+with Sinfo.Utils;    use Sinfo.Utils;
+with Sinfo.CN;       use Sinfo.CN;
+with Sinput;         use Sinput;
+with Snames;         use Snames;
+with Style;          use Style;
+with Stylesw;        use Stylesw;
+with Tbuild;         use Tbuild;
+with Uname;          use Uname;
 
 package body Sem_Ch10 is
 
@@ -137,28 +143,25 @@ package body Sem_Ch10 is
    --  Check that the shadow entity is not already in the homonym chain, for
    --  example through a limited_with clause in a parent unit.
 
-   procedure Install_Context_Clauses (N : Node_Id);
+   procedure Install_Context_Clauses (N : Node_Id; Chain : Boolean := True);
    --  Subsidiary to Install_Context and Install_Parents. Process all with
-   --  and use clauses for current unit and its library unit if any.
+   --  and use clauses for current unit and its library unit if any. The flag
+   --  Chain is used to control the "chaining" or linking together of use-type
+   --  and use-package clauses to avoid circularities with reinstalling
+   --  clauses.
 
    procedure Install_Limited_Context_Clauses (N : Node_Id);
    --  Subsidiary to Install_Context. Process only limited with_clauses for
    --  current unit. Implements Ada 2005 (AI-50217).
 
-   procedure Install_Limited_Withed_Unit (N : Node_Id);
+   procedure Install_Limited_With_Clause (N : Node_Id);
    --  Place shadow entities for a limited_with package in the visibility
    --  structures for the current compilation. Implements Ada 2005 (AI-50217).
 
-   procedure Install_Withed_Unit
-     (With_Clause     : Node_Id;
-      Private_With_OK : Boolean := False);
-   --  If the unit is not a child unit, make unit immediately visible. The
-   --  caller ensures that the unit is not already currently installed. The
-   --  flag Private_With_OK is set true in Install_Private_With_Clauses, which
-   --  is called when compiling the private part of a package, or installing
-   --  the private declarations of a parent unit.
-
-   procedure Install_Parents (Lib_Unit : Node_Id; Is_Private : Boolean);
+   procedure Install_Parents
+     (Lib_Unit   : Node_Id;
+      Is_Private : Boolean;
+      Chain      : Boolean := True);
    --  This procedure establishes the context for the compilation of a child
    --  unit. If Lib_Unit is a child library spec then the context of the parent
    --  is installed, and the parent itself made immediately visible, so that
@@ -167,7 +170,9 @@ package body Sem_Ch10 is
    --  parents are loaded in the nested case. If Lib_Unit is a library body,
    --  the only effect of Install_Parents is to install the private decls of
    --  the parents, because the visible parent declarations will have been
-   --  installed as part of the context of the corresponding spec.
+   --  installed as part of the context of the corresponding spec. The flag
+   --  Chain is used to control the "chaining" or linking of use-type and
+   --  use-package clauses to avoid circularities when installing context.
 
    procedure Install_Siblings (U_Name : Entity_Id; N : Node_Id);
    --  In the compilation of a child unit, a child of any of the  ancestor
@@ -175,6 +180,15 @@ package body Sem_Ch10 is
    --  an enclosing scope. Iterate over context to find child units of U_Name
    --  or of some ancestor of it.
 
+   procedure Install_With_Clause
+     (With_Clause     : Node_Id;
+      Private_With_OK : Boolean := False);
+   --  If the unit is not a child unit, make unit immediately visible. The
+   --  caller ensures that the unit is not already currently installed. The
+   --  flag Private_With_OK is set true in Install_Private_With_Clauses, which
+   --  is called when compiling the private part of a package, or installing
+   --  the private declarations of a parent unit.
+
    function Is_Ancestor_Unit (U1 : Node_Id; U2 : Node_Id) return Boolean;
    --  When compiling a unit Q descended from some parent unit P, a limited
    --  with_clause in the context of P that names some other ancestor of Q
@@ -194,8 +208,15 @@ package body Sem_Ch10 is
    --  Subsidiary of previous one. Remove use_ and with_clauses
 
    procedure Remove_Limited_With_Clause (N : Node_Id);
-   --  Remove from visibility the shadow entities introduced for a package
-   --  mentioned in a limited_with clause. Implements Ada 2005 (AI-50217).
+   --  Remove the shadow entities from visibility introduced for a package
+   --  mentioned in limited with clause N. Implements Ada 2005 (AI-50217).
+
+   procedure Remove_Limited_With_Unit
+     (Pack_Decl  : Node_Id;
+      Lim_Clause : Node_Id := Empty);
+   --  Remove the shadow entities from visibility introduced for a package
+   --  denoted by declaration Pack_Decl. Lim_Clause is the related limited
+   --  with clause, if any. Implements Ada 2005 (AI-50217).
 
    procedure Remove_Parents (Lib_Unit : Node_Id);
    --  Remove_Parents checks if Lib_Unit is a child spec. If so then the parent
@@ -238,7 +259,7 @@ package body Sem_Ch10 is
    --  of the package. Links between corresponding entities in both chains
    --  allow the compiler to select the proper view of a given type, depending
    --  on the context. Note that in contrast with the handling of private
-   --  types, the limited view and the non-limited view of a type are treated
+   --  types, the limited view and the nonlimited view of a type are treated
    --  as separate entities, and no entity exchange needs to take place, which
    --  makes the implementation much simpler than could be feared.
 
@@ -304,7 +325,6 @@ package body Sem_Ch10 is
             Nam_Ent   : constant Entity_Id := Entity (Name (Clause));
             Cont_Item : Node_Id;
             Prag_Unit : Node_Id;
-            Subt_Mark : Node_Id;
             Use_Item  : Node_Id;
 
             function Same_Unit (N : Node_Id; P : Entity_Id) return Boolean;
@@ -341,60 +361,64 @@ package body Sem_Ch10 is
                then
                   --  Search through use clauses
 
-                  Use_Item := First (Names (Cont_Item));
-                  while Present (Use_Item) and then not Used loop
+                  Use_Item := Name (Cont_Item);
 
-                     --  Case of a direct use of the one we are looking for
+                  --  Case of a direct use of the one we are looking for
 
-                     if Entity (Use_Item) = Nam_Ent then
-                        Used := True;
+                  if Entity (Use_Item) = Nam_Ent then
+                     Used := True;
 
-                     --  Handle nested case, as in "with P; use P.Q.R"
+                  --  Handle nested case, as in "with P; use P.Q.R"
 
-                     else
-                        declare
-                           UE : Node_Id;
-
-                        begin
-                           --  Loop through prefixes looking for match
+                  else
+                     declare
+                        UE : Node_Id;
 
-                           UE := Use_Item;
-                           while Nkind (UE) = N_Expanded_Name loop
-                              if Same_Unit (Prefix (UE), Nam_Ent) then
-                                 Used := True;
-                                 exit;
-                              end if;
+                     begin
+                        --  Loop through prefixes looking for match
 
-                              UE := Prefix (UE);
-                           end loop;
-                        end;
-                     end if;
+                        UE := Use_Item;
+                        while Nkind (UE) = N_Expanded_Name loop
+                           if Same_Unit (Prefix (UE), Nam_Ent) then
+                              Used := True;
+                              exit;
+                           end if;
 
-                     Next (Use_Item);
-                  end loop;
+                           UE := Prefix (UE);
+                        end loop;
+                     end;
+                  end if;
 
                --  USE TYPE clause
 
                elsif Nkind (Cont_Item) = N_Use_Type_Clause
                  and then not Used_Type_Or_Elab
                then
-                  Subt_Mark := First (Subtype_Marks (Cont_Item));
-                  while Present (Subt_Mark)
-                    and then not Used_Type_Or_Elab
-                  loop
-                     if Same_Unit (Prefix (Subt_Mark), Nam_Ent) then
-                        Used_Type_Or_Elab := True;
-                     end if;
+                  declare
+                     UE : Node_Id;
 
-                     Next (Subt_Mark);
-                  end loop;
+                  begin
+                     --  Loop through prefixes looking for a match
+
+                     UE := Prefix (Subtype_Mark (Cont_Item));
+                     loop
+                        if not Used_Type_Or_Elab
+                          and then Same_Unit (UE, Nam_Ent)
+                        then
+                           Used_Type_Or_Elab := True;
+                        end if;
+
+                        exit when Nkind (UE) /= N_Expanded_Name;
+                        UE := Prefix (UE);
+                     end loop;
+                  end;
 
                --  Pragma Elaborate or Elaborate_All
 
                elsif Nkind (Cont_Item) = N_Pragma
                  and then
-                   Nam_In (Pragma_Name_Unmapped (Cont_Item),
-                           Name_Elaborate, Name_Elaborate_All)
+                   Pragma_Name_Unmapped (Cont_Item)
+                     in Name_Elaborate | Name_Elaborate_All
                  and then not Used_Type_Or_Elab
                then
                   Prag_Unit :=
@@ -425,7 +449,6 @@ package body Sem_Ch10 is
          is
             Nam_Ent   : constant Entity_Id := Entity (Name (Clause));
             Cont_Item : Node_Id;
-            Use_Item  : Node_Id;
 
          begin
             Used := False;
@@ -449,14 +472,9 @@ package body Sem_Ch10 is
                if Nkind (Cont_Item) = N_Use_Package_Clause
                  and then not Used
                then
-                  Use_Item := First (Names (Cont_Item));
-                  while Present (Use_Item) and then not Used loop
-                     if Entity (Use_Item) = Nam_Ent then
-                        Used := True;
-                     end if;
-
-                     Next (Use_Item);
-                  end loop;
+                  if Entity (Name (Cont_Item)) = Nam_Ent then
+                     Used := True;
+                  end if;
 
                --  Package with clause. Avoid processing self, implicitly
                --  generated with clauses or limited with clauses. Note that
@@ -477,8 +495,8 @@ package body Sem_Ch10 is
                --  visibility analysis, but is also not redundant.
 
                elsif Nkind (Cont_Item) = N_With_Clause
-                 and then not Implicit_With (Cont_Item)
                  and then Comes_From_Source (Cont_Item)
+                 and then not Implicit_With (Cont_Item)
                  and then not Limited_Present (Cont_Item)
                  and then Cont_Item /= Clause
                  and then Entity (Name (Cont_Item)) = Nam_Ent
@@ -522,16 +540,16 @@ package body Sem_Ch10 is
 
                   begin
                      Process_Spec_Clauses
-                      (Context_List => Spec_Context_Items,
-                       Clause       => Clause,
-                       Used         => Used_In_Spec,
-                       Withed       => Withed_In_Spec);
+                       (Context_List => Spec_Context_Items,
+                        Clause       => Clause,
+                        Used         => Used_In_Spec,
+                        Withed       => Withed_In_Spec);
 
                      Process_Body_Clauses
-                      (Context_List      => Context_Items,
-                       Clause            => Clause,
-                       Used              => Used_In_Body,
-                       Used_Type_Or_Elab => Used_Type_Or_Elab);
+                       (Context_List      => Context_Items,
+                        Clause            => Clause,
+                        Used              => Used_In_Body,
+                        Used_Type_Or_Elab => Used_Type_Or_Elab);
 
                      --  "Type Elab" refers to the presence of either a use
                      --  type clause, pragmas Elaborate or Elaborate_All.
@@ -560,29 +578,29 @@ package body Sem_Ch10 is
                           ("redundant with clause in body?r?", Clause);
                      end if;
 
-                     Used_In_Body := False;
-                     Used_In_Spec := False;
+                     Used_In_Body      := False;
+                     Used_In_Spec      := False;
                      Used_Type_Or_Elab := False;
-                     Withed_In_Spec := False;
+                     Withed_In_Spec    := False;
                   end;
 
                --  Standalone package spec or body check
 
                else
                   declare
-                     Dont_Care : Boolean := False;
-                     Withed    : Boolean := False;
+                     Dummy  : Boolean := False;
+                     Withed : Boolean := False;
 
                   begin
                      --  The mechanism for examining the context clauses of a
                      --  package spec can be applied to package body clauses.
 
                      Process_Spec_Clauses
-                      (Context_List => Context_Items,
-                       Clause       => Clause,
-                       Used         => Dont_Care,
-                       Withed       => Withed,
-                       Exit_On_Self => True);
+                       (Context_List => Context_Items,
+                        Clause       => Clause,
+                        Used         => Dummy,
+                        Withed       => Withed,
+                        Exit_On_Self => True);
 
                      if Withed then
                         Error_Msg_N -- CODEFIX
@@ -608,6 +626,8 @@ package body Sem_Ch10 is
    --  Start of processing for Analyze_Compilation_Unit
 
    begin
+      Exp_Put_Image.Preload_Sink (N);
+
       Process_Compilation_Unit_Pragmas (N);
 
       --  If the unit is a subunit whose parent has not been analyzed (which
@@ -647,9 +667,7 @@ package body Sem_Ch10 is
             Circularity : Boolean := True;
 
          begin
-            if Is_Predefined_File_Name
-                 (Unit_File_Name (Get_Source_Unit (Unit (N))))
-            then
+            if In_Predefined_Unit (N) then
                Circularity := False;
 
             else
@@ -710,8 +728,8 @@ package body Sem_Ch10 is
 
             --  Verify that the library unit is a package declaration
 
-            if not Nkind_In (Unit (Lib_Unit), N_Package_Declaration,
-                                              N_Generic_Package_Declaration)
+            if Nkind (Unit (Lib_Unit)) not in
+                 N_Package_Declaration | N_Generic_Package_Declaration
             then
                Error_Msg_N
                  ("no legal package declaration for package body", N);
@@ -754,7 +772,7 @@ package body Sem_Ch10 is
             Unum := Get_Cunit_Unit_Number (N);
             Par_Spec_Name := Get_Parent_Spec_Name (Unit_Name (Unum));
 
-            if Par_Spec_Name /= No_Unit_Name then
+            if Present (Par_Spec_Name) then
                Unum :=
                  Load_Unit
                    (Load_Name  => Par_Spec_Name,
@@ -814,6 +832,7 @@ package body Sem_Ch10 is
                      --  of the child unit does not act as spec any longer.
 
                      Set_Acts_As_Spec (N, False);
+                     Move_Aspects (From => Unit_Node, To => Unit (Lib_Unit));
                      Set_Is_Child_Unit (Defining_Entity (Unit_Node));
                      Set_Debug_Info_Needed (Defining_Entity (Unit (Lib_Unit)));
                      Set_Comes_From_Source_Default (SCS);
@@ -918,13 +937,9 @@ package body Sem_Ch10 is
 
       --  Register predefined units in Rtsfind
 
-      declare
-         Unum : constant Unit_Number_Type := Get_Source_Unit (Sloc (N));
-      begin
-         if Is_Predefined_File_Name (Unit_File_Name (Unum)) then
-            Set_RTU_Loaded (Unit_Node);
-         end if;
-      end;
+      if In_Predefined_Unit (N) then
+         Set_RTU_Loaded (Unit_Node);
+      end if;
 
       --  Treat compilation unit pragmas that appear after the library unit
 
@@ -942,8 +957,8 @@ package body Sem_Ch10 is
       --  Analyze the contract of a [generic] subprogram that acts as a
       --  compilation unit after all compilation pragmas have been analyzed.
 
-      if Nkind_In (Unit_Node, N_Generic_Subprogram_Declaration,
-                              N_Subprogram_Declaration)
+      if Nkind (Unit_Node) in
+           N_Generic_Subprogram_Declaration | N_Subprogram_Declaration
       then
          Analyze_Entry_Or_Subprogram_Contract (Defining_Entity (Unit_Node));
       end if;
@@ -988,10 +1003,10 @@ package body Sem_Ch10 is
       --  next compilation, which is either the main unit or some other unit
       --  in the context.
 
-      if Nkind_In (Unit_Node, N_Package_Declaration,
-                              N_Package_Renaming_Declaration,
-                              N_Subprogram_Declaration)
-        or else Nkind (Unit_Node) in N_Generic_Declaration
+      if Nkind (Unit_Node) in N_Package_Declaration
+                            | N_Package_Renaming_Declaration
+                            | N_Subprogram_Declaration
+                            | N_Generic_Declaration
         or else (Nkind (Unit_Node) = N_Subprogram_Body
                   and then Acts_As_Spec (Unit_Node))
       then
@@ -1069,7 +1084,7 @@ package body Sem_Ch10 is
                if Nkind (Item) = N_With_Clause
                  and then not Implicit_With (Item)
 
-                  --  Ada 2005 (AI-50217): Ignore limited-withed units
+                 --  Ada 2005 (AI-50217): Ignore limited-withed units
 
                  and then not Limited_Present (Item)
                then
@@ -1132,6 +1147,47 @@ package body Sem_Ch10 is
 
             Style_Check := Save_Style_Check;
          end;
+
+         --  In GNATprove mode, force the loading of an Interrupt_Priority when
+         --  processing compilation units with potentially "main" subprograms.
+         --  This is required for the ceiling priority protocol checks, which
+         --  are triggered by these subprograms.
+
+         if GNATprove_Mode
+           and then Nkind (Unit_Node) in N_Function_Instantiation
+                                       | N_Procedure_Instantiation
+                                       | N_Subprogram_Body
+         then
+            declare
+               Spec : Node_Id;
+
+            begin
+               case Nkind (Unit_Node) is
+                  when N_Subprogram_Body =>
+                     Spec := Specification (Unit_Node);
+
+                  when N_Subprogram_Instantiation =>
+                     Spec :=
+                       Subprogram_Specification (Entity (Name (Unit_Node)));
+
+                  when others =>
+                     raise Program_Error;
+               end case;
+
+               pragma Assert (Nkind (Spec) in N_Subprogram_Specification);
+
+               --  Main subprogram must have no parameters, and if it is a
+               --  function, it must return an integer.
+
+               if No (Parameter_Specifications (Spec))
+                 and then (Nkind (Spec) = N_Procedure_Specification
+                             or else
+                           Is_Integer_Type (Etype (Result_Definition (Spec))))
+               then
+                  SPARK_Implicit_Load (RE_Interrupt_Priority);
+               end if;
+            end;
+         end if;
       end if;
 
       --  Deal with creating elaboration counter if needed. We create an
@@ -1139,10 +1195,10 @@ package body Sem_Ch10 is
       --  units manufactured by the compiler never need elab checks.
 
       if Comes_From_Source (N)
-        and then Nkind_In (Unit_Node, N_Package_Declaration,
-                                      N_Generic_Package_Declaration,
-                                      N_Subprogram_Declaration,
-                                      N_Generic_Subprogram_Declaration)
+        and then Nkind (Unit_Node) in N_Package_Declaration
+                                    | N_Generic_Package_Declaration
+                                    | N_Subprogram_Declaration
+                                    | N_Generic_Subprogram_Declaration
       then
          declare
             Loc  : constant Source_Ptr       := Sloc (N);
@@ -1162,43 +1218,47 @@ package body Sem_Ch10 is
             --  where the elaboration routine might otherwise be called more
             --  than once.
 
-            --  Case of units which do not require elaboration checks
+            --  They are also needed to ensure explicit visibility from the
+            --  binder generated code of all the units involved in a partition
+            --  when control-flow preservation is requested.
 
-            if
-              --  Pure units do not need checks
+            if not Opt.Suppress_Control_Flow_Optimizations
+              and then
+              ( --  Pure units do not need checks
 
-              Is_Pure (Spec_Id)
+                Is_Pure (Spec_Id)
 
-              --  Preelaborated units do not need checks
+                --  Preelaborated units do not need checks
 
-              or else Is_Preelaborated (Spec_Id)
+                or else Is_Preelaborated (Spec_Id)
 
-              --  No checks needed if pragma Elaborate_Body present
+                --  No checks needed if pragma Elaborate_Body present
 
-              or else Has_Pragma_Elaborate_Body (Spec_Id)
+                or else Has_Pragma_Elaborate_Body (Spec_Id)
 
-              --  No checks needed if unit does not require a body
+                --  No checks needed if unit does not require a body
 
-              or else not Unit_Requires_Body (Spec_Id)
+                or else not Unit_Requires_Body (Spec_Id)
 
-              --  No checks needed for predefined files
+                --  No checks needed for predefined files
 
-              or else Is_Predefined_File_Name (Unit_File_Name (Unum))
+                or else Is_Predefined_Unit (Unum)
 
-              --  No checks required if no separate spec
+                --  No checks required if no separate spec
 
-              or else Acts_As_Spec (N)
+                or else Acts_As_Spec (N)
+              )
             then
-               --  This is a case where we only need the entity for
-               --  checking to prevent multiple elaboration checks.
+               --  This is a case where we only need the entity for checking to
+               --  prevent multiple elaboration checks.
 
                Set_Elaboration_Entity_Required (Spec_Id, False);
 
-            --  Case of elaboration entity is required for access before
-            --  elaboration checking (so certainly we must build it).
+            --  Otherwise the unit requires an elaboration entity because it
+            --  carries a body.
 
             else
-               Set_Elaboration_Entity_Required (Spec_Id, True);
+               Set_Elaboration_Entity_Required (Spec_Id);
             end if;
 
             Build_Elaboration_Entity (N, Spec_Id);
@@ -1350,7 +1410,7 @@ package body Sem_Ch10 is
 
       --  Loop through actual context items. This is done in two passes:
 
-      --  a) The first pass analyzes non-limited with-clauses and also any
+      --  a) The first pass analyzes nonlimited with clauses and also any
       --     configuration pragmas (we need to get the latter analyzed right
       --     away, since they can affect processing of subsequent items).
 
@@ -1423,10 +1483,10 @@ package body Sem_Ch10 is
                --  Verify that the illegal contexts given in 10.1.2 (18/2) are
                --  properly rejected, including renaming declarations.
 
-               if not Nkind_In (Ukind, N_Package_Declaration,
-                                       N_Subprogram_Declaration)
-                 and then Ukind not in N_Generic_Declaration
-                 and then Ukind not in N_Generic_Instantiation
+               if Ukind not in N_Package_Declaration
+                             | N_Subprogram_Declaration
+                             | N_Generic_Declaration
+                             | N_Generic_Instantiation
                then
                   Error_Msg_N ("limited with_clause not allowed here", Item);
 
@@ -1451,8 +1511,9 @@ package body Sem_Ch10 is
                      P := Parent_Spec (Unit (N));
                      loop
                         if Unit (P) = Lib_U then
-                           Error_Msg_N ("limited with_clause cannot "
-                                        & "name ancestor", Item);
+                           Error_Msg_N
+                             ("limited with_clause cannot name ancestor",
+                              Item);
                            exit;
                         end if;
 
@@ -1480,10 +1541,9 @@ package body Sem_Ch10 is
                         if Item /= It
                           and then Nkind (It) = N_With_Clause
                           and then not Limited_Present (It)
-                          and then
-                            Nkind_In (Unit (Library_Unit (It)),
-                                      N_Package_Declaration,
-                                      N_Package_Renaming_Declaration)
+                          and then Nkind (Unit (Library_Unit (It))) in
+                                     N_Package_Declaration |
+                                     N_Package_Renaming_Declaration
                         then
                            if Nkind (Unit (Library_Unit (It))) =
                                                       N_Package_Declaration
@@ -1503,13 +1563,11 @@ package body Sem_Ch10 is
                               then
                                  Error_Msg_Sloc := Sloc (It);
                                  Error_Msg_N
-                                   ("simultaneous visibility of limited "
-                                    & "and unlimited views not allowed",
-                                    Item);
-                                 Error_Msg_NE
-                                   ("\unlimited view visible through "
-                                    & "context clause #",
-                                    Item, It);
+                                   ("simultaneous visibility of limited and "
+                                    & "unlimited views not allowed", Item);
+                                 Error_Msg_N
+                                   ("\unlimited view visible through context "
+                                    & "clause #", Item);
                                  exit;
 
                               elsif Nkind (Unit_Name) = N_Identifier then
@@ -1536,15 +1594,15 @@ package body Sem_Ch10 is
                Analyze (Item);
             end if;
 
-            --  A limited_with does not impose an elaboration order, but
-            --  there is a semantic dependency for recompilation purposes.
+            --  A limited_with does not impose an elaboration order, but there
+            --  is a semantic dependency for recompilation purposes.
 
             if not Implicit_With (Item) then
                Version_Update (N, Library_Unit (Item));
             end if;
 
-            --  Pragmas and use clauses and with clauses other than limited
-            --  with's are ignored in this pass through the context items.
+         --  Pragmas and use clauses and with clauses other than limited with's
+         --  are ignored in this pass through the context items.
 
          else
             null;
@@ -1559,7 +1617,7 @@ package body Sem_Ch10 is
    -------------------------------
 
    procedure Analyze_Package_Body_Stub (N : Node_Id) is
-      Id   : constant Entity_Id := Defining_Identifier (N);
+      Id   : constant Entity_Id := Defining_Entity (N);
       Nam  : Entity_Id;
       Opts : Config_Switches_Type;
 
@@ -1581,21 +1639,27 @@ package body Sem_Ch10 is
          --  Retain and restore the configuration options of the enclosing
          --  context as the proper body may introduce a set of its own.
 
-         Save_Opt_Config_Switches (Opts);
+         Opts := Save_Config_Switches;
 
          --  Indicate that the body of the package exists. If we are doing
          --  only semantic analysis, the stub stands for the body. If we are
          --  generating code, the existence of the body will be confirmed
          --  when we load the proper body.
 
+         Set_Scope (Id, Current_Scope);
+         Mutate_Ekind (Id, E_Package_Body);
+         Set_Etype (Id, Standard_Void_Type);
+
+         if Has_Aspects (N) then
+            Analyze_Aspect_Specifications (N, Id);
+         end if;
+
          Set_Has_Completion (Nam);
-         Set_Scope (Defining_Entity (N), Current_Scope);
-         Set_Ekind (Defining_Entity (N), E_Package_Body);
          Set_Corresponding_Spec_Of_Stub (N, Nam);
          Generate_Reference (Nam, Id, 'b');
          Analyze_Proper_Body (N, Nam);
 
-         Restore_Opt_Config_Switches (Opts);
+         Restore_Config_Switches (Opts);
       end if;
    end Analyze_Package_Body_Stub;
 
@@ -1609,9 +1673,9 @@ package body Sem_Ch10 is
       procedure Optional_Subunit;
       --  This procedure is called when the main unit is a stub, or when we
       --  are not generating code. In such a case, we analyze the subunit if
-      --  present, which is user-friendly and in fact required for ASIS, but we
-      --  don't complain if the subunit is missing. In GNATprove_Mode, we issue
-      --  an error to avoid formal verification of a partial unit.
+      --  present, which is user-friendly, but we don't complain if the subunit
+      --  is missing. In GNATprove_Mode, we issue an error to avoid formal
+      --  verification of a partial unit.
 
       ----------------------
       -- Optional_Subunit --
@@ -1627,7 +1691,7 @@ package body Sem_Ch10 is
          --  ignore all errors. Note that Fatal_Error will still be set, so we
          --  will be able to check for this case below.
 
-         if not (ASIS_Mode or GNATprove_Mode) then
+         if not GNATprove_Mode then
             Ignore_Errors_Enable := Ignore_Errors_Enable + 1;
          end if;
 
@@ -1638,7 +1702,7 @@ package body Sem_Ch10 is
               Subunit    => True,
               Error_Node => N);
 
-         if not (ASIS_Mode or GNATprove_Mode) then
+         if not GNATprove_Mode then
             Ignore_Errors_Enable := Ignore_Errors_Enable - 1;
          end if;
 
@@ -1706,7 +1770,7 @@ package body Sem_Ch10 is
             --  body may not be available, in which case do not try analysis.
 
             if Serious_Errors_Detected > 0
-              and then  No (Library_Unit (Library_Unit (N)))
+              and then No (Library_Unit (Library_Unit (N)))
             then
                return;
             end if;
@@ -1762,27 +1826,13 @@ package body Sem_Ch10 is
 
       --  If the main unit is a subunit, then we are just performing semantic
       --  analysis on that subunit, and any other subunits of any parent unit
-      --  should be ignored, except that if we are building trees for ASIS
-      --  usage we want to annotate the stub properly. If the main unit is
-      --  itself a subunit, another subunit is irrelevant unless it is a
-      --  subunit of the current one, that is to say appears in the current
-      --  source tree.
+      --  should be ignored. If the main unit is itself a subunit, another
+      --  subunit is irrelevant unless it is a subunit of the current one, that
+      --  is to say appears in the current source tree.
 
       elsif Nkind (Unit (Cunit (Main_Unit))) = N_Subunit
         and then Subunit_Name /= Unit_Name (Main_Unit)
       then
-         if ASIS_Mode then
-            declare
-               PB : constant Node_Id := Proper_Body (Unit (Cunit (Main_Unit)));
-            begin
-               if Nkind_In (PB, N_Package_Body, N_Subprogram_Body)
-                 and then List_Containing (N) = Declarations (PB)
-               then
-                  Optional_Subunit;
-               end if;
-            end;
-         end if;
-
          --  But before we return, set the flag for unloaded subunits. This
          --  will suppress junk warnings of variables in the same declarative
          --  part (or a higher level one) that are in danger of looking unused
@@ -1916,7 +1966,9 @@ package body Sem_Ch10 is
    ----------------------------------
 
    procedure Analyze_Protected_Body_Stub (N : Node_Id) is
-      Nam : Entity_Id := Current_Entity_In_Scope (Defining_Identifier (N));
+      Id   : constant Entity_Id := Defining_Entity (N);
+      Nam  : Entity_Id          := Current_Entity_In_Scope (Id);
+      Opts : Config_Switches_Type;
 
    begin
       Check_Stub_Level (N);
@@ -1931,12 +1983,25 @@ package body Sem_Ch10 is
          Error_Msg_N ("missing specification for Protected body", N);
 
       else
-         Set_Scope (Defining_Entity (N), Current_Scope);
-         Set_Ekind (Defining_Entity (N), E_Protected_Body);
+         --  Retain and restore the configuration options of the enclosing
+         --  context as the proper body may introduce a set of its own.
+
+         Opts := Save_Config_Switches;
+
+         Set_Scope (Id, Current_Scope);
+         Mutate_Ekind (Id, E_Protected_Body);
+         Set_Etype (Id, Standard_Void_Type);
+
+         if Has_Aspects (N) then
+            Analyze_Aspect_Specifications (N, Id);
+         end if;
+
          Set_Has_Completion (Etype (Nam));
          Set_Corresponding_Spec_Of_Stub (N, Nam);
-         Generate_Reference (Nam, Defining_Identifier (N), 'b');
+         Generate_Reference (Nam, Id, 'b');
          Analyze_Proper_Body (N, Etype (Nam));
+
+         Restore_Config_Switches (Opts);
       end if;
    end Analyze_Protected_Body_Stub;
 
@@ -1961,9 +2026,8 @@ package body Sem_Ch10 is
       --  Verify that the identifier for the stub is unique within this
       --  declarative part.
 
-      if Nkind_In (Parent (N), N_Block_Statement,
-                               N_Package_Body,
-                               N_Subprogram_Body)
+      if Nkind (Parent (N)) in
+           N_Block_Statement | N_Package_Body | N_Subprogram_Body
       then
          Decl := First (Declarations (Parent (N)));
          while Present (Decl) and then Decl /= N loop
@@ -1981,7 +2045,7 @@ package body Sem_Ch10 is
       --  Retain and restore the configuration options of the enclosing context
       --  as the proper body may introduce a set of its own.
 
-      Save_Opt_Config_Switches (Opts);
+      Opts := Save_Config_Switches;
 
       --  Treat stub as a body, which checks conformance if there is a previous
       --  declaration, or else introduces entity and its signature.
@@ -1989,7 +2053,7 @@ package body Sem_Ch10 is
       Analyze_Subprogram_Body (N);
       Analyze_Proper_Body (N, Empty);
 
-      Restore_Opt_Config_Switches (Opts);
+      Restore_Config_Switches (Opts);
    end Analyze_Subprogram_Body_Stub;
 
    ---------------------
@@ -2010,6 +2074,10 @@ package body Sem_Ch10 is
    --  context before analyzing the proper body itself. On exit, we remove only
    --  the explicit context of the subunit.
 
+   --  WARNING: This routine manages SPARK regions. Return statements must be
+   --  replaced by gotos which jump to the end of the routine and restore the
+   --  SPARK mode.
+
    procedure Analyze_Subunit (N : Node_Id) is
       Lib_Unit : constant Node_Id   := Library_Unit (N);
       Par_Unit : constant Entity_Id := Current_Scope;
@@ -2057,7 +2125,6 @@ package body Sem_Ch10 is
 
       procedure Analyze_Subunit_Context is
          Item      :  Node_Id;
-         Nam       :  Node_Id;
          Unit_Name : Entity_Id;
 
       begin
@@ -2083,7 +2150,7 @@ package body Sem_Ch10 is
                      --  attempt processing.
 
                      if Serious_Errors_Detected > 0
-                       and then  No (Entity (Name (Item)))
+                       and then No (Entity (Name (Item)))
                      then
                         Set_Entity (Name (Item), Standard_Standard);
                      end if;
@@ -2108,18 +2175,10 @@ package body Sem_Ch10 is
                end if;
 
             elsif Nkind (Item) = N_Use_Package_Clause then
-               Nam := First (Names (Item));
-               while Present (Nam) loop
-                  Analyze (Nam);
-                  Next (Nam);
-               end loop;
+               Analyze (Name (Item));
 
             elsif Nkind (Item) = N_Use_Type_Clause then
-               Nam := First (Subtype_Marks (Item));
-               while Present (Nam) loop
-                  Analyze (Nam);
-                  Next (Nam);
-               end loop;
+               Analyze (Subtype_Mark (Item));
             end if;
 
             Next (Item);
@@ -2166,13 +2225,22 @@ package body Sem_Ch10 is
             Re_Install_Parents (Library_Unit (L), Scope (Scop));
          end if;
 
-         Install_Context (L);
+         Install_Context (L, False);
 
          --  If the subunit occurs within a child unit, we must restore the
          --  immediate visibility of any siblings that may occur in context.
+         --  In addition, we must reset the previous visibility of the
+         --  parent unit which is now on the scope stack. This is because
+         --  the Previous_Visibility was previously set when removing the
+         --  context. This is necessary to prevent the parent entity from
+         --  remaining visible after the subunit is compiled. This only
+         --  has an effect if a homonym exists in a body to be processed
+         --  later if inlining is enabled.
 
          if Present (Enclosing_Child) then
             Install_Siblings (Enclosing_Child, L);
+            Scope_Stack.Table (Scope_Stack.Last).Previous_Visibility :=
+              False;
          end if;
 
          Push_Scope (Scop);
@@ -2213,7 +2281,7 @@ package body Sem_Ch10 is
          for J in reverse 1 .. Num_Scopes loop
             U := Use_Clauses (J);
             Scope_Stack.Table (Scope_Stack.Last - J + 1).First_Use_Clause := U;
-            Install_Use_Clauses (U, Force_Installation => True);
+            Install_Use_Clauses (U);
          end loop;
       end Re_Install_Use_Clauses;
 
@@ -2242,6 +2310,12 @@ package body Sem_Ch10 is
          Pop_Scope;
       end Remove_Scope;
 
+      Saved_SM  : SPARK_Mode_Type := SPARK_Mode;
+      Saved_SMP : Node_Id         := SPARK_Mode_Pragma;
+      --  Save the SPARK mode-related data to restore on exit. Removing
+      --  enclosing scopes and contexts to provide a clean environment for the
+      --  context of the subunit will eliminate any previously set SPARK_Mode.
+
    --  Start of processing for Analyze_Subunit
 
    begin
@@ -2290,7 +2364,8 @@ package body Sem_Ch10 is
                Remove_Scope;
             end if;
 
-            if Nkind (Unit (Lib_Spec)) = N_Package_Body then
+            if Nkind (Unit (Lib_Spec)) in N_Package_Body | N_Subprogram_Body
+            then
                Remove_Context (Library_Unit (Lib_Spec));
             end if;
          end if;
@@ -2299,6 +2374,15 @@ package body Sem_Ch10 is
 
          Analyze_Subunit_Context;
 
+         --  Take into account the effect of any SPARK_Mode configuration
+         --  pragma, which takes precedence over a different value of
+         --  SPARK_Mode inherited from the context of the stub.
+
+         if SPARK_Mode /= None then
+            Saved_SM  := SPARK_Mode;
+            Saved_SMP := SPARK_Mode_Pragma;
+         end if;
+
          Re_Install_Parents (Lib_Unit, Par_Unit);
          Set_Is_Immediately_Visible (Par_Unit);
 
@@ -2322,7 +2406,7 @@ package body Sem_Ch10 is
          end if;
 
          Re_Install_Use_Clauses;
-         Install_Context (N);
+         Install_Context (N, Chain => False);
 
          --  Restore state of suppress flags for current body
 
@@ -2338,6 +2422,35 @@ package body Sem_Ch10 is
       end if;
 
       Generate_Parent_References (Unit (N), Par_Unit);
+
+      --  Reinstall the SPARK_Mode which was in effect prior to any scope and
+      --  context manipulations, taking into account a possible SPARK_Mode
+      --  configuration pragma if present.
+
+      Install_SPARK_Mode (Saved_SM, Saved_SMP);
+
+      --  If the subunit is part of a compilation unit which is subject to
+      --  pragma Elaboration_Checks, set the model specified by the pragma
+      --  because it applies to all parts of the unit.
+
+      Install_Elaboration_Model (Par_Unit);
+
+      --  The syntax rules require a proper body for a subprogram subunit
+
+      if Nkind (Proper_Body (Sinfo.Nodes.Unit (N))) = N_Subprogram_Declaration
+      then
+         if Null_Present (Specification (Proper_Body (Sinfo.Nodes.Unit (N))))
+         then
+            Error_Msg_N
+              ("null procedure not allowed as subunit",
+               Proper_Body (Unit (N)));
+         else
+            Error_Msg_N
+              ("subprogram declaration not allowed as subunit",
+               Defining_Unit_Name (Specification (Proper_Body (Unit (N)))));
+         end if;
+      end if;
+
       Analyze (Proper_Body (Unit (N)));
       Remove_Context (N);
 
@@ -2369,8 +2482,9 @@ package body Sem_Ch10 is
    ----------------------------
 
    procedure Analyze_Task_Body_Stub (N : Node_Id) is
+      Id  : constant Entity_Id  := Defining_Entity (N);
       Loc : constant Source_Ptr := Sloc (N);
-      Nam : Entity_Id := Current_Entity_In_Scope (Defining_Identifier (N));
+      Nam : Entity_Id           := Current_Entity_In_Scope (Id);
 
    begin
       Check_Stub_Level (N);
@@ -2385,9 +2499,15 @@ package body Sem_Ch10 is
          Error_Msg_N ("missing specification for task body", N);
 
       else
-         Set_Scope (Defining_Entity (N), Current_Scope);
-         Set_Ekind (Defining_Entity (N), E_Task_Body);
-         Generate_Reference (Nam, Defining_Identifier (N), 'b');
+         Set_Scope (Id, Current_Scope);
+         Mutate_Ekind (Id, E_Task_Body);
+         Set_Etype (Id, Standard_Void_Type);
+
+         if Has_Aspects (N) then
+            Analyze_Aspect_Specifications (N, Id);
+         end if;
+
+         Generate_Reference (Nam, Id, 'b');
          Set_Corresponding_Spec_Of_Stub (N, Nam);
 
          --  Check for duplicate stub, if so give message and terminate
@@ -2460,18 +2580,10 @@ package body Sem_Ch10 is
       --  himself, but that's a marginal case, and fixing it is hard ???
 
       if Restriction_Check_Required (No_Obsolescent_Features) then
-         declare
-            F : constant File_Name_Type :=
-                  Unit_File_Name (Get_Source_Unit (U));
-         begin
-            if Is_Predefined_File_Name (F, Renamings_Included => True)
-                 and then not
-               Is_Predefined_File_Name (F, Renamings_Included => False)
-            then
-               Check_Restriction (No_Obsolescent_Features, N);
-               Restriction_Violation := True;
-            end if;
-         end;
+         if In_Predefined_Renaming (U) then
+            Check_Restriction (No_Obsolescent_Features, N);
+            Restriction_Violation := True;
+         end if;
       end if;
 
       --  Check No_Implementation_Units violation
@@ -2502,14 +2614,7 @@ package body Sem_Ch10 is
          --  clauses into regular with clauses.
 
          if Sloc (U) /= No_Location then
-            if Is_Predefined_File_Name (Unit_File_Name (Get_Source_Unit (U)))
-
-              --  In ASIS mode the rtsfind mechanism plays no role, and
-              --  we need to maintain the original tree structure, so
-              --  this transformation is not performed in this case.
-
-              and then not ASIS_Mode
-            then
+            if In_Predefined_Unit (U) then
                Set_Limited_Present (N, False);
                Analyze_With_Clause (N);
             else
@@ -2534,7 +2639,7 @@ package body Sem_Ch10 is
 
       Semantics (Library_Unit (N));
 
-      Intunit := Is_Internal_File_Name (Unit_File_Name (Current_Sem_Unit));
+      Intunit := Is_Internal_Unit (Current_Sem_Unit);
 
       if Sloc (U) /= No_Location then
 
@@ -2554,9 +2659,8 @@ package body Sem_Ch10 is
          if Nkind (Nam) = N_Selected_Component
            and then Nkind (Prefix (Nam)) = N_Identifier
            and then Chars (Prefix (Nam)) = Name_Gnat
-           and then Nam_In (Chars (Selector_Name (Nam)),
-                            Name_Most_Recent_Exception,
-                            Name_Exception_Traces)
+           and then Chars (Selector_Name (Nam))
+                      in Name_Most_Recent_Exception | Name_Exception_Traces
          then
             Check_Restriction (No_Exception_Propagation, N);
             Special_Exception_Package_Used := True;
@@ -2572,12 +2676,8 @@ package body Sem_Ch10 is
            and then not Implicit_With (N)
            and then not Restriction_Violation
          then
-            declare
-               U_Kind : constant Kind_Of_Unit :=
-                          Get_Kind_Of_Unit (Get_Source_Unit (U));
-
-            begin
-               if U_Kind = Implementation_Unit then
+            case Get_Kind_Of_Unit (Get_Source_Unit (U)) is
+               when Implementation_Unit =>
                   Error_Msg_F ("& is an internal 'G'N'A'T unit?i?", Name (N));
 
                   --  Add alternative name if available, otherwise issue a
@@ -2587,23 +2687,34 @@ package body Sem_Ch10 is
                      Error_Msg_F ("\use ""~"" instead?i?", Name (N));
                   else
                      Error_Msg_F
-                       ("\use of this unit is non-portable " &
-                        "and version-dependent?i?", Name (N));
+                       ("\use of this unit is non-portable and "
+                        & "version-dependent?i?", Name (N));
                   end if;
 
-               elsif U_Kind = Ada_2005_Unit
-                 and then Ada_Version < Ada_2005
-                 and then Warn_On_Ada_2005_Compatibility
-               then
-                  Error_Msg_N ("& is an Ada 2005 unit?i?", Name (N));
+               when Not_Predefined_Unit | Ada_95_Unit =>
+                  null; -- no checks needed
 
-               elsif U_Kind = Ada_2012_Unit
-                 and then Ada_Version < Ada_2012
-                 and then Warn_On_Ada_2012_Compatibility
-               then
-                  Error_Msg_N ("& is an Ada 2012 unit?i?", Name (N));
-               end if;
-            end;
+               when Ada_2005_Unit =>
+                  if Ada_Version < Ada_2005
+                    and then Warn_On_Ada_2005_Compatibility
+                  then
+                     Error_Msg_N ("& is an Ada 2005 unit?i?", Name (N));
+                  end if;
+
+               when Ada_2012_Unit =>
+                  if Ada_Version < Ada_2012
+                    and then Warn_On_Ada_2012_Compatibility
+                  then
+                     Error_Msg_N ("& is an Ada 2012 unit?i?", Name (N));
+                  end if;
+
+               when Ada_2022_Unit =>
+                  if Ada_Version < Ada_2022
+                    and then Warn_On_Ada_2022_Compatibility
+                  then
+                     Error_Msg_N ("& is an Ada 2022 unit?i?", Name (N));
+                  end if;
+            end case;
          end if;
       end if;
 
@@ -2859,7 +2970,7 @@ package body Sem_Ch10 is
    --  Start of processing for Check_Private_Child_Unit
 
    begin
-      if Nkind_In (Lib_Unit, N_Package_Body, N_Subprogram_Body) then
+      if Nkind (Lib_Unit) in N_Package_Body | N_Subprogram_Body then
          Curr_Unit := Defining_Entity (Unit (Library_Unit (N)));
          Par_Lib   := Curr_Unit;
 
@@ -2949,10 +3060,12 @@ package body Sem_Ch10 is
                   if Ekind (Priv_Child) = E_Generic_Package
                     and then Chars (Priv_Child) in Text_IO_Package_Name
                     and then Chars (Scope (Scope (Priv_Child))) = Name_Ada
+                    and then Scope (Scope (Scope (Priv_Child))) =
+                               Standard_Standard
                   then
                      Error_Msg_NE
                        ("& is a nested package, not a compilation unit",
-                       Name (Item), Priv_Child);
+                        Name (Item), Priv_Child);
 
                   else
                      Error_Msg_N
@@ -2964,7 +3077,7 @@ package body Sem_Ch10 is
 
                elsif Curr_Private
                  or else Private_Present (Item)
-                 or else Nkind_In (Lib_Unit, N_Package_Body, N_Subunit)
+                 or else Nkind (Lib_Unit) in N_Package_Body | N_Subunit
                  or else (Nkind (Lib_Unit) = N_Subprogram_Body
                            and then not Acts_As_Spec (Parent (Lib_Unit)))
                then
@@ -2980,7 +3093,6 @@ package body Sem_Ch10 is
 
          Next (Item);
       end loop;
-
    end Check_Private_Child_Unit;
 
    ----------------------
@@ -2992,11 +3104,9 @@ package body Sem_Ch10 is
       Kind : constant Node_Kind := Nkind (Par);
 
    begin
-      if Nkind_In (Kind, N_Package_Body,
-                         N_Subprogram_Body,
-                         N_Task_Body,
-                         N_Protected_Body)
-        and then Nkind_In (Parent (Par), N_Compilation_Unit, N_Subunit)
+      if Kind in
+           N_Package_Body | N_Subprogram_Body | N_Task_Body | N_Protected_Body
+        and then Nkind (Parent (Par)) in N_Compilation_Unit | N_Subunit
       then
          null;
 
@@ -3016,10 +3126,7 @@ package body Sem_Ch10 is
    ------------------------
 
    procedure Expand_With_Clause (Item : Node_Id; Nam : Node_Id; N : Node_Id) is
-      Loc   : constant Source_Ptr := Sloc (Nam);
-      Ent   : constant Entity_Id := Entity (Nam);
-      Withn : Node_Id;
-      P     : Node_Id;
+      Loc : constant Source_Ptr := Sloc (Nam);
 
       function Build_Unit_Name (Nam : Node_Id) return Node_Id;
       --  Build name to be used in implicit with_clause. In most cases this
@@ -3046,8 +3153,8 @@ package body Sem_Ch10 is
             if Present (Entity (Selector_Name (Nam)))
               and then Chars (Entity (Selector_Name (Nam))) /= Chars (Ent)
               and then
-                Nkind (Unit_Declaration_Node (Entity (Selector_Name (Nam))))
-                  N_Package_Renaming_Declaration
+                Nkind (Unit_Declaration_Node (Entity (Selector_Name (Nam)))) =
+                  N_Package_Renaming_Declaration
             then
                --  The name in the with_clause is of the form A.B.C, and B is
                --  given by a renaming declaration. In that case we may not
@@ -3064,14 +3171,20 @@ package body Sem_Ch10 is
 
             Result :=
               Make_Expanded_Name (Loc,
-                Chars  => Chars (Entity (Nam)),
-                Prefix => Build_Unit_Name (Prefix (Nam)),
+                Chars         => Chars (Entity (Nam)),
+                Prefix        => Build_Unit_Name (Prefix (Nam)),
                 Selector_Name => New_Occurrence_Of (Ent, Loc));
             Set_Entity (Result, Ent);
+
             return Result;
          end if;
       end Build_Unit_Name;
 
+      --  Local variables
+
+      Ent   : constant Entity_Id  := Entity (Nam);
+      Withn : Node_Id;
+
    --  Start of processing for Expand_With_Clause
 
    begin
@@ -3079,25 +3192,30 @@ package body Sem_Ch10 is
         Make_With_Clause (Loc,
           Name => Build_Unit_Name (Nam));
 
-      P := Parent (Unit_Declaration_Node (Ent));
-      Set_Library_Unit       (Withn, P);
       Set_Corresponding_Spec (Withn, Ent);
-      Set_First_Name         (Withn, True);
-      Set_Implicit_With      (Withn, True);
-
-      --  If the unit is a package or generic package declaration, a private_
-      --  with_clause on a child unit implies that the implicit with on the
-      --  parent is also private.
-
-      if Nkind_In (Unit (N), N_Package_Declaration,
-                             N_Generic_Package_Declaration)
+      Set_First_Name         (Withn);
+      Set_Implicit_With      (Withn);
+      Set_Library_Unit       (Withn, Parent (Unit_Declaration_Node (Ent)));
+      Set_Parent_With        (Withn);
+
+      --  If the unit is a [generic] package or subprogram declaration
+      --  (including a subprogram body acting as spec), a private_with_clause
+      --  on a child unit implies that the implicit with on the parent is also
+      --  private.
+
+      if Nkind (Unit (N)) in N_Generic_Package_Declaration
+                           | N_Package_Declaration
+                           | N_Generic_Subprogram_Declaration
+                           | N_Subprogram_Declaration
+                           | N_Subprogram_Body
       then
          Set_Private_Present (Withn, Private_Present (Item));
       end if;
 
       Prepend (Withn, Context_Items (N));
       Mark_Rewrite_Insertion (Withn);
-      Install_Withed_Unit (Withn);
+
+      Install_With_Clause (Withn);
 
       --  If we have "with X.Y;", we want to recurse on "X", except in the
       --  unusual case where X.Y is a renaming of X. In that case, the scope
@@ -3230,8 +3348,8 @@ package body Sem_Ch10 is
          P_Spec : Node_Id := P;
 
       begin
-         --  Ancestor may have been rewritten as a package body. Retrieve
-         --  the original spec to trace earlier ancestors.
+         --  Ancestor may have been rewritten as a package body. Retrieve the
+         --  original spec to trace earlier ancestors.
 
          if Nkind (P) = N_Package_Body
            and then Nkind (Original_Node (P)) = N_Package_Instantiation
@@ -3244,7 +3362,8 @@ package body Sem_Ch10 is
          else
             return
               Make_Selected_Component (Loc,
-                Prefix => Build_Ancestor_Name (Unit (Parent_Spec (P_Spec))),
+                Prefix        =>
+                  Build_Ancestor_Name (Unit (Parent_Spec (P_Spec))),
                 Selector_Name => P_Ref);
          end if;
       end Build_Ancestor_Name;
@@ -3263,10 +3382,12 @@ package body Sem_Ch10 is
          else
             Result :=
               Make_Expanded_Name (Loc,
-                Chars  => Chars (P_Name),
-                Prefix => Build_Ancestor_Name (Unit (Parent_Spec (P_Unit))),
+                Chars         => Chars (P_Name),
+                Prefix        =>
+                  Build_Ancestor_Name (Unit (Parent_Spec (P_Unit))),
                 Selector_Name => New_Occurrence_Of (P_Name, Loc));
             Set_Entity (Result, P_Name);
+
             return Result;
          end if;
       end Build_Unit_Name;
@@ -3296,17 +3417,19 @@ package body Sem_Ch10 is
 
       Withn := Make_With_Clause (Loc, Name => Build_Unit_Name);
 
-      Set_Library_Unit          (Withn, P);
-      Set_Corresponding_Spec    (Withn, P_Name);
-      Set_First_Name            (Withn, True);
-      Set_Implicit_With         (Withn, True);
+      Set_Corresponding_Spec (Withn, P_Name);
+      Set_First_Name         (Withn);
+      Set_Implicit_With      (Withn);
+      Set_Library_Unit       (Withn, P);
+      Set_Parent_With        (Withn);
 
       --  Node is placed at the beginning of the context items, so that
       --  subsequent use clauses on the parent can be validated.
 
       Prepend (Withn, Context_Items (N));
       Mark_Rewrite_Insertion (Withn);
-      Install_Withed_Unit (Withn);
+
+      Install_With_Clause (Withn);
 
       if Is_Child_Spec (P_Unit) then
          Implicit_With_On_Parent (P_Unit, N);
@@ -3337,14 +3460,17 @@ package body Sem_Ch10 is
    -- Install_Context --
    ---------------------
 
-   procedure Install_Context (N : Node_Id) is
+   procedure Install_Context (N : Node_Id; Chain : Boolean := True) is
       Lib_Unit : constant Node_Id := Unit (N);
 
    begin
-      Install_Context_Clauses (N);
+      Install_Context_Clauses (N, Chain);
 
       if Is_Child_Spec (Lib_Unit) then
-         Install_Parents (Lib_Unit, Private_Present (Parent (Lib_Unit)));
+         Install_Parents
+           (Lib_Unit   => Lib_Unit,
+            Is_Private => Private_Present (Parent (Lib_Unit)),
+            Chain      => Chain);
       end if;
 
       Install_Limited_Context_Clauses (N);
@@ -3354,7 +3480,7 @@ package body Sem_Ch10 is
    -- Install_Context_Clauses --
    -----------------------------
 
-   procedure Install_Context_Clauses (N : Node_Id) is
+   procedure Install_Context_Clauses (N : Node_Id; Chain : Boolean := True) is
       Lib_Unit      : constant Node_Id := Unit (N);
       Item          : Node_Id;
       Uname_Node    : Entity_Id;
@@ -3409,7 +3535,7 @@ package body Sem_Ch10 is
                Check_Private := True;
             end if;
 
-            Install_Withed_Unit (Item);
+            Install_With_Clause (Item);
 
             Decl_Node := Unit_Declaration_Node (Uname_Node);
 
@@ -3471,7 +3597,7 @@ package body Sem_Ch10 is
                   --  Exclude license check if withed unit is an internal unit.
                   --  This situation arises e.g. with the GPL version of GNAT.
 
-                  if Is_Internal_File_Name (Unit_File_Name (Withu)) then
+                  if Is_Internal_Unit (Withu) then
                      null;
 
                      --  Otherwise check various cases
@@ -3505,12 +3631,12 @@ package body Sem_Ch10 is
          --  Case of USE PACKAGE clause
 
          elsif Nkind (Item) = N_Use_Package_Clause then
-            Analyze_Use_Package (Item);
+            Analyze_Use_Package (Item, Chain);
 
          --  Case of USE TYPE clause
 
          elsif Nkind (Item) = N_Use_Type_Clause then
-            Analyze_Use_Type (Item);
+            Analyze_Use_Type (Item, Chain);
 
          --  case of PRAGMA
 
@@ -3540,7 +3666,7 @@ package body Sem_Ch10 is
         or else (Nkind (Lib_Unit) = N_Subprogram_Body
                   and then not Acts_As_Spec (N))
       then
-         Install_Context (Library_Unit (N));
+         Install_Context (Library_Unit (N), Chain);
 
          --  Only install private with-clauses of a spec that comes from
          --  source, excluding specs created for a subprogram body that is
@@ -3590,10 +3716,10 @@ package body Sem_Ch10 is
          Install_Siblings (Defining_Entity (Unit (Library_Unit (N))), N);
       end if;
 
-      if Nkind_In (Lib_Unit, N_Generic_Package_Declaration,
-                             N_Generic_Subprogram_Declaration,
-                             N_Package_Declaration,
-                             N_Subprogram_Declaration)
+      if Nkind (Lib_Unit) in N_Generic_Package_Declaration
+                           | N_Generic_Subprogram_Declaration
+                           | N_Package_Declaration
+                           | N_Subprogram_Declaration
       then
          if Is_Child_Spec (Lib_Unit) then
             Lib_Parent := Defining_Entity (Unit (Parent_Spec (Lib_Unit)));
@@ -3654,7 +3780,6 @@ package body Sem_Ch10 is
          Item   : Node_Id;
          Spec   : Node_Id;
          WEnt   : Entity_Id;
-         Nam    : Node_Id;
          E      : Entity_Id;
          E2     : Entity_Id;
 
@@ -3687,43 +3812,36 @@ package body Sem_Ch10 is
 
             if Nkind (Item) = N_Use_Package_Clause then
 
-               --  Traverse the list of packages
-
-               Nam := First (Names (Item));
-               while Present (Nam) loop
-                  E := Entity (Nam);
+               E := Entity (Name (Item));
 
-                  pragma Assert (Present (Parent (E)));
+               pragma Assert (Present (Parent (E)));
 
-                  if Nkind (Parent (E)) = N_Package_Renaming_Declaration
-                    and then Renamed_Entity (E) = WEnt
-                  then
-                     --  The unlimited view is visible through use clause and
-                     --  renamings. There is no need to generate the error
-                     --  message here because Is_Visible_Through_Renamings
-                     --  takes care of generating the precise error message.
+               if Nkind (Parent (E)) = N_Package_Renaming_Declaration
+                 and then Renamed_Entity (E) = WEnt
+               then
+                  --  The unlimited view is visible through use clause and
+                  --  renamings. There is no need to generate the error
+                  --  message here because Is_Visible_Through_Renamings
+                  --  takes care of generating the precise error message.
 
-                     return;
+                  return;
 
-                  elsif Nkind (Parent (E)) = N_Package_Specification then
+               elsif Nkind (Parent (E)) = N_Package_Specification then
 
-                     --  The use clause may refer to a local package.
-                     --  Check all the enclosing scopes.
+                  --  The use clause may refer to a local package.
+                  --  Check all the enclosing scopes.
 
-                     E2 := E;
-                     while E2 /= Standard_Standard and then E2 /= WEnt loop
-                        E2 := Scope (E2);
-                     end loop;
+                  E2 := E;
+                  while E2 /= Standard_Standard and then E2 /= WEnt loop
+                     E2 := Scope (E2);
+                  end loop;
 
-                     if E2 = WEnt then
-                        Error_Msg_N
-                          ("unlimited view visible through use clause ", W);
-                        return;
-                     end if;
+                  if E2 = WEnt then
+                     Error_Msg_N
+                       ("unlimited view visible through use clause", W);
+                     return;
                   end if;
-
-                  Next (Nam);
-               end loop;
+               end if;
             end if;
 
             Next (Item);
@@ -3791,9 +3909,8 @@ package body Sem_Ch10 is
          elsif Private_Present (Parent (Item))
             or else Curr_Private
             or else Private_Present (Item)
-            or else Nkind_In (Unit (Parent (Item)), N_Package_Body,
-                                                    N_Subprogram_Body,
-                                                    N_Subunit)
+            or else Nkind (Unit (Parent (Item))) in
+                      N_Package_Body | N_Subprogram_Body | N_Subunit
          then
             --  Current unit is private, of descendant of a private unit
 
@@ -3821,7 +3938,7 @@ package body Sem_Ch10 is
 
          function Previous_Withed_Unit (W : Node_Id) return Boolean;
          --  Returns true if the context already includes a with_clause for
-         --  this unit. If the with_clause is non-limited, the unit is fully
+         --  this unit. If the with_clause is nonlimited, the unit is fully
          --  visible and an implicit limited_with should not be created. If
          --  there is already a limited_with clause for W, a second one is
          --  simply redundant.
@@ -3871,9 +3988,9 @@ package body Sem_Ch10 is
             Set_Parent (Withn, Parent (N));
          end if;
 
-         Set_Limited_Present (Withn);
          Set_First_Name      (Withn);
          Set_Implicit_With   (Withn);
+         Set_Limited_Present (Withn);
 
          Unum :=
            Load_Unit
@@ -3908,7 +4025,7 @@ package body Sem_Ch10 is
             Analyze (Withn);
 
             if not Limited_View_Installed (Withn) then
-               Install_Limited_Withed_Unit (Withn);
+               Install_Limited_With_Clause (Withn);
             end if;
          end if;
       end Expand_Limited_With_Clause;
@@ -3951,11 +4068,10 @@ package body Sem_Ch10 is
             then
                if not Private_Present (Item)
                  or else Private_Present (N)
-                 or else Nkind_In (Unit (N), N_Package_Body,
-                                             N_Subprogram_Body,
-                                             N_Subunit)
+                 or else Nkind (Unit (N)) in
+                           N_Package_Body | N_Subprogram_Body | N_Subunit
                then
-                  Install_Limited_Withed_Unit (Item);
+                  Install_Limited_With_Clause (Item);
                end if;
             end if;
          end if;
@@ -3991,12 +4107,12 @@ package body Sem_Ch10 is
                   if not Is_Incomplete_Type (Non_Lim_View) then
 
                      --  Convert an incomplete subtype declaration into a
-                     --  corresponding non-limited view subtype declaration.
+                     --  corresponding nonlimited view subtype declaration.
                      --  This is usually the case when analyzing a body that
                      --  has regular with clauses,  when the spec has limited
                      --  ones.
 
-                     --  If the non-limited view is still incomplete, it is
+                     --  If the nonlimited view is still incomplete, it is
                      --  the dummy entry already created, and the declaration
                      --  cannot be reanalyzed. This is the case when installing
                      --  a parent unit that has limited with-clauses.
@@ -4004,7 +4120,8 @@ package body Sem_Ch10 is
                      Set_Subtype_Indication (Decl,
                        New_Occurrence_Of (Non_Lim_View, Sloc (Def_Id)));
                      Set_Etype (Def_Id, Non_Lim_View);
-                     Set_Ekind (Def_Id, Subtype_Kind (Ekind (Non_Lim_View)));
+                     Mutate_Ekind
+                       (Def_Id, Subtype_Kind (Ekind (Non_Lim_View)));
                      Set_Analyzed (Decl, False);
 
                      --  Reanalyze the declaration, suppressing the call to
@@ -4026,7 +4143,11 @@ package body Sem_Ch10 is
    -- Install_Parents --
    ---------------------
 
-   procedure Install_Parents (Lib_Unit : Node_Id; Is_Private : Boolean) is
+   procedure Install_Parents
+     (Lib_Unit   : Node_Id;
+      Is_Private : Boolean;
+      Chain      : Boolean := True)
+   is
       P      : Node_Id;
       E_Name : Entity_Id;
       P_Name : Entity_Id;
@@ -4041,9 +4162,9 @@ package body Sem_Ch10 is
       end if;
 
       if Ekind (P_Name) = E_Generic_Package
-        and then not Nkind_In (Lib_Unit, N_Generic_Subprogram_Declaration,
-                                         N_Generic_Package_Declaration)
-        and then Nkind (Lib_Unit) not in N_Generic_Renaming_Declaration
+        and then Nkind (Lib_Unit) not in N_Generic_Subprogram_Declaration
+                                       | N_Generic_Package_Declaration
+                                       | N_Generic_Renaming_Declaration
       then
          Error_Msg_N
            ("child of a generic package must be a generic unit", Lib_Unit);
@@ -4082,13 +4203,16 @@ package body Sem_Ch10 is
       --  This is the recursive call that ensures all parents are loaded
 
       if Is_Child_Spec (P) then
-         Install_Parents (P,
-           Is_Private or else Private_Present (Parent (Lib_Unit)));
+         Install_Parents
+           (Lib_Unit   => P,
+            Is_Private =>
+              Is_Private or else Private_Present (Parent (Lib_Unit)),
+            Chain      => Chain);
       end if;
 
       --  Now we can install the context for this parent
 
-      Install_Context_Clauses (Parent_Spec (Lib_Unit));
+      Install_Context_Clauses (Parent_Spec (Lib_Unit), Chain);
       Install_Limited_Context_Clauses (Parent_Spec (Lib_Unit));
       Install_Siblings (P_Name, Parent (Lib_Unit));
 
@@ -4171,10 +4295,10 @@ package body Sem_Ch10 is
                       not Is_Ancestor_Unit (Library_Unit (Item),
                                             Cunit (Current_Sem_Unit))
                   then
-                     Install_Limited_Withed_Unit (Item);
+                     Install_Limited_With_Clause (Item);
                   end if;
                else
-                  Install_Withed_Unit (Item, Private_With_OK => True);
+                  Install_With_Clause (Item, Private_With_OK => True);
                end if;
             end if;
 
@@ -4202,16 +4326,18 @@ package body Sem_Ch10 is
 
          --  Do not install private_with_clauses declaration, unless unit
          --  is itself a private child unit, or is a body. Note that for a
-         --  subprogram body the private_with_clause does not take effect until
-         --  after the specification.
+         --  subprogram body the private_with_clause does not take effect
+         --  until after the specification.
 
          if Nkind (Item) /= N_With_Clause
            or else Implicit_With (Item)
            or else Limited_Present (Item)
            or else Error_Posted (Item)
+
             --  Skip processing malformed trees
+
            or else (Try_Semantics
-                      and then Nkind (Name (Item)) not in N_Has_Entity)
+                     and then Nkind (Name (Item)) not in N_Has_Entity)
          then
             null;
 
@@ -4256,7 +4382,7 @@ package body Sem_Ch10 is
                   end;
                end if;
 
-            --  The With_Clause may be on a grand-child or one of its further
+            --  The With_Clause may be on a grandchild or one of its further
             --  descendants, which makes a child immediately visible. Examine
             --  ancestry to determine whether such a child exists. For example,
             --  if current unit is A.C, and with_clause is on A.X.Y.Z, then X
@@ -4295,7 +4421,7 @@ package body Sem_Ch10 is
                   --  Scan context of current unit, to check whether there is
                   --  a with_clause on the same unit as a private with-clause
                   --  on a parent, in which case child unit is visible. If the
-                  --  unit is a grand-child, the same applies to its parent.
+                  --  unit is a grandchild, the same applies to its parent.
 
                   ----------------
                   -- In_Context --
@@ -4337,10 +4463,10 @@ package body Sem_Ch10 is
    end Install_Siblings;
 
    ---------------------------------
-   -- Install_Limited_Withed_Unit --
+   -- Install_Limited_With_Clause --
    ---------------------------------
 
-   procedure Install_Limited_Withed_Unit (N : Node_Id) is
+   procedure Install_Limited_With_Clause (N : Node_Id) is
       P_Unit           : constant Entity_Id := Unit (Library_Unit (N));
       E                : Entity_Id;
       P                : Entity_Id;
@@ -4362,10 +4488,6 @@ package body Sem_Ch10 is
       --  Determine whether any package in the ancestor chain starting with
       --  C_Unit has a limited with clause for package Pack.
 
-      function Is_Visible_Through_Renamings (P : Entity_Id) return Boolean;
-      --  Check if some package installed though normal with-clauses has a
-      --  renaming declaration of package P. AARM 10.1.2(21/2).
-
       -------------------------
       -- Check_Body_Required --
       -------------------------
@@ -4501,17 +4623,17 @@ package body Sem_Ch10 is
                --  Save for subsequent examination of import pragmas.
 
                if Comes_From_Source (Decl)
-                 and then (Nkind_In (Decl, N_Subprogram_Declaration,
-                                           N_Subprogram_Renaming_Declaration,
-                                           N_Generic_Subprogram_Declaration))
+                 and then (Nkind (Decl) in N_Subprogram_Declaration
+                                         | N_Subprogram_Renaming_Declaration
+                                         | N_Generic_Subprogram_Declaration)
                then
                   Append_Elmt (Defining_Entity (Decl), Subp_List);
 
                --  Package declaration of generic package declaration. We need
                --  to recursively examine nested declarations.
 
-               elsif Nkind_In (Decl, N_Package_Declaration,
-                                     N_Generic_Package_Declaration)
+               elsif Nkind (Decl) in N_Package_Declaration
+                                   | N_Generic_Package_Declaration
                then
                   Check_Declarations (Specification (Decl));
 
@@ -4531,14 +4653,14 @@ package body Sem_Ch10 is
             Decl := First (Private_Declarations (Spec));
             while Present (Decl) loop
                if Comes_From_Source (Decl)
-                 and then (Nkind_In (Decl, N_Subprogram_Declaration,
-                                           N_Subprogram_Renaming_Declaration,
-                                           N_Generic_Subprogram_Declaration))
+                 and then Nkind (Decl) in N_Subprogram_Declaration
+                                        | N_Subprogram_Renaming_Declaration
+                                        | N_Generic_Subprogram_Declaration
                then
                   Append_Elmt (Defining_Entity (Decl), Subp_List);
 
-               elsif Nkind_In (Decl, N_Package_Declaration,
-                                     N_Generic_Package_Declaration)
+               elsif Nkind (Decl) in N_Package_Declaration
+                                   | N_Generic_Package_Declaration
                then
                   Check_Declarations (Specification (Decl));
 
@@ -4695,109 +4817,7 @@ package body Sem_Ch10 is
          return False;
       end Has_Limited_With_Clause;
 
-      ----------------------------------
-      -- Is_Visible_Through_Renamings --
-      ----------------------------------
-
-      function Is_Visible_Through_Renamings (P : Entity_Id) return Boolean is
-         Kind     : constant Node_Kind :=
-                      Nkind (Unit (Cunit (Current_Sem_Unit)));
-         Aux_Unit : Node_Id;
-         Item     : Node_Id;
-         Decl     : Entity_Id;
-
-      begin
-         --  Example of the error detected by this subprogram:
-
-         --  package P is
-         --    type T is ...
-         --  end P;
-
-         --  with P;
-         --  package Q is
-         --     package Ren_P renames P;
-         --  end Q;
-
-         --  with Q;
-         --  package R is ...
-
-         --  limited with P; -- ERROR
-         --  package R.C is ...
-
-         Aux_Unit := Cunit (Current_Sem_Unit);
-
-         loop
-            Item := First (Context_Items (Aux_Unit));
-            while Present (Item) loop
-               if Nkind (Item) = N_With_Clause
-                 and then not Limited_Present (Item)
-                 and then Nkind (Unit (Library_Unit (Item))) =
-                                                  N_Package_Declaration
-               then
-                  Decl :=
-                    First (Visible_Declarations
-                            (Specification (Unit (Library_Unit (Item)))));
-                  while Present (Decl) loop
-                     if Nkind (Decl) = N_Package_Renaming_Declaration
-                       and then Entity (Name (Decl)) = P
-                     then
-                        --  Generate the error message only if the current unit
-                        --  is a package declaration; in case of subprogram
-                        --  bodies and package bodies we just return True to
-                        --  indicate that the limited view must not be
-                        --  installed.
-
-                        if Kind = N_Package_Declaration then
-                           Error_Msg_N
-                             ("simultaneous visibility of the limited and " &
-                              "unlimited views not allowed", N);
-                           Error_Msg_Sloc := Sloc (Item);
-                           Error_Msg_NE
-                             ("\\  unlimited view of & visible through the " &
-                              "context clause #", N, P);
-                           Error_Msg_Sloc := Sloc (Decl);
-                           Error_Msg_NE ("\\  and the renaming #", N, P);
-                        end if;
-
-                        return True;
-                     end if;
-
-                     Next (Decl);
-                  end loop;
-               end if;
-
-               Next (Item);
-            end loop;
-
-            --  If it is a body not acting as spec, follow pointer to the
-            --  corresponding spec, otherwise follow pointer to parent spec.
-
-            if Present (Library_Unit (Aux_Unit))
-              and then Nkind_In (Unit (Aux_Unit),
-                                 N_Package_Body, N_Subprogram_Body)
-            then
-               if Aux_Unit = Library_Unit (Aux_Unit) then
-
-                  --  Aux_Unit is a body that acts as a spec. Clause has
-                  --  already been flagged as illegal.
-
-                  return False;
-
-               else
-                  Aux_Unit := Library_Unit (Aux_Unit);
-               end if;
-
-            else
-               Aux_Unit := Parent_Spec (Unit (Aux_Unit));
-            end if;
-
-            exit when No (Aux_Unit);
-         end loop;
-
-         return False;
-      end Is_Visible_Through_Renamings;
-
-   --  Start of processing for Install_Limited_Withed_Unit
+   --  Start of processing for Install_Limited_With_Clause
 
    begin
       pragma Assert (not Limited_View_Installed (N));
@@ -4834,7 +4854,7 @@ package body Sem_Ch10 is
       --  Do not install the limited-view if the full-view is already visible
       --  through renaming declarations.
 
-      if Is_Visible_Through_Renamings (P) then
+      if Is_Visible_Through_Renamings (P, N) then
          return;
       end if;
 
@@ -4858,7 +4878,7 @@ package body Sem_Ch10 is
       --  compilation of sibling Par.Sib forces the load of parent Par which
       --  tries to install the limited view of Lim_Pack [1]. However Par.Sib
       --  has a with clause for Lim_Pack [2] in its body, and thus needs the
-      --  non-limited views of all entities from Lim_Pack.
+      --  nonlimited views of all entities from Lim_Pack.
 
       --     limited with Lim_Pack;   --  [1]
       --     package Par is ...           package Lim_Pack is ...
@@ -4967,7 +4987,7 @@ package body Sem_Ch10 is
 
             --  Minimum decoration
 
-            Set_Ekind (P, E_Package);
+            Mutate_Ekind (P, E_Package);
             Set_Etype (P, Standard_Void_Type);
             Set_Scope (P, Standard_Standard);
             Set_Is_Visible_Lib_Unit (P);
@@ -5064,7 +5084,7 @@ package body Sem_Ch10 is
                   --  Replace E in the homonyms list, so that the limited view
                   --  becomes available.
 
-                  --  If the non-limited view is a record with an anonymous
+                  --  If the nonlimited view is a record with an anonymous
                   --  self-referential component, the analysis of the record
                   --  declaration creates an incomplete type with the same name
                   --  in order to define an internal access type. The visible
@@ -5144,9 +5164,8 @@ package body Sem_Ch10 is
 
                --  Set entity of parent identifiers if the unit is a child
                --  unit. This ensures that the tree is properly formed from
-               --  semantic point of view (e.g. for ASIS queries). The unit
-               --  entities are not fully analyzed, so we need to follow unit
-               --  links in the tree.
+               --  semantic point of view. The unit entities are not fully
+               --  analyzed, so we need to follow unit links in the tree.
 
                Set_Entity (Nam, Ent);
 
@@ -5166,13 +5185,13 @@ package body Sem_Ch10 is
 
       Set_Entity (Name (N), P);
       Set_From_Limited_With (P);
-   end Install_Limited_Withed_Unit;
+   end Install_Limited_With_Clause;
 
    -------------------------
-   -- Install_Withed_Unit --
+   -- Install_With_Clause --
    -------------------------
 
-   procedure Install_Withed_Unit
+   procedure Install_With_Clause
      (With_Clause     : Node_Id;
       Private_With_OK : Boolean := False)
    is
@@ -5186,8 +5205,9 @@ package body Sem_Ch10 is
       --  analyzing the private part of the package).
 
       if Private_Present (With_Clause)
-        and then Nkind (Unit (Parent (With_Clause))) = N_Package_Declaration
-        and then not (Private_With_OK)
+        and then Nkind (Unit (Parent (With_Clause)))
+                   in N_Package_Declaration | N_Generic_Package_Declaration
+        and then not Private_With_OK
       then
          return;
       end if;
@@ -5208,7 +5228,7 @@ package body Sem_Ch10 is
       --  skipped for dummy units (for missing packages).
 
       if Sloc (Uname) /= No_Location
-        and then (not Is_Internal_File_Name (Unit_File_Name (Current_Sem_Unit))
+        and then (not Is_Internal_Unit (Current_Sem_Unit)
                    or else Current_Sem_Unit = Main_Unit)
       then
          Check_Restricted_Unit
@@ -5228,6 +5248,20 @@ package body Sem_Ch10 is
             Error_Msg_N
               ("instantiation depends on itself", Name (With_Clause));
 
+         elsif not Analyzed (Uname)
+           and then Is_Internal_Unit (Current_Sem_Unit)
+           and then not Is_Visible_Lib_Unit (Uname)
+           and then No (Scope (Uname))
+         then
+            if Is_Predefined_Unit (Current_Sem_Unit) then
+               Error_Msg_N
+                 ("predefined unit depends on itself", Name (With_Clause));
+            else
+               Error_Msg_N
+                 ("GNAT-defined unit depends on itself", Name (With_Clause));
+            end if;
+            return;
+
          elsif not Is_Visible_Lib_Unit (Uname) then
 
             --  Abandon processing in case of previous errors
@@ -5240,7 +5274,7 @@ package body Sem_Ch10 is
             Set_Is_Visible_Lib_Unit (Uname);
 
             --  If the unit is a wrapper package for a compilation unit that is
-            --  a subprogrm instance, indicate that the instance itself is a
+            --  a subprogram instance, indicate that the instance itself is a
             --  visible unit. This is necessary if the instance is inlined.
 
             if Is_Wrapper_Package (Uname) then
@@ -5285,11 +5319,21 @@ package body Sem_Ch10 is
          Set_Context_Installed (With_Clause);
       end if;
 
-      --   A with-clause overrides a with-type clause: there are no restric-
-      --   tions on the use of package entities.
-
-      if Ekind (Uname) = E_Package then
-         Set_From_Limited_With (Uname, False);
+      --  A [private] with clause overrides a limited with clause. Restore the
+      --  proper view of the package by performing the following actions:
+      --
+      --    * Remove all shadow entities which hide their corresponding
+      --      entities from direct visibility by updating the entity and
+      --      homonym chains.
+      --
+      --    * Enter the corresponding entities back in direct visibility
+      --
+      --  Note that the original limited with clause which installed its view
+      --  is still marked as "active". This effect is undone when the clause
+      --  itself is removed, see Remove_Limited_With_Clause.
+
+      if Ekind (Uname) = E_Package and then From_Limited_With (Uname) then
+         Remove_Limited_With_Unit (Unit_Declaration_Node (Uname));
       end if;
 
       --  Ada 2005 (AI-377): it is illegal for a with_clause to name a child
@@ -5361,7 +5405,7 @@ package body Sem_Ch10 is
             end loop;
          end;
       end if;
-   end Install_Withed_Unit;
+   end Install_With_Clause;
 
    -------------------
    -- Is_Child_Spec --
@@ -5402,7 +5446,7 @@ package body Sem_Ch10 is
       E1 : constant Entity_Id := Defining_Entity (Unit (U1));
       E2 : Entity_Id;
    begin
-      if Nkind_In (Unit (U2), N_Package_Body, N_Subprogram_Body) then
+      if Nkind (Unit (U2)) in N_Package_Body | N_Subprogram_Body then
          E2 := Defining_Entity (Unit (Library_Unit (U2)));
          return Is_Ancestor_Package (E1, E2);
       else
@@ -5410,6 +5454,148 @@ package body Sem_Ch10 is
       end if;
    end Is_Ancestor_Unit;
 
+   ----------------------------------
+   -- Is_Visible_Through_Renamings --
+   ----------------------------------
+
+   function Is_Visible_Through_Renamings
+     (P          : Entity_Id;
+      Error_Node : Node_Id := Empty) return Boolean
+   is
+      function Is_Limited_Withed_Unit
+        (Lib_Unit : Node_Id;
+         Pkg_Ent  : Entity_Id) return Boolean;
+      --  Return True if Pkg_Ent is a limited-withed package of the given
+      --  library unit.
+
+      ----------------------------
+      -- Is_Limited_Withed_Unit --
+      ----------------------------
+
+      function Is_Limited_Withed_Unit
+        (Lib_Unit : Node_Id;
+         Pkg_Ent  : Entity_Id) return Boolean
+      is
+         Item : Node_Id := First (Context_Items (Lib_Unit));
+
+      begin
+         while Present (Item) loop
+            if Nkind (Item) = N_With_Clause
+              and then Limited_Present (Item)
+              and then Entity (Name (Item)) = Pkg_Ent
+            then
+               return True;
+            end if;
+
+            Next (Item);
+         end loop;
+
+         return False;
+      end Is_Limited_Withed_Unit;
+
+      --  Local variables
+
+      Kind     : constant Node_Kind := Nkind (Unit (Cunit (Current_Sem_Unit)));
+      Aux_Unit : Node_Id;
+      Item     : Node_Id;
+      Decl     : Entity_Id;
+
+   begin
+      --  Example of the error detected by this subprogram:
+
+      --  package P is
+      --    type T is ...
+      --  end P;
+
+      --  with P;
+      --  package Q is
+      --     package Ren_P renames P;
+      --  end Q;
+
+      --  with Q;
+      --  package R is ...
+
+      --  limited with P; -- ERROR
+      --  package R.C is ...
+
+      Aux_Unit := Cunit (Current_Sem_Unit);
+
+      loop
+         Item := First (Context_Items (Aux_Unit));
+         while Present (Item) loop
+            if Nkind (Item) = N_With_Clause
+              and then not Limited_Present (Item)
+              and then Nkind (Unit (Library_Unit (Item))) =
+                                               N_Package_Declaration
+            then
+               Decl :=
+                 First (Visible_Declarations
+                         (Specification (Unit (Library_Unit (Item)))));
+               while Present (Decl) loop
+                  if Nkind (Decl) = N_Package_Renaming_Declaration
+                    and then Entity (Name (Decl)) = P
+                    and then not Is_Limited_Withed_Unit
+                                   (Lib_Unit => Library_Unit (Item),
+                                    Pkg_Ent  => Entity (Name (Decl)))
+                  then
+                     --  Generate the error message only if the current unit
+                     --  is a package declaration; in case of subprogram
+                     --  bodies and package bodies we just return True to
+                     --  indicate that the limited view must not be
+                     --  installed.
+
+                     if Kind = N_Package_Declaration
+                       and then Present (Error_Node)
+                     then
+                        Error_Msg_N
+                          ("simultaneous visibility of the limited and " &
+                           "unlimited views not allowed", Error_Node);
+                        Error_Msg_Sloc := Sloc (Item);
+                        Error_Msg_NE
+                          ("\\  unlimited view of & visible through the " &
+                           "context clause #", Error_Node, P);
+                        Error_Msg_Sloc := Sloc (Decl);
+                        Error_Msg_NE ("\\  and the renaming #", Error_Node, P);
+                     end if;
+
+                     return True;
+                  end if;
+
+                  Next (Decl);
+               end loop;
+            end if;
+
+            Next (Item);
+         end loop;
+
+         --  If it is a body not acting as spec, follow pointer to the
+         --  corresponding spec, otherwise follow pointer to parent spec.
+
+         if Present (Library_Unit (Aux_Unit))
+           and then Nkind (Unit (Aux_Unit)) in
+                      N_Package_Body | N_Subprogram_Body
+         then
+            if Aux_Unit = Library_Unit (Aux_Unit) then
+
+               --  Aux_Unit is a body that acts as a spec. Clause has
+               --  already been flagged as illegal.
+
+               return False;
+
+            else
+               Aux_Unit := Library_Unit (Aux_Unit);
+            end if;
+
+         else
+            Aux_Unit := Parent_Spec (Unit (Aux_Unit));
+         end if;
+
+         exit when No (Aux_Unit);
+      end loop;
+
+      return False;
+   end Is_Visible_Through_Renamings;
+
    -----------------------
    -- Load_Needed_Body --
    -----------------------
@@ -5553,9 +5739,9 @@ package body Sem_Ch10 is
          --  The abstract view of a variable is a state, not another variable
 
          if Ekind (Ent) = E_Variable then
-            Set_Ekind (Shadow, E_Abstract_State);
+            Mutate_Ekind (Shadow, E_Abstract_State);
          else
-            Set_Ekind (Shadow, Ekind (Ent));
+            Mutate_Ekind (Shadow, Ekind (Ent));
          end if;
 
          Set_Is_Internal       (Shadow);
@@ -5600,7 +5786,7 @@ package body Sem_Ch10 is
 
       procedure Decorate_Package (Ent : Entity_Id; Scop : Entity_Id) is
       begin
-         Set_Ekind (Ent, E_Package);
+         Mutate_Ekind (Ent, E_Package);
          Set_Etype (Ent, Standard_Void_Type);
          Set_Scope (Ent, Scop);
       end Decorate_Package;
@@ -5611,7 +5797,7 @@ package body Sem_Ch10 is
 
       procedure Decorate_State (Ent : Entity_Id; Scop : Entity_Id) is
       begin
-         Set_Ekind               (Ent, E_Abstract_State);
+         Mutate_Ekind            (Ent, E_Abstract_State);
          Set_Etype               (Ent, Standard_Void_Type);
          Set_Scope               (Ent, Scop);
          Set_Encapsulating_State (Ent, Empty);
@@ -5633,7 +5819,7 @@ package body Sem_Ch10 is
          --  An unanalyzed type or a shadow entity of a type is treated as an
          --  incomplete type, and carries the corresponding attributes.
 
-         Set_Ekind              (Ent, E_Incomplete_Type);
+         Mutate_Ekind           (Ent, E_Incomplete_Type);
          Set_Etype              (Ent, Ent);
          Set_Full_View          (Ent, Empty);
          Set_Is_First_Subtype   (Ent);
@@ -5669,7 +5855,7 @@ package body Sem_Ch10 is
 
             Set_Parent (CW_Typ, Parent (Ent));
 
-            Set_Ekind                     (CW_Typ, E_Class_Wide_Type);
+            Mutate_Ekind                  (CW_Typ, E_Class_Wide_Type);
             Set_Class_Wide_Type           (CW_Typ, CW_Typ);
             Set_Etype                     (CW_Typ, Ent);
             Set_Equivalent_Type           (CW_Typ, Empty);
@@ -5689,7 +5875,7 @@ package body Sem_Ch10 is
 
       procedure Decorate_Variable (Ent : Entity_Id; Scop : Entity_Id) is
       begin
-         Set_Ekind (Ent, E_Variable);
+         Mutate_Ekind (Ent, E_Variable);
          Set_Etype (Ent, Standard_Void_Type);
          Set_Scope (Ent, Scop);
       end Decorate_Variable;
@@ -5901,19 +6087,20 @@ package body Sem_Ch10 is
                Build_Shadow_Entity (Def_Id, Scop, Shadow);
 
                Process_Declarations_And_States
-                 (Pack  => Def_Id,
-                  Decls => Visible_Declarations (Specification (Decl)),
-                  Scop  => Shadow,
+                 (Pack                  => Def_Id,
+                  Decls                 =>
+                    Visible_Declarations (Specification (Decl)),
+                  Scop                  => Shadow,
                   Create_Abstract_Views => Create_Abstract_Views);
 
             --  Types
 
-            elsif Nkind_In (Decl, N_Full_Type_Declaration,
-                                  N_Incomplete_Type_Declaration,
-                                  N_Private_Extension_Declaration,
-                                  N_Private_Type_Declaration,
-                                  N_Protected_Type_Declaration,
-                                  N_Task_Type_Declaration)
+            elsif Nkind (Decl) in N_Full_Type_Declaration
+                                | N_Incomplete_Type_Declaration
+                                | N_Private_Extension_Declaration
+                                | N_Private_Type_Declaration
+                                | N_Protected_Type_Declaration
+                                | N_Task_Type_Declaration
             then
                Def_Id := Defining_Entity (Decl);
 
@@ -5932,8 +6119,8 @@ package body Sem_Ch10 is
                      (Nkind (Def) = N_Derived_Type_Definition
                         and then Present (Record_Extension_Part (Def)));
 
-               elsif Nkind_In (Decl, N_Incomplete_Type_Declaration,
-                                     N_Private_Type_Declaration)
+               elsif Nkind (Decl) in N_Incomplete_Type_Declaration
+                                   | N_Private_Type_Declaration
                then
                   Is_Tagged := Tagged_Present (Decl);
 
@@ -6004,34 +6191,35 @@ package body Sem_Ch10 is
             null;
 
          when N_Subprogram_Declaration =>
-            Error_Msg_N ("subprograms not allowed in limited with_clauses", N);
+            Error_Msg_N
+              ("subprogram not allowed in `LIMITED WITH` clause", N);
             return;
 
          when N_Generic_Package_Declaration
             | N_Generic_Subprogram_Declaration
          =>
-            Error_Msg_N ("generics not allowed in limited with_clauses", N);
+            Error_Msg_N ("generic not allowed in `LIMITED WITH` clause", N);
             return;
 
          when N_Generic_Instantiation =>
             Error_Msg_N
-              ("generic instantiations not allowed in limited with_clauses",
+              ("generic instantiation not allowed in `LIMITED WITH` clause",
                N);
             return;
 
          when N_Generic_Renaming_Declaration =>
             Error_Msg_N
-              ("generic renamings not allowed in limited with_clauses", N);
+              ("generic renaming not allowed in `LIMITED WITH` clause", N);
             return;
 
          when N_Subprogram_Renaming_Declaration =>
             Error_Msg_N
-              ("renamed subprograms not allowed in limited with_clauses", N);
+              ("renamed subprogram not allowed in `LIMITED WITH` clause", N);
             return;
 
          when N_Package_Renaming_Declaration =>
             Error_Msg_N
-              ("renamed packages not allowed in limited with_clauses", N);
+              ("renamed package not allowed in `LIMITED WITH` clause", N);
             return;
 
          when others =>
@@ -6042,7 +6230,7 @@ package body Sem_Ch10 is
       --  must be minimally decorated. This ensures that the checks on unused
       --  with clauses also process limieted withs.
 
-      Set_Ekind (Pack, E_Package);
+      Mutate_Ekind (Pack, E_Package);
       Set_Etype (Pack, Standard_Void_Type);
 
       if Is_Entity_Name (Nam) then
@@ -6064,7 +6252,7 @@ package body Sem_Ch10 is
       --  incomplete view of all types and packages declared within.
 
       Shadow_Pack := Make_Temporary (Sloc (N), 'Z');
-      Set_Ekind        (Shadow_Pack, E_Package);
+      Mutate_Ekind     (Shadow_Pack, E_Package);
       Set_Is_Internal  (Shadow_Pack);
       Set_Limited_View (Pack, Shadow_Pack);
 
@@ -6073,20 +6261,20 @@ package body Sem_Ch10 is
       --  variables and types.
 
       Process_Declarations_And_States
-        (Pack  => Pack,
-         Decls => Visible_Declarations (Spec),
-         Scop  => Pack,
+        (Pack                  => Pack,
+         Decls                 => Visible_Declarations (Spec),
+         Scop                  => Pack,
          Create_Abstract_Views => True);
 
       Last_Public_Shadow := Last_Shadow;
 
       --  Ada 2005 (AI-262): Build the limited view of the private declarations
-      --  to accomodate limited private with clauses.
+      --  to accommodate limited private with clauses.
 
       Process_Declarations_And_States
-        (Pack  => Pack,
-         Decls => Private_Declarations (Spec),
-         Scop  => Pack,
+        (Pack                  => Pack,
+         Decls                 => Private_Declarations (Spec),
+         Scop                  => Pack,
          Create_Abstract_Views => False);
 
       if Present (Last_Public_Shadow) then
@@ -6163,7 +6351,7 @@ package body Sem_Ch10 is
          if Is_Subprogram (E) and then Has_Pragma_Inline (E) then
             return True;
 
-         elsif Ekind_In (E, E_Generic_Function, E_Generic_Procedure) then
+         elsif Is_Generic_Subprogram (E) then
 
             --  A generic subprogram always requires the presence of its
             --  body because an instantiation needs both templates. The only
@@ -6215,7 +6403,7 @@ package body Sem_Ch10 is
       then
          Set_Body_Needed_For_SAL (Unit_Name);
 
-      elsif Ekind_In (Unit_Name, E_Generic_Procedure, E_Generic_Function) then
+      elsif Ekind (Unit_Name) in E_Generic_Procedure | E_Generic_Function then
          Set_Body_Needed_For_SAL (Unit_Name);
 
       elsif Is_Subprogram (Unit_Name)
@@ -6269,22 +6457,38 @@ package body Sem_Ch10 is
 
    begin
       --  Ada 2005 (AI-50217): We remove the context clauses in two phases:
-      --  limited-views first and regular-views later (to maintain the
-      --  stack model).
+      --  limited-views first and regular-views later (to maintain the stack
+      --  model).
 
       --  First Phase: Remove limited_with context clauses
 
       Item := First (Context_Items (N));
       while Present (Item) loop
 
-         --  We are interested only in with clauses which got installed
-         --  on entry.
+         --  We are interested only in with clauses that got installed on entry
 
          if Nkind (Item) = N_With_Clause
            and then Limited_Present (Item)
-           and then Limited_View_Installed (Item)
          then
-            Remove_Limited_With_Clause (Item);
+            if Limited_View_Installed (Item) then
+               Remove_Limited_With_Clause (Item);
+
+            --  An unusual case: If the library unit of the Main_Unit has a
+            --  limited with_clause on some unit P and the context somewhere
+            --  includes a with_clause on P, P has been analyzed. The entity
+            --  for P is still visible, which in general is harmless because
+            --  this is the end of the compilation, but it can affect pending
+            --  instantiations that may have been generated elsewhere, so it
+            --  it is necessary to remove U from visibility so that inlining
+            --  and the analysis of instance bodies can proceed cleanly.
+
+            elsif Current_Sem_Unit = Main_Unit
+              and then Serious_Errors_Detected = 0
+              and then not Implicit_With (Item)
+            then
+               Set_Is_Immediately_Visible
+                 (Defining_Entity (Unit (Library_Unit (Item))), False);
+            end if;
          end if;
 
          Next (Item);
@@ -6306,7 +6510,7 @@ package body Sem_Ch10 is
             null;
 
          elsif Nkind (Item) = N_With_Clause
-            and then Context_Installed (Item)
+           and then Context_Installed (Item)
          then
             --  Remove items from one with'ed unit
 
@@ -6330,149 +6534,268 @@ package body Sem_Ch10 is
    --------------------------------
 
    procedure Remove_Limited_With_Clause (N : Node_Id) is
-      P_Unit     : constant Entity_Id := Unit (Library_Unit (N));
-      E          : Entity_Id;
-      P          : Entity_Id;
-      Lim_Header : Entity_Id;
-      Lim_Typ    : Entity_Id;
-      Prev       : Entity_Id;
+      Pack_Decl : constant Entity_Id := Unit (Library_Unit (N));
 
    begin
       pragma Assert (Limited_View_Installed (N));
 
-      --  In case of limited with_clause on subprograms, generics, instances,
-      --  or renamings, the corresponding error was previously posted and we
-      --  have nothing to do here.
+      --  Limited with clauses that designate units other than packages are
+      --  illegal and are never installed.
 
-      if Nkind (P_Unit) /= N_Package_Declaration then
-         return;
+      if Nkind (Pack_Decl) = N_Package_Declaration then
+         Remove_Limited_With_Unit (Pack_Decl, N);
       end if;
 
-      P := Defining_Unit_Name (Specification (P_Unit));
+      --  Indicate that the limited views of the clause have been removed
 
-      --  Handle child packages
+      Set_Limited_View_Installed (N, False);
+   end Remove_Limited_With_Clause;
 
-      if Nkind (P) = N_Defining_Program_Unit_Name then
-         P := Defining_Identifier (P);
-      end if;
+   ------------------------------
+   -- Remove_Limited_With_Unit --
+   ------------------------------
 
-      if Debug_Flag_I then
-         Write_Str ("remove limited view of ");
-         Write_Name (Chars (P));
-         Write_Str (" from visibility");
-         Write_Eol;
-      end if;
+   procedure Remove_Limited_With_Unit
+     (Pack_Decl  : Node_Id;
+      Lim_Clause : Node_Id := Empty)
+   is
+      procedure Remove_Shadow_Entities_From_Visibility (Pack_Id : Entity_Id);
+      --  Remove the shadow entities of package Pack_Id from direct visibility
 
-      --  Prepare the removal of the shadow entities from visibility. The first
-      --  element of the limited view is a header (an E_Package entity) that is
-      --  used to reference the first shadow entity in the private part of the
-      --  package
+      procedure Remove_Shadow_Entities_With_Restore (Pack_Id : Entity_Id);
+      --  Remove the shadow entities of package Pack_Id from direct visibility,
+      --  restore the corresponding entities they hide into direct visibility,
+      --  and update the entity and homonym chains.
 
-      Lim_Header := Limited_View (P);
-      Lim_Typ    := First_Entity (Lim_Header);
+      --------------------------------------------
+      -- Remove_Shadow_Entities_From_Visibility --
+      --------------------------------------------
 
-      --  Remove package and shadow entities from visibility if it has not
-      --  been analyzed
+      procedure Remove_Shadow_Entities_From_Visibility (Pack_Id : Entity_Id) is
+         Lim_Header : constant Entity_Id := Limited_View (Pack_Id);
+         Upto       : constant Entity_Id := First_Private_Entity (Lim_Header);
 
-      if not Analyzed (P_Unit) then
-         Unchain (P);
-         Set_Is_Immediately_Visible (P, False);
+         Shadow : Entity_Id;
 
-         while Present (Lim_Typ) loop
-            Unchain (Lim_Typ);
-            Next_Entity (Lim_Typ);
+      begin
+         --  Remove the package from direct visibility
+
+         Unchain (Pack_Id);
+         Set_Is_Immediately_Visible (Pack_Id, False);
+
+         --  Remove all shadow entities from direct visibility
+
+         Shadow := First_Entity (Lim_Header);
+         while Present (Shadow) and then Shadow /= Upto loop
+            Unchain (Shadow);
+            Next_Entity (Shadow);
          end loop;
+      end Remove_Shadow_Entities_From_Visibility;
 
-      --  Otherwise this package has already appeared in the closure and its
-      --  shadow entities must be replaced by its real entities. This code
-      --  must be kept synchronized with the complementary code in Install
-      --  Limited_Withed_Unit.
+      -----------------------------------------
+      -- Remove_Shadow_Entities_With_Restore --
+      -----------------------------------------
 
-      else
-         --  If the limited_with_clause is in some other unit in the context
-         --  then it is not visible in the main unit.
+      procedure Remove_Shadow_Entities_With_Restore (Pack_Id : Entity_Id) is
+         procedure Restore_Chain_For_Shadow (Shadow : Entity_Id);
+         --  Remove shadow entity Shadow by updating the entity and homonym
+         --  chains.
 
-         if not In_Extended_Main_Source_Unit (N) then
-            Set_Is_Immediately_Visible (P, False);
-         end if;
+         procedure Restore_Chains
+           (From : Entity_Id;
+            Upto : Entity_Id);
+         --  Remove a sequence of shadow entities starting from From and ending
+         --  prior to Upto by updating the entity and homonym chains.
 
-         --  Real entities that are type or subtype declarations were hidden
-         --  from visibility at the point of installation of the limited-view.
-         --  Now we recover the previous value of the hidden attribute.
+         procedure Restore_Type_Visibility
+           (From : Entity_Id;
+            Upto : Entity_Id);
+         --  Restore a sequence of types starting from From and ending prior to
+         --  Upto back in direct visibility.
 
-         E := First_Entity (P);
-         while Present (E) and then E /= First_Private_Entity (P) loop
-            if Is_Type (E) then
-               Set_Is_Hidden (E, Was_Hidden (E));
+         ------------------------------
+         -- Restore_Chain_For_Shadow --
+         ------------------------------
+
+         procedure Restore_Chain_For_Shadow (Shadow : Entity_Id) is
+            Prev : Entity_Id;
+            Typ  : Entity_Id;
+
+         begin
+            --  If the package has incomplete types, the limited view of the
+            --  incomplete type is in fact never visible (AI05-129) but we
+            --  have created a shadow entity E1 for it, that points to E2,
+            --  a nonlimited incomplete type. This in turn has a full view
+            --  E3 that is the full declaration. There is a corresponding
+            --  shadow entity E4. When reinstalling the nonlimited view,
+            --  E2 must become the current entity and E3 must be ignored.
+
+            Typ := Non_Limited_View (Shadow);
+
+            --  Shadow is the limited view of a full type declaration that has
+            --  a previous incomplete declaration, i.e. E3 from the previous
+            --  description. Nothing to insert.
+
+            if Present (Current_Entity (Typ))
+              and then Ekind (Current_Entity (Typ)) = E_Incomplete_Type
+              and then Full_View (Current_Entity (Typ)) = Typ
+            then
+               return;
             end if;
 
-            Next_Entity (E);
-         end loop;
+            pragma Assert (not In_Chain (Typ));
 
-         while Present (Lim_Typ)
-           and then Lim_Typ /= First_Private_Entity (Lim_Header)
-         loop
-            --  Nested packages and child units were not unchained
+            Prev := Current_Entity (Shadow);
 
-            if Ekind (Lim_Typ) /= E_Package
-              and then not Is_Child_Unit (Non_Limited_View (Lim_Typ))
-            then
-               --  If the package has incomplete types, the limited view of the
-               --  incomplete type is in fact never visible (AI05-129) but we
-               --  have created a shadow entity E1 for it, that points to E2,
-               --  a non-limited incomplete type. This in turn has a full view
-               --  E3 that is the full declaration. There is a corresponding
-               --  shadow entity E4. When reinstalling the non-limited view,
-               --  E2 must become the current entity and E3 must be ignored.
-
-               E := Non_Limited_View (Lim_Typ);
-
-               if Present (Current_Entity (E))
-                 and then Ekind (Current_Entity (E)) = E_Incomplete_Type
-                 and then Full_View (Current_Entity (E)) = E
-               then
+            if Prev = Shadow then
+               Set_Current_Entity (Typ);
+
+            else
+               while Present (Prev) and then Homonym (Prev) /= Shadow loop
+                  Prev := Homonym (Prev);
+               end loop;
+
+               if Present (Prev) then
+                  Set_Homonym (Prev, Typ);
+               end if;
+            end if;
+
+            Set_Homonym (Typ, Homonym (Shadow));
+         end Restore_Chain_For_Shadow;
+
+         --------------------
+         -- Restore_Chains --
+         --------------------
+
+         procedure Restore_Chains
+           (From : Entity_Id;
+            Upto : Entity_Id)
+         is
+            Shadow : Entity_Id;
+
+         begin
+            Shadow := From;
+            while Present (Shadow) and then Shadow /= Upto loop
 
-                  --  Lim_Typ is the limited view of a full type declaration
-                  --  that has a previous incomplete declaration, i.e. E3 from
-                  --  the previous description. Nothing to insert.
+               --  Do not unchain nested packages and child units
 
+               if Ekind (Shadow) = E_Package then
+                  null;
+
+               elsif Is_Child_Unit (Non_Limited_View (Shadow)) then
                   null;
 
                else
-                  pragma Assert (not In_Chain (E));
+                  Restore_Chain_For_Shadow (Shadow);
+               end if;
 
-                  Prev := Current_Entity (Lim_Typ);
+               Next_Entity (Shadow);
+            end loop;
+         end Restore_Chains;
 
-                  if Prev = Lim_Typ then
-                     Set_Current_Entity (E);
+         -----------------------------
+         -- Restore_Type_Visibility --
+         -----------------------------
 
-                  else
-                     while Present (Prev)
-                       and then Homonym (Prev) /= Lim_Typ
-                     loop
-                        Prev := Homonym (Prev);
-                     end loop;
+         procedure Restore_Type_Visibility
+           (From : Entity_Id;
+            Upto : Entity_Id)
+         is
+            Typ : Entity_Id;
 
-                     if Present (Prev) then
-                        Set_Homonym (Prev, E);
-                     end if;
-                  end if;
+         begin
+            Typ := From;
+            while Present (Typ) and then Typ /= Upto loop
+               if Is_Type (Typ) then
+                  Set_Is_Hidden (Typ, Was_Hidden (Typ));
+               end if;
+
+               Next_Entity (Typ);
+            end loop;
+         end Restore_Type_Visibility;
 
-                  --  Preserve structure of homonym chain
+         --  Local variables
 
-                  Set_Homonym (E, Homonym (Lim_Typ));
-               end if;
-            end if;
+         Lim_Header : constant Entity_Id := Limited_View (Pack_Id);
 
-            Next_Entity (Lim_Typ);
-         end loop;
+      --  Start of processing Remove_Shadow_Entities_With_Restore
+
+      begin
+         --  The limited view of a package is being uninstalled by removing
+         --  the effects of a limited with clause. If the clause appears in a
+         --  unit which is not part of the main unit closure, then the related
+         --  package must not be visible.
+
+         if Present (Lim_Clause)
+           and then not In_Extended_Main_Source_Unit (Lim_Clause)
+         then
+            Set_Is_Immediately_Visible (Pack_Id, False);
+
+         --  Otherwise a limited view is being overridden by a nonlimited view.
+         --  Leave the visibility of the package as is because the unit must be
+         --  visible when the nonlimited view is installed.
+
+         else
+            null;
+         end if;
+
+         --  Remove the shadow entities from visibility by updating the entity
+         --  and homonym chains.
+
+         Restore_Chains
+           (From => First_Entity (Lim_Header),
+            Upto => First_Private_Entity (Lim_Header));
+
+         --  Reinstate the types that were hidden by the shadow entities back
+         --  into direct visibility.
+
+         Restore_Type_Visibility
+           (From => First_Entity (Pack_Id),
+            Upto => First_Private_Entity (Pack_Id));
+      end Remove_Shadow_Entities_With_Restore;
+
+      --  Local variables
+
+      Pack_Id : constant Entity_Id := Defining_Entity (Pack_Decl);
+
+   --  Start of processing for Remove_Limited_With_Unit
+
+   begin
+      --  Nothing to do when the limited view of the package is not installed
+
+      if not From_Limited_With (Pack_Id) then
+         return;
+      end if;
+
+      if Debug_Flag_I then
+         Write_Str ("remove limited view of ");
+         Write_Name (Chars (Pack_Id));
+         Write_Str (" from visibility");
+         Write_Eol;
+      end if;
+
+      --  The package already appears in the compilation closure. As a result,
+      --  its shadow entities must be replaced by the real entities they hide
+      --  and the previously hidden entities must be entered back into direct
+      --  visibility.
+
+      --  WARNING: This code must be kept synchronized with that of routine
+      --  Install_Limited_Withed_Clause.
+
+      if Analyzed (Pack_Decl) then
+         Remove_Shadow_Entities_With_Restore (Pack_Id);
+
+      --  Otherwise the package is not analyzed and its shadow entities must be
+      --  removed from direct visibility.
+
+      else
+         Remove_Shadow_Entities_From_Visibility (Pack_Id);
       end if;
 
       --  Indicate that the limited view of the package is not installed
 
-      Set_From_Limited_With      (P, False);
-      Set_Limited_View_Installed (N, False);
-   end Remove_Limited_With_Clause;
+      Set_From_Limited_With (Pack_Id, False);
+   end Remove_Limited_With_Unit;
 
    --------------------
    -- Remove_Parents --
@@ -6541,12 +6864,12 @@ package body Sem_Ch10 is
       -- In_Regular_With_Clause --
       ----------------------------
 
-      function In_Regular_With_Clause (E : Entity_Id) return Boolean
-      is
+      function In_Regular_With_Clause (E : Entity_Id) return Boolean is
          Item : Node_Id;
 
       begin
          Item := First (Context_Items (Comp_Unit));
+
          while Present (Item) loop
             if Nkind (Item) = N_With_Clause
 
@@ -6559,6 +6882,7 @@ package body Sem_Ch10 is
             then
                return True;
             end if;
+
             Next (Item);
          end loop;
 
@@ -6574,13 +6898,16 @@ package body Sem_Ch10 is
 
             --  If private_with_clause is redundant, remove it from context,
             --  as a small optimization to subsequent handling of private_with
-            --  clauses in other nested packages.
+            --  clauses in other nested packages. We replace the clause with
+            --  a null statement, which is otherwise ignored by the rest of
+            --  the compiler.
 
             if In_Regular_With_Clause (Entity (Name (Item))) then
                declare
                   Nxt : constant Node_Id := Next (Item);
                begin
-                  Remove (Item);
+                  Rewrite (Item, Make_Null_Statement (Sloc (Item)));
+                  Analyze (Item);
                   Item := Nxt;
                end;
 
This page took 0.130024 seconds and 5 git commands to generate.