OSDN Git Service

2009-04-17 Ed Schonberg <schonberg@adacore.com>
authorcharlet <charlet@138bc75d-0d04-0410-961f-82ee72b054a4>
Fri, 17 Apr 2009 09:38:12 +0000 (09:38 +0000)
committercharlet <charlet@138bc75d-0d04-0410-961f-82ee72b054a4>
Fri, 17 Apr 2009 09:38:12 +0000 (09:38 +0000)
* atree.ads, atree.adb: Move New_Copy_Tree.to sem_util.

* nlists.ads, nlists.adb: Move New_Copy_List to sem_util.

* lib-load.adb: Use Copy_Separate_Tree rather than New_Copy_Tree

* sem_util.ads, sem_util.adb: New_Copy_Tree and New_Copy_List belong in
semantic units, because the handling of itypes in the copied tree
requires semantic information that does not belong in atree.

2009-04-17  Robert Dewar  <dewar@adacore.com>

* par-ch6.adb: Minor reformatting

* prj.adb: Minor reformatting

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@146230 138bc75d-0d04-0410-961f-82ee72b054a4

gcc/ada/ChangeLog
gcc/ada/atree.adb
gcc/ada/atree.ads
gcc/ada/lib-load.adb
gcc/ada/nlists.adb
gcc/ada/nlists.ads
gcc/ada/par-ch6.adb
gcc/ada/prj.adb
gcc/ada/sem_util.adb
gcc/ada/sem_util.ads

index eaa602b..1533016 100644 (file)
@@ -1,3 +1,35 @@
+2009-04-17  Ed Schonberg  <schonberg@adacore.com>
+
+       * sem_ch3.adb (Access_Subprogram_Definition): Additional checks on
+       illegal uses of incomplete types in formal parts and return types.
+
+       * sem_ch6.adb (Process_Formals): Taft-amendment types are legal in
+       access to subprograms.
+
+       * sem_ch7.adb (Uninstall_Declarations): diagnose attempts to use
+       Taft-amendment types as the return type of an access_to_function type.
+
+       * freeze.adb (Freeze_Entity): Remove tests on formals of an incomplete
+       type for access_to_subprograms. The check is performed on package exit.
+
+2009-04-17  Ed Schonberg  <schonberg@adacore.com>
+
+       * atree.ads, atree.adb: Move New_Copy_Tree.to sem_util.
+
+       * nlists.ads, nlists.adb: Move New_Copy_List to sem_util.
+       
+       * lib-load.adb: Use Copy_Separate_Tree rather than New_Copy_Tree
+
+       * sem_util.ads, sem_util.adb: New_Copy_Tree and New_Copy_List belong in
+       semantic units, because the handling of itypes in the copied tree
+       requires semantic information that does not belong in atree.
+
+2009-04-17  Robert Dewar  <dewar@adacore.com>
+
+       * par-ch6.adb: Minor reformatting
+
+       * prj.adb: Minor reformatting
+
 2009-04-17  Gary Dismukes  <dismukes@adacore.com>
 
        * par-ch6.adb (P_Subprogram): Overriding indicators should be allowed
index 027df3c..3745b38 100644 (file)
@@ -105,8 +105,6 @@ package body Atree is
    use Atree_Private_Part;
    --  We are also allowed to see our private data structures!
 
-   function E_To_N is new Unchecked_Conversion (Entity_Kind, Node_Kind);
-   function N_To_E is new Unchecked_Conversion (Node_Kind, Entity_Kind);
    --  Functions used to store Entity_Kind value in Nkind field
 
    --  The following declarations are used to store flags 65-72 in the
@@ -395,91 +393,6 @@ package body Atree is
    function To_Flag_Word5_Ptr is new
      Unchecked_Conversion (Union_Id_Ptr, Flag_Word5_Ptr);
 
-   --  Default value used to initialize default nodes. Note that some of the
-   --  fields get overwritten, and in particular, Nkind always gets reset.
-
-   Default_Node : Node_Record := (
-      Is_Extension      => False,
-      Pflag1            => False,
-      Pflag2            => False,
-      In_List           => False,
-      Unused_1          => False,
-      Rewrite_Ins       => False,
-      Analyzed          => False,
-      Comes_From_Source => False, -- modified by Set_Comes_From_Source_Default
-      Error_Posted      => False,
-      Flag4             => False,
-
-      Flag5             => False,
-      Flag6             => False,
-      Flag7             => False,
-      Flag8             => False,
-      Flag9             => False,
-      Flag10            => False,
-      Flag11            => False,
-      Flag12            => False,
-
-      Flag13            => False,
-      Flag14            => False,
-      Flag15            => False,
-      Flag16            => False,
-      Flag17            => False,
-      Flag18            => False,
-
-      Nkind             => N_Unused_At_Start,
-
-      Sloc              => No_Location,
-      Link              => Empty_List_Or_Node,
-      Field1            => Empty_List_Or_Node,
-      Field2            => Empty_List_Or_Node,
-      Field3            => Empty_List_Or_Node,
-      Field4            => Empty_List_Or_Node,
-      Field5            => Empty_List_Or_Node);
-
-   --  Default value used to initialize node extensions (i.e. the second
-   --  and third and fourth components of an extended node). Note we are
-   --  cheating a bit here when it comes to Node12, which really holds
-   --  flags an (for the third component), the convention. But it works
-   --  because Empty, False, Convention_Ada, all happen to be all zero bits.
-
-   Default_Node_Extension : constant Node_Record := (
-      Is_Extension      => True,
-      Pflag1            => False,
-      Pflag2            => False,
-      In_List           => False,
-      Unused_1          => False,
-      Rewrite_Ins       => False,
-      Analyzed          => False,
-      Comes_From_Source => False,
-      Error_Posted      => False,
-      Flag4             => False,
-
-      Flag5             => False,
-      Flag6             => False,
-      Flag7             => False,
-      Flag8             => False,
-      Flag9             => False,
-      Flag10            => False,
-      Flag11            => False,
-      Flag12            => False,
-
-      Flag13            => False,
-      Flag14            => False,
-      Flag15            => False,
-      Flag16            => False,
-      Flag17            => False,
-      Flag18            => False,
-
-      Nkind             => E_To_N (E_Void),
-
-      Field6            => Empty_List_Or_Node,
-      Field7            => Empty_List_Or_Node,
-      Field8            => Empty_List_Or_Node,
-      Field9            => Empty_List_Or_Node,
-      Field10           => Empty_List_Or_Node,
-      Field11           => Empty_List_Or_Node,
-      Field12           => Empty_List_Or_Node);
-
    --------------------------------------------------
    -- Implementation of Tree Substitution Routines --
    --------------------------------------------------
@@ -1218,7 +1131,7 @@ package body Atree is
 
    --  Start of processing for New_Copy_Tree function
 
-   function New_Copy_Tree
+   function New_Copy_Tree1
      (Source    : Node_Id;
       Map       : Elist_Id := No_Elist;
       New_Sloc  : Source_Ptr := No_Location;
@@ -1835,12 +1748,9 @@ package body Atree is
          --  The new Itype has all the attributes of the old one, and
          --  we just copy the contents of the entity. However, the back-end
          --  needs different names for debugging purposes, so we create a
-         --  new internal name by appending the letter 'c' (copy) to the
-         --  name of the original.
+         --  new internal name for it in all cases.
 
-         Get_Name_String (Chars (Old_Itype));
-         Add_Char_To_Name_Buffer ('c');
-         Set_Chars (New_Itype, Name_Enter);
+         --  Set_Chars (New_Itype, New_Internal_Name ('T'));
 
          --  If our associated node is an entity that has already been copied,
          --  then set the associated node of the copy to point to the right
@@ -1952,6 +1862,10 @@ package body Atree is
                             Old_Itype);
             end if;
          end if;
+         Get_Name_String (Chars (Old_Itype));
+         Add_Char_To_Name_Buffer ('c');
+         Add_Nat_To_Name_Buffer (Int (Associated_Node_For_Itype (New_Itype)));
+         Set_Chars (New_Itype, Name_Enter);
       end Visit_Itype;
 
       ----------------
@@ -2085,7 +1999,7 @@ package body Atree is
       --  Now we can copy the actual tree
 
       return Copy_Node_With_Replacement (Source);
-   end New_Copy_Tree;
+   end New_Copy_Tree1;
 
    ----------------
    -- New_Entity --
index df25f6e..8807638 100644 (file)
@@ -430,7 +430,7 @@ package Atree is
    --  Source to be Empty, in which case Relocate_Node simply returns
    --  Empty as the result.
 
-   function New_Copy_Tree
+   function New_Copy_Tree1
      (Source    : Node_Id;
       Map       : Elist_Id   := No_Elist;
       New_Sloc  : Source_Ptr := No_Location;
@@ -3114,6 +3114,95 @@ package Atree is
       for Node_Record'Size use 8*32;
       for Node_Record'Alignment use 4;
 
+      function E_To_N is new Unchecked_Conversion (Entity_Kind, Node_Kind);
+      function N_To_E is new Unchecked_Conversion (Node_Kind, Entity_Kind);
+
+      --  Default value used to initialize default nodes. Note that some of the
+      --  fields get overwritten, and in particular, Nkind always gets reset.
+
+      Default_Node : Node_Record := (
+         Is_Extension      => False,
+         Pflag1            => False,
+         Pflag2            => False,
+         In_List           => False,
+         Unused_1          => False,
+         Rewrite_Ins       => False,
+         Analyzed          => False,
+         Comes_From_Source => False,
+         --  modified by Set_Comes_From_Source_Default
+         Error_Posted      => False,
+         Flag4             => False,
+
+         Flag5             => False,
+         Flag6             => False,
+         Flag7             => False,
+         Flag8             => False,
+         Flag9             => False,
+         Flag10            => False,
+         Flag11            => False,
+         Flag12            => False,
+
+         Flag13            => False,
+         Flag14            => False,
+         Flag15            => False,
+         Flag16            => False,
+         Flag17            => False,
+         Flag18            => False,
+
+         Nkind             => N_Unused_At_Start,
+
+         Sloc              => No_Location,
+         Link              => Empty_List_Or_Node,
+         Field1            => Empty_List_Or_Node,
+         Field2            => Empty_List_Or_Node,
+         Field3            => Empty_List_Or_Node,
+         Field4            => Empty_List_Or_Node,
+         Field5            => Empty_List_Or_Node);
+
+      --  Default value used to initialize node extensions (i.e. the second
+      --  and third and fourth components of an extended node). Note we are
+      --  cheating a bit here when it comes to Node12, which really holds
+      --  flags an (for the third component), the convention. But it works
+      --  because Empty, False, Convention_Ada, all happen to be all zero bits.
+
+      Default_Node_Extension : constant Node_Record := (
+         Is_Extension      => True,
+         Pflag1            => False,
+         Pflag2            => False,
+         In_List           => False,
+         Unused_1          => False,
+         Rewrite_Ins       => False,
+         Analyzed          => False,
+         Comes_From_Source => False,
+         Error_Posted      => False,
+         Flag4             => False,
+
+         Flag5             => False,
+         Flag6             => False,
+         Flag7             => False,
+         Flag8             => False,
+         Flag9             => False,
+         Flag10            => False,
+         Flag11            => False,
+         Flag12            => False,
+
+         Flag13            => False,
+         Flag14            => False,
+         Flag15            => False,
+         Flag16            => False,
+         Flag17            => False,
+         Flag18            => False,
+
+         Nkind             => E_To_N (E_Void),
+
+         Field6            => Empty_List_Or_Node,
+         Field7            => Empty_List_Or_Node,
+         Field8            => Empty_List_Or_Node,
+         Field9            => Empty_List_Or_Node,
+         Field10           => Empty_List_Or_Node,
+         Field11           => Empty_List_Or_Node,
+         Field12           => Empty_List_Or_Node);
+
       --  The following defines the extendable array used for the nodes table
       --  Nodes with extensions use five consecutive entries in the array
 
index 1ceb389..857b609 100644 (file)
@@ -169,14 +169,14 @@ package body Lib.Load is
              Chars => Chars (Selector_Name (Name (With_Node))));
          Du_Name :=
            Make_Defining_Program_Unit_Name (No_Location,
-             Name => New_Copy_Tree (Prefix (Name (With_Node))),
+             Name => Copy_Separate_Tree (Prefix (Name (With_Node))),
              Defining_Identifier => Cunit_Entity);
 
          Set_Is_Child_Unit (Cunit_Entity);
 
          End_Lab :=
            Make_Designator (No_Location,
-             Name => New_Copy_Tree (Prefix (Name (With_Node))),
+             Name => Copy_Separate_Tree (Prefix (Name (With_Node))),
              Identifier => New_Occurrence_Of (Cunit_Entity, No_Location));
       end if;
 
index 7a2b4b4..09bd85a 100644 (file)
@@ -745,31 +745,6 @@ package body Nlists is
       end if;
    end New_Copy_List_Original;
 
-   ------------------------
-   -- New_Copy_List_Tree --
-   ------------------------
-
-   function New_Copy_List_Tree (List : List_Id) return List_Id is
-      NL : List_Id;
-      E  : Node_Id;
-
-   begin
-      if List = No_List then
-         return No_List;
-
-      else
-         NL := New_List;
-         E := First (List);
-
-         while Present (E) loop
-            Append (New_Copy_Tree (E), NL);
-            E := Next (E);
-         end loop;
-
-         return NL;
-      end if;
-   end New_Copy_List_Tree;
-
    --------------
    -- New_List --
    --------------
index 5a6b94f..3753936 100644 (file)
@@ -108,13 +108,6 @@ package Nlists is
    function New_Copy_List_Original (List : List_Id) return List_Id;
    --  Same as New_Copy_List but copies only nodes coming from source
 
-   function New_Copy_List_Tree (List : List_Id) return List_Id;
-   --  Similar to New_Copy_List, except that the copies are done using the
-   --  Atree.New_Copy_Tree function, which means that a full recursive copy
-   --  of the subtrees in the list is performed, setting proper parents. As
-   --  for New_Copy_Tree, it is illegal to attempt to copy extended nodes
-   --  (entities) either directly or indirectly using this function.
-
    function First (List : List_Id) return Node_Id;
    pragma Inline (First);
    --  Obtains the first element of the given node list or, if the node list
index 263efe1..d91b2d9 100644 (file)
@@ -221,13 +221,12 @@ package body Ch6 is
          --  and bodies can occur.
 
          if Pf_Flags /= Pf_Decl_Gins_Pbod_Rnam_Stub
-           and then Pf_Flags /= Pf_Decl_Pbod
+              and then
+            Pf_Flags /= Pf_Decl_Pbod
          then
             Error_Msg_SC ("overriding indicator not allowed here!");
 
-         elsif Token /= Tok_Function
-           and then Token /= Tok_Procedure
-         then
+         elsif Token /= Tok_Function and then Token /= Tok_Procedure then
             Error_Msg_SC ("FUNCTION or PROCEDURE expected!");
          end if;
       end if;
index 73e1f40..d8f368d 100644 (file)
@@ -715,8 +715,8 @@ package body Prj is
    is
    begin
       if Object_File_Suffix = No_Name then
-         return Extend_Name (Source_File_Name, Object_Suffix);
-
+         return Extend_Name
+           (Source_File_Name, Object_Suffix);
       else
          return Extend_Name
            (Source_File_Name, Get_Name_String (Object_File_Suffix));
@@ -880,6 +880,7 @@ package body Prj is
          loop
             Free (Tree.Projects.Table (P));
          end loop;
+
          Project_Table.Free (Tree.Projects);
 
          --  Private part
@@ -929,6 +930,7 @@ package body Prj is
             Free (Tree.Projects.Table (P));
          end loop;
       end if;
+
       Project_Table.Init            (Tree.Projects);
 
       --  Private part table
index d036c85..337d1ac 100644 (file)
@@ -59,8 +59,38 @@ with Tbuild;   use Tbuild;
 with Ttypes;   use Ttypes;
 with Uname;    use Uname;
 
+with GNAT.HTable; use GNAT.HTable;
 package body Sem_Util is
 
+   ----------------------------------------
+   -- Global_Variables for New_Copy_Tree --
+   ----------------------------------------
+
+   --  These global variables are used by New_Copy_Tree. See description
+   --  of the body of this subprogram for details. Global variables can be
+   --  safely used by New_Copy_Tree, since there is no case of a recursive
+   --  call from the processing inside New_Copy_Tree.
+
+   NCT_Hash_Threshhold : constant := 20;
+   --  If there are more than this number of pairs of entries in the
+   --  map, then Hash_Tables_Used will be set, and the hash tables will
+   --  be initialized and used for the searches.
+
+   NCT_Hash_Tables_Used : Boolean := False;
+   --  Set to True if hash tables are in use
+
+   NCT_Table_Entries : Nat;
+   --  Count entries in table to see if threshhold is reached
+
+   NCT_Hash_Table_Setup : Boolean := False;
+   --  Set to True if hash table contains data. We set this True if we
+   --  setup the hash table with data, and leave it set permanently
+   --  from then on, this is a signal that second and subsequent users
+   --  of the hash table must clear the old entries before reuse.
+
+   subtype NCT_Header_Num is Int range 0 .. 511;
+   --  Defines range of headers in hash tables (512 headers)
+
    -----------------------
    -- Local Subprograms --
    -----------------------
@@ -7431,6 +7461,954 @@ package body Sem_Util is
       end if;
    end Needs_One_Actual;
 
+   ------------------------
+   -- New_Copy_List_Tree --
+   ------------------------
+
+   function New_Copy_List_Tree (List : List_Id) return List_Id is
+      NL : List_Id;
+      E  : Node_Id;
+
+   begin
+      if List = No_List then
+         return No_List;
+
+      else
+         NL := New_List;
+         E := First (List);
+
+         while Present (E) loop
+            Append (New_Copy_Tree (E), NL);
+            E := Next (E);
+         end loop;
+
+         return NL;
+      end if;
+   end New_Copy_List_Tree;
+
+   -------------------
+   -- New_Copy_Tree --
+   -------------------
+
+   use Atree.Unchecked_Access;
+   use Atree_Private_Part;
+
+   --  Our approach here requires a two pass traversal of the tree. The
+   --  first pass visits all nodes that eventually will be copied looking
+   --  for defining Itypes. If any defining Itypes are found, then they are
+   --  copied, and an entry is added to the replacement map. In the second
+   --  phase, the tree is copied, using the replacement map to replace any
+   --  Itype references within the copied tree.
+
+   --  The following hash tables are used if the Map supplied has more
+   --  than hash threshhold entries to speed up access to the map. If
+   --  there are fewer entries, then the map is searched sequentially
+   --  (because setting up a hash table for only a few entries takes
+   --  more time than it saves.
+
+   function New_Copy_Hash (E : Entity_Id) return NCT_Header_Num;
+   --  Hash function used for hash operations
+
+   -------------------
+   -- New_Copy_Hash --
+   -------------------
+
+   function New_Copy_Hash (E : Entity_Id) return NCT_Header_Num is
+   begin
+      return Nat (E) mod (NCT_Header_Num'Last + 1);
+   end New_Copy_Hash;
+
+   ---------------
+   -- NCT_Assoc --
+   ---------------
+
+   --  The hash table NCT_Assoc associates old entities in the table
+   --  with their corresponding new entities (i.e. the pairs of entries
+   --  presented in the original Map argument are Key-Element pairs).
+
+   package NCT_Assoc is new Simple_HTable (
+     Header_Num => NCT_Header_Num,
+     Element    => Entity_Id,
+     No_Element => Empty,
+     Key        => Entity_Id,
+     Hash       => New_Copy_Hash,
+     Equal      => Types."=");
+
+   ---------------------
+   -- NCT_Itype_Assoc --
+   ---------------------
+
+   --  The hash table NCT_Itype_Assoc contains entries only for those
+   --  old nodes which have a non-empty Associated_Node_For_Itype set.
+   --  The key is the associated node, and the element is the new node
+   --  itself (NOT the associated node for the new node).
+
+   package NCT_Itype_Assoc is new Simple_HTable (
+     Header_Num => NCT_Header_Num,
+     Element    => Entity_Id,
+     No_Element => Empty,
+     Key        => Entity_Id,
+     Hash       => New_Copy_Hash,
+     Equal      => Types."=");
+
+   --  Start of processing for New_Copy_Tree function
+
+   function New_Copy_Tree
+     (Source    : Node_Id;
+      Map       : Elist_Id := No_Elist;
+      New_Sloc  : Source_Ptr := No_Location;
+      New_Scope : Entity_Id := Empty) return Node_Id
+   is
+      Actual_Map : Elist_Id := Map;
+      --  This is the actual map for the copy. It is initialized with the
+      --  given elements, and then enlarged as required for Itypes that are
+      --  copied during the first phase of the copy operation. The visit
+      --  procedures add elements to this map as Itypes are encountered.
+      --  The reason we cannot use Map directly, is that it may well be
+      --  (and normally is) initialized to No_Elist, and if we have mapped
+      --  entities, we have to reset it to point to a real Elist.
+
+      function Assoc (N : Node_Or_Entity_Id) return Node_Id;
+      --  Called during second phase to map entities into their corresponding
+      --  copies using Actual_Map. If the argument is not an entity, or is not
+      --  in Actual_Map, then it is returned unchanged.
+
+      procedure Build_NCT_Hash_Tables;
+      --  Builds hash tables (number of elements >= threshold value)
+
+      function Copy_Elist_With_Replacement
+        (Old_Elist : Elist_Id) return Elist_Id;
+      --  Called during second phase to copy element list doing replacements
+
+      procedure Copy_Itype_With_Replacement (New_Itype : Entity_Id);
+      --  Called during the second phase to process a copied Itype. The actual
+      --  copy happened during the first phase (so that we could make the entry
+      --  in the mapping), but we still have to deal with the descendents of
+      --  the copied Itype and copy them where necessary.
+
+      function Copy_List_With_Replacement (Old_List : List_Id) return List_Id;
+      --  Called during second phase to copy list doing replacements
+
+      function Copy_Node_With_Replacement (Old_Node : Node_Id) return Node_Id;
+      --  Called during second phase to copy node doing replacements
+
+      procedure Visit_Elist (E : Elist_Id);
+      --  Called during first phase to visit all elements of an Elist
+
+      procedure Visit_Field (F : Union_Id; N : Node_Id);
+      --  Visit a single field, recursing to call Visit_Node or Visit_List
+      --  if the field is a syntactic descendent of the current node (i.e.
+      --  its parent is Node N).
+
+      procedure Visit_Itype (Old_Itype : Entity_Id);
+      --  Called during first phase to visit subsidiary fields of a defining
+      --  Itype, and also create a copy and make an entry in the replacement
+      --  map for the new copy.
+
+      procedure Visit_List (L : List_Id);
+      --  Called during first phase to visit all elements of a List
+
+      procedure Visit_Node (N : Node_Or_Entity_Id);
+      --  Called during first phase to visit a node and all its subtrees
+
+      -----------
+      -- Assoc --
+      -----------
+
+      function Assoc (N : Node_Or_Entity_Id) return Node_Id is
+         E   : Elmt_Id;
+         Ent : Entity_Id;
+
+      begin
+         if not Has_Extension (N) or else No (Actual_Map) then
+            return N;
+
+         elsif NCT_Hash_Tables_Used then
+            Ent := NCT_Assoc.Get (Entity_Id (N));
+
+            if Present (Ent) then
+               return Ent;
+            else
+               return N;
+            end if;
+
+         --  No hash table used, do serial search
+
+         else
+            E := First_Elmt (Actual_Map);
+            while Present (E) loop
+               if Node (E) = N then
+                  return Node (Next_Elmt (E));
+               else
+                  E := Next_Elmt (Next_Elmt (E));
+               end if;
+            end loop;
+         end if;
+
+         return N;
+      end Assoc;
+
+      ---------------------------
+      -- Build_NCT_Hash_Tables --
+      ---------------------------
+
+      procedure Build_NCT_Hash_Tables is
+         Elmt : Elmt_Id;
+         Ent  : Entity_Id;
+      begin
+         if NCT_Hash_Table_Setup then
+            NCT_Assoc.Reset;
+            NCT_Itype_Assoc.Reset;
+         end if;
+
+         Elmt := First_Elmt (Actual_Map);
+         while Present (Elmt) loop
+            Ent := Node (Elmt);
+
+            --  Get new entity, and associate old and new
+
+            Next_Elmt (Elmt);
+            NCT_Assoc.Set (Ent, Node (Elmt));
+
+            if Is_Type (Ent) then
+               declare
+                  Anode : constant Entity_Id :=
+                            Associated_Node_For_Itype (Ent);
+
+               begin
+                  if Present (Anode) then
+
+                     --  Enter a link between the associated node of the
+                     --  old Itype and the new Itype, for updating later
+                     --  when node is copied.
+
+                     NCT_Itype_Assoc.Set (Anode, Node (Elmt));
+                  end if;
+               end;
+            end if;
+
+            Next_Elmt (Elmt);
+         end loop;
+
+         NCT_Hash_Tables_Used := True;
+         NCT_Hash_Table_Setup := True;
+      end Build_NCT_Hash_Tables;
+
+      ---------------------------------
+      -- Copy_Elist_With_Replacement --
+      ---------------------------------
+
+      function Copy_Elist_With_Replacement
+        (Old_Elist : Elist_Id) return Elist_Id
+      is
+         M         : Elmt_Id;
+         New_Elist : Elist_Id;
+
+      begin
+         if No (Old_Elist) then
+            return No_Elist;
+
+         else
+            New_Elist := New_Elmt_List;
+
+            M := First_Elmt (Old_Elist);
+            while Present (M) loop
+               Append_Elmt (Copy_Node_With_Replacement (Node (M)), New_Elist);
+               Next_Elmt (M);
+            end loop;
+         end if;
+
+         return New_Elist;
+      end Copy_Elist_With_Replacement;
+
+      ---------------------------------
+      -- Copy_Itype_With_Replacement --
+      ---------------------------------
+
+      --  This routine exactly parallels its phase one analog Visit_Itype,
+
+      procedure Copy_Itype_With_Replacement (New_Itype : Entity_Id) is
+      begin
+         --  Translate Next_Entity, Scope and Etype fields, in case they
+         --  reference entities that have been mapped into copies.
+
+         Set_Next_Entity (New_Itype, Assoc (Next_Entity (New_Itype)));
+         Set_Etype       (New_Itype, Assoc (Etype       (New_Itype)));
+
+         if Present (New_Scope) then
+            Set_Scope    (New_Itype, New_Scope);
+         else
+            Set_Scope    (New_Itype, Assoc (Scope       (New_Itype)));
+         end if;
+
+         --  Copy referenced fields
+
+         if Is_Discrete_Type (New_Itype) then
+            Set_Scalar_Range (New_Itype,
+              Copy_Node_With_Replacement (Scalar_Range (New_Itype)));
+
+         elsif Has_Discriminants (Base_Type (New_Itype)) then
+            Set_Discriminant_Constraint (New_Itype,
+              Copy_Elist_With_Replacement
+                (Discriminant_Constraint (New_Itype)));
+
+         elsif Is_Array_Type (New_Itype) then
+            if Present (First_Index (New_Itype)) then
+               Set_First_Index (New_Itype,
+                 First (Copy_List_With_Replacement
+                         (List_Containing (First_Index (New_Itype)))));
+            end if;
+
+            if Is_Packed (New_Itype) then
+               Set_Packed_Array_Type (New_Itype,
+                 Copy_Node_With_Replacement
+                   (Packed_Array_Type (New_Itype)));
+            end if;
+         end if;
+      end Copy_Itype_With_Replacement;
+
+      --------------------------------
+      -- Copy_List_With_Replacement --
+      --------------------------------
+
+      function Copy_List_With_Replacement
+        (Old_List : List_Id) return List_Id
+      is
+         New_List : List_Id;
+         E        : Node_Id;
+
+      begin
+         if Old_List = No_List then
+            return No_List;
+
+         else
+            New_List := Empty_List;
+
+            E := First (Old_List);
+            while Present (E) loop
+               Append (Copy_Node_With_Replacement (E), New_List);
+               Next (E);
+            end loop;
+
+            return New_List;
+         end if;
+      end Copy_List_With_Replacement;
+
+      --------------------------------
+      -- Copy_Node_With_Replacement --
+      --------------------------------
+
+      function Copy_Node_With_Replacement
+        (Old_Node : Node_Id) return Node_Id
+      is
+         New_Node : Node_Id;
+
+         procedure Adjust_Named_Associations
+           (Old_Node : Node_Id;
+            New_Node : Node_Id);
+         --  If a call node has named associations, these are chained through
+         --  the First_Named_Actual, Next_Named_Actual links. These must be
+         --  propagated separately to the new parameter list, because these
+         --  are not syntactic fields.
+
+         function Copy_Field_With_Replacement
+           (Field : Union_Id) return Union_Id;
+         --  Given Field, which is a field of Old_Node, return a copy of it
+         --  if it is a syntactic field (i.e. its parent is Node), setting
+         --  the parent of the copy to poit to New_Node. Otherwise returns
+         --  the field (possibly mapped if it is an entity).
+
+         -------------------------------
+         -- Adjust_Named_Associations --
+         -------------------------------
+
+         procedure Adjust_Named_Associations
+           (Old_Node : Node_Id;
+            New_Node : Node_Id)
+         is
+            Old_E : Node_Id;
+            New_E : Node_Id;
+
+            Old_Next : Node_Id;
+            New_Next : Node_Id;
+
+         begin
+            Old_E := First (Parameter_Associations (Old_Node));
+            New_E := First (Parameter_Associations (New_Node));
+            while Present (Old_E) loop
+               if Nkind (Old_E) = N_Parameter_Association
+                 and then Present (Next_Named_Actual (Old_E))
+               then
+                  if First_Named_Actual (Old_Node)
+                    =  Explicit_Actual_Parameter (Old_E)
+                  then
+                     Set_First_Named_Actual
+                       (New_Node, Explicit_Actual_Parameter (New_E));
+                  end if;
+
+                  --  Now scan parameter list from the beginning,to locate
+                  --  next named actual, which can be out of order.
+
+                  Old_Next := First (Parameter_Associations (Old_Node));
+                  New_Next := First (Parameter_Associations (New_Node));
+
+                  while Nkind (Old_Next) /= N_Parameter_Association
+                    or else  Explicit_Actual_Parameter (Old_Next)
+                      /= Next_Named_Actual (Old_E)
+                  loop
+                     Next (Old_Next);
+                     Next (New_Next);
+                  end loop;
+
+                  Set_Next_Named_Actual
+                    (New_E, Explicit_Actual_Parameter (New_Next));
+               end if;
+
+               Next (Old_E);
+               Next (New_E);
+            end loop;
+         end Adjust_Named_Associations;
+
+         ---------------------------------
+         -- Copy_Field_With_Replacement --
+         ---------------------------------
+
+         function Copy_Field_With_Replacement
+           (Field : Union_Id) return Union_Id
+         is
+         begin
+            if Field = Union_Id (Empty) then
+               return Field;
+
+            elsif Field in Node_Range then
+               declare
+                  Old_N : constant Node_Id := Node_Id (Field);
+                  New_N : Node_Id;
+
+               begin
+                  --  If syntactic field, as indicated by the parent pointer
+                  --  being set, then copy the referenced node recursively.
+
+                  if Parent (Old_N) = Old_Node then
+                     New_N := Copy_Node_With_Replacement (Old_N);
+
+                     if New_N /= Old_N then
+                        Set_Parent (New_N, New_Node);
+                     end if;
+
+                  --  For semantic fields, update possible entity reference
+                  --  from the replacement map.
+
+                  else
+                     New_N := Assoc (Old_N);
+                  end if;
+
+                  return Union_Id (New_N);
+               end;
+
+            elsif Field in List_Range then
+               declare
+                  Old_L : constant List_Id := List_Id (Field);
+                  New_L : List_Id;
+
+               begin
+                  --  If syntactic field, as indicated by the parent pointer,
+                  --  then recursively copy the entire referenced list.
+
+                  if Parent (Old_L) = Old_Node then
+                     New_L := Copy_List_With_Replacement (Old_L);
+                     Set_Parent (New_L, New_Node);
+
+                  --  For semantic list, just returned unchanged
+
+                  else
+                     New_L := Old_L;
+                  end if;
+
+                  return Union_Id (New_L);
+               end;
+
+            --  Anything other than a list or a node is returned unchanged
+
+            else
+               return Field;
+            end if;
+         end Copy_Field_With_Replacement;
+
+      --  Start of processing for Copy_Node_With_Replacement
+
+      begin
+         if Old_Node <= Empty_Or_Error then
+            return Old_Node;
+
+         elsif Has_Extension (Old_Node) then
+            return Assoc (Old_Node);
+
+         else
+            New_Node := New_Copy (Old_Node);
+
+            --  If the node we are copying is the associated node of a
+            --  previously copied Itype, then adjust the associated node
+            --  of the copy of that Itype accordingly.
+
+            if Present (Actual_Map) then
+               declare
+                  E   : Elmt_Id;
+                  Ent : Entity_Id;
+
+               begin
+                  --  Case of hash table used
+
+                  if NCT_Hash_Tables_Used then
+                     Ent := NCT_Itype_Assoc.Get (Old_Node);
+
+                     if Present (Ent) then
+                        Set_Associated_Node_For_Itype (Ent, New_Node);
+                     end if;
+
+                  --  Case of no hash table used
+
+                  else
+                     E := First_Elmt (Actual_Map);
+                     while Present (E) loop
+                        if Is_Itype (Node (E))
+                          and then
+                            Old_Node = Associated_Node_For_Itype (Node (E))
+                        then
+                           Set_Associated_Node_For_Itype
+                             (Node (Next_Elmt (E)), New_Node);
+                        end if;
+
+                        E := Next_Elmt (Next_Elmt (E));
+                     end loop;
+                  end if;
+               end;
+            end if;
+
+            --  Recursively copy descendents
+
+            Set_Field1
+              (New_Node, Copy_Field_With_Replacement (Field1 (New_Node)));
+            Set_Field2
+              (New_Node, Copy_Field_With_Replacement (Field2 (New_Node)));
+            Set_Field3
+              (New_Node, Copy_Field_With_Replacement (Field3 (New_Node)));
+            Set_Field4
+              (New_Node, Copy_Field_With_Replacement (Field4 (New_Node)));
+            Set_Field5
+              (New_Node, Copy_Field_With_Replacement (Field5 (New_Node)));
+
+            --  Adjust Sloc of new node if necessary
+
+            if New_Sloc /= No_Location then
+               Set_Sloc (New_Node, New_Sloc);
+
+               --  If we adjust the Sloc, then we are essentially making
+               --  a completely new node, so the Comes_From_Source flag
+               --  should be reset to the proper default value.
+
+               Nodes.Table (New_Node).Comes_From_Source :=
+                 Default_Node.Comes_From_Source;
+            end if;
+
+            --  If the node is call and has named associations,
+            --  set the corresponding links in the copy.
+
+            if (Nkind (Old_Node) = N_Function_Call
+                 or else Nkind (Old_Node) = N_Entry_Call_Statement
+                 or else
+                   Nkind (Old_Node) = N_Procedure_Call_Statement)
+              and then Present (First_Named_Actual (Old_Node))
+            then
+               Adjust_Named_Associations (Old_Node, New_Node);
+            end if;
+
+            --  Reset First_Real_Statement for Handled_Sequence_Of_Statements.
+            --  The replacement mechanism applies to entities, and is not used
+            --  here. Eventually we may need a more general graph-copying
+            --  routine. For now, do a sequential search to find desired node.
+
+            if Nkind (Old_Node) = N_Handled_Sequence_Of_Statements
+              and then Present (First_Real_Statement (Old_Node))
+            then
+               declare
+                  Old_F  : constant Node_Id := First_Real_Statement (Old_Node);
+                  N1, N2 : Node_Id;
+
+               begin
+                  N1 := First (Statements (Old_Node));
+                  N2 := First (Statements (New_Node));
+
+                  while N1 /= Old_F loop
+                     Next (N1);
+                     Next (N2);
+                  end loop;
+
+                  Set_First_Real_Statement (New_Node, N2);
+               end;
+            end if;
+         end if;
+
+         --  All done, return copied node
+
+         return New_Node;
+      end Copy_Node_With_Replacement;
+
+      -----------------
+      -- Visit_Elist --
+      -----------------
+
+      procedure Visit_Elist (E : Elist_Id) is
+         Elmt : Elmt_Id;
+      begin
+         if Present (E) then
+            Elmt := First_Elmt (E);
+
+            while Elmt /= No_Elmt loop
+               Visit_Node (Node (Elmt));
+               Next_Elmt (Elmt);
+            end loop;
+         end if;
+      end Visit_Elist;
+
+      -----------------
+      -- Visit_Field --
+      -----------------
+
+      procedure Visit_Field (F : Union_Id; N : Node_Id) is
+      begin
+         if F = Union_Id (Empty) then
+            return;
+
+         elsif F in Node_Range then
+
+            --  Copy node if it is syntactic, i.e. its parent pointer is
+            --  set to point to the field that referenced it (certain
+            --  Itypes will also meet this criterion, which is fine, since
+            --  these are clearly Itypes that do need to be copied, since
+            --  we are copying their parent.)
+
+            if Parent (Node_Id (F)) = N then
+               Visit_Node (Node_Id (F));
+               return;
+
+            --  Another case, if we are pointing to an Itype, then we want
+            --  to copy it if its associated node is somewhere in the tree
+            --  being copied.
+
+            --  Note: the exclusion of self-referential copies is just an
+            --  optimization, since the search of the already copied list
+            --  would catch it, but it is a common case (Etype pointing
+            --  to itself for an Itype that is a base type).
+
+            elsif Has_Extension (Node_Id (F))
+              and then Is_Itype (Entity_Id (F))
+              and then Node_Id (F) /= N
+            then
+               declare
+                  P : Node_Id;
+
+               begin
+                  P := Associated_Node_For_Itype (Node_Id (F));
+                  while Present (P) loop
+                     if P = Source then
+                        Visit_Node (Node_Id (F));
+                        return;
+                     else
+                        P := Parent (P);
+                     end if;
+                  end loop;
+
+                  --  An Itype whose parent is not being copied definitely
+                  --  should NOT be copied, since it does not belong in any
+                  --  sense to the copied subtree.
+
+                  return;
+               end;
+            end if;
+
+         elsif F in List_Range
+           and then Parent (List_Id (F)) = N
+         then
+            Visit_List (List_Id (F));
+            return;
+         end if;
+      end Visit_Field;
+
+      -----------------
+      -- Visit_Itype --
+      -----------------
+
+      procedure Visit_Itype (Old_Itype : Entity_Id) is
+         New_Itype : Entity_Id;
+         E         : Elmt_Id;
+         Ent       : Entity_Id;
+
+      begin
+         --  Itypes that describe the designated type of access to subprograms
+         --  have the structure of subprogram declarations, with signatures,
+         --  etc. Either we duplicate the signatures completely, or choose to
+         --  share such itypes, which is fine because their elaboration will
+         --  have no side effects.
+
+         if Ekind (Old_Itype) = E_Subprogram_Type then
+            return;
+         end if;
+
+         New_Itype := New_Copy (Old_Itype);
+
+         --  The new Itype has all the attributes of the old one, and
+         --  we just copy the contents of the entity. However, the back-end
+         --  needs different names for debugging purposes, so we create a
+         --  new internal name for it in all cases.
+
+         Set_Chars (New_Itype, New_Internal_Name ('T'));
+
+         --  If our associated node is an entity that has already been copied,
+         --  then set the associated node of the copy to point to the right
+         --  copy. If we have copied an Itype that is itself the associated
+         --  node of some previously copied Itype, then we set the right
+         --  pointer in the other direction.
+
+         if Present (Actual_Map) then
+
+            --  Case of hash tables used
+
+            if NCT_Hash_Tables_Used then
+
+               Ent := NCT_Assoc.Get (Associated_Node_For_Itype (Old_Itype));
+
+               if Present (Ent) then
+                  Set_Associated_Node_For_Itype (New_Itype, Ent);
+               end if;
+
+               Ent := NCT_Itype_Assoc.Get (Old_Itype);
+               if Present (Ent) then
+                  Set_Associated_Node_For_Itype (Ent, New_Itype);
+
+               --  If the hash table has no association for this Itype and
+               --  its associated node, enter one now.
+
+               else
+                  NCT_Itype_Assoc.Set
+                    (Associated_Node_For_Itype (Old_Itype), New_Itype);
+               end if;
+
+            --  Case of hash tables not used
+
+            else
+               E := First_Elmt (Actual_Map);
+               while Present (E) loop
+                  if Associated_Node_For_Itype (Old_Itype) = Node (E) then
+                     Set_Associated_Node_For_Itype
+                       (New_Itype, Node (Next_Elmt (E)));
+                  end if;
+
+                  if Is_Type (Node (E))
+                    and then
+                      Old_Itype = Associated_Node_For_Itype (Node (E))
+                  then
+                     Set_Associated_Node_For_Itype
+                       (Node (Next_Elmt (E)), New_Itype);
+                  end if;
+
+                  E := Next_Elmt (Next_Elmt (E));
+               end loop;
+            end if;
+         end if;
+
+         if Present (Freeze_Node (New_Itype)) then
+            Set_Is_Frozen (New_Itype, False);
+            Set_Freeze_Node (New_Itype, Empty);
+         end if;
+
+         --  Add new association to map
+
+         if No (Actual_Map) then
+            Actual_Map := New_Elmt_List;
+         end if;
+
+         Append_Elmt (Old_Itype, Actual_Map);
+         Append_Elmt (New_Itype, Actual_Map);
+
+         if NCT_Hash_Tables_Used then
+            NCT_Assoc.Set (Old_Itype, New_Itype);
+
+         else
+            NCT_Table_Entries := NCT_Table_Entries + 1;
+
+            if NCT_Table_Entries > NCT_Hash_Threshhold then
+               Build_NCT_Hash_Tables;
+            end if;
+         end if;
+
+         --  If a record subtype is simply copied, the entity list will be
+         --  shared. Thus cloned_Subtype must be set to indicate the sharing.
+
+         if Ekind (Old_Itype) = E_Record_Subtype
+           or else Ekind (Old_Itype) = E_Class_Wide_Subtype
+         then
+            Set_Cloned_Subtype (New_Itype, Old_Itype);
+         end if;
+
+         --  Visit descendents that eventually get copied
+
+         Visit_Field (Union_Id (Etype (Old_Itype)), Old_Itype);
+
+         if Is_Discrete_Type (Old_Itype) then
+            Visit_Field (Union_Id (Scalar_Range (Old_Itype)), Old_Itype);
+
+         elsif Has_Discriminants (Base_Type (Old_Itype)) then
+            --  ??? This should involve call to Visit_Field
+            Visit_Elist (Discriminant_Constraint (Old_Itype));
+
+         elsif Is_Array_Type (Old_Itype) then
+            if Present (First_Index (Old_Itype)) then
+               Visit_Field (Union_Id (List_Containing
+                                (First_Index (Old_Itype))),
+                            Old_Itype);
+            end if;
+
+            if Is_Packed (Old_Itype) then
+               Visit_Field (Union_Id (Packed_Array_Type (Old_Itype)),
+                            Old_Itype);
+            end if;
+         end if;
+      end Visit_Itype;
+
+      ----------------
+      -- Visit_List --
+      ----------------
+
+      procedure Visit_List (L : List_Id) is
+         N : Node_Id;
+      begin
+         if L /= No_List then
+            N := First (L);
+
+            while Present (N) loop
+               Visit_Node (N);
+               Next (N);
+            end loop;
+         end if;
+      end Visit_List;
+
+      ----------------
+      -- Visit_Node --
+      ----------------
+
+      procedure Visit_Node (N : Node_Or_Entity_Id) is
+
+      --  Start of processing for Visit_Node
+
+      begin
+         --  Handle case of an Itype, which must be copied
+
+         if Has_Extension (N)
+           and then Is_Itype (N)
+         then
+            --  Nothing to do if already in the list. This can happen with an
+            --  Itype entity that appears more than once in the tree.
+            --  Note that we do not want to visit descendents in this case.
+
+            --  Test for already in list when hash table is used
+
+            if NCT_Hash_Tables_Used then
+               if Present (NCT_Assoc.Get (Entity_Id (N))) then
+                  return;
+               end if;
+
+            --  Test for already in list when hash table not used
+
+            else
+               declare
+                  E : Elmt_Id;
+               begin
+                  if Present (Actual_Map) then
+                     E := First_Elmt (Actual_Map);
+                     while Present (E) loop
+                        if Node (E) = N then
+                           return;
+                        else
+                           E := Next_Elmt (Next_Elmt (E));
+                        end if;
+                     end loop;
+                  end if;
+               end;
+            end if;
+
+            Visit_Itype (N);
+         end if;
+
+         --  Visit descendents
+
+         Visit_Field (Field1 (N), N);
+         Visit_Field (Field2 (N), N);
+         Visit_Field (Field3 (N), N);
+         Visit_Field (Field4 (N), N);
+         Visit_Field (Field5 (N), N);
+      end Visit_Node;
+
+   --  Start of processing for New_Copy_Tree
+
+   begin
+      Actual_Map := Map;
+
+      --  See if we should use hash table
+
+      if No (Actual_Map) then
+         NCT_Hash_Tables_Used := False;
+
+      else
+         declare
+            Elmt : Elmt_Id;
+
+         begin
+            NCT_Table_Entries := 0;
+
+            Elmt := First_Elmt (Actual_Map);
+            while Present (Elmt) loop
+               NCT_Table_Entries := NCT_Table_Entries + 1;
+               Next_Elmt (Elmt);
+               Next_Elmt (Elmt);
+            end loop;
+
+            if NCT_Table_Entries > NCT_Hash_Threshhold then
+               Build_NCT_Hash_Tables;
+            else
+               NCT_Hash_Tables_Used := False;
+            end if;
+         end;
+      end if;
+
+      --  Hash table set up if required, now start phase one by visiting
+      --  top node (we will recursively visit the descendents).
+
+      Visit_Node (Source);
+
+      --  Now the second phase of the copy can start. First we process
+      --  all the mapped entities, copying their descendents.
+
+      if Present (Actual_Map) then
+         declare
+            Elmt      : Elmt_Id;
+            New_Itype : Entity_Id;
+         begin
+            Elmt := First_Elmt (Actual_Map);
+            while Present (Elmt) loop
+               Next_Elmt (Elmt);
+               New_Itype := Node (Elmt);
+               Copy_Itype_With_Replacement (New_Itype);
+               Next_Elmt (Elmt);
+            end loop;
+         end;
+      end if;
+
+      --  Now we can copy the actual tree
+
+      return Copy_Node_With_Replacement (Source);
+   end New_Copy_Tree;
+
    -------------------------
    -- New_External_Entity --
    -------------------------
index ce6d4bd..4046b78 100644 (file)
@@ -876,6 +876,57 @@ package Sem_Util is
    --  formal. Used in Ada 2005 mode to solve the syntactic ambiguity that
    --  results from an indexing of a function call written in prefix form.
 
+   function New_Copy_List_Tree (List : List_Id) return List_Id;
+   --  Copy recursively an analyzed list of nodes. Uses New_Copy_Tree defined
+   --  below. As for New_Copy_Tree, it is illegal to attempt to copy extended
+   --  nodes (entities) either directly or indirectly using this function.
+
+   function New_Copy_Tree
+     (Source    : Node_Id;
+      Map       : Elist_Id   := No_Elist;
+      New_Sloc  : Source_Ptr := No_Location;
+      New_Scope : Entity_Id  := Empty) return Node_Id;
+   --  Given a node that is the root of a subtree, Copy_Tree copies the entire
+   --  syntactic subtree, including recursively any descendents whose parent
+   --  field references a copied node (descendents not linked to a copied node
+   --  by the parent field are not copied, instead the copied tree references
+   --  the same descendent as the original in this case, which is appropriate
+   --  for non-syntactic fields such as Etype). The parent pointers in the
+   --  copy are properly set. Copy_Tree (Empty/Error) returns Empty/Error.
+   --  The one exception to the rule of not copying semantic fields is that
+   --  any implicit types attached to the subtree are duplicated, so that
+   --  the copy contains a distinct set of implicit type entities. Thus this
+   --  function is used when it is necessary to duplicate an analyzed tree,
+   --  declared in the same or some other compilation unit. This function is
+   --  declared here rather than in atree because it uses semantic information
+   --  in particular concerning the structure of itypes and the generation of
+   --  public symbols.
+
+   --  The Map argument, if set to a non-empty Elist, specifies a set of
+   --  mappings to be applied to entities in the tree. The map has the form:
+   --
+   --     old entity 1
+   --     new entity to replace references to entity 1
+   --     old entity 2
+   --     new entity to replace references to entity 2
+   --     ...
+   --
+   --  The call destroys the contents of Map in this case
+   --
+   --  The parameter New_Sloc, if set to a value other than No_Location, is
+   --  used as the Sloc value for all nodes in the new copy. If New_Sloc is
+   --  set to its default value No_Location, then the Sloc values of the
+   --  nodes in the copy are simply copied from the corresponding original.
+   --
+   --  The Comes_From_Source indication is unchanged if New_Sloc is set to
+   --  the default No_Location value, but is reset if New_Sloc is given, since
+   --  in this case the result clearly is neither a source node or an exact
+   --  copy of a source node.
+   --
+   --  The parameter New_Scope, if set to a value other than Empty, is the
+   --  value to use as the Scope for any Itypes that are copied. The most
+   --  typical value for this parameter, if given, is Current_Scope.
+
    function New_External_Entity
      (Kind         : Entity_Kind;
       Scope_Id     : Entity_Id;