]> git.ipfire.org Git - thirdparty/gcc.git/blobdiff - gcc/ada/sem_ch8.adb
[Ada] Follow-on cleanups for Uint fields
[thirdparty/gcc.git] / gcc / ada / sem_ch8.adb
index 3bdce445ffa849d5259baad550590aa45bc0641a..686d4378f8cc6b7c6e31674c11d7b358bdea7b48 100644 (file)
@@ -6,7 +6,7 @@
 --                                                                          --
 --                                 B o d y                                  --
 --                                                                          --
---          Copyright (C) 1992-2020, 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 Atree;    use Atree;
-with Debug;    use Debug;
-with Einfo;    use Einfo;
-with Elists;   use Elists;
-with Errout;   use Errout;
-with Exp_Disp; use Exp_Disp;
-with Exp_Tss;  use Exp_Tss;
-with Exp_Util; use Exp_Util;
-with Freeze;   use Freeze;
-with Ghost;    use Ghost;
-with Impunit;  use Impunit;
-with Lib;      use Lib;
-with Lib.Load; use Lib.Load;
-with Lib.Xref; use Lib.Xref;
-with Namet;    use Namet;
-with Namet.Sp; use Namet.Sp;
-with Nlists;   use Nlists;
-with Nmake;    use Nmake;
-with Opt;      use Opt;
-with Output;   use Output;
-with Restrict; use Restrict;
-with Rident;   use Rident;
-with Rtsfind;  use Rtsfind;
-with Sem;      use Sem;
-with Sem_Aux;  use Sem_Aux;
-with Sem_Cat;  use Sem_Cat;
-with Sem_Ch3;  use Sem_Ch3;
-with Sem_Ch4;  use Sem_Ch4;
-with Sem_Ch6;  use Sem_Ch6;
-with Sem_Ch10; use Sem_Ch10;
-with Sem_Ch12; use Sem_Ch12;
-with Sem_Ch13; use Sem_Ch13;
-with Sem_Dim;  use Sem_Dim;
-with Sem_Disp; use Sem_Disp;
-with Sem_Dist; use Sem_Dist;
-with Sem_Elab; use Sem_Elab;
-with Sem_Eval; use Sem_Eval;
-with Sem_Prag; use Sem_Prag;
-with Sem_Res;  use Sem_Res;
-with Sem_Util; use Sem_Util;
-with Sem_Type; use Sem_Type;
-with Stand;    use Stand;
-with Sinfo;    use Sinfo;
-with Sinfo.CN; use Sinfo.CN;
-with Snames;   use Snames;
+with Atree;          use Atree;
+with Debug;          use Debug;
+with Einfo;          use Einfo;
+with Einfo.Entities; use Einfo.Entities;
+with Einfo.Utils;    use Einfo.Utils;
+with Elists;         use Elists;
+with Errout;         use Errout;
+with Exp_Disp;       use Exp_Disp;
+with Exp_Tss;        use Exp_Tss;
+with Exp_Util;       use Exp_Util;
+with Freeze;         use Freeze;
+with Ghost;          use Ghost;
+with Impunit;        use Impunit;
+with Lib;            use Lib;
+with Lib.Load;       use Lib.Load;
+with Lib.Xref;       use Lib.Xref;
+with Namet;          use Namet;
+with Namet.Sp;       use Namet.Sp;
+with Nlists;         use Nlists;
+with Nmake;          use Nmake;
+with Opt;            use Opt;
+with Output;         use Output;
+with Restrict;       use Restrict;
+with Rident;         use Rident;
+with Rtsfind;        use Rtsfind;
+with Sem;            use Sem;
+with Sem_Aux;        use Sem_Aux;
+with Sem_Cat;        use Sem_Cat;
+with Sem_Ch3;        use Sem_Ch3;
+with Sem_Ch4;        use Sem_Ch4;
+with Sem_Ch6;        use Sem_Ch6;
+with Sem_Ch10;       use Sem_Ch10;
+with Sem_Ch12;       use Sem_Ch12;
+with Sem_Ch13;       use Sem_Ch13;
+with Sem_Dim;        use Sem_Dim;
+with Sem_Disp;       use Sem_Disp;
+with Sem_Dist;       use Sem_Dist;
+with Sem_Elab;       use Sem_Elab;
+with Sem_Eval;       use Sem_Eval;
+with Sem_Prag;       use Sem_Prag;
+with Sem_Res;        use Sem_Res;
+with Sem_Util;       use Sem_Util;
+with Sem_Type;       use Sem_Type;
+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 Snames;         use Snames;
 with Style;
 with Table;
-with Tbuild;   use Tbuild;
-with Uintp;    use Uintp;
+with Tbuild;         use Tbuild;
+with Uintp;          use Uintp;
 
 package body Sem_Ch8 is
 
@@ -422,12 +426,10 @@ package body Sem_Ch8 is
    --  body at the point of freezing will not work. Subp is the subprogram
    --  for which N provides the Renaming_As_Body.
 
-   procedure Check_In_Previous_With_Clause
-     (N   : Node_Id;
-      Nam : Node_Id);
+   procedure Check_In_Previous_With_Clause (N, Nam : Node_Id);
    --  N is a use_package clause and Nam the package name, or N is a use_type
    --  clause and Nam is the prefix of the type name. In either case, verify
-   --  that the package is visible at that point in the context: either  it
+   --  that the package is visible at that point in the context: either it
    --  appears in a previous with_clause, or because it is a fully qualified
    --  name and the root ancestor appears in a previous with_clause.
 
@@ -477,11 +479,10 @@ package body Sem_Ch8 is
    --  legality of selector given the scope denoted by prefix, and change node
    --  N into a expanded name with a properly set Entity field.
 
-   function Find_Most_Prev (Use_Clause : Node_Id) return Node_Id;
+   function Find_First_Use (Use_Clause : Node_Id) return Node_Id;
    --  Find the most previous use clause (that is, the first one to appear in
    --  the source) by traversing the previous clause chain that exists in both
    --  N_Use_Package_Clause nodes and N_Use_Type_Clause nodes.
-   --  ??? a better subprogram name is in order
 
    function Find_Renamed_Entity
      (N         : Node_Id;
@@ -525,7 +526,6 @@ package body Sem_Ch8 is
       Clause2 : Entity_Id) return Entity_Id;
    --  Determine which use clause parameter is the most descendant in terms of
    --  scope.
-   --  ??? a better subprogram name is in order
 
    procedure Premature_Usage (N : Node_Id);
    --  Diagnose usage of an entity before it is visible
@@ -568,7 +568,7 @@ package body Sem_Ch8 is
       Enter_Name (Id);
       Analyze (Nam);
 
-      Set_Ekind   (Id, E_Exception);
+      Mutate_Ekind   (Id, E_Exception);
       Set_Etype   (Id, Standard_Exception_Type);
       Set_Is_Pure (Id, Is_Pure (Current_Scope));
 
@@ -576,10 +576,10 @@ package body Sem_Ch8 is
         and then Present (Entity (Nam))
         and then Ekind (Entity (Nam)) = E_Exception
       then
-         if Present (Renamed_Object (Entity (Nam))) then
-            Set_Renamed_Object (Id, Renamed_Object (Entity (Nam)));
+         if Present (Renamed_Entity (Entity (Nam))) then
+            Set_Renamed_Entity (Id, Renamed_Entity (Entity (Nam)));
          else
-            Set_Renamed_Object (Id, Entity (Nam));
+            Set_Renamed_Entity (Id, Entity (Nam));
          end if;
 
          --  The exception renaming declaration may become Ghost if it renames
@@ -697,7 +697,7 @@ package body Sem_Ch8 is
       end if;
 
       Enter_Name (New_P);
-      Set_Ekind (New_P, K);
+      Mutate_Ekind (New_P, K);
 
       if Etype (Old_P) = Any_Type then
          null;
@@ -706,10 +706,10 @@ package body Sem_Ch8 is
          Error_Msg_N ("invalid generic unit name", Name (N));
 
       else
-         if Present (Renamed_Object (Old_P)) then
-            Set_Renamed_Object (New_P, Renamed_Object (Old_P));
+         if Present (Renamed_Entity (Old_P)) then
+            Set_Renamed_Entity (New_P, Renamed_Entity (Old_P));
          else
-            Set_Renamed_Object (New_P, Old_P);
+            Set_Renamed_Entity (New_P, Old_P);
          end if;
 
          --  The generic renaming declaration may become Ghost if it renames a
@@ -759,6 +759,7 @@ package body Sem_Ch8 is
       Dec           : Node_Id;
       T             : Entity_Id;
       T2            : Entity_Id;
+      Q             : Node_Id;
 
       procedure Check_Constrained_Object;
       --  If the nominal type is unconstrained but the renamed object is
@@ -772,6 +773,31 @@ package body Sem_Ch8 is
       --  Obtain the name of the object from node Nod which is being renamed by
       --  the object renaming declaration N.
 
+      function Find_Raise_Node (N : Node_Id) return Traverse_Result;
+      --  Process one node in search for N_Raise_xxx_Error nodes.
+      --  Return Abandon if found, OK otherwise.
+
+      ---------------------
+      -- Find_Raise_Node --
+      ---------------------
+
+      function Find_Raise_Node (N : Node_Id) return Traverse_Result is
+      begin
+         if Nkind (N) in N_Raise_xxx_Error then
+            return Abandon;
+         else
+            return OK;
+         end if;
+      end Find_Raise_Node;
+
+      ------------------------
+      -- No_Raise_xxx_Error --
+      ------------------------
+
+      function No_Raise_xxx_Error is new Traverse_Func (Find_Raise_Node);
+      --  Traverse tree to look for a N_Raise_xxx_Error node and returns
+      --  Abandon if so and OK if none found.
+
       ------------------------------
       -- Check_Constrained_Object --
       ------------------------------
@@ -805,11 +831,19 @@ package body Sem_Ch8 is
             --  that are used in iterators. This is an optimization, but it
             --  also prevents typing anomalies when the prefix is further
             --  expanded.
+
             --  Note that we cannot just use the Is_Limited_Record flag because
             --  it does not apply to records with limited components, for which
             --  this syntactic flag is not set, but whose size is also fixed.
 
-            elsif Is_Limited_Type (Typ) then
+            --  Note also that we need to build the constrained subtype for an
+            --  array in order to make the bounds explicit in most cases, but
+            --  not if the object comes from an extended return statement, as
+            --  this would create dangling references to them later on.
+
+            elsif Is_Limited_Type (Typ)
+              and then (not Is_Array_Type (Typ) or else Is_Return_Object (Id))
+            then
                null;
 
             else
@@ -946,7 +980,7 @@ package body Sem_Ch8 is
                   Error_Msg_N
                     ("object name or value expected in renaming", Nam);
 
-                  Set_Ekind (Id, E_Variable);
+                  Mutate_Ekind (Id, E_Variable);
                   Set_Etype (Id, Any_Type);
 
                   return;
@@ -994,7 +1028,7 @@ package body Sem_Ch8 is
                      Error_Msg_N
                        ("object name or value expected in renaming", Nam);
 
-                     Set_Ekind (Id, E_Variable);
+                     Mutate_Ekind (Id, E_Variable);
                      Set_Etype (Id, Any_Type);
 
                      return;
@@ -1038,6 +1072,60 @@ package body Sem_Ch8 is
             Mark_Ghost_Renaming (N, Entity (Nam));
          end if;
 
+         --  Check against AI12-0401 here before Resolve may rewrite Nam and
+         --  potentially generate spurious warnings.
+
+         --   In the case where the object_name is a qualified_expression with
+         --   a nominal subtype T and whose expression is a name that denotes
+         --   an object Q:
+         --    * if T is an elementary subtype, then:
+         --      * Q shall be a constant other than a dereference of an access
+         --        type; or
+         --      * the nominal subtype of Q shall be statically compatible with
+         --        T; or
+         --      * T shall statically match the base subtype of its type if
+         --        scalar, or the first subtype of its type if an access type.
+         --    * if T is a composite subtype, then Q shall be known to be
+         --      constrained or T shall statically match the first subtype of
+         --      its type.
+
+         if Nkind (Nam) = N_Qualified_Expression
+           and then Is_Object_Reference (Expression (Nam))
+         then
+            Q := Expression (Nam);
+
+            if (Is_Elementary_Type (T)
+                  and then
+                not ((not Is_Variable (Q)
+                       and then Nkind (Q) /= N_Explicit_Dereference)
+                      or else Subtypes_Statically_Compatible (Etype (Q), T)
+                      or else (Is_Scalar_Type (T)
+                                and then Subtypes_Statically_Match
+                                           (T, Base_Type (T)))
+                      or else (Is_Access_Type (T)
+                                and then Subtypes_Statically_Match
+                                           (T, First_Subtype (T)))))
+              or else (Is_Composite_Type (T)
+                         and then
+
+                       --  If Q is an aggregate, Is_Constrained may not be set
+                       --  yet and its type may not be resolved yet.
+                       --  This doesn't quite correspond to the complex notion
+                       --  of "known to be constrained" but this is good enough
+                       --  for a rule which is in any case too complex.
+
+                       not (Is_Constrained (Etype (Q))
+                             or else Nkind (Q) = N_Aggregate
+                             or else Subtypes_Statically_Match
+                                       (T, First_Subtype (T))))
+            then
+               Error_Msg_N
+                 ("subtype of renamed qualified expression does not " &
+                  "statically match", N);
+               return;
+            end if;
+         end if;
+
          Resolve (Nam, T);
 
          --  If the renamed object is a function call of a limited type,
@@ -1053,7 +1141,7 @@ package body Sem_Ch8 is
            and then Comes_From_Source (N)
          then
             Set_Etype (Id, T);
-            Set_Ekind (Id, E_Constant);
+            Mutate_Ekind (Id, E_Constant);
             Rewrite (N,
               Make_Object_Declaration (Loc,
                 Defining_Identifier => Id,
@@ -1076,7 +1164,9 @@ package body Sem_Ch8 is
            and then Is_Anonymous_Access_Type (Etype (Expression (Nam)))
            and then not Is_Anonymous_Access_Type (T)
          then
-            Wrong_Type (Expression (Nam), T); -- Should we give better error???
+            Error_Msg_NE
+              ("cannot rename anonymous access object "
+                & "as a named access type", Expression (Nam), T);
          end if;
 
          --  Check that a class-wide object is not being renamed as an object
@@ -1237,13 +1327,13 @@ package body Sem_Ch8 is
                  and then Comes_From_Source (Nam)
                then
                   Error_Msg_N
-                    ("renaming function result object is suspicious?R?", Nam);
+                    ("renaming function result object is suspicious?.r?", Nam);
                   Error_Msg_NE
-                    ("\function & will be called only once?R?", Nam,
+                    ("\function & will be called only once?.r?", Nam,
                      Entity (Name (Nam)));
                   Error_Msg_N -- CODEFIX
                     ("\suggest using an initialized constant object "
-                     & "instead?R?", Nam);
+                     & "instead?.r?", Nam);
                end if;
          end case;
       end if;
@@ -1366,14 +1456,10 @@ package body Sem_Ch8 is
       --  want to change it to a variable.
 
       if Ekind (Id) /= E_Constant then
-         Set_Ekind (Id, E_Variable);
+         Mutate_Ekind (Id, E_Variable);
       end if;
 
-      --  Initialize the object size and alignment. Note that we used to call
-      --  Init_Size_Align here, but that's wrong for objects which have only
-      --  an Esize, not an RM_Size field.
-
-      Init_Object_Size_Align (Id);
+      Reinit_Object_Size_Align (Id);
 
       --  If N comes from source then check that the original node is an
       --  object reference since there may have been several rewritting and
@@ -1438,16 +1524,17 @@ package body Sem_Ch8 is
       then
          Error_Msg_N ("incompatible types in renaming", Nam);
 
-      --  AI12-0383: Names that denote values can be renamed
+      --  AI12-0383: Names that denote values can be renamed.
+      --  Ignore (accept) N_Raise_xxx_Error nodes in this context.
 
-      elsif Ada_Version < Ada_2020 then
-         Error_Msg_N ("value in renaming requires -gnat2020", Nam);
+      elsif No_Raise_xxx_Error (Nam) = OK then
+         Error_Msg_Ada_2022_Feature ("value in renaming", Sloc (Nam));
       end if;
 
       Set_Etype (Id, T2);
 
       if not Is_Variable (Nam) then
-         Set_Ekind               (Id, E_Constant);
+         Mutate_Ekind            (Id, E_Constant);
          Set_Never_Set_In_Source (Id, True);
          Set_Is_True_Constant    (Id, True);
       end if;
@@ -1456,10 +1543,11 @@ package body Sem_Ch8 is
       --  renamed object is atomic, independent, volatile or VFA. These flags
       --  are set on the renamed object in the RM legality sense.
 
-      Set_Is_Atomic               (Id, Is_Atomic_Object (Nam));
-      Set_Is_Independent          (Id, Is_Independent_Object (Nam));
-      Set_Is_Volatile             (Id, Is_Volatile_Object (Nam));
-      Set_Is_Volatile_Full_Access (Id, Is_Volatile_Full_Access_Object (Nam));
+      Set_Is_Atomic (Id, Is_Atomic_Object (Nam));
+      Set_Is_Independent (Id, Is_Independent_Object (Nam));
+      Set_Is_Volatile (Id, Is_Volatile_Object_Ref (Nam));
+      Set_Is_Volatile_Full_Access
+        (Id, Is_Volatile_Full_Access_Object_Ref (Nam));
 
       --  Treat as volatile if we just set the Volatile flag
 
@@ -1542,7 +1630,7 @@ package body Sem_Ch8 is
 
          --  Set basic attributes to minimize cascaded errors
 
-         Set_Ekind (New_P, E_Package);
+         Mutate_Ekind (New_P, E_Package);
          Set_Etype (New_P, Standard_Void_Type);
 
       elsif Present (Renamed_Entity (Old_P))
@@ -1557,7 +1645,7 @@ package body Sem_Ch8 is
 
          --  Set basic attributes to minimize cascaded errors
 
-         Set_Ekind (New_P, E_Package);
+         Mutate_Ekind (New_P, E_Package);
          Set_Etype (New_P, Standard_Void_Type);
 
       --  Here for OK package renaming
@@ -1567,13 +1655,13 @@ package body Sem_Ch8 is
          --  entity. The simplest implementation is to have both packages share
          --  the entity list.
 
-         Set_Ekind (New_P, E_Package);
+         Mutate_Ekind (New_P, E_Package);
          Set_Etype (New_P, Standard_Void_Type);
 
-         if Present (Renamed_Object (Old_P)) then
-            Set_Renamed_Object (New_P, Renamed_Object (Old_P));
+         if Present (Renamed_Entity (Old_P)) then
+            Set_Renamed_Entity (New_P, Renamed_Entity (Old_P));
          else
-            Set_Renamed_Object (New_P, Old_P);
+            Set_Renamed_Entity (New_P, Old_P);
          end if;
 
          --  The package renaming declaration may become Ghost if it renames a
@@ -1773,7 +1861,7 @@ package body Sem_Ch8 is
       Old_S := Find_Renamed_Entity (N, Selector_Name (Nam), New_S);
 
       if Old_S = Any_Id then
-         Error_Msg_N (" no subprogram or entry matches specification",  N);
+         Error_Msg_N ("no subprogram or entry matches specification",  N);
       else
          if Is_Body then
             Check_Subtype_Conformant (New_S, Old_S, N);
@@ -2021,42 +2109,6 @@ package body Sem_Ch8 is
       Old_S       : Entity_Id := Empty;
       Rename_Spec : Entity_Id;
 
-      procedure Build_Class_Wide_Wrapper
-        (Ren_Id  : out Entity_Id;
-         Wrap_Id : out Entity_Id);
-      --  Ada 2012 (AI05-0071): A generic/instance scenario involving a formal
-      --  type with unknown discriminants and a generic primitive operation of
-      --  the said type with a box require special processing when the actual
-      --  is a class-wide type:
-      --
-      --    generic
-      --       type Formal_Typ (<>) is private;
-      --       with procedure Prim_Op (Param : Formal_Typ) is <>;
-      --    package Gen is ...
-      --
-      --    package Inst is new Gen (Actual_Typ'Class);
-      --
-      --  In this case the general renaming mechanism used in the prologue of
-      --  an instance no longer applies:
-      --
-      --    procedure Prim_Op (Param : Formal_Typ) renames Prim_Op;
-      --
-      --  The above is replaced the following wrapper/renaming combination:
-      --
-      --    procedure Wrapper (Param : Formal_Typ) is  --  wrapper
-      --    begin
-      --       Prim_Op (Param);                        --  primitive
-      --    end Wrapper;
-      --
-      --    procedure Prim_Op (Param : Formal_Typ) renames Wrapper;
-      --
-      --  This transformation applies only if there is no explicit visible
-      --  class-wide operation at the point of the instantiation. Ren_Id is
-      --  the entity of the renaming declaration. When the transformation
-      --  applies, Wrap_Id is the entity of the generated class-wide wrapper
-      --  (or Any_Id). Otherwise, Wrap_Id is the entity of the class-wide
-      --  operation.
-
       procedure Check_Null_Exclusion
         (Ren : Entity_Id;
          Sub : Entity_Id);
@@ -2082,9 +2134,21 @@ package body Sem_Ch8 is
       --  incomplete untagged formal (RM 13.14(10.2/3)).
 
       function Has_Class_Wide_Actual return Boolean;
-      --  Ada 2012 (AI05-071, AI05-0131): True if N is the renaming for a
-      --  defaulted formal subprogram where the actual for the controlling
-      --  formal type is class-wide.
+      --  Ada 2012 (AI05-071, AI05-0131) and Ada 2022 (AI12-0165): True if N is
+      --  the renaming for a defaulted formal subprogram where the actual for
+      --  the controlling formal type is class-wide.
+
+      procedure Handle_Instance_With_Class_Wide_Type
+        (Inst_Node    : Node_Id;
+         Ren_Id       : Entity_Id;
+         Wrapped_Prim : out Entity_Id;
+         Wrap_Id      : out Entity_Id);
+      --  Ada 2012 (AI05-0071), Ada 2022 (AI12-0165): when the actual type
+      --  of an instantiation is a class-wide type T'Class we may need to
+      --  wrap a primitive operation of T; this routine looks for a suitable
+      --  primitive to be wrapped and (if the wrapper is required) returns the
+      --  Id of the wrapped primitive and the Id of the built wrapper. Ren_Id
+      --  is the defining entity for the renamed subprogram specification.
 
       function Original_Subprogram (Subp : Entity_Id) return Entity_Id;
       --  Find renamed entity when the declaration is a renaming_as_body and
@@ -2093,732 +2157,896 @@ package body Sem_Ch8 is
       --  before the subprogram it completes is frozen, and renaming indirectly
       --  renames the subprogram itself.(Defect Report 8652/0027).
 
-      ------------------------------
-      -- Build_Class_Wide_Wrapper --
-      ------------------------------
+      --------------------------
+      -- Check_Null_Exclusion --
+      --------------------------
 
-      procedure Build_Class_Wide_Wrapper
-        (Ren_Id  : out Entity_Id;
-         Wrap_Id : out Entity_Id)
+      procedure Check_Null_Exclusion
+        (Ren : Entity_Id;
+         Sub : Entity_Id)
       is
-         Loc : constant Source_Ptr := Sloc (N);
-
-         function Build_Call
-           (Subp_Id : Entity_Id;
-            Params  : List_Id) return Node_Id;
-         --  Create a dispatching call to invoke routine Subp_Id with actuals
-         --  built from the parameter specifications of list Params.
-
-         function Build_Expr_Fun_Call
-           (Subp_Id : Entity_Id;
-            Params  : List_Id) return Node_Id;
-         --  Create a dispatching call to invoke function Subp_Id with actuals
-         --  built from the parameter specifications of list Params. Return
-         --  directly the call, so that it can be used inside an expression
-         --  function. This is a specificity of the GNATprove mode.
-
-         function Build_Spec (Subp_Id : Entity_Id) return Node_Id;
-         --  Create a subprogram specification based on the subprogram profile
-         --  of Subp_Id.
-
-         function Find_Primitive (Typ : Entity_Id) return Entity_Id;
-         --  Find a primitive subprogram of type Typ which matches the profile
-         --  of the renaming declaration.
-
-         procedure Interpretation_Error (Subp_Id : Entity_Id);
-         --  Emit a continuation error message suggesting subprogram Subp_Id as
-         --  a possible interpretation.
-
-         function Is_Intrinsic_Equality (Subp_Id : Entity_Id) return Boolean;
-         --  Determine whether subprogram Subp_Id denotes the intrinsic "="
-         --  operator.
-
-         function Is_Suitable_Candidate (Subp_Id : Entity_Id) return Boolean;
-         --  Determine whether subprogram Subp_Id is a suitable candidate for
-         --  the role of a wrapped subprogram.
-
-         ----------------
-         -- Build_Call --
-         ----------------
-
-         function Build_Call
-           (Subp_Id : Entity_Id;
-            Params  : List_Id) return Node_Id
-         is
-            Actuals  : constant List_Id := New_List;
-            Call_Ref : constant Node_Id := New_Occurrence_Of (Subp_Id, Loc);
-            Formal   : Node_Id;
+         Ren_Formal : Entity_Id;
+         Sub_Formal : Entity_Id;
+
+         function Null_Exclusion_Mismatch
+           (Renaming : Entity_Id; Renamed : Entity_Id) return Boolean;
+         --  Return True if there is a null exclusion mismatch between
+         --  Renaming and Renamed, False otherwise.
 
+         -----------------------------
+         -- Null_Exclusion_Mismatch --
+         -----------------------------
+
+         function Null_Exclusion_Mismatch
+           (Renaming : Entity_Id; Renamed : Entity_Id) return Boolean is
          begin
-            --  Build the actual parameters of the call
+            return Has_Null_Exclusion (Parent (Renaming))
+              and then
+                not (Has_Null_Exclusion (Parent (Renamed))
+                      or else (Can_Never_Be_Null (Etype (Renamed))
+                                and then not
+                                  (Is_Formal_Subprogram (Sub)
+                                   and then In_Generic_Body (Current_Scope))));
+         end Null_Exclusion_Mismatch;
 
-            Formal := First (Params);
-            while Present (Formal) loop
-               Append_To (Actuals,
-                 Make_Identifier (Loc, Chars (Defining_Identifier (Formal))));
-               Next (Formal);
-            end loop;
+      begin
+         --  Parameter check
 
-            --  Generate:
-            --    return Subp_Id (Actuals);
+         Ren_Formal := First_Formal (Ren);
+         Sub_Formal := First_Formal (Sub);
+         while Present (Ren_Formal) and then Present (Sub_Formal) loop
+            if Null_Exclusion_Mismatch (Ren_Formal, Sub_Formal) then
+               Error_Msg_Sloc := Sloc (Sub_Formal);
+               Error_Msg_NE
+                 ("`NOT NULL` required for parameter &#",
+                  Ren_Formal, Sub_Formal);
+            end if;
 
-            if Ekind (Subp_Id) in E_Function | E_Operator then
-               return
-                 Make_Simple_Return_Statement (Loc,
-                   Expression =>
-                     Make_Function_Call (Loc,
-                       Name                   => Call_Ref,
-                       Parameter_Associations => Actuals));
+            Next_Formal (Ren_Formal);
+            Next_Formal (Sub_Formal);
+         end loop;
 
-            --  Generate:
-            --    Subp_Id (Actuals);
+         --  Return profile check
 
-            else
-               return
-                 Make_Procedure_Call_Statement (Loc,
-                   Name                   => Call_Ref,
-                   Parameter_Associations => Actuals);
-            end if;
-         end Build_Call;
+         if Nkind (Parent (Ren)) = N_Function_Specification
+           and then Nkind (Parent (Sub)) = N_Function_Specification
+           and then Null_Exclusion_Mismatch (Ren, Sub)
+         then
+            Error_Msg_Sloc := Sloc (Sub);
+            Error_Msg_N ("return must specify `NOT NULL`#", Ren);
+         end if;
+      end Check_Null_Exclusion;
 
-         -------------------------
-         -- Build_Expr_Fun_Call --
-         -------------------------
+      -------------------------------------
+      -- Check_SPARK_Primitive_Operation --
+      -------------------------------------
 
-         function Build_Expr_Fun_Call
-           (Subp_Id : Entity_Id;
-            Params  : List_Id) return Node_Id
-         is
-            Actuals  : constant List_Id := New_List;
-            Call_Ref : constant Node_Id := New_Occurrence_Of (Subp_Id, Loc);
-            Formal   : Node_Id;
+      procedure Check_SPARK_Primitive_Operation (Subp_Id : Entity_Id) is
+         Prag : constant Node_Id := SPARK_Pragma (Subp_Id);
+         Typ  : Entity_Id;
 
-         begin
-            pragma Assert (Ekind (Subp_Id) in E_Function | E_Operator);
+      begin
+         --  Nothing to do when the subprogram is not subject to SPARK_Mode On
+         --  because this check applies to SPARK code only.
 
-            --  Build the actual parameters of the call
+         if not (Present (Prag)
+                  and then Get_SPARK_Mode_From_Annotation (Prag) = On)
+         then
+            return;
 
-            Formal := First (Params);
-            while Present (Formal) loop
-               Append_To (Actuals,
-                 Make_Identifier (Loc, Chars (Defining_Identifier (Formal))));
-               Next (Formal);
-            end loop;
+         --  Nothing to do when the subprogram is not a primitive operation
 
-            --  Generate:
-            --    Subp_Id (Actuals);
+         elsif not Is_Primitive (Subp_Id) then
+            return;
+         end if;
 
-            return
-              Make_Function_Call (Loc,
-                Name                   => Call_Ref,
-                Parameter_Associations => Actuals);
-         end Build_Expr_Fun_Call;
+         Typ := Find_Dispatching_Type (Subp_Id);
 
-         ----------------
-         -- Build_Spec --
-         ----------------
+         --  Nothing to do when the subprogram is a primitive operation of an
+         --  untagged type.
 
-         function Build_Spec (Subp_Id : Entity_Id) return Node_Id is
-            Params  : constant List_Id   := Copy_Parameter_List (Subp_Id);
-            Spec_Id : constant Entity_Id :=
-                        Make_Defining_Identifier (Loc,
-                          Chars => New_External_Name (Chars (Subp_Id), 'R'));
+         if No (Typ) then
+            return;
+         end if;
 
-         begin
-            if Ekind (Formal_Spec) = E_Procedure then
-               return
-                 Make_Procedure_Specification (Loc,
-                   Defining_Unit_Name       => Spec_Id,
-                   Parameter_Specifications => Params);
-            else
-               return
-                 Make_Function_Specification (Loc,
-                   Defining_Unit_Name       => Spec_Id,
-                   Parameter_Specifications => Params,
-                   Result_Definition =>
-                     New_Copy_Tree (Result_Definition (Spec)));
-            end if;
-         end Build_Spec;
+         --  At this point a renaming declaration introduces a new primitive
+         --  operation for a tagged type.
 
-         --------------------
-         -- Find_Primitive --
-         --------------------
+         Error_Msg_Node_2 := Typ;
+         Error_Msg_NE
+           ("subprogram renaming & cannot declare primitive for type & "
+            & "(SPARK RM 6.1.1(3))", N, Subp_Id);
+      end Check_SPARK_Primitive_Operation;
 
-         function Find_Primitive (Typ : Entity_Id) return Entity_Id is
-            procedure Replace_Parameter_Types (Spec : Node_Id);
-            --  Given a specification Spec, replace all class-wide parameter
-            --  types with reference to type Typ.
+      ---------------------------
+      -- Freeze_Actual_Profile --
+      ---------------------------
 
-            -----------------------------
-            -- Replace_Parameter_Types --
-            -----------------------------
+      procedure Freeze_Actual_Profile is
+         F                  : Entity_Id;
+         Has_Untagged_Inc   : Boolean;
+         Instantiation_Node : constant Node_Id := Parent (N);
 
-            procedure Replace_Parameter_Types (Spec : Node_Id) is
-               Formal     : Node_Id;
-               Formal_Id  : Entity_Id;
-               Formal_Typ : Node_Id;
+      begin
+         if Ada_Version >= Ada_2012 then
+            F := First_Formal (Formal_Spec);
+            Has_Untagged_Inc := False;
+            while Present (F) loop
+               if Ekind (Etype (F)) = E_Incomplete_Type
+                 and then not Is_Tagged_Type (Etype (F))
+               then
+                  Has_Untagged_Inc := True;
+                  exit;
+               end if;
 
-            begin
-               Formal := First (Parameter_Specifications (Spec));
-               while Present (Formal) loop
-                  Formal_Id  := Defining_Identifier (Formal);
-                  Formal_Typ := Parameter_Type (Formal);
+               Next_Formal (F);
+            end loop;
 
-                  --  Create a new entity for each class-wide formal to prevent
-                  --  aliasing with the original renaming. Replace the type of
-                  --  such a parameter with the candidate type.
+            if Ekind (Formal_Spec) = E_Function
+              and then not Is_Tagged_Type (Etype (Formal_Spec))
+            then
+               Has_Untagged_Inc := True;
+            end if;
 
-                  if Nkind (Formal_Typ) = N_Identifier
-                    and then Is_Class_Wide_Type (Etype (Formal_Typ))
+            if not Has_Untagged_Inc then
+               F := First_Formal (Old_S);
+               while Present (F) loop
+                  Freeze_Before (Instantiation_Node, Etype (F));
+
+                  if Is_Incomplete_Or_Private_Type (Etype (F))
+                    and then No (Underlying_Type (Etype (F)))
                   then
-                     Set_Defining_Identifier (Formal,
-                       Make_Defining_Identifier (Loc, Chars (Formal_Id)));
+                     --  Exclude generic types, or types derived  from them.
+                     --  They will be frozen in the enclosing instance.
 
-                     Set_Parameter_Type (Formal, New_Occurrence_Of (Typ, Loc));
+                     if Is_Generic_Type (Etype (F))
+                       or else Is_Generic_Type (Root_Type (Etype (F)))
+                     then
+                        null;
+
+                     --  A limited view of a type declared elsewhere needs no
+                     --  freezing actions.
+
+                     elsif From_Limited_With (Etype (F)) then
+                        null;
+
+                     else
+                        Error_Msg_NE
+                          ("type& must be frozen before this point",
+                           Instantiation_Node, Etype (F));
+                     end if;
                   end if;
 
-                  Next (Formal);
+                  Next_Formal (F);
                end loop;
-            end Replace_Parameter_Types;
-
-            --  Local variables
+            end if;
+         end if;
+      end Freeze_Actual_Profile;
 
-            Alt_Ren  : constant Node_Id := New_Copy_Tree (N);
-            Alt_Nam  : constant Node_Id := Name (Alt_Ren);
-            Alt_Spec : constant Node_Id := Specification (Alt_Ren);
-            Subp_Id  : Entity_Id;
+      ---------------------------
+      -- Has_Class_Wide_Actual --
+      ---------------------------
 
-         --  Start of processing for Find_Primitive
+      function Has_Class_Wide_Actual return Boolean is
+         Formal     : Entity_Id;
+         Formal_Typ : Entity_Id;
 
-         begin
-            --  Each attempt to find a suitable primitive of a particular type
-            --  operates on its own copy of the original renaming. As a result
-            --  the original renaming is kept decoration and side-effect free.
+      begin
+         if Is_Actual then
+            Formal := First_Formal (Formal_Spec);
+            while Present (Formal) loop
+               Formal_Typ := Etype (Formal);
 
-            --  Inherit the overloaded status of the renamed subprogram name
+               if Has_Unknown_Discriminants (Formal_Typ)
+                 and then not Is_Class_Wide_Type (Formal_Typ)
+                 and then Is_Class_Wide_Type (Get_Instance_Of (Formal_Typ))
+               then
+                  return True;
+               end if;
 
-            if Is_Overloaded (Nam) then
-               Set_Is_Overloaded (Alt_Nam);
-               Save_Interps (Nam, Alt_Nam);
-            end if;
+               Next_Formal (Formal);
+            end loop;
+         end if;
 
-            --  The copied renaming is hidden from visibility to prevent the
-            --  pollution of the enclosing context.
+         return False;
+      end Has_Class_Wide_Actual;
 
-            Set_Defining_Unit_Name (Alt_Spec, Make_Temporary (Loc, 'R'));
+      ------------------------------------------
+      -- Handle_Instance_With_Class_Wide_Type --
+      ------------------------------------------
 
-            --  The types of all class-wide parameters must be changed to the
-            --  candidate type.
+      procedure Handle_Instance_With_Class_Wide_Type
+        (Inst_Node    : Node_Id;
+         Ren_Id       : Entity_Id;
+         Wrapped_Prim : out Entity_Id;
+         Wrap_Id      : out Entity_Id)
+      is
+         procedure Build_Class_Wide_Wrapper
+           (Ren_Id  : Entity_Id;
+            Prim_Op : Entity_Id;
+            Wrap_Id : out Entity_Id);
+         --  Build a wrapper for the renaming Ren_Id of subprogram Prim_Op.
+
+         procedure Find_Suitable_Candidate
+           (Prim_Op    : out Entity_Id;
+            Is_CW_Prim : out Boolean);
+         --  Look for a suitable primitive to be wrapped (Prim_Op); Is_CW_Prim
+         --  indicates that the found candidate is a class-wide primitive (to
+         --  help the caller decide if the wrapper is required).
+
+         ------------------------------
+         -- Build_Class_Wide_Wrapper --
+         ------------------------------
+
+         procedure Build_Class_Wide_Wrapper
+           (Ren_Id  : Entity_Id;
+            Prim_Op : Entity_Id;
+            Wrap_Id : out Entity_Id)
+         is
+            Loc : constant Source_Ptr := Sloc (N);
+
+            function Build_Call
+              (Subp_Id : Entity_Id;
+               Params  : List_Id) return Node_Id;
+            --  Create a dispatching call to invoke routine Subp_Id with
+            --  actuals built from the parameter specifications of list Params.
+
+            function Build_Expr_Fun_Call
+              (Subp_Id : Entity_Id;
+               Params  : List_Id) return Node_Id;
+            --  Create a dispatching call to invoke function Subp_Id with
+            --  actuals built from the parameter specifications of list Params.
+            --  Directly return the call, so that it can be used inside an
+            --  expression function. This is a requirement of GNATprove mode.
+
+            function Build_Spec (Subp_Id : Entity_Id) return Node_Id;
+            --  Create a subprogram specification based on the subprogram
+            --  profile of Subp_Id.
+
+            ----------------
+            -- Build_Call --
+            ----------------
+
+            function Build_Call
+              (Subp_Id : Entity_Id;
+               Params  : List_Id) return Node_Id
+            is
+               Actuals  : constant List_Id := New_List;
+               Call_Ref : constant Node_Id := New_Occurrence_Of (Subp_Id, Loc);
+               Formal   : Node_Id;
 
-            Replace_Parameter_Types (Alt_Spec);
+            begin
+               --  Build the actual parameters of the call
 
-            --  Try to find a suitable primitive which matches the altered
-            --  profile of the renaming specification.
+               Formal := First (Params);
+               while Present (Formal) loop
+                  Append_To (Actuals,
+                    Make_Identifier (Loc,
+                      Chars (Defining_Identifier (Formal))));
+                  Next (Formal);
+               end loop;
 
-            Subp_Id :=
-              Find_Renamed_Entity
-                (N         => Alt_Ren,
-                 Nam       => Name (Alt_Ren),
-                 New_S     => Analyze_Subprogram_Specification (Alt_Spec),
-                 Is_Actual => Is_Actual);
+               --  Generate:
+               --    return Subp_Id (Actuals);
 
-            --  Do not return Any_Id if the resolion of the altered profile
-            --  failed as this complicates further checks on the caller side,
-            --  return Empty instead.
+               if Ekind (Subp_Id) in E_Function | E_Operator then
+                  return
+                    Make_Simple_Return_Statement (Loc,
+                      Expression =>
+                        Make_Function_Call (Loc,
+                          Name                   => Call_Ref,
+                          Parameter_Associations => Actuals));
 
-            if Subp_Id = Any_Id then
-               return Empty;
-            else
-               return Subp_Id;
-            end if;
-         end Find_Primitive;
+               --  Generate:
+               --    Subp_Id (Actuals);
 
-         --------------------------
-         -- Interpretation_Error --
-         --------------------------
+               else
+                  return
+                    Make_Procedure_Call_Statement (Loc,
+                      Name                   => Call_Ref,
+                      Parameter_Associations => Actuals);
+               end if;
+            end Build_Call;
 
-         procedure Interpretation_Error (Subp_Id : Entity_Id) is
-         begin
-            Error_Msg_Sloc := Sloc (Subp_Id);
+            -------------------------
+            -- Build_Expr_Fun_Call --
+            -------------------------
 
-            if Is_Internal (Subp_Id) then
-               Error_Msg_NE
-                 ("\\possible interpretation: predefined & #",
-                  Spec, Formal_Spec);
-            else
-               Error_Msg_NE
-                 ("\\possible interpretation: & defined #", Spec, Formal_Spec);
-            end if;
-         end Interpretation_Error;
+            function Build_Expr_Fun_Call
+              (Subp_Id : Entity_Id;
+               Params  : List_Id) return Node_Id
+            is
+               Actuals  : constant List_Id := New_List;
+               Call_Ref : constant Node_Id := New_Occurrence_Of (Subp_Id, Loc);
+               Formal   : Node_Id;
 
-         ---------------------------
-         -- Is_Intrinsic_Equality --
-         ---------------------------
+            begin
+               pragma Assert (Ekind (Subp_Id) in E_Function | E_Operator);
 
-         function Is_Intrinsic_Equality (Subp_Id : Entity_Id) return Boolean is
-         begin
-            return
-              Ekind (Subp_Id) = E_Operator
-                and then Chars (Subp_Id) = Name_Op_Eq
-                and then Is_Intrinsic_Subprogram (Subp_Id);
-         end Is_Intrinsic_Equality;
+               --  Build the actual parameters of the call
 
-         ---------------------------
-         -- Is_Suitable_Candidate --
-         ---------------------------
+               Formal := First (Params);
+               while Present (Formal) loop
+                  Append_To (Actuals,
+                    Make_Identifier (Loc,
+                      Chars (Defining_Identifier (Formal))));
+                  Next (Formal);
+               end loop;
 
-         function Is_Suitable_Candidate (Subp_Id : Entity_Id) return Boolean is
-         begin
-            if No (Subp_Id) then
-               return False;
+               --  Generate:
+               --    Subp_Id (Actuals);
 
-            --  An intrinsic subprogram is never a good candidate. This is an
-            --  indication of a missing primitive, either defined directly or
-            --  inherited from a parent tagged type.
+               return
+                 Make_Function_Call (Loc,
+                   Name                   => Call_Ref,
+                   Parameter_Associations => Actuals);
+            end Build_Expr_Fun_Call;
 
-            elsif Is_Intrinsic_Subprogram (Subp_Id) then
-               return False;
+            ----------------
+            -- Build_Spec --
+            ----------------
 
-            else
-               return True;
-            end if;
-         end Is_Suitable_Candidate;
+            function Build_Spec (Subp_Id : Entity_Id) return Node_Id is
+               Params  : constant List_Id   := Copy_Parameter_List (Subp_Id);
+               Spec_Id : constant Entity_Id :=
+                           Make_Defining_Identifier (Loc,
+                             New_External_Name (Chars (Subp_Id), 'R'));
 
-         --  Local variables
+            begin
+               if Ekind (Formal_Spec) = E_Procedure then
+                  return
+                    Make_Procedure_Specification (Loc,
+                      Defining_Unit_Name       => Spec_Id,
+                      Parameter_Specifications => Params);
+               else
+                  return
+                    Make_Function_Specification (Loc,
+                      Defining_Unit_Name       => Spec_Id,
+                      Parameter_Specifications => Params,
+                      Result_Definition =>
+                        New_Copy_Tree (Result_Definition (Spec)));
+               end if;
+            end Build_Spec;
 
-         Actual_Typ : Entity_Id := Empty;
-         --  The actual class-wide type for Formal_Typ
+            --  Local variables
 
-         CW_Prim_OK : Boolean;
-         CW_Prim_Op : Entity_Id;
-         --  The class-wide subprogram (if available) which corresponds to the
-         --  renamed generic formal subprogram.
+            Body_Decl : Node_Id;
+            Spec_Decl : Node_Id;
+            New_Spec  : Node_Id;
 
-         Formal_Typ : Entity_Id := Empty;
-         --  The generic formal type with unknown discriminants
+         --  Start of processing for Build_Class_Wide_Wrapper
 
-         Root_Prim_OK : Boolean;
-         Root_Prim_Op : Entity_Id;
-         --  The root type primitive (if available) which corresponds to the
-         --  renamed generic formal subprogram.
+         begin
+            pragma Assert (not Error_Posted (Nam));
 
-         Root_Typ : Entity_Id := Empty;
-         --  The root type of Actual_Typ
+            --  Step 1: Create the declaration and the body of the wrapper,
+            --  insert all the pieces into the tree.
 
-         Body_Decl : Node_Id;
-         Formal    : Node_Id;
-         Prim_Op   : Entity_Id;
-         Spec_Decl : Node_Id;
-         New_Spec  : Node_Id;
+            --  In GNATprove mode, create a function wrapper in the form of an
+            --  expression function, so that an implicit postcondition relating
+            --  the result of calling the wrapper function and the result of
+            --  the dispatching call to the wrapped function is known during
+            --  proof.
 
-      --  Start of processing for Build_Class_Wide_Wrapper
+            if GNATprove_Mode
+              and then Ekind (Ren_Id) in E_Function | E_Operator
+            then
+               New_Spec := Build_Spec (Ren_Id);
+               Body_Decl :=
+                 Make_Expression_Function (Loc,
+                   Specification => New_Spec,
+                   Expression    =>
+                     Build_Expr_Fun_Call
+                       (Subp_Id => Prim_Op,
+                        Params  => Parameter_Specifications (New_Spec)));
 
-      begin
-         --  Analyze the specification of the renaming in case the generation
-         --  of the class-wide wrapper fails.
+               Wrap_Id := Defining_Entity (Body_Decl);
 
-         Ren_Id  := Analyze_Subprogram_Specification (Spec);
-         Wrap_Id := Any_Id;
+            --  Otherwise, create separate spec and body for the subprogram
 
-         --  Do not attempt to build a wrapper if the renaming is in error
+            else
+               Spec_Decl :=
+                 Make_Subprogram_Declaration (Loc,
+                   Specification => Build_Spec (Ren_Id));
+               Insert_Before_And_Analyze (N, Spec_Decl);
+
+               Wrap_Id := Defining_Entity (Spec_Decl);
+
+               Body_Decl :=
+                 Make_Subprogram_Body (Loc,
+                   Specification              => Build_Spec (Ren_Id),
+                   Declarations               => New_List,
+                   Handled_Statement_Sequence =>
+                     Make_Handled_Sequence_Of_Statements (Loc,
+                       Statements => New_List (
+                         Build_Call
+                           (Subp_Id => Prim_Op,
+                            Params  =>
+                              Parameter_Specifications
+                                (Specification (Spec_Decl))))));
+
+               Set_Corresponding_Body (Spec_Decl, Defining_Entity (Body_Decl));
+            end if;
 
-         if Error_Posted (Nam) then
-            return;
-         end if;
+            Set_Is_Class_Wide_Wrapper (Wrap_Id);
 
-         --  Analyze the renamed name, but do not resolve it. The resolution is
-         --  completed once a suitable subprogram is found.
+            --  If the operator carries an Eliminated pragma, indicate that
+            --  the wrapper is also to be eliminated, to prevent spurious
+            --  errors when using gnatelim on programs that include box-
+            --  defaulted initialization of equality operators.
 
-         Analyze (Nam);
+            Set_Is_Eliminated (Wrap_Id, Is_Eliminated (Prim_Op));
 
-         --  When the renamed name denotes the intrinsic operator equals, the
-         --  name must be treated as overloaded. This allows for a potential
-         --  match against the root type's predefined equality function.
+            --  In GNATprove mode, insert the body in the tree for analysis
 
-         if Is_Intrinsic_Equality (Entity (Nam)) then
-            Set_Is_Overloaded (Nam);
-            Collect_Interps   (Nam);
-         end if;
+            if GNATprove_Mode then
+               Insert_Before_And_Analyze (N, Body_Decl);
+            end if;
 
-         --  Step 1: Find the generic formal type with unknown discriminants
-         --  and its corresponding class-wide actual type from the renamed
-         --  generic formal subprogram.
+            --  The generated body does not freeze and must be analyzed when
+            --  the class-wide wrapper is frozen. The body is only needed if
+            --  expansion is enabled.
 
-         Formal := First_Formal (Formal_Spec);
-         while Present (Formal) loop
-            if Has_Unknown_Discriminants (Etype (Formal))
-              and then not Is_Class_Wide_Type (Etype (Formal))
-              and then Is_Class_Wide_Type (Get_Instance_Of (Etype (Formal)))
-            then
-               Formal_Typ := Etype (Formal);
-               Actual_Typ := Get_Instance_Of (Formal_Typ);
-               Root_Typ   := Etype (Actual_Typ);
-               exit;
+            if Expander_Active then
+               Append_Freeze_Action (Wrap_Id, Body_Decl);
             end if;
 
-            Next_Formal (Formal);
-         end loop;
+            --  Step 2: The subprogram renaming aliases the wrapper
 
-         --  The specification of the generic formal subprogram should always
-         --  contain a formal type with unknown discriminants whose actual is
-         --  a class-wide type, otherwise this indicates a failure in routine
-         --  Has_Class_Wide_Actual.
+            Rewrite (Name (N), New_Occurrence_Of (Wrap_Id, Loc));
+         end Build_Class_Wide_Wrapper;
 
-         pragma Assert (Present (Formal_Typ));
+         -----------------------------
+         -- Find_Suitable_Candidate --
+         -----------------------------
 
-         --  Step 2: Find the proper class-wide subprogram or primitive which
-         --  corresponds to the renamed generic formal subprogram.
+         procedure Find_Suitable_Candidate
+           (Prim_Op    : out Entity_Id;
+            Is_CW_Prim : out Boolean)
+         is
+            Loc : constant Source_Ptr := Sloc (N);
 
-         CW_Prim_Op   := Find_Primitive (Actual_Typ);
-         CW_Prim_OK   := Is_Suitable_Candidate (CW_Prim_Op);
-         Root_Prim_Op := Find_Primitive (Root_Typ);
-         Root_Prim_OK := Is_Suitable_Candidate (Root_Prim_Op);
+            function Find_Primitive (Typ : Entity_Id) return Entity_Id;
+            --  Find a primitive subprogram of type Typ which matches the
+            --  profile of the renaming declaration.
 
-         --  The class-wide actual type has two subprograms which correspond to
-         --  the renamed generic formal subprogram:
+            procedure Interpretation_Error (Subp_Id : Entity_Id);
+            --  Emit a continuation error message suggesting subprogram Subp_Id
+            --  as a possible interpretation.
 
-         --    with procedure Prim_Op (Param : Formal_Typ);
+            function Is_Intrinsic_Equality
+              (Subp_Id : Entity_Id) return Boolean;
+            --  Determine whether subprogram Subp_Id denotes the intrinsic "="
+            --  operator.
 
-         --    procedure Prim_Op (Param : Actual_Typ);  --  may be inherited
-         --    procedure Prim_Op (Param : Actual_Typ'Class);
+            function Is_Suitable_Candidate
+              (Subp_Id : Entity_Id) return Boolean;
+            --  Determine whether subprogram Subp_Id is a suitable candidate
+            --  for the role of a wrapped subprogram.
 
-         --  Even though the declaration of the two subprograms is legal, a
-         --  call to either one is ambiguous and therefore illegal.
+            --------------------
+            -- Find_Primitive --
+            --------------------
 
-         if CW_Prim_OK and Root_Prim_OK then
+            function Find_Primitive (Typ : Entity_Id) return Entity_Id is
+               procedure Replace_Parameter_Types (Spec : Node_Id);
+               --  Given a specification Spec, replace all class-wide parameter
+               --  types with reference to type Typ.
 
-            --  A user-defined primitive has precedence over a predefined one
+               -----------------------------
+               -- Replace_Parameter_Types --
+               -----------------------------
 
-            if Is_Internal (CW_Prim_Op)
-              and then not Is_Internal (Root_Prim_Op)
-            then
-               Prim_Op := Root_Prim_Op;
+               procedure Replace_Parameter_Types (Spec : Node_Id) is
+                  Formal     : Node_Id;
+                  Formal_Id  : Entity_Id;
+                  Formal_Typ : Node_Id;
 
-            elsif Is_Internal (Root_Prim_Op)
-              and then not Is_Internal (CW_Prim_Op)
-            then
-               Prim_Op := CW_Prim_Op;
+               begin
+                  Formal := First (Parameter_Specifications (Spec));
+                  while Present (Formal) loop
+                     Formal_Id  := Defining_Identifier (Formal);
+                     Formal_Typ := Parameter_Type (Formal);
 
-            elsif CW_Prim_Op = Root_Prim_Op then
-               Prim_Op := Root_Prim_Op;
+                     --  Create a new entity for each class-wide formal to
+                     --  prevent aliasing with the original renaming. Replace
+                     --  the type of such a parameter with the candidate type.
 
-            --  Otherwise both candidate subprograms are user-defined and
-            --  ambiguous.
+                     if Nkind (Formal_Typ) = N_Identifier
+                       and then Is_Class_Wide_Type (Etype (Formal_Typ))
+                     then
+                        Set_Defining_Identifier (Formal,
+                          Make_Defining_Identifier (Loc, Chars (Formal_Id)));
 
-            else
-               Error_Msg_NE
-                 ("ambiguous actual for generic subprogram &",
-                  Spec, Formal_Spec);
-               Interpretation_Error (Root_Prim_Op);
-               Interpretation_Error (CW_Prim_Op);
-               return;
-            end if;
+                        Set_Parameter_Type (Formal,
+                          New_Occurrence_Of (Typ, Loc));
+                     end if;
 
-         elsif CW_Prim_OK and not Root_Prim_OK then
-            Prim_Op := CW_Prim_Op;
+                     Next (Formal);
+                  end loop;
+               end Replace_Parameter_Types;
 
-         elsif not CW_Prim_OK and Root_Prim_OK then
-            Prim_Op := Root_Prim_Op;
+               --  Local variables
 
-         --  An intrinsic equality may act as a suitable candidate in the case
-         --  of a null type extension where the parent's equality is hidden. A
-         --  call to an intrinsic equality is expanded as dispatching.
+               Alt_Ren  : constant Node_Id := New_Copy_Tree (N);
+               Alt_Nam  : constant Node_Id := Name (Alt_Ren);
+               Alt_Spec : constant Node_Id := Specification (Alt_Ren);
+               Subp_Id  : Entity_Id;
 
-         elsif Present (Root_Prim_Op)
-           and then Is_Intrinsic_Equality (Root_Prim_Op)
-         then
-            Prim_Op := Root_Prim_Op;
+            --  Start of processing for Find_Primitive
 
-         --  Otherwise there are no candidate subprograms. Let the caller
-         --  diagnose the error.
+            begin
+               --  Each attempt to find a suitable primitive of a particular
+               --  type operates on its own copy of the original renaming.
+               --  As a result the original renaming is kept decoration and
+               --  side-effect free.
 
-         else
-            return;
-         end if;
+               --  Inherit the overloaded status of the renamed subprogram name
 
-         --  At this point resolution has taken place and the name is no longer
-         --  overloaded. Mark the primitive as referenced.
+               if Is_Overloaded (Nam) then
+                  Set_Is_Overloaded (Alt_Nam);
+                  Save_Interps (Nam, Alt_Nam);
+               end if;
 
-         Set_Is_Overloaded (Name (N), False);
-         Set_Referenced    (Prim_Op);
+               --  The copied renaming is hidden from visibility to prevent the
+               --  pollution of the enclosing context.
 
-         --  Do not generate a wrapper when the only candidate is a class-wide
-         --  subprogram. Instead modify the renaming to directly map the actual
-         --  to the generic formal.
+               Set_Defining_Unit_Name (Alt_Spec, Make_Temporary (Loc, 'R'));
 
-         if CW_Prim_OK and then Prim_Op = CW_Prim_Op then
-            Wrap_Id := Prim_Op;
-            Rewrite (Nam, New_Occurrence_Of (Prim_Op, Loc));
-            return;
-         end if;
+               --  The types of all class-wide parameters must be changed to
+               --  the candidate type.
 
-         --  Step 3: Create the declaration and the body of the wrapper, insert
-         --  all the pieces into the tree.
+               Replace_Parameter_Types (Alt_Spec);
 
-         --  In GNATprove mode, create a function wrapper in the form of an
-         --  expression function, so that an implicit postcondition relating
-         --  the result of calling the wrapper function and the result of the
-         --  dispatching call to the wrapped function is known during proof.
+               --  Try to find a suitable primitive that matches the altered
+               --  profile of the renaming specification.
 
-         if GNATprove_Mode
-           and then Ekind (Ren_Id) in E_Function | E_Operator
-         then
-            New_Spec := Build_Spec (Ren_Id);
-            Body_Decl :=
-              Make_Expression_Function (Loc,
-                Specification => New_Spec,
-                Expression    =>
-                  Build_Expr_Fun_Call
-                    (Subp_Id => Prim_Op,
-                     Params  => Parameter_Specifications (New_Spec)));
+               Subp_Id :=
+                 Find_Renamed_Entity
+                   (N         => Alt_Ren,
+                    Nam       => Name (Alt_Ren),
+                    New_S     => Analyze_Subprogram_Specification (Alt_Spec),
+                    Is_Actual => Is_Actual);
 
-            Wrap_Id := Defining_Entity (Body_Decl);
+               --  Do not return Any_Id if the resolution of the altered
+               --  profile failed as this complicates further checks on
+               --  the caller side; return Empty instead.
 
-         --  Otherwise, create separate spec and body for the subprogram
+               if Subp_Id = Any_Id then
+                  return Empty;
+               else
+                  return Subp_Id;
+               end if;
+            end Find_Primitive;
 
-         else
-            Spec_Decl :=
-              Make_Subprogram_Declaration (Loc,
-                Specification => Build_Spec (Ren_Id));
-            Insert_Before_And_Analyze (N, Spec_Decl);
+            --------------------------
+            -- Interpretation_Error --
+            --------------------------
 
-            Wrap_Id := Defining_Entity (Spec_Decl);
+            procedure Interpretation_Error (Subp_Id : Entity_Id) is
+            begin
+               Error_Msg_Sloc := Sloc (Subp_Id);
 
-            Body_Decl :=
-              Make_Subprogram_Body (Loc,
-                Specification              => Build_Spec (Ren_Id),
-                Declarations               => New_List,
-                Handled_Statement_Sequence =>
-                  Make_Handled_Sequence_Of_Statements (Loc,
-                    Statements => New_List (
-                      Build_Call
-                        (Subp_Id => Prim_Op,
-                         Params  =>
-                           Parameter_Specifications
-                             (Specification (Spec_Decl))))));
+               if Is_Internal (Subp_Id) then
+                  Error_Msg_NE
+                    ("\\possible interpretation: predefined & #",
+                     Spec, Formal_Spec);
+               else
+                  Error_Msg_NE
+                    ("\\possible interpretation: & defined #",
+                     Spec, Formal_Spec);
+               end if;
+            end Interpretation_Error;
 
-            Set_Corresponding_Body (Spec_Decl, Defining_Entity (Body_Decl));
-         end if;
+            ---------------------------
+            -- Is_Intrinsic_Equality --
+            ---------------------------
 
-         --  If the operator carries an Eliminated pragma, indicate that the
-         --  wrapper is also to be eliminated, to prevent spurious error when
-         --  using gnatelim on programs that include box-initialization of
-         --  equality operators.
+            function Is_Intrinsic_Equality (Subp_Id : Entity_Id) return Boolean
+            is
+            begin
+               return
+                 Ekind (Subp_Id) = E_Operator
+                   and then Chars (Subp_Id) = Name_Op_Eq
+                   and then Is_Intrinsic_Subprogram (Subp_Id);
+            end Is_Intrinsic_Equality;
 
-         Set_Is_Eliminated (Wrap_Id, Is_Eliminated (Prim_Op));
+            ---------------------------
+            -- Is_Suitable_Candidate --
+            ---------------------------
 
-         --  In GNATprove mode, insert the body in the tree for analysis
+            function Is_Suitable_Candidate (Subp_Id : Entity_Id) return Boolean
+            is
+            begin
+               if No (Subp_Id) then
+                  return False;
 
-         if GNATprove_Mode then
-            Insert_Before_And_Analyze (N, Body_Decl);
-         end if;
+               --  An intrinsic subprogram is never a good candidate. This
+               --  is an indication of a missing primitive, either defined
+               --  directly or inherited from a parent tagged type.
 
-         --  The generated body does not freeze and must be analyzed when the
-         --  class-wide wrapper is frozen. The body is only needed if expansion
-         --  is enabled.
+               elsif Is_Intrinsic_Subprogram (Subp_Id) then
+                  return False;
 
-         if Expander_Active then
-            Append_Freeze_Action (Wrap_Id, Body_Decl);
-         end if;
+               else
+                  return True;
+               end if;
+            end Is_Suitable_Candidate;
 
-         --  Step 4: The subprogram renaming aliases the wrapper
+            --  Local variables
 
-         Rewrite (Nam, New_Occurrence_Of (Wrap_Id, Loc));
-      end Build_Class_Wide_Wrapper;
+            Actual_Typ : Entity_Id := Empty;
+            --  The actual class-wide type for Formal_Typ
 
-      --------------------------
-      -- Check_Null_Exclusion --
-      --------------------------
+            CW_Prim_OK : Boolean;
+            CW_Prim_Op : Entity_Id;
+            --  The class-wide subprogram (if available) that corresponds to
+            --  the renamed generic formal subprogram.
 
-      procedure Check_Null_Exclusion
-        (Ren : Entity_Id;
-         Sub : Entity_Id)
-      is
-         Ren_Formal : Entity_Id;
-         Sub_Formal : Entity_Id;
+            Formal_Typ : Entity_Id := Empty;
+            --  The generic formal type with unknown discriminants
 
-         function Null_Exclusion_Mismatch
-           (Renaming : Entity_Id; Renamed : Entity_Id) return Boolean;
-         --  Return True if there is a null exclusion mismatch between
-         --  Renaming and Renamed, False otherwise.
+            Root_Prim_OK : Boolean;
+            Root_Prim_Op : Entity_Id;
+            --  The root type primitive (if available) that corresponds to the
+            --  renamed generic formal subprogram.
 
-         -----------------------------
-         -- Null_Exclusion_Mismatch --
-         -----------------------------
+            Root_Typ : Entity_Id := Empty;
+            --  The root type of Actual_Typ
+
+            Formal   : Node_Id;
+
+         --  Start of processing for Find_Suitable_Candidate
 
-         function Null_Exclusion_Mismatch
-           (Renaming : Entity_Id; Renamed : Entity_Id) return Boolean is
          begin
-            return Has_Null_Exclusion (Parent (Renaming))
-              and then
-                not (Has_Null_Exclusion (Parent (Renamed))
-                      or else (Can_Never_Be_Null (Etype (Renamed))
-                                and then not
-                                  (Is_Formal_Subprogram (Sub)
-                                   and then In_Generic_Body (Current_Scope))));
-         end Null_Exclusion_Mismatch;
+            pragma Assert (not Error_Posted (Nam));
 
-      begin
-         --  Parameter check
+            Prim_Op    := Empty;
+            Is_CW_Prim := False;
 
-         Ren_Formal := First_Formal (Ren);
-         Sub_Formal := First_Formal (Sub);
-         while Present (Ren_Formal) and then Present (Sub_Formal) loop
-            if Null_Exclusion_Mismatch (Ren_Formal, Sub_Formal) then
-               Error_Msg_Sloc := Sloc (Sub_Formal);
-               Error_Msg_NE
-                 ("`NOT NULL` required for parameter &#",
-                  Ren_Formal, Sub_Formal);
+            --  Analyze the renamed name, but do not resolve it. The resolution
+            --  is completed once a suitable subprogram is found.
+
+            Analyze (Nam);
+
+            --  When the renamed name denotes the intrinsic operator equals,
+            --  the name must be treated as overloaded. This allows for a
+            --  potential match against the root type's predefined equality
+            --  function.
+
+            if Is_Intrinsic_Equality (Entity (Nam)) then
+               Set_Is_Overloaded (Nam);
+               Collect_Interps   (Nam);
             end if;
 
-            Next_Formal (Ren_Formal);
-            Next_Formal (Sub_Formal);
-         end loop;
+            --  Step 1: Find the generic formal type and its corresponding
+            --  class-wide actual type from the renamed generic formal
+            --  subprogram.
 
-         --  Return profile check
+            Formal := First_Formal (Formal_Spec);
+            while Present (Formal) loop
+               if Has_Unknown_Discriminants (Etype (Formal))
+                 and then not Is_Class_Wide_Type (Etype (Formal))
+                 and then Is_Class_Wide_Type (Get_Instance_Of (Etype (Formal)))
+               then
+                  Formal_Typ := Etype (Formal);
+                  Actual_Typ := Base_Type (Get_Instance_Of (Formal_Typ));
+                  Root_Typ   := Root_Type (Actual_Typ);
+                  exit;
+               end if;
 
-         if Nkind (Parent (Ren)) = N_Function_Specification
-           and then Nkind (Parent (Sub)) = N_Function_Specification
-           and then Null_Exclusion_Mismatch (Ren, Sub)
-         then
-            Error_Msg_Sloc := Sloc (Sub);
-            Error_Msg_N ("return must specify `NOT NULL`#", Ren);
-         end if;
-      end Check_Null_Exclusion;
+               Next_Formal (Formal);
+            end loop;
 
-      -------------------------------------
-      -- Check_SPARK_Primitive_Operation --
-      -------------------------------------
+            --  The specification of the generic formal subprogram should
+            --  always contain a formal type with unknown discriminants whose
+            --  actual is a class-wide type; otherwise this indicates a failure
+            --  in function Has_Class_Wide_Actual.
 
-      procedure Check_SPARK_Primitive_Operation (Subp_Id : Entity_Id) is
-         Prag : constant Node_Id := SPARK_Pragma (Subp_Id);
-         Typ  : Entity_Id;
+            pragma Assert (Present (Formal_Typ));
 
-      begin
-         --  Nothing to do when the subprogram is not subject to SPARK_Mode On
-         --  because this check applies to SPARK code only.
+            --  Step 2: Find the proper class-wide subprogram or primitive
+            --  that corresponds to the renamed generic formal subprogram.
 
-         if not (Present (Prag)
-                  and then Get_SPARK_Mode_From_Annotation (Prag) = On)
-         then
-            return;
+            CW_Prim_Op   := Find_Primitive (Actual_Typ);
+            CW_Prim_OK   := Is_Suitable_Candidate (CW_Prim_Op);
+            Root_Prim_Op := Find_Primitive (Root_Typ);
+            Root_Prim_OK := Is_Suitable_Candidate (Root_Prim_Op);
 
-         --  Nothing to do when the subprogram is not a primitive operation
+            --  The class-wide actual type has two subprograms that correspond
+            --  to the renamed generic formal subprogram:
 
-         elsif not Is_Primitive (Subp_Id) then
-            return;
-         end if;
+            --    with procedure Prim_Op (Param : Formal_Typ);
 
-         Typ := Find_Dispatching_Type (Subp_Id);
+            --    procedure Prim_Op (Param : Actual_Typ);  --  may be inherited
+            --    procedure Prim_Op (Param : Actual_Typ'Class);
 
-         --  Nothing to do when the subprogram is a primitive operation of an
-         --  untagged type.
+            --  Even though the declaration of the two subprograms is legal, a
+            --  call to either one is ambiguous and therefore illegal.
 
-         if No (Typ) then
-            return;
-         end if;
+            if CW_Prim_OK and Root_Prim_OK then
 
-         --  At this point a renaming declaration introduces a new primitive
-         --  operation for a tagged type.
+               --  A user-defined primitive has precedence over a predefined
+               --  one.
 
-         Error_Msg_Node_2 := Typ;
-         Error_Msg_NE
-           ("subprogram renaming & cannot declare primitive for type & "
-            & "(SPARK RM 6.1.1(3))", N, Subp_Id);
-      end Check_SPARK_Primitive_Operation;
+               if Is_Internal (CW_Prim_Op)
+                 and then not Is_Internal (Root_Prim_Op)
+               then
+                  Prim_Op := Root_Prim_Op;
 
-      ---------------------------
-      -- Freeze_Actual_Profile --
-      ---------------------------
+               elsif Is_Internal (Root_Prim_Op)
+                 and then not Is_Internal (CW_Prim_Op)
+               then
+                  Prim_Op := CW_Prim_Op;
+                  Is_CW_Prim := True;
 
-      procedure Freeze_Actual_Profile is
-         F                  : Entity_Id;
-         Has_Untagged_Inc   : Boolean;
-         Instantiation_Node : constant Node_Id := Parent (N);
+               elsif CW_Prim_Op = Root_Prim_Op then
+                  Prim_Op := Root_Prim_Op;
 
-      begin
-         if Ada_Version >= Ada_2012 then
-            F := First_Formal (Formal_Spec);
-            Has_Untagged_Inc := False;
-            while Present (F) loop
-               if Ekind (Etype (F)) = E_Incomplete_Type
-                 and then not Is_Tagged_Type (Etype (F))
+               --  The two subprograms are legal but the class-wide subprogram
+               --  is a class-wide wrapper built for a previous instantiation;
+               --  the wrapper has precedence.
+
+               elsif Present (Alias (CW_Prim_Op))
+                 and then Is_Class_Wide_Wrapper (Ultimate_Alias (CW_Prim_Op))
                then
-                  Has_Untagged_Inc := True;
-                  exit;
+                  Prim_Op := CW_Prim_Op;
+                  Is_CW_Prim := True;
+
+               --  Otherwise both candidate subprograms are user-defined and
+               --  ambiguous.
+
+               else
+                  Error_Msg_NE
+                    ("ambiguous actual for generic subprogram &",
+                     Spec, Formal_Spec);
+                  Interpretation_Error (Root_Prim_Op);
+                  Interpretation_Error (CW_Prim_Op);
+                  return;
                end if;
 
-               Next_Formal (F);
-            end loop;
+            elsif CW_Prim_OK and not Root_Prim_OK then
+               Prim_Op := CW_Prim_Op;
+               Is_CW_Prim := True;
 
-            if Ekind (Formal_Spec) = E_Function
-              and then not Is_Tagged_Type (Etype (Formal_Spec))
+            elsif not CW_Prim_OK and Root_Prim_OK then
+               Prim_Op := Root_Prim_Op;
+
+            --  An intrinsic equality may act as a suitable candidate in the
+            --  case of a null type extension where the parent's equality
+            --  is hidden. A call to an intrinsic equality is expanded as
+            --  dispatching.
+
+            elsif Present (Root_Prim_Op)
+              and then Is_Intrinsic_Equality (Root_Prim_Op)
             then
-               Has_Untagged_Inc := True;
+               Prim_Op := Root_Prim_Op;
+
+            --  Otherwise there are no candidate subprograms. Let the caller
+            --  diagnose the error.
+
+            else
+               return;
             end if;
 
-            if not Has_Untagged_Inc then
-               F := First_Formal (Old_S);
-               while Present (F) loop
-                  Freeze_Before (Instantiation_Node, Etype (F));
+            --  At this point resolution has taken place and the name is no
+            --  longer overloaded. Mark the primitive as referenced.
 
-                  if Is_Incomplete_Or_Private_Type (Etype (F))
-                    and then No (Underlying_Type (Etype (F)))
-                  then
-                     --  Exclude generic types, or types derived  from them.
-                     --  They will be frozen in the enclosing instance.
+            Set_Is_Overloaded (Name (N), False);
+            Set_Referenced    (Prim_Op);
+         end Find_Suitable_Candidate;
 
-                     if Is_Generic_Type (Etype (F))
-                       or else Is_Generic_Type (Root_Type (Etype (F)))
-                     then
-                        null;
+         --  Local variables
 
-                     --  A limited view of a type declared elsewhere needs no
-                     --  freezing actions.
+         Is_CW_Prim : Boolean;
 
-                     elsif From_Limited_With (Etype (F)) then
-                        null;
+      --  Start of processing for Handle_Instance_With_Class_Wide_Type
 
-                     else
-                        Error_Msg_NE
-                          ("type& must be frozen before this point",
-                           Instantiation_Node, Etype (F));
-                     end if;
-                  end if;
+      begin
+         Wrapped_Prim := Empty;
+         Wrap_Id := Empty;
+
+         --  Ada 2012 (AI05-0071): A generic/instance scenario involving a
+         --  formal type with unknown discriminants and a generic primitive
+         --  operation of the said type with a box require special processing
+         --  when the actual is a class-wide type:
+         --
+         --    generic
+         --       type Formal_Typ (<>) is private;
+         --       with procedure Prim_Op (Param : Formal_Typ) is <>;
+         --    package Gen is ...
+         --
+         --    package Inst is new Gen (Actual_Typ'Class);
+         --
+         --  In this case the general renaming mechanism used in the prologue
+         --  of an instance no longer applies:
+         --
+         --    procedure Prim_Op (Param : Formal_Typ) renames Prim_Op;
+         --
+         --  The above is replaced the following wrapper/renaming combination:
+         --
+         --    procedure Wrapper (Param : Formal_Typ) is  --  wrapper
+         --    begin
+         --       Prim_Op (Param);                        --  primitive
+         --    end Wrapper;
+         --
+         --    procedure Prim_Op (Param : Formal_Typ) renames Wrapper;
+         --
+         --  This transformation applies only if there is no explicit visible
+         --  class-wide operation at the point of the instantiation. Ren_Id is
+         --  the entity of the renaming declaration. When the transformation
+         --  applies, Wrapped_Prim is the entity of the wrapped primitive.
+
+         if Box_Present (Inst_Node) then
+            Find_Suitable_Candidate
+              (Prim_Op    => Wrapped_Prim,
+               Is_CW_Prim => Is_CW_Prim);
+
+            if Present (Wrapped_Prim) then
+               if not Is_CW_Prim then
+                  Build_Class_Wide_Wrapper (Ren_Id, Wrapped_Prim, Wrap_Id);
+
+               --  Small optimization: When the candidate is a class-wide
+               --  subprogram we don't build the wrapper; we modify the
+               --  renaming declaration to directly map the actual to the
+               --  generic formal and discard the candidate.
 
-                  Next_Formal (F);
-               end loop;
+               else
+                  Rewrite (Nam, New_Occurrence_Of (Wrapped_Prim, Sloc (N)));
+                  Wrapped_Prim := Empty;
+               end if;
             end if;
-         end if;
-      end Freeze_Actual_Profile;
 
-      ---------------------------
-      -- Has_Class_Wide_Actual --
-      ---------------------------
+         --  Ada 2022 (AI12-0165, RM 12.6(8.5/3)): The actual subprogram for a
+         --  formal_abstract_subprogram_declaration shall be:
+         --   a) a dispatching operation of the controlling type; or
+         --   b) if the controlling type is a formal type, and the actual
+         --      type corresponding to that formal type is a specific type T,
+         --      a dispatching operation of type T; or
+         --   c) if the controlling type is a formal type, and the actual
+         --      type is a class-wide type T'Class, an implicitly declared
+         --      subprogram corresponding to a primitive operation of type T.
+
+         elsif Nkind (Inst_Node) = N_Formal_Abstract_Subprogram_Declaration
+           and then Is_Entity_Name (Nam)
+         then
+            Find_Suitable_Candidate
+              (Prim_Op    => Wrapped_Prim,
+               Is_CW_Prim => Is_CW_Prim);
 
-      function Has_Class_Wide_Actual return Boolean is
-         Formal     : Entity_Id;
-         Formal_Typ : Entity_Id;
+            if Present (Wrapped_Prim) then
 
-      begin
-         if Is_Actual then
-            Formal := First_Formal (Formal_Spec);
-            while Present (Formal) loop
-               Formal_Typ := Etype (Formal);
+               --  Cases (a) and (b); see previous description.
 
-               if Has_Unknown_Discriminants (Formal_Typ)
-                 and then not Is_Class_Wide_Type (Formal_Typ)
-                 and then Is_Class_Wide_Type (Get_Instance_Of (Formal_Typ))
+               if not Is_CW_Prim then
+                  Build_Class_Wide_Wrapper (Ren_Id, Wrapped_Prim, Wrap_Id);
+
+               --  Case (c); see previous description.
+
+               --  Implicit operations of T'Class for subtype declarations
+               --  are built by Derive_Subprogram, and their Alias attribute
+               --  references the primitive operation of T.
+
+               elsif not Comes_From_Source (Wrapped_Prim)
+                 and then Nkind (Parent (Wrapped_Prim)) = N_Subtype_Declaration
+                 and then Present (Alias (Wrapped_Prim))
                then
-                  return True;
-               end if;
+                  --  We don't need to build the wrapper; we modify the
+                  --  renaming declaration to directly map the actual to
+                  --  the generic formal and discard the candidate.
 
-               Next_Formal (Formal);
-            end loop;
-         end if;
+                  Rewrite (Nam,
+                    New_Occurrence_Of (Alias (Wrapped_Prim), Sloc (N)));
+                  Wrapped_Prim := Empty;
 
-         return False;
-      end Has_Class_Wide_Actual;
+               --  Legality rules do not apply; discard the candidate.
+
+               else
+                  Wrapped_Prim := Empty;
+               end if;
+            end if;
+         end if;
+      end Handle_Instance_With_Class_Wide_Type;
 
       -------------------------
       -- Original_Subprogram --
@@ -2866,12 +3094,13 @@ package body Sem_Ch8 is
       --  Local variables
 
       CW_Actual : constant Boolean := Has_Class_Wide_Actual;
-      --  Ada 2012 (AI05-071, AI05-0131): True if the renaming is for a
-      --  defaulted formal subprogram when the actual for a related formal
-      --  type is class-wide.
+      --  Ada 2012 (AI05-071, AI05-0131) and Ada 2022 (AI12-0165): True if the
+      --  renaming is for a defaulted formal subprogram when the actual for a
+      --  related formal type is class-wide.
 
-      Inst_Node : Node_Id := Empty;
-      New_S     : Entity_Id;
+      Inst_Node    : Node_Id   := Empty;
+      New_S        : Entity_Id := Empty;
+      Wrapped_Prim : Entity_Id := Empty;
 
    --  Start of processing for Analyze_Subprogram_Renaming
 
@@ -3002,20 +3231,64 @@ package body Sem_Ch8 is
       if Is_Actual then
          Inst_Node := Unit_Declaration_Node (Formal_Spec);
 
-         --  Check whether the renaming is for a defaulted actual subprogram
-         --  with a class-wide actual.
+         --  Ada 2012 (AI05-0071) and Ada 2022 (AI12-0165): when the actual
+         --  type is a class-wide type T'Class we may need to wrap a primitive
+         --  operation of T. Search for the wrapped primitive and (if required)
+         --  build a wrapper whose body consists of a dispatching call to the
+         --  wrapped primitive of T, with its formal parameters as the actual
+         --  parameters.
+
+         if CW_Actual and then
+
+         --  Ada 2012 (AI05-0071): Check whether the renaming is for a
+         --  defaulted actual subprogram with a class-wide actual.
+
+            (Box_Present (Inst_Node)
+
+                or else
 
-         --  The class-wide wrapper is not needed in GNATprove_Mode and there
-         --  is an external axiomatization on the package.
+         --  Ada 2022 (AI12-0165): Check whether the renaming is for a formal
+         --  abstract subprogram declaration with a class-wide actual.
 
-         if CW_Actual
-           and then Box_Present (Inst_Node)
-           and then not
-             (GNATprove_Mode
-               and then
-                 Present (Containing_Package_With_Ext_Axioms (Formal_Spec)))
+             (Nkind (Inst_Node) = N_Formal_Abstract_Subprogram_Declaration
+               and then Is_Entity_Name (Nam)))
          then
-            Build_Class_Wide_Wrapper (New_S, Old_S);
+            New_S := Analyze_Subprogram_Specification (Spec);
+
+            --  Do not attempt to build the wrapper if the renaming is in error
+
+            if not Error_Posted (Nam) then
+               Handle_Instance_With_Class_Wide_Type
+                 (Inst_Node    => Inst_Node,
+                  Ren_Id       => New_S,
+                  Wrapped_Prim => Wrapped_Prim,
+                  Wrap_Id      => Old_S);
+
+               --  If several candidates were found, then we reported the
+               --  ambiguity; stop processing the renaming declaration to
+               --  avoid reporting further (spurious) errors.
+
+               if Error_Posted (Spec) then
+                  return;
+               end if;
+
+            end if;
+         end if;
+
+         if Present (Wrapped_Prim) then
+
+            --  When the wrapper is built, the subprogram renaming aliases
+            --  the wrapper.
+
+            Analyze (Nam);
+
+            pragma Assert (Old_S = Entity (Nam)
+              and then Is_Class_Wide_Wrapper (Old_S));
+
+            --  The subprogram renaming declaration may become Ghost if it
+            --  renames a wrapper of a Ghost entity.
+
+            Mark_Ghost_Renaming (N, Wrapped_Prim);
 
          elsif Is_Entity_Name (Nam)
            and then Present (Entity (Nam))
@@ -3197,7 +3470,10 @@ package body Sem_Ch8 is
          --  constructed later at the freeze point, so indicate that the
          --  completion has not been seen yet.
 
-         Set_Ekind (New_S, E_Subprogram_Body);
+         Reinit_Field_To_Zero (New_S, F_Has_Out_Or_In_Out_Parameter);
+         Reinit_Field_To_Zero (New_S, F_Needs_No_Actuals,
+           Old_Ekind => (E_Function | E_Procedure => True, others => False));
+         Mutate_Ekind (New_S, E_Subprogram_Body);
          New_S := Rename_Spec;
          Set_Has_Completion (Rename_Spec, False);
 
@@ -3215,7 +3491,9 @@ package body Sem_Ch8 is
                Style.Missing_Overriding (N, Rename_Spec);
             end if;
 
-         elsif Must_Override (Specification (N)) then
+         elsif Must_Override (Specification (N))
+           and then not Can_Override_Operator (Rename_Spec)
+         then
             Error_Msg_NE ("subprogram& is not overriding", N, Rename_Spec);
          end if;
 
@@ -3497,7 +3775,7 @@ package body Sem_Ch8 is
                end if;
 
                if Original_Subprogram (Old_S) = Rename_Spec then
-                  Error_Msg_N ("unfrozen subprogram cannot rename itself ", N);
+                  Error_Msg_N ("unfrozen subprogram cannot rename itself", N);
                else
                   Check_Formal_Subprogram_Conformance (New_S, Old_S, Spec);
                end if;
@@ -3590,7 +3868,15 @@ package body Sem_Ch8 is
             --  indicate that the renaming is an abstract dispatching operation
             --  with a controlling type.
 
-            if Is_Actual and then Is_Abstract_Subprogram (Formal_Spec) then
+            --  Skip this decoration when the renaming corresponds to an
+            --  association with class-wide wrapper (see above) because such
+            --  wrapper is neither abstract nor a dispatching operation (its
+            --  body has the dispatching call to the wrapped primitive).
+
+            if Is_Actual
+              and then Is_Abstract_Subprogram (Formal_Spec)
+              and then No (Wrapped_Prim)
+            then
 
                --  Mark the renaming as abstract here, so Find_Dispatching_Type
                --  see it as corresponding to a generic association for a
@@ -3704,15 +3990,31 @@ package body Sem_Ch8 is
             Set_Has_Delayed_Freeze (New_S, False);
             Freeze_Before (N, New_S);
 
-            --  An abstract subprogram is only allowed as an actual in the case
-            --  where the formal subprogram is also abstract.
-
             if (Ekind (Old_S) = E_Procedure or else Ekind (Old_S) = E_Function)
-              and then Is_Abstract_Subprogram (Old_S)
               and then not Is_Abstract_Subprogram (Formal_Spec)
             then
-               Error_Msg_N
-                 ("abstract subprogram not allowed as generic actual", Nam);
+               --  An abstract subprogram is only allowed as an actual in the
+               --  case where the formal subprogram is also abstract.
+
+               if Is_Abstract_Subprogram (Old_S) then
+                  Error_Msg_N
+                    ("abstract subprogram not allowed as generic actual", Nam);
+               end if;
+
+               --  AI12-0412: A primitive of an abstract type with Pre'Class
+               --  or Post'Class aspects specified with nonstatic expressions
+               --  is not allowed as actual for a nonabstract formal subprogram
+               --  (see RM 6.1.1(18.2/5).
+
+               if Is_Dispatching_Operation (Old_S)
+                 and then
+                   Is_Prim_Of_Abst_Type_With_Nonstatic_CW_Pre_Post (Old_S)
+               then
+                  Error_Msg_N
+                    ("primitive of abstract type with nonstatic class-wide "
+                      & "pre/postconditions not allowed as actual",
+                     Nam);
+               end if;
             end if;
          end if;
 
@@ -3874,29 +4176,6 @@ package body Sem_Ch8 is
       Ada_Version_Pragma := Save_AVP;
       Ada_Version_Explicit := Save_AV_Exp;
 
-      --  In GNATprove mode, the renamings of actual subprograms are replaced
-      --  with wrapper functions that make it easier to propagate axioms to the
-      --  points of call within an instance. Wrappers are generated if formal
-      --  subprogram is subject to axiomatization.
-
-      --  The types in the wrapper profiles are obtained from (instances of)
-      --  the types of the formal subprogram.
-
-      if Is_Actual
-        and then GNATprove_Mode
-        and then Present (Containing_Package_With_Ext_Axioms (Formal_Spec))
-        and then not Inside_A_Generic
-      then
-         if Ekind (Old_S) = E_Function then
-            Rewrite (N, Build_Function_Wrapper (Formal_Spec, Old_S));
-            Analyze (N);
-
-         elsif Ekind (Old_S) = E_Operator then
-            Rewrite (N, Build_Operator_Wrapper (Formal_Spec, Old_S));
-            Analyze (N);
-         end if;
-      end if;
-
       --  Check if we are looking at an Ada 2012 defaulted formal subprogram
       --  and mark any use_package_clauses that affect the visibility of the
       --  implicit generic actual.
@@ -4386,7 +4665,7 @@ package body Sem_Ch8 is
 
       if not Configurable_Run_Time_Mode
         and then not Present (Corresponding_Formal_Spec (N))
-        and then Etype (Nam) /= RTE (RE_AST_Handler)
+        and then not Is_RTE (Etype (Nam), RE_AST_Handler)
       then
          declare
             P : constant Node_Id := Prefix (Nam);
@@ -4591,10 +4870,7 @@ package body Sem_Ch8 is
    -- Check_In_Previous_With_Clause --
    -----------------------------------
 
-   procedure Check_In_Previous_With_Clause
-     (N   : Node_Id;
-      Nam : Entity_Id)
-   is
+   procedure Check_In_Previous_With_Clause (N, Nam : Node_Id) is
       Pack : constant Entity_Id := Entity (Original_Node (Nam));
       Item : Node_Id;
       Par  : Node_Id;
@@ -4801,7 +5077,7 @@ package body Sem_Ch8 is
 
             Pop_Scope;
 
-            while not (Is_List_Member (Decl))
+            while not Is_List_Member (Decl)
               or else Nkind (Parent (Decl)) in N_Protected_Definition
                                              | N_Task_Definition
             loop
@@ -4923,9 +5199,9 @@ package body Sem_Ch8 is
                Next_Entity (Id);
             end loop;
 
-            if Present (Renamed_Object (Pack)) then
-               Set_In_Use (Renamed_Object (Pack), False);
-               Set_Current_Use_Clause (Renamed_Object (Pack), Empty);
+            if Present (Renamed_Entity (Pack)) then
+               Set_In_Use (Renamed_Entity (Pack), False);
+               Set_Current_Use_Clause (Renamed_Entity (Pack), Empty);
             end if;
 
             if Chars (Pack) = Name_System
@@ -5139,8 +5415,8 @@ package body Sem_Ch8 is
          ------------------------
 
          function Declared_In_Actual (Pack : Entity_Id) return Boolean is
+            pragma Assert (Ekind (Pack) = E_Package);
             Act : Entity_Id;
-
          begin
             if No (Associated_Formal_Package (Pack)) then
                return False;
@@ -5148,13 +5424,13 @@ package body Sem_Ch8 is
             else
                Act := First_Entity (Pack);
                while Present (Act) loop
-                  if Renamed_Object (Pack) = Scop then
+                  if Renamed_Entity (Pack) = Scop then
                      return True;
 
                   --  Check for end of list of actuals
 
                   elsif Ekind (Act) = E_Package
-                    and then Renamed_Object (Act) = Pack
+                    and then Renamed_Entity (Act) = Pack
                   then
                      return False;
 
@@ -5253,16 +5529,6 @@ package body Sem_Ch8 is
 
          elsif not Comes_From_Source (E) then
             return False;
-
-         --  In gnat internal mode, we consider all entities known. The
-         --  historical reason behind this discrepancy is not known??? But the
-         --  only effect is to modify the error message given, so it is not
-         --  critical. Since it only affects the exact wording of error
-         --  messages in illegal programs, we do not mention this as an
-         --  effect of -gnatg, since it is not a language modification.
-
-         elsif GNAT_Mode then
-            return True;
          end if;
 
          --  Here we have an entity that is not from package Standard, and
@@ -5583,9 +5849,25 @@ package body Sem_Ch8 is
               and then N = Prefix (Parent (N))
               and then Is_Known_Unit (Parent (N))
             then
-               Error_Msg_Node_2 := Selector_Name (Parent (N));
-               Error_Msg_N -- CODEFIX
-                 ("\\missing `WITH &.&;`", Prefix (Parent (N)));
+               declare
+                  P : Node_Id := Parent (N);
+               begin
+                  Error_Msg_Name_1 := Chars (N);
+                  Error_Msg_Name_2 := Chars (Selector_Name (P));
+
+                  if Nkind (Parent (P)) = N_Selected_Component
+                    and then Is_Known_Unit (Parent (P))
+                  then
+                     P := Parent (P);
+                     Error_Msg_Name_3 := Chars (Selector_Name (P));
+                     Error_Msg_N -- CODEFIX
+                       ("\\missing `WITH %.%.%;`", N);
+
+                  else
+                     Error_Msg_N -- CODEFIX
+                       ("\\missing `WITH %.%;`", N);
+                  end if;
+               end;
             end if;
 
             --  Now check for possible misspellings
@@ -5622,7 +5904,10 @@ package body Sem_Ch8 is
          --  undefined reference. The entry is not added if we are ignoring
          --  errors.
 
-         if not All_Errors_Mode and then Ignore_Errors_Enable = 0 then
+         if not All_Errors_Mode
+           and then Ignore_Errors_Enable = 0
+           and then not Get_Ignore_Errors
+         then
             Urefs.Append (
               (Node => N,
                Err  => Emsg,
@@ -5675,8 +5960,7 @@ package body Sem_Ch8 is
                --  happens for trees generated from Exp_Pakd, where expressions
                --  can be deliberately "mis-typed" to the packed array type.
 
-               if Is_Array_Type (Entyp)
-                 and then Is_Packed (Entyp)
+               if Is_Packed_Array (Entyp)
                  and then Present (Etype (N))
                  and then Etype (N) = Packed_Array_Impl_Type (Entyp)
                then
@@ -5753,12 +6037,6 @@ package body Sem_Ch8 is
          E := Homonym (E);
       end loop;
 
-      --  If we are ignoring errors, skip the error processing
-
-      if Get_Ignore_Errors then
-         return;
-      end if;
-
       --  If no entries on homonym chain that were potentially visible,
       --  and no entities reasonably considered as non-visible, then
       --  we have a plain undefined reference, with no additional
@@ -5969,9 +6247,9 @@ package body Sem_Ch8 is
 
                if Scope (E) = Scope (E2)
                  and then Ekind (E) = E_Package
-                 and then Present (Renamed_Object (E))
-                 and then Is_Generic_Instance (Renamed_Object (E))
-                 and then In_Open_Scopes (Renamed_Object (E))
+                 and then Present (Renamed_Entity (E))
+                 and then Is_Generic_Instance (Renamed_Entity (E))
+                 and then In_Open_Scopes (Renamed_Entity (E))
                  and then Comes_From_Source (N)
                then
                   Set_Is_Immediately_Visible (E, False);
@@ -6302,9 +6580,9 @@ package body Sem_Ch8 is
       --  original package.
 
       if Ekind (P_Name) = E_Package
-        and then Present (Renamed_Object (P_Name))
+        and then Present (Renamed_Entity (P_Name))
       then
-         P_Name := Renamed_Object (P_Name);
+         P_Name := Renamed_Entity (P_Name);
 
          if From_Limited_With (P_Name)
            and then not Unit_Is_Visible (Cunit (Get_Source_Unit (P_Name)))
@@ -6760,7 +7038,17 @@ package body Sem_Ch8 is
          end if;
       end if;
 
-      Change_Selected_Component_To_Expanded_Name (N);
+      case Nkind (N) is
+         when N_Selected_Component =>
+            Reinit_Field_To_Zero (N, F_Is_Prefixed_Call);
+            Change_Selected_Component_To_Expanded_Name (N);
+
+         when N_Expanded_Name =>
+            null;
+
+         when others =>
+            pragma Assert (False);
+      end case;
 
       --  Preserve relevant elaboration-related attributes of the context which
       --  are no longer available or very expensive to recompute once analysis,
@@ -6906,10 +7194,10 @@ package body Sem_Ch8 is
    end Find_Expanded_Name;
 
    --------------------
-   -- Find_Most_Prev --
+   -- Find_First_Use --
    --------------------
 
-   function Find_Most_Prev (Use_Clause : Node_Id) return Node_Id is
+   function Find_First_Use (Use_Clause : Node_Id) return Node_Id is
       Curr : Node_Id;
 
    begin
@@ -6921,7 +7209,7 @@ package body Sem_Ch8 is
       end loop;
 
       return Curr;
-   end Find_Most_Prev;
+   end Find_First_Use;
 
    -------------------------
    -- Find_Renamed_Entity --
@@ -7099,9 +7387,9 @@ package body Sem_Ch8 is
                Scop := Entity (Prefix (Nam));
 
                if Ekind (Scop) = E_Package
-                 and then Present (Renamed_Object (Scop))
+                 and then Present (Renamed_Entity (Scop))
                then
-                  Scop := Renamed_Object (Scop);
+                  Scop := Renamed_Entity (Scop);
                end if;
 
                --  Operator is visible if prefix of expanded name denotes
@@ -7182,8 +7470,10 @@ package body Sem_Ch8 is
                         if Within (It.Nam, Inst) then
                            if Within (Old_S, Inst) then
                               declare
-                                 It_D  : constant Uint := Scope_Depth (It.Nam);
-                                 Old_D : constant Uint := Scope_Depth (Old_S);
+                                 It_D  : constant Uint :=
+                                   Scope_Depth_Default_0 (It.Nam);
+                                 Old_D : constant Uint :=
+                                   Scope_Depth_Default_0 (Old_S);
                                  N_Ent : Entity_Id;
                               begin
                                  --  Choose the innermost subprogram, which
@@ -7439,15 +7729,9 @@ package body Sem_Ch8 is
                   --  dispatch table wrappers. Required to avoid generating
                   --  elaboration code with HI runtimes.
 
-                  elsif RTU_Loaded (Ada_Tags)
-                    and then
-                      ((RTE_Available (RE_Dispatch_Table_Wrapper)
-                         and then Scope (Selector) =
-                                     RTE (RE_Dispatch_Table_Wrapper))
-                        or else
-                          (RTE_Available (RE_No_Dispatch_Table_Wrapper)
-                            and then Scope (Selector) =
-                                     RTE (RE_No_Dispatch_Table_Wrapper)))
+                  elsif Is_RTE (Scope (Selector), RE_Dispatch_Table_Wrapper)
+                    or else
+                      Is_RTE (Scope (Selector), RE_No_Dispatch_Table_Wrapper)
                   then
                      C_Etype := Empty;
                   else
@@ -7519,10 +7803,16 @@ package body Sem_Ch8 is
             P_Type := Implicitly_Designated_Type (P_Type);
          end if;
 
-         --  First check for components of a record object (not the
-         --  result of a call, which is handled below).
+         --  First check for components of a record object (not the result of
+         --  a call, which is handled below). This also covers the case where
+         --  where the extension feature that supports the prefixed form of
+         --  calls for primitives of untagged types is enabled (excluding
+         --  concurrent cases, which are handled further below).
 
-         if Has_Components (P_Type)
+         if Is_Type (P_Type)
+           and then (Has_Components (P_Type)
+                      or else (Extensions_Allowed
+                                and then not Is_Concurrent_Type (P_Type)))
            and then not Is_Overloadable (P_Name)
            and then not Is_Type (P_Name)
          then
@@ -7536,7 +7826,7 @@ package body Sem_Ch8 is
 
          --  Reference to type name in predicate/invariant expression
 
-         elsif (Is_Task_Type (P_Type) or else Is_Protected_Type (P_Type))
+         elsif Is_Concurrent_Type (P_Type)
            and then not In_Open_Scopes (P_Name)
            and then (not Is_Concurrent_Type (Etype (P_Name))
                       or else not In_Open_Scopes (Etype (P_Name)))
@@ -7863,16 +8153,18 @@ package body Sem_Ch8 is
                         Set_Entity (N, Any_Type);
                         return;
 
-                     --  ??? This test is temporarily disabled (always
-                     --  False) because it causes an unwanted warning on
-                     --  GNAT sources (built with -gnatg, which includes
-                     --  Warn_On_Obsolescent_ Feature). Once this issue
-                     --  is cleared in the sources, it can be enabled.
+                     else
+                        if Restriction_Check_Required (No_Obsolescent_Features)
+                        then
+                           Check_Restriction
+                             (No_Obsolescent_Features, Prefix (N));
+                        end if;
 
-                     elsif Warn_On_Obsolescent_Feature and then False then
-                        Error_Msg_N
-                          ("applying 'Class to an untagged incomplete type"
-                           & " is an obsolescent feature (RM J.11)?r?", N);
+                        if Warn_On_Obsolescent_Feature then
+                           Error_Msg_N
+                             ("applying ''Class to an untagged incomplete type"
+                              & " is an obsolescent feature (RM J.11)?r?", N);
+                        end if;
                      end if;
                   end if;
 
@@ -8057,25 +8349,14 @@ package body Sem_Ch8 is
                if Ekind (Base_Type (T_Name)) = E_Task_Type then
 
                   --  In Ada 2005, a task name can be used in an access
-                  --  definition within its own body. It cannot be used
-                  --  in the discriminant part of the task declaration,
-                  --  nor anywhere else in the declaration because entries
-                  --  cannot have access parameters.
+                  --  definition within its own body.
 
                   if Ada_Version >= Ada_2005
                     and then Nkind (Parent (N)) = N_Access_Definition
                   then
                      Set_Entity (N, T_Name);
                      Set_Etype  (N, T_Name);
-
-                     if Has_Completion (T_Name) then
-                        return;
-
-                     else
-                        Error_Msg_N
-                          ("task type cannot be used as type mark " &
-                           "within its own declaration", N);
-                     end if;
+                     return;
 
                   else
                      Error_Msg_N
@@ -8767,9 +9048,8 @@ package body Sem_Ch8 is
 
          --  Mark primitives
 
-         elsif (Ekind (Id) in Overloadable_Kind
-                 or else Ekind (Id) in
-                           E_Generic_Function | E_Generic_Procedure)
+         elsif (Is_Overloadable (Id)
+                 or else Is_Generic_Subprogram (Id))
            and then (Is_Potentially_Use_Visible (Id)
                       or else Is_Intrinsic_Subprogram (Id)
                       or else (Ekind (Id) in E_Function | E_Procedure
@@ -8930,11 +9210,33 @@ package body Sem_Ch8 is
    procedure Push_Scope (S : Entity_Id) is
       E : constant Entity_Id := Scope (S);
 
+      function Component_Alignment_Default return Component_Alignment_Kind;
+      --  Return Component_Alignment_Kind for the newly-pushed scope.
+
+      function Component_Alignment_Default return Component_Alignment_Kind is
+      begin
+         --  Each new scope pushed onto the scope stack inherits the component
+         --  alignment of the previous scope. This emulates the "visibility"
+         --  semantics of pragma Component_Alignment.
+
+         if Scope_Stack.Last > Scope_Stack.First then
+            return Scope_Stack.Table
+              (Scope_Stack.Last - 1).Component_Alignment_Default;
+
+         --  Otherwise, this is the first scope being pushed on the scope
+         --  stack. Inherit the component alignment from the configuration
+         --  form of pragma Component_Alignment (if any).
+
+         else
+            return Configuration_Component_Alignment;
+         end if;
+      end Component_Alignment_Default;
+
    begin
       if Ekind (S) = E_Void then
          null;
 
-      --  Set scope depth if not a non-concurrent type, and we have not yet set
+      --  Set scope depth if not a nonconcurrent type, and we have not yet set
       --  the scope depth. This means that we have the first occurrence of the
       --  scope, and this is where the depth is set.
 
@@ -8948,59 +9250,39 @@ package body Sem_Ch8 is
             Set_Scope_Depth_Value (S, Uint_1);
 
          elsif not Is_Record_Type (Current_Scope) then
-            if Ekind (S) = E_Loop then
-               Set_Scope_Depth_Value (S, Scope_Depth (Current_Scope));
-            else
-               Set_Scope_Depth_Value (S, Scope_Depth (Current_Scope) + 1);
+            if Scope_Depth_Set (Current_Scope) then
+               if Ekind (S) = E_Loop then
+                  Set_Scope_Depth_Value (S, Scope_Depth (Current_Scope));
+               else
+                  Set_Scope_Depth_Value (S, Scope_Depth (Current_Scope) + 1);
+               end if;
             end if;
          end if;
       end if;
 
       Scope_Stack.Increment_Last;
 
-      declare
-         SST : Scope_Stack_Entry renames Scope_Stack.Table (Scope_Stack.Last);
-
-      begin
-         SST.Entity                        := S;
-         SST.Save_Scope_Suppress           := Scope_Suppress;
-         SST.Save_Local_Suppress_Stack_Top := Local_Suppress_Stack_Top;
-         SST.Save_Check_Policy_List        := Check_Policy_List;
-         SST.Save_Default_Storage_Pool     := Default_Pool;
-         SST.Save_No_Tagged_Streams        := No_Tagged_Streams;
-         SST.Save_SPARK_Mode               := SPARK_Mode;
-         SST.Save_SPARK_Mode_Pragma        := SPARK_Mode_Pragma;
-         SST.Save_Default_SSO              := Default_SSO;
-         SST.Save_Uneval_Old               := Uneval_Old;
-
-         --  Each new scope pushed onto the scope stack inherits the component
-         --  alignment of the previous scope. This emulates the "visibility"
-         --  semantics of pragma Component_Alignment.
-
-         if Scope_Stack.Last > Scope_Stack.First then
-            SST.Component_Alignment_Default :=
-              Scope_Stack.Table
-                (Scope_Stack.Last - 1).Component_Alignment_Default;
-
-         --  Otherwise, this is the first scope being pushed on the scope
-         --  stack. Inherit the component alignment from the configuration
-         --  form of pragma Component_Alignment (if any).
-
-         else
-            SST.Component_Alignment_Default :=
-              Configuration_Component_Alignment;
-         end if;
-
-         SST.Last_Subprogram_Name           := null;
-         SST.Is_Transient                   := False;
-         SST.Node_To_Be_Wrapped             := Empty;
-         SST.Pending_Freeze_Actions         := No_List;
-         SST.Actions_To_Be_Wrapped          := (others => No_List);
-         SST.First_Use_Clause               := Empty;
-         SST.Is_Active_Stack_Base           := False;
-         SST.Previous_Visibility            := False;
-         SST.Locked_Shared_Objects          := No_Elist;
-      end;
+      Scope_Stack.Table (Scope_Stack.Last) :=
+        (Entity                        => S,
+         Save_Scope_Suppress           => Scope_Suppress,
+         Save_Local_Suppress_Stack_Top => Local_Suppress_Stack_Top,
+         Save_Check_Policy_List        => Check_Policy_List,
+         Save_Default_Storage_Pool     => Default_Pool,
+         Save_No_Tagged_Streams        => No_Tagged_Streams,
+         Save_SPARK_Mode               => SPARK_Mode,
+         Save_SPARK_Mode_Pragma        => SPARK_Mode_Pragma,
+         Save_Default_SSO              => Default_SSO,
+         Save_Uneval_Old               => Uneval_Old,
+         Component_Alignment_Default   => Component_Alignment_Default,
+         Last_Subprogram_Name          => null,
+         Is_Transient                  => False,
+         Node_To_Be_Wrapped            => Empty,
+         Pending_Freeze_Actions        => No_List,
+         Actions_To_Be_Wrapped         => (others => No_List),
+         First_Use_Clause              => Empty,
+         Is_Active_Stack_Base          => False,
+         Previous_Visibility           => False,
+         Locked_Shared_Objects         => No_Elist);
 
       if Debug_Flag_W then
          Write_Str ("--> new scope: ");
@@ -9737,16 +10019,16 @@ package body Sem_Ch8 is
          if Present (Redundant) and then Parent (Redundant) /= Prev_Use then
 
             --  Make sure we are looking at most-descendant use_package_clause
-            --  by traversing the chain with Find_Most_Prev and then verifying
+            --  by traversing the chain with Find_First_Use and then verifying
             --  there is no scope manipulation via Most_Descendant_Use_Clause.
 
             if Nkind (Prev_Use) = N_Use_Package_Clause
               and then
                 (Nkind (Parent (Prev_Use)) /= N_Compilation_Unit
                   or else Most_Descendant_Use_Clause
-                            (Prev_Use, Find_Most_Prev (Prev_Use)) /= Prev_Use)
+                            (Prev_Use, Find_First_Use (Prev_Use)) /= Prev_Use)
             then
-               Prev_Use := Find_Most_Prev (Prev_Use);
+               Prev_Use := Find_First_Use (Prev_Use);
             end if;
 
             Error_Msg_Sloc := Sloc (Prev_Use);
@@ -9791,8 +10073,8 @@ package body Sem_Ch8 is
          --  When a renaming exists we must check it for redundancy. The
          --  original package would have already been seen at this point.
 
-         if Present (Renamed_Object (Entity (Pack_Name))) then
-            P := Renamed_Object (Entity (Pack_Name));
+         if Present (Renamed_Entity (Entity (Pack_Name))) then
+            P := Renamed_Entity (Entity (Pack_Name));
          else
             P := Entity (Pack_Name);
          end if;
@@ -9858,10 +10140,10 @@ package body Sem_Ch8 is
       --  also in use (the flags on both entities must remain consistent, and a
       --  subsequent use of either of them should be recognized as redundant).
 
-      if Present (Renamed_Object (P)) then
-         Set_In_Use (Renamed_Object (P));
-         Set_Current_Use_Clause (Renamed_Object (P), N);
-         Real_P := Renamed_Object (P);
+      if Present (Renamed_Entity (P)) then
+         Set_In_Use (Renamed_Entity (P));
+         Set_Current_Use_Clause (Renamed_Entity (P), N);
+         Real_P := Renamed_Entity (P);
       else
          Real_P := P;
       end if;
@@ -10300,7 +10582,7 @@ package body Sem_Ch8 is
             if Present (Current_Use_Clause (T)) then
                Use_Clause_Known : declare
                   Clause1 : constant Node_Id :=
-                              Find_Most_Prev (Current_Use_Clause (T));
+                              Find_First_Use (Current_Use_Clause (T));
                   Clause2 : constant Node_Id := Parent (Id);
                   Ent1    : Entity_Id;
                   Ent2    : Entity_Id;
@@ -10440,10 +10722,10 @@ package body Sem_Ch8 is
             --  a spurious warning - so verify there is a previous use clause.
 
             if Current_Use_Clause (Scope (T)) /=
-                 Find_Most_Prev (Current_Use_Clause (Scope (T)))
+                 Find_First_Use (Current_Use_Clause (Scope (T)))
             then
                Error_Msg_Sloc :=
-                 Sloc (Find_Most_Prev (Current_Use_Clause (Scope (T))));
+                 Sloc (Find_First_Use (Current_Use_Clause (Scope (T))));
                Error_Msg_NE -- CODEFIX
                  ("& is already use-visible through package use clause #??",
                   Id, T);