New Language: Ada
authorkenner <kenner@138bc75d-0d04-0410-961f-82ee72b054a4>
Tue, 2 Oct 2001 14:52:00 +0000 (14:52 +0000)
committerkenner <kenner@138bc75d-0d04-0410-961f-82ee72b054a4>
Tue, 2 Oct 2001 14:52:00 +0000 (14:52 +0000)
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@45959 138bc75d-0d04-0410-961f-82ee72b054a4

101 files changed:
gcc/ada/scans.adb [new file with mode: 0644]
gcc/ada/scans.ads [new file with mode: 0644]
gcc/ada/scn-nlit.adb [new file with mode: 0644]
gcc/ada/scn-slit.adb [new file with mode: 0644]
gcc/ada/scn.adb [new file with mode: 0644]
gcc/ada/scn.ads [new file with mode: 0644]
gcc/ada/sdefault.ads [new file with mode: 0644]
gcc/ada/sem.adb [new file with mode: 0644]
gcc/ada/sem.ads [new file with mode: 0644]
gcc/ada/sem_aggr.adb [new file with mode: 0644]
gcc/ada/sem_aggr.ads [new file with mode: 0644]
gcc/ada/sem_attr.adb [new file with mode: 0644]
gcc/ada/sem_attr.ads [new file with mode: 0644]
gcc/ada/sem_case.adb [new file with mode: 0644]
gcc/ada/sem_case.ads [new file with mode: 0644]
gcc/ada/sem_cat.adb [new file with mode: 0644]
gcc/ada/sem_cat.ads [new file with mode: 0644]
gcc/ada/sem_ch10.adb [new file with mode: 0644]
gcc/ada/sem_ch10.ads [new file with mode: 0644]
gcc/ada/sem_ch11.adb [new file with mode: 0644]
gcc/ada/sem_ch11.ads [new file with mode: 0644]
gcc/ada/sem_ch12.adb [new file with mode: 0644]
gcc/ada/sem_ch12.ads [new file with mode: 0644]
gcc/ada/sem_ch13.adb [new file with mode: 0644]
gcc/ada/sem_ch13.ads [new file with mode: 0644]
gcc/ada/sem_ch2.adb [new file with mode: 0644]
gcc/ada/sem_ch2.ads [new file with mode: 0644]
gcc/ada/sem_ch3.adb [new file with mode: 0644]
gcc/ada/sem_ch3.ads [new file with mode: 0644]
gcc/ada/sem_ch4.adb [new file with mode: 0644]
gcc/ada/sem_ch4.ads [new file with mode: 0644]
gcc/ada/sem_ch5.adb [new file with mode: 0644]
gcc/ada/sem_ch5.ads [new file with mode: 0644]
gcc/ada/sem_ch6.adb [new file with mode: 0644]
gcc/ada/sem_ch6.ads [new file with mode: 0644]
gcc/ada/sem_ch7.adb [new file with mode: 0644]
gcc/ada/sem_ch7.ads [new file with mode: 0644]
gcc/ada/sem_ch8.adb [new file with mode: 0644]
gcc/ada/sem_ch8.ads [new file with mode: 0644]
gcc/ada/sem_ch9.adb [new file with mode: 0644]
gcc/ada/sem_ch9.ads [new file with mode: 0644]
gcc/ada/sem_disp.adb [new file with mode: 0644]
gcc/ada/sem_disp.ads [new file with mode: 0644]
gcc/ada/sem_dist.adb [new file with mode: 0644]
gcc/ada/sem_dist.ads [new file with mode: 0644]
gcc/ada/sem_elab.adb [new file with mode: 0644]
gcc/ada/sem_elab.ads [new file with mode: 0644]
gcc/ada/sem_elim.adb [new file with mode: 0644]
gcc/ada/sem_elim.ads [new file with mode: 0644]
gcc/ada/sem_eval.adb [new file with mode: 0644]
gcc/ada/sem_eval.ads [new file with mode: 0644]
gcc/ada/sem_intr.adb [new file with mode: 0644]
gcc/ada/sem_intr.ads [new file with mode: 0644]
gcc/ada/sem_maps.adb [new file with mode: 0644]
gcc/ada/sem_maps.ads [new file with mode: 0644]
gcc/ada/sem_mech.adb [new file with mode: 0644]
gcc/ada/sem_mech.ads [new file with mode: 0644]
gcc/ada/sem_prag.adb [new file with mode: 0644]
gcc/ada/sem_prag.ads [new file with mode: 0644]
gcc/ada/sem_res.adb [new file with mode: 0644]
gcc/ada/sem_res.ads [new file with mode: 0644]
gcc/ada/sem_smem.adb [new file with mode: 0644]
gcc/ada/sem_smem.ads [new file with mode: 0644]
gcc/ada/sem_type.adb [new file with mode: 0644]
gcc/ada/sem_type.ads [new file with mode: 0644]
gcc/ada/sem_util.adb [new file with mode: 0644]
gcc/ada/sem_util.ads [new file with mode: 0644]
gcc/ada/sem_vfpt.adb [new file with mode: 0644]
gcc/ada/sem_vfpt.ads [new file with mode: 0644]
gcc/ada/sem_warn.adb [new file with mode: 0644]
gcc/ada/sem_warn.ads [new file with mode: 0644]
gcc/ada/sequenio.ads [new file with mode: 0644]
gcc/ada/sfn_scan.adb [new file with mode: 0644]
gcc/ada/sfn_scan.ads [new file with mode: 0644]
gcc/ada/sinfo-cn.adb [new file with mode: 0644]
gcc/ada/sinfo-cn.ads [new file with mode: 0644]
gcc/ada/sinfo.adb [new file with mode: 0644]
gcc/ada/sinfo.ads [new file with mode: 0644]
gcc/ada/sinput-l.adb [new file with mode: 0644]
gcc/ada/sinput-l.ads [new file with mode: 0644]
gcc/ada/sinput-p.adb [new file with mode: 0644]
gcc/ada/sinput-p.ads [new file with mode: 0644]
gcc/ada/sinput.adb [new file with mode: 0644]
gcc/ada/sinput.ads [new file with mode: 0644]
gcc/ada/snames.adb [new file with mode: 0644]
gcc/ada/snames.ads [new file with mode: 0644]
gcc/ada/snames.h [new file with mode: 0644]
gcc/ada/sprint.adb [new file with mode: 0644]
gcc/ada/sprint.ads [new file with mode: 0644]
gcc/ada/stand.adb [new file with mode: 0644]
gcc/ada/stand.ads [new file with mode: 0644]
gcc/ada/stringt.adb [new file with mode: 0644]
gcc/ada/stringt.ads [new file with mode: 0644]
gcc/ada/stringt.h [new file with mode: 0644]
gcc/ada/style.adb [new file with mode: 0644]
gcc/ada/style.ads [new file with mode: 0644]
gcc/ada/stylesw.adb [new file with mode: 0644]
gcc/ada/stylesw.ads [new file with mode: 0644]
gcc/ada/switch.adb [new file with mode: 0644]
gcc/ada/switch.ads [new file with mode: 0644]
gcc/ada/sysdep.c [new file with mode: 0644]

diff --git a/gcc/ada/scans.adb b/gcc/ada/scans.adb
new file mode 100644 (file)
index 0000000..327f3aa
--- /dev/null
@@ -0,0 +1,76 @@
+------------------------------------------------------------------------------
+--                                                                          --
+--                         GNAT COMPILER COMPONENTS                         --
+--                                                                          --
+--                                S C A N S                                 --
+--                                                                          --
+--                                 B o d y                                  --
+--                                                                          --
+--                            $Revision: 1.12 $
+--                                                                          --
+--          Copyright (C) 1992-2001 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- --
+-- ware  Foundation;  either version 2,  or (at your option) any later ver- --
+-- sion.  GNAT is distributed in the hope that it will be useful, but WITH- --
+-- OUT ANY WARRANTY;  without even the  implied warranty of MERCHANTABILITY --
+-- or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License --
+-- for  more details.  You should have  received  a copy of the GNU General --
+-- Public License  distributed with GNAT;  see file COPYING.  If not, write --
+-- to  the Free Software Foundation,  59 Temple Place - Suite 330,  Boston, --
+-- MA 02111-1307, USA.                                                      --
+--                                                                          --
+-- As a special exception,  if other files  instantiate  generics from this --
+-- unit, or you link  this unit with other files  to produce an executable, --
+-- this  unit  does not  by itself cause  the resulting  executable  to  be --
+-- covered  by the  GNU  General  Public  License.  This exception does not --
+-- however invalidate  any other reasons why  the executable file  might be --
+-- covered by the  GNU Public License.                                      --
+--                                                                          --
+-- GNAT was originally developed  by the GNAT team at  New York University. --
+-- It is now maintained by Ada Core Technologies Inc (http://www.gnat.com). --
+--                                                                          --
+------------------------------------------------------------------------------
+
+package body Scans is
+
+   ------------------------
+   -- Restore_Scan_State --
+   ------------------------
+
+   procedure Restore_Scan_State (Saved_State : in Saved_Scan_State) is
+   begin
+      Scan_Ptr                 := Saved_State.Save_Scan_Ptr;
+      Token                    := Saved_State.Save_Token;
+      Token_Ptr                := Saved_State.Save_Token_Ptr;
+      Current_Line_Start       := Saved_State.Save_Current_Line_Start;
+      Start_Column             := Saved_State.Save_Start_Column;
+      Checksum                 := Saved_State.Save_Checksum;
+      First_Non_Blank_Location := Saved_State.Save_First_Non_Blank_Location;
+      Token_Node               := Saved_State.Save_Token_Node;
+      Token_Name               := Saved_State.Save_Token_Name;
+      Prev_Token               := Saved_State.Save_Prev_Token;
+      Prev_Token_Ptr           := Saved_State.Save_Prev_Token_Ptr;
+   end Restore_Scan_State;
+
+   ---------------------
+   -- Save_Scan_State --
+   ---------------------
+
+   procedure Save_Scan_State (Saved_State : out Saved_Scan_State) is
+   begin
+      Saved_State.Save_Scan_Ptr                 := Scan_Ptr;
+      Saved_State.Save_Token                    := Token;
+      Saved_State.Save_Token_Ptr                := Token_Ptr;
+      Saved_State.Save_Current_Line_Start       := Current_Line_Start;
+      Saved_State.Save_Start_Column             := Start_Column;
+      Saved_State.Save_Checksum                 := Checksum;
+      Saved_State.Save_First_Non_Blank_Location := First_Non_Blank_Location;
+      Saved_State.Save_Token_Node               := Token_Node;
+      Saved_State.Save_Token_Name               := Token_Name;
+      Saved_State.Save_Prev_Token               := Prev_Token;
+      Saved_State.Save_Prev_Token_Ptr           := Prev_Token_Ptr;
+   end Save_Scan_State;
+
+end Scans;
diff --git a/gcc/ada/scans.ads b/gcc/ada/scans.ads
new file mode 100644 (file)
index 0000000..b9d89e1
--- /dev/null
@@ -0,0 +1,418 @@
+------------------------------------------------------------------------------
+--                                                                          --
+--                         GNAT COMPILER COMPONENTS                         --
+--                                                                          --
+--                                S C A N S                                 --
+--                                                                          --
+--                                 S p e c                                  --
+--                                                                          --
+--                            $Revision: 1.32 $
+--                                                                          --
+--          Copyright (C) 1992-2000 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- --
+-- ware  Foundation;  either version 2,  or (at your option) any later ver- --
+-- sion.  GNAT is distributed in the hope that it will be useful, but WITH- --
+-- OUT ANY WARRANTY;  without even the  implied warranty of MERCHANTABILITY --
+-- or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License --
+-- for  more details.  You should have  received  a copy of the GNU General --
+-- Public License  distributed with GNAT;  see file COPYING.  If not, write --
+-- to  the Free Software Foundation,  59 Temple Place - Suite 330,  Boston, --
+-- MA 02111-1307, USA.                                                      --
+--                                                                          --
+-- As a special exception,  if other files  instantiate  generics from this --
+-- unit, or you link  this unit with other files  to produce an executable, --
+-- this  unit  does not  by itself cause  the resulting  executable  to  be --
+-- covered  by the  GNU  General  Public  License.  This exception does not --
+-- however invalidate  any other reasons why  the executable file  might be --
+-- covered by the  GNU Public License.                                      --
+--                                                                          --
+-- GNAT was originally developed  by the GNAT team at  New York University. --
+-- It is now maintained by Ada Core Technologies Inc (http://www.gnat.com). --
+--                                                                          --
+------------------------------------------------------------------------------
+
+with Types; use Types;
+package Scans is
+
+--  The scanner maintains a current state in the global variables defined
+--  in this package. The call to the Scan routine advances this state to
+--  the next token. The state is initialized by the call to one of the
+--  initialization routines in Sinput.
+
+   --  The following type is used to identify token types returned by Scan.
+   --  The class column in this table indicates the token classes which
+   --  apply to the token, as defined by subsquent subtype declarations.
+
+   --  Note: the coding in SCN depends on the fact that the first entry in
+   --  this type declaration is *not* for a reserved word. For details on
+   --  why there is this requirement, see Scn.Initialize_Scanner.
+
+   type Token_Type is (
+
+      --  Token name          Token type   Class(es)
+
+      Tok_Integer_Literal, -- numeric lit  Literal, Lit_Or_Name
+
+      Tok_Real_Literal,    -- numeric lit  Literal, Lit_Or_Name
+
+      Tok_String_Literal,  -- string lit   Literal. Lit_Or_Name
+
+      Tok_Char_Literal,    -- char lit     Name, Literal. Lit_Or_Name
+
+      Tok_Operator_Symbol, -- op symbol    Name, Literal, Lit_Or_Name, Desig
+
+      Tok_Identifier,      -- identifer    Name, Lit_Or_Name, Desig
+
+      Tok_Double_Asterisk, -- **
+
+      Tok_Ampersand,       -- &            Binary_Addop
+      Tok_Minus,           -- -            Binary_Addop, Unary_Addop
+      Tok_Plus,            -- +            Binary_Addop, Unary_Addop
+
+      Tok_Asterisk,        -- *            Mulop
+      Tok_Mod,             -- MOD          Mulop
+      Tok_Rem,             -- REM          Mulop
+      Tok_Slash,           -- /            Mulop
+
+      Tok_New,             -- NEW
+
+      Tok_Abs,             -- ABS
+      Tok_Others,          -- OTHERS
+      Tok_Null,            -- NULL
+
+      Tok_Dot,             -- .            Namext
+      Tok_Apostrophe,      -- '            Namext
+
+      Tok_Left_Paren,      -- (            Namext, Consk
+
+      Tok_Delta,           -- DELTA        Atkwd, Sterm, Consk
+      Tok_Digits,          -- DIGITS       Atkwd, Sterm, Consk
+      Tok_Range,           -- RANGE        Atkwd, Sterm, Consk
+
+      Tok_Right_Paren,     -- )            Sterm
+      Tok_Comma,           -- ,            Sterm
+
+      Tok_And,             -- AND          Logop, Sterm
+      Tok_Or,              -- OR           Logop, Sterm
+      Tok_Xor,             -- XOR          Logop, Sterm
+
+      Tok_Less,            -- <            Relop, Sterm
+      Tok_Equal,           -- =            Relop, Sterm
+      Tok_Greater,         -- >            Relop, Sterm
+      Tok_Not_Equal,       -- /=           Relop, Sterm
+      Tok_Greater_Equal,   -- >=           Relop, Sterm
+      Tok_Less_Equal,      -- <=           Relop, Sterm
+
+      Tok_In,              -- IN           Relop, Sterm
+      Tok_Not,             -- NOT          Relop, Sterm
+
+      Tok_Box,             -- <>           Relop, Eterm, Sterm
+      Tok_Colon_Equal,     -- :=           Eterm, Sterm
+      Tok_Colon,           -- :            Eterm, Sterm
+      Tok_Greater_Greater, -- >>           Eterm, Sterm
+
+      Tok_Abstract,        -- ABSTRACT     Eterm, Sterm
+      Tok_Access,          -- ACCESS       Eterm, Sterm
+      Tok_Aliased,         -- ALIASED      Eterm, Sterm
+      Tok_All,             -- ALL          Eterm, Sterm
+      Tok_Array,           -- ARRAY        Eterm, Sterm
+      Tok_At,              -- AT           Eterm, Sterm
+      Tok_Body,            -- BODY         Eterm, Sterm
+      Tok_Constant,        -- CONSTANT     Eterm, Sterm
+      Tok_Do,              -- DO           Eterm, Sterm
+      Tok_Is,              -- IS           Eterm, Sterm
+      Tok_Limited,         -- LIMITED      Eterm, Sterm
+      Tok_Of,              -- OF           Eterm, Sterm
+      Tok_Out,             -- OUT          Eterm, Sterm
+      Tok_Record,          -- RECORD       Eterm, Sterm
+      Tok_Renames,         -- RENAMES      Eterm, Sterm
+      Tok_Reverse,         -- REVERSE      Eterm, Sterm
+      Tok_Tagged,          -- TAGGED       Eterm, Sterm
+      Tok_Then,            -- THEN         Eterm, Sterm
+
+      Tok_Less_Less,       -- <<           Eterm, Sterm, After_SM
+
+      Tok_Abort,           -- ABORT        Eterm, Sterm, After_SM
+      Tok_Accept,          -- ACCEPT       Eterm, Sterm, After_SM
+      Tok_Case,            -- CASE         Eterm, Sterm, After_SM
+      Tok_Delay,           -- DELAY        Eterm, Sterm, After_SM
+      Tok_Else,            -- ELSE         Eterm, Sterm, After_SM
+      Tok_Elsif,           -- ELSIF        Eterm, Sterm, After_SM
+      Tok_End,             -- END          Eterm, Sterm, After_SM
+      Tok_Exception,       -- EXCEPTION    Eterm, Sterm, After_SM
+      Tok_Exit,            -- EXIT         Eterm, Sterm, After_SM
+      Tok_Goto,            -- GOTO         Eterm, Sterm, After_SM
+      Tok_If,              -- IF           Eterm, Sterm, After_SM
+      Tok_Pragma,          -- PRAGMA       Eterm, Sterm, After_SM
+      Tok_Raise,           -- RAISE        Eterm, Sterm, After_SM
+      Tok_Requeue,         -- REQUEUE      Eterm, Sterm, After_SM
+      Tok_Return,          -- RETURN       Eterm, Sterm, After_SM
+      Tok_Select,          -- SELECT       Eterm, Sterm, After_SM
+      Tok_Terminate,       -- TERMINATE    Eterm, Sterm, After_SM
+      Tok_Until,           -- UNTIL        Eterm, Sterm, After_SM
+      Tok_When,            -- WHEN         Eterm, Sterm, After_SM
+
+      Tok_Begin,           -- BEGIN        Eterm, Sterm, After_SM, Labeled_Stmt
+      Tok_Declare,         -- DECLARE      Eterm, Sterm, After_SM, Labeled_Stmt
+      Tok_For,             -- FOR          Eterm, Sterm, After_SM, Labeled_Stmt
+      Tok_Loop,            -- LOOP         Eterm, Sterm, After_SM, Labeled_Stmt
+      Tok_While,           -- WHILE        Eterm, Sterm, After_SM, Labeled_Stmt
+
+      Tok_Entry,           -- ENTRY        Eterm, Sterm, Declk, Deckn, After_SM
+      Tok_Protected,       -- PROTECTED    Eterm, Sterm, Declk, Deckn, After_SM
+      Tok_Task,            -- TASK         Eterm, Sterm, Declk, Deckn, After_SM
+      Tok_Type,            -- TYPE         Eterm, Sterm, Declk, Deckn, After_SM
+      Tok_Subtype,         -- SUBTYPE      Eterm, Sterm, Declk, Deckn, After_SM
+      Tok_Use,             -- USE          Eterm, Sterm, Declk, Deckn, After_SM
+
+      Tok_Function,        -- FUNCTION     Eterm, Sterm, Cunit, Declk, After_SM
+      Tok_Generic,         -- GENERIC      Eterm, Sterm, Cunit, Declk, After_SM
+      Tok_Package,         -- PACKAGE      Eterm, Sterm, Cunit, Declk, After_SM
+      Tok_Procedure,       -- PROCEDURE    Eterm, Sterm, Cunit, Declk, After_SM
+
+      Tok_Private,         -- PRIVATE      Eterm, Sterm, Cunit, After_SM
+      Tok_With,            -- WITH         Eterm, Sterm, Cunit, After_SM
+      Tok_Separate,        -- SEPARATE     Eterm, Sterm, Cunit, After_SM
+
+      Tok_EOF,             -- End of file  Eterm, Sterm, Cterm, After_SM
+
+      Tok_Semicolon,       -- ;            Eterm, Sterm, Cterm
+
+      Tok_Arrow,           -- =>           Sterm, Cterm, Chtok
+
+      Tok_Vertical_Bar,    -- |            Cterm, Sterm, Chtok
+
+      Tok_Dot_Dot,         -- ..           Sterm, Chtok
+
+      --  The following three entries are used only when scanning
+      --  project files.
+
+      Tok_Project,
+      Tok_Modifying,
+      Tok_External,
+
+      No_Token);
+      --  No_Token is used for initializing Token values to indicate that
+      --  no value has been set yet.
+
+   --  Note: in the RM, operator symbol is a special case of string literal.
+   --  We distinguish at the lexical level in this compiler, since there are
+   --  many syntactic situations in which only an operator symbol is allowed.
+
+   --  The following subtype declarations group the token types into classes.
+   --  These are used for class tests in the parser.
+
+      subtype Token_Class_Numeric_Literal is
+        Token_Type range Tok_Integer_Literal .. Tok_Real_Literal;
+      --  Numeric literal
+
+      subtype Token_Class_Literal is
+        Token_Type range Tok_Integer_Literal .. Tok_Operator_Symbol;
+      --  Literal
+
+      subtype Token_Class_Lit_Or_Name is
+        Token_Type range Tok_Integer_Literal .. Tok_Identifier;
+
+      subtype Token_Class_Binary_Addop is
+        Token_Type range Tok_Ampersand .. Tok_Plus;
+      --  Binary adding operator (& + -)
+
+      subtype Token_Class_Unary_Addop is
+        Token_Type range Tok_Minus .. Tok_Plus;
+      --  Unary adding operator (+ -)
+
+      subtype Token_Class_Mulop is
+        Token_Type range Tok_Asterisk .. Tok_Slash;
+      --  Multiplying operator
+
+      subtype Token_Class_Logop is
+        Token_Type range Tok_And .. Tok_Xor;
+      --  Logical operator (and, or, xor)
+
+      subtype Token_Class_Relop is
+        Token_Type range Tok_Less .. Tok_Box;
+      --  Relational operator (= /= < <= > >= not, in plus <> to catch misuse
+      --  of Pascal style not equal operator).
+
+      subtype Token_Class_Name is
+        Token_Type range Tok_Char_Literal .. Tok_Identifier;
+      --  First token of name (4.1),
+      --    (identifier, char literal, operator symbol)
+
+      subtype Token_Class_Desig is
+        Token_Type range Tok_Operator_Symbol .. Tok_Identifier;
+      --  Token which can be a Designator (identifier, operator symbol)
+
+      subtype Token_Class_Namext is
+        Token_Type range Tok_Dot .. Tok_Left_Paren;
+      --  Name extension tokens. These are tokens which can appear immediately
+      --  after a name to extend it recursively (period, quote, left paren)
+
+      subtype Token_Class_Consk is
+        Token_Type range Tok_Left_Paren .. Tok_Range;
+      --  Keywords which can start constraint
+      --    (left paren, delta, digits, range)
+
+      subtype Token_Class_Eterm is
+        Token_Type range Tok_Colon_Equal .. Tok_Semicolon;
+      --  Expression terminators. These tokens can never appear within a simple
+      --  expression. This is used for error recovery purposes (if we encounter
+      --  an error in an expression, we simply scan to the next Eterm token).
+
+      subtype Token_Class_Sterm is
+        Token_Type range Tok_Delta .. Tok_Dot_Dot;
+      --  Simple_Expression terminators. A Simple_Expression must be followed
+      --  by a token in this class, or an error message is issued complaining
+      --  about a missing binary operator.
+
+      subtype Token_Class_Atkwd is
+        Token_Type range Tok_Delta .. Tok_Range;
+      --  Attribute keywords. This class includes keywords which can be used
+      --  as an Attribute_Designator, namely DELTA, DIGITS and RANGE
+
+      subtype Token_Class_Cterm is
+        Token_Type range Tok_EOF .. Tok_Vertical_Bar;
+      --  Choice terminators. These tokens terminate a choice. This is used for
+      --  error recovery purposes (if we encounter an error in a Choice, we
+      --  simply scan to the next Cterm token).
+
+      subtype Token_Class_Chtok is
+        Token_Type range Tok_Arrow .. Tok_Dot_Dot;
+      --  Choice tokens. These tokens signal a choice when used in an Aggregate
+
+      subtype Token_Class_Cunit is
+        Token_Type range Tok_Function .. Tok_Separate;
+      --  Tokens which can begin a compilation unit
+
+      subtype Token_Class_Declk is
+        Token_Type range Tok_Entry .. Tok_Procedure;
+      --  Keywords which start a declaration
+
+      subtype Token_Class_Deckn is
+        Token_Type range Tok_Entry .. Tok_Use;
+      --  Keywords which start a declaration but can't start a compilation unit
+
+      subtype Token_Class_After_SM is
+        Token_Type range Tok_Less_Less .. Tok_EOF;
+      --  Tokens which always, or almost always, appear after a semicolon. Used
+      --  in the Resync_Past_Semicolon routine to avoid gobbling up stuff when
+      --  a semicolon is missing. Of significance only for error recovery.
+
+      subtype Token_Class_Labeled_Stmt is
+        Token_Type range Tok_Begin .. Tok_While;
+      --  Tokens which start labeled statements
+
+      type Token_Flag_Array is array (Token_Type) of Boolean;
+      Is_Reserved_Keyword : constant Token_Flag_Array := Token_Flag_Array'(
+         Tok_Mod      .. Tok_Rem      => True,
+         Tok_New      .. Tok_Null     => True,
+         Tok_Delta    .. Tok_Range    => True,
+         Tok_And      .. Tok_Xor      => True,
+         Tok_In       .. Tok_Not      => True,
+         Tok_Abstract .. Tok_Then     => True,
+         Tok_Abort    .. Tok_Separate => True,
+         others                       => False);
+      --  Flag array used to test for reserved word
+
+   --------------------------
+   -- Scan State Variables --
+   --------------------------
+
+   --  Note: these variables can only be referenced during the parsing of a
+   --  file. Reference to any of them from Sem or the expander is wrong.
+
+   Scan_Ptr : Source_Ptr;
+   --  Current scan pointer location. After a call to Scan, this points
+   --  just past the end of the token just scanned.
+
+   Token : Token_Type;
+   --  Type of current token
+
+   Token_Ptr : Source_Ptr;
+   --  Pointer to first character of current token
+
+   Current_Line_Start : Source_Ptr;
+   --  Pointer to first character of line containing current token
+
+   Start_Column : Column_Number;
+   --  Starting column number (zero origin) of the first non-blank character
+   --  on the line containing the current token. This is used for error
+   --  recovery circuits which depend on looking at the column line up.
+
+   Checksum : Word;
+   --  Used to accumulate a checksum representing the tokens in the source
+   --  file being compiled. This checksum includes only program tokens, and
+   --  excludes comments.
+
+   First_Non_Blank_Location : Source_Ptr;
+   --  Location of first non-blank character on the line containing the
+   --  current token (i.e. the location of the character whose column number
+   --  is stored in Start_Column).
+
+   Token_Node : Node_Id := Empty;
+   --  Node table Id for the current token. This is set only if the current
+   --  token is one for which the scanner constructs a node (i.e. it is an
+   --  identifier, operator symbol, or literal. For other token types,
+   --  Token_Node is undefined.
+
+   Token_Name : Name_Id := No_Name;
+   --  For identifiers, this is set to the Name_Id of the identifier scanned.
+   --  For all other tokens, Token_Name is set to Error_Name. Note that it
+   --  would be possible for the caller to extract this information from
+   --  Token_Node. We set Token_Name separately for two reasons. First it
+   --  allows a quicker test for a specific identifier. Second, it allows
+   --  a version of the parser to be built that does not build tree nodes,
+   --  usable as a syntax checker.
+
+   Prev_Token : Token_Type := No_Token;
+   --  Type of previous token
+
+   Prev_Token_Ptr : Source_Ptr;
+   --  Pointer to first character of previous token
+
+   Version_To_Be_Found : Boolean;
+   --  This flag is True if the scanner is still looking for an RCS version
+   --  number in a comment. Normally it is initialized to False so that this
+   --  circuit is not activated. If the -dv switch is set, then this flag is
+   --  initialized to True, and then reset when the version number is found.
+   --  We do things this way to minimize the impact on comment scanning.
+
+   --------------------------------------------------------
+   -- Procedures for Saving and Restoring the Scan State --
+   --------------------------------------------------------
+
+   --  The following procedures can be used to save and restore the entire
+   --  scan state. They are used in cases where it is necessary to backup
+   --  the scan during the parse.
+
+   type Saved_Scan_State is private;
+   --  Used for saving and restoring the scan state
+
+   procedure Save_Scan_State (Saved_State : out Saved_Scan_State);
+   pragma Inline (Save_Scan_State);
+   --  Saves the current scan state for possible later restoration. Note that
+   --  there is no harm in saving the state and then never restoring it.
+
+   procedure Restore_Scan_State (Saved_State : in Saved_Scan_State);
+   pragma Inline (Restore_Scan_State);
+   --  Restores a scan state saved by a call to Save_Scan_State.
+   --  The saved scan state must refer to the current source file.
+
+private
+   type Saved_Scan_State is record
+      Save_Scan_Ptr                 : Source_Ptr;
+      Save_Token                    : Token_Type;
+      Save_Token_Ptr                : Source_Ptr;
+      Save_Current_Line_Start       : Source_Ptr;
+      Save_Start_Column             : Column_Number;
+      Save_Checksum                 : Word;
+      Save_First_Non_Blank_Location : Source_Ptr;
+      Save_Token_Node               : Node_Id;
+      Save_Token_Name               : Name_Id;
+      Save_Prev_Token               : Token_Type;
+      Save_Prev_Token_Ptr           : Source_Ptr;
+   end record;
+
+end Scans;
diff --git a/gcc/ada/scn-nlit.adb b/gcc/ada/scn-nlit.adb
new file mode 100644 (file)
index 0000000..f027ba2
--- /dev/null
@@ -0,0 +1,371 @@
+------------------------------------------------------------------------------
+--                                                                          --
+--                         GNAT COMPILER COMPONENTS                         --
+--                                                                          --
+--                             S C N . N L I T                              --
+--                                                                          --
+--                                 B o d y                                  --
+--                                                                          --
+--                            $Revision: 1.32 $                             --
+--                                                                          --
+--   Copyright (C) 1992,1993,1994,1995,1996 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- --
+-- ware  Foundation;  either version 2,  or (at your option) any later ver- --
+-- sion.  GNAT is distributed in the hope that it will be useful, but WITH- --
+-- OUT ANY WARRANTY;  without even the  implied warranty of MERCHANTABILITY --
+-- or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License --
+-- for  more details.  You should have  received  a copy of the GNU General --
+-- Public License  distributed with GNAT;  see file COPYING.  If not, write --
+-- to  the Free Software Foundation,  59 Temple Place - Suite 330,  Boston, --
+-- MA 02111-1307, USA.                                                      --
+--                                                                          --
+-- GNAT was originally developed  by the GNAT team at  New York University. --
+-- It is now maintained by Ada Core Technologies Inc (http://www.gnat.com). --
+--                                                                          --
+------------------------------------------------------------------------------
+
+with Uintp;  use Uintp;
+with Urealp; use Urealp;
+
+separate (Scn)
+procedure Nlit is
+
+   C : Character;
+   --  Current source program character
+
+   Base_Char : Character;
+   --  Either # or : (character at start of based number)
+
+   Base : Int;
+   --  Value of base
+
+   UI_Base : Uint;
+   --  Value of base in Uint format
+
+   UI_Int_Value : Uint;
+   --  Value of integer scanned by Scan_Integer in Uint format
+
+   UI_Num_Value : Uint;
+   --  Value of integer in numeric value being scanned
+
+   Scale : Int;
+   --  Scale value for real literal
+
+   UI_Scale : Uint;
+   --  Scale in Uint format
+
+   Exponent_Is_Negative : Boolean;
+   --  Set true for negative exponent
+
+   Extended_Digit_Value : Int;
+   --  Extended digit value
+
+   Point_Scanned : Boolean;
+   --  Flag for decimal point scanned in numeric literal
+
+   -----------------------
+   -- Local Subprograms --
+   -----------------------
+
+   procedure Error_Digit_Expected;
+   --  Signal error of bad digit, Scan_Ptr points to the location at which
+   --  the digit was expected on input, and is unchanged on return.
+
+   procedure Scan_Integer;
+   --  Procedure to scan integer literal. On entry, Scan_Ptr points to a
+   --  digit, on exit Scan_Ptr points past the last character of the integer.
+   --  For each digit encountered, UI_Int_Value is multiplied by 10, and the
+   --  value of the digit added to the result. In addition, the value in
+   --  Scale is decremented by one for each actual digit scanned.
+
+   --------------------------
+   -- Error_Digit_Expected --
+   --------------------------
+
+   procedure Error_Digit_Expected is
+   begin
+      Error_Msg_S ("digit expected");
+   end Error_Digit_Expected;
+
+   -------------------
+   --  Scan_Integer --
+   -------------------
+
+   procedure Scan_Integer is
+      C : Character;
+      --  Next character scanned
+
+   begin
+      C := Source (Scan_Ptr);
+
+      --  Loop through digits (allowing underlines)
+
+      loop
+         Accumulate_Checksum (C);
+         UI_Int_Value :=
+           UI_Int_Value * 10 + (Character'Pos (C) - Character'Pos ('0'));
+         Scan_Ptr := Scan_Ptr + 1;
+         Scale := Scale - 1;
+         C := Source (Scan_Ptr);
+
+         if C = '_' then
+            Accumulate_Checksum ('_');
+
+            loop
+               Scan_Ptr := Scan_Ptr + 1;
+               C := Source (Scan_Ptr);
+               exit when C /= '_';
+               Error_No_Double_Underline;
+            end loop;
+
+            if C not in '0' .. '9' then
+               Error_Digit_Expected;
+               exit;
+            end if;
+
+         else
+            exit when C not in '0' .. '9';
+         end if;
+      end loop;
+
+   end Scan_Integer;
+
+----------------------------------
+-- Start of Processing for Nlit --
+----------------------------------
+
+begin
+   Base := 10;
+   UI_Base := Uint_10;
+   UI_Int_Value := Uint_0;
+   Scale := 0;
+   Scan_Integer;
+   Scale := 0;
+   Point_Scanned := False;
+   UI_Num_Value := UI_Int_Value;
+
+   --  Various possibilities now for continuing the literal are
+   --  period, E/e (for exponent), or :/# (for based literal).
+
+   Scale := 0;
+   C := Source (Scan_Ptr);
+
+   if C = '.' then
+
+      --  Scan out point, but do not scan past .. which is a range sequence,
+      --  and must not be eaten up scanning a numeric literal.
+
+      while C = '.' and then Source (Scan_Ptr + 1) /= '.' loop
+         Accumulate_Checksum ('.');
+
+         if Point_Scanned then
+            Error_Msg_S ("duplicate point ignored");
+         end if;
+
+         Point_Scanned := True;
+         Scan_Ptr := Scan_Ptr + 1;
+         C := Source (Scan_Ptr);
+
+         if C not in '0' .. '9' then
+            Error_Msg ("real literal cannot end with point", Scan_Ptr - 1);
+         else
+            Scan_Integer;
+            UI_Num_Value := UI_Int_Value;
+         end if;
+      end loop;
+
+   --  Based literal case. The base is the value we already scanned.
+   --  In the case of colon, we insist that the following character
+   --  is indeed an extended digit or a period. This catches a number
+   --  of common errors, as well as catching the well known tricky
+   --  bug otherwise arising from "x : integer range 1 .. 10:= 6;"
+
+   elsif C = '#'
+     or else (C = ':' and then
+                        (Source (Scan_Ptr + 1) = '.'
+                           or else
+                         Source (Scan_Ptr + 1) in '0' .. '9'
+                           or else
+                         Source (Scan_Ptr + 1) in 'A' .. 'Z'
+                           or else
+                         Source (Scan_Ptr + 1) in 'a' .. 'z'))
+   then
+      Accumulate_Checksum (C);
+      Base_Char := C;
+      UI_Base := UI_Int_Value;
+
+      if UI_Base < 2 or else UI_Base > 16 then
+         Error_Msg_SC ("base not 2-16");
+         UI_Base := Uint_16;
+      end if;
+
+      Base := UI_To_Int (UI_Base);
+      Scan_Ptr := Scan_Ptr + 1;
+
+      --  Scan out extended integer [. integer]
+
+      C := Source (Scan_Ptr);
+      UI_Int_Value := Uint_0;
+      Scale := 0;
+
+      loop
+         if C in '0' .. '9' then
+            Accumulate_Checksum (C);
+            Extended_Digit_Value :=
+              Int'(Character'Pos (C)) - Int'(Character'Pos ('0'));
+
+         elsif C in 'A' .. 'F' then
+            Accumulate_Checksum (Character'Val (Character'Pos (C) + 32));
+            Extended_Digit_Value :=
+              Int'(Character'Pos (C)) - Int'(Character'Pos ('A')) + 10;
+
+         elsif C in 'a' .. 'f' then
+            Accumulate_Checksum (C);
+            Extended_Digit_Value :=
+              Int'(Character'Pos (C)) - Int'(Character'Pos ('a')) + 10;
+
+         else
+            Error_Msg_S ("extended digit expected");
+            exit;
+         end if;
+
+         if Extended_Digit_Value >= Base then
+            Error_Msg_S ("digit >= base");
+         end if;
+
+         UI_Int_Value := UI_Int_Value * UI_Base + Extended_Digit_Value;
+         Scale := Scale - 1;
+         Scan_Ptr := Scan_Ptr + 1;
+         C := Source (Scan_Ptr);
+
+         if C = '_' then
+            loop
+               Accumulate_Checksum ('_');
+               Scan_Ptr := Scan_Ptr + 1;
+               C := Source (Scan_Ptr);
+               exit when C /= '_';
+               Error_No_Double_Underline;
+            end loop;
+
+         elsif C = '.' then
+            Accumulate_Checksum ('.');
+
+            if Point_Scanned then
+               Error_Msg_S ("duplicate point ignored");
+            end if;
+
+            Scan_Ptr := Scan_Ptr + 1;
+            C := Source (Scan_Ptr);
+            Point_Scanned := True;
+            Scale := 0;
+
+         elsif C = Base_Char then
+            Accumulate_Checksum (C);
+            Scan_Ptr := Scan_Ptr + 1;
+            exit;
+
+         elsif C = '#' or else C = ':' then
+            Error_Msg_S ("based number delimiters must match");
+            Scan_Ptr := Scan_Ptr + 1;
+            exit;
+
+         elsif not Identifier_Char (C) then
+            if Base_Char = '#' then
+               Error_Msg_S ("missing '#");
+            else
+               Error_Msg_S ("missing ':");
+            end if;
+
+            exit;
+         end if;
+
+      end loop;
+
+      UI_Num_Value := UI_Int_Value;
+   end if;
+
+   --  Scan out exponent
+
+   if not Point_Scanned then
+      Scale := 0;
+      UI_Scale := Uint_0;
+   else
+      UI_Scale := UI_From_Int (Scale);
+   end if;
+
+   if Source (Scan_Ptr) = 'e' or else Source (Scan_Ptr) = 'E' then
+      Accumulate_Checksum ('e');
+      Scan_Ptr := Scan_Ptr + 1;
+      Exponent_Is_Negative := False;
+
+      if Source (Scan_Ptr) = '+' then
+         Accumulate_Checksum ('+');
+         Scan_Ptr := Scan_Ptr + 1;
+
+      elsif Source (Scan_Ptr) = '-' then
+         Accumulate_Checksum ('-');
+
+         if not Point_Scanned then
+            Error_Msg_S ("negative exponent not allowed for integer literal");
+         else
+            Exponent_Is_Negative := True;
+         end if;
+
+         Scan_Ptr := Scan_Ptr + 1;
+      end if;
+
+      UI_Int_Value := Uint_0;
+
+      if Source (Scan_Ptr) in '0' .. '9' then
+         Scan_Integer;
+      else
+         Error_Digit_Expected;
+      end if;
+
+      if Exponent_Is_Negative then
+         UI_Scale := UI_Scale - UI_Int_Value;
+      else
+         UI_Scale := UI_Scale + UI_Int_Value;
+      end if;
+   end if;
+
+   --  Case of real literal to be returned
+
+   if Point_Scanned then
+      Token := Tok_Real_Literal;
+      Token_Node := New_Node (N_Real_Literal, Token_Ptr);
+      Set_Realval (Token_Node,
+        UR_From_Components (
+          Num   => UI_Num_Value,
+          Den   => -UI_Scale,
+          Rbase => Base));
+
+   --  Case of integer literal to be returned
+
+   else
+      Token := Tok_Integer_Literal;
+      Token_Node := New_Node (N_Integer_Literal, Token_Ptr);
+
+      if UI_Scale = 0 then
+         Set_Intval (Token_Node, UI_Num_Value);
+
+      --  Avoid doing possibly expensive calculations in cases like
+      --  parsing 163E800_000# when semantics will not be done anyway.
+      --  This is especially useful when parsing garbled input.
+
+      elsif Operating_Mode /= Check_Syntax
+        and then (Errors_Detected = 0 or else Try_Semantics)
+      then
+         Set_Intval (Token_Node, UI_Num_Value * UI_Base ** UI_Scale);
+
+      else
+         Set_Intval (Token_Node, No_Uint);
+      end if;
+
+   end if;
+
+   return;
+
+end Nlit;
diff --git a/gcc/ada/scn-slit.adb b/gcc/ada/scn-slit.adb
new file mode 100644 (file)
index 0000000..508d5c2
--- /dev/null
@@ -0,0 +1,373 @@
+------------------------------------------------------------------------------
+--                                                                          --
+--                         GNAT COMPILER COMPONENTS                         --
+--                                                                          --
+--                             S C N . S L I T                              --
+--                                                                          --
+--                                 B o d y                                  --
+--                                                                          --
+--                            $Revision: 1.29 $                             --
+--                                                                          --
+--          Copyright (C) 1992-1999 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- --
+-- ware  Foundation;  either version 2,  or (at your option) any later ver- --
+-- sion.  GNAT is distributed in the hope that it will be useful, but WITH- --
+-- OUT ANY WARRANTY;  without even the  implied warranty of MERCHANTABILITY --
+-- or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License --
+-- for  more details.  You should have  received  a copy of the GNU General --
+-- Public License  distributed with GNAT;  see file COPYING.  If not, write --
+-- to  the Free Software Foundation,  59 Temple Place - Suite 330,  Boston, --
+-- MA 02111-1307, USA.                                                      --
+--                                                                          --
+-- GNAT was originally developed  by the GNAT team at  New York University. --
+-- It is now maintained by Ada Core Technologies Inc (http://www.gnat.com). --
+--                                                                          --
+------------------------------------------------------------------------------
+
+with Stringt; use Stringt;
+
+separate (Scn)
+procedure Slit is
+
+   Delimiter : Character;
+   --  Delimiter (first character of string)
+
+   C : Character;
+   --  Current source program character
+
+   Code : Char_Code;
+   --  Current character code value
+
+   Err : Boolean;
+   --  Error flag for Scan_Wide call
+
+   String_Literal_Id : String_Id;
+   --  Id for currently scanned string value
+
+   Wide_Character_Found : Boolean := False;
+   --  Set True if wide character found
+
+   procedure Error_Bad_String_Char;
+   --  Signal bad character in string/character literal. On entry Scan_Ptr
+   --  points to the improper character encountered during the scan. Scan_Ptr
+   --  is not modified, so it still points to the bad character on return.
+
+   procedure Error_Unterminated_String;
+   --  Procedure called if a line terminator character is encountered during
+   --  scanning a string, meaning that the string is not properly terminated.
+
+   procedure Set_String;
+   --  Procedure used to distinguish between string and operator symbol.
+   --  On entry the string has been scanned out, and its characters start
+   --  at Token_Ptr and end one character before Scan_Ptr. On exit Token
+   --  is set to Tok_String_Literal or Tok_Operator_Symbol as appropriate,
+   --  and Token_Node is appropriately initialized. In addition, in the
+   --  operator symbol case, Token_Name is appropriately set.
+
+   ---------------------------
+   -- Error_Bad_String_Char --
+   ---------------------------
+
+   procedure Error_Bad_String_Char is
+      C : constant Character := Source (Scan_Ptr);
+
+   begin
+      if C = HT then
+         Error_Msg_S ("horizontal tab not allowed in string");
+
+      elsif C = VT or else C = FF then
+         Error_Msg_S ("format effector not allowed in string");
+
+      elsif C in Upper_Half_Character then
+         Error_Msg_S ("(Ada 83) upper half character not allowed");
+
+      else
+         Error_Msg_S ("control character not allowed in string");
+      end if;
+   end Error_Bad_String_Char;
+
+   -------------------------------
+   -- Error_Unterminated_String --
+   -------------------------------
+
+   procedure Error_Unterminated_String is
+   begin
+      --  An interesting little refinement. Consider the following examples:
+
+      --     A := "this is an unterminated string;
+      --     A := "this is an unterminated string &
+      --     P(A, "this is a parameter that didn't get terminated);
+
+      --  We fiddle a little to do slightly better placement in these cases
+      --  also if there is white space at the end of the line we place the
+      --  flag at the start of this white space, not at the end. Note that
+      --  we only have to test for blanks, since tabs aren't allowed in
+      --  strings in the first place and would have caused an error message.
+
+      --  Two more cases that we treat specially are:
+
+      --     A := "this string uses the wrong terminator'
+      --     A := "this string uses the wrong terminator' &
+
+      --  In these cases we give a different error message as well
+
+      --  We actually reposition the scan pointer to the point where we
+      --  place the flag in these cases, since it seems a better bet on
+      --  the original intention.
+
+      while Source (Scan_Ptr - 1) = ' '
+        or else Source (Scan_Ptr - 1) = '&'
+      loop
+         Scan_Ptr := Scan_Ptr - 1;
+         Unstore_String_Char;
+      end loop;
+
+      --  Check for case of incorrect string terminator, but single quote is
+      --  not considered incorrect if the opening terminator misused a single
+      --  quote (error message already given).
+
+      if Delimiter /= '''
+        and then Source (Scan_Ptr - 1) = '''
+      then
+         Unstore_String_Char;
+         Error_Msg ("incorrect string terminator character", Scan_Ptr - 1);
+         return;
+      end if;
+
+      if Source (Scan_Ptr - 1) = ';' then
+         Scan_Ptr := Scan_Ptr - 1;
+         Unstore_String_Char;
+
+         if Source (Scan_Ptr - 1) = ')' then
+            Scan_Ptr := Scan_Ptr - 1;
+            Unstore_String_Char;
+         end if;
+      end if;
+
+      Error_Msg_S ("missing string quote");
+   end Error_Unterminated_String;
+
+   ----------------
+   -- Set_String --
+   ----------------
+
+   procedure Set_String is
+      Slen : Int := Int (Scan_Ptr - Token_Ptr - 2);
+      C1   : Character;
+      C2   : Character;
+      C3   : Character;
+
+   begin
+      --  Token_Name is currently set to Error_Name. The following section of
+      --  code resets Token_Name to the proper Name_Op_xx value if the string
+      --  is a valid operator symbol, otherwise it is left set to Error_Name.
+
+      if Slen = 1 then
+         C1 := Source (Token_Ptr + 1);
+
+         case C1 is
+            when '=' =>
+               Token_Name := Name_Op_Eq;
+
+            when '>' =>
+               Token_Name := Name_Op_Gt;
+
+            when '<' =>
+               Token_Name := Name_Op_Lt;
+
+            when '+' =>
+               Token_Name := Name_Op_Add;
+
+            when '-' =>
+               Token_Name := Name_Op_Subtract;
+
+            when '&' =>
+               Token_Name := Name_Op_Concat;
+
+            when '*' =>
+               Token_Name := Name_Op_Multiply;
+
+            when '/' =>
+               Token_Name := Name_Op_Divide;
+
+            when others =>
+               null;
+         end case;
+
+      elsif Slen = 2 then
+         C1 := Source (Token_Ptr + 1);
+         C2 := Source (Token_Ptr + 2);
+
+         if C1 = '*' and then C2 = '*' then
+            Token_Name := Name_Op_Expon;
+
+         elsif C2 = '=' then
+
+            if C1 = '/' then
+               Token_Name := Name_Op_Ne;
+            elsif C1 = '<' then
+               Token_Name := Name_Op_Le;
+            elsif C1 = '>' then
+               Token_Name := Name_Op_Ge;
+            end if;
+
+         elsif (C1 = 'O' or else C1 = 'o') and then    -- OR
+               (C2 = 'R' or else C2 = 'r')
+         then
+            Token_Name := Name_Op_Or;
+         end if;
+
+      elsif Slen = 3 then
+         C1 := Source (Token_Ptr + 1);
+         C2 := Source (Token_Ptr + 2);
+         C3 := Source (Token_Ptr + 3);
+
+         if (C1 = 'A' or else C1 = 'a') and then       -- AND
+            (C2 = 'N' or else C2 = 'n') and then
+            (C3 = 'D' or else C3 = 'd')
+         then
+            Token_Name := Name_Op_And;
+
+         elsif (C1 = 'A' or else C1 = 'a') and then    -- ABS
+               (C2 = 'B' or else C2 = 'b') and then
+               (C3 = 'S' or else C3 = 's')
+         then
+            Token_Name := Name_Op_Abs;
+
+         elsif (C1 = 'M' or else C1 = 'm') and then    -- MOD
+               (C2 = 'O' or else C2 = 'o') and then
+               (C3 = 'D' or else C3 = 'd')
+         then
+            Token_Name := Name_Op_Mod;
+
+         elsif (C1 = 'N' or else C1 = 'n') and then    -- NOT
+               (C2 = 'O' or else C2 = 'o') and then
+               (C3 = 'T' or else C3 = 't')
+         then
+            Token_Name := Name_Op_Not;
+
+         elsif (C1 = 'R' or else C1 = 'r') and then    -- REM
+               (C2 = 'E' or else C2 = 'e') and then
+               (C3 = 'M' or else C3 = 'm')
+         then
+            Token_Name := Name_Op_Rem;
+
+         elsif (C1 = 'X' or else C1 = 'x') and then    -- XOR
+               (C2 = 'O' or else C2 = 'o') and then
+               (C3 = 'R' or else C3 = 'r')
+         then
+            Token_Name := Name_Op_Xor;
+         end if;
+
+      end if;
+
+      --  If it is an operator symbol, then Token_Name is set. If it is some
+      --  other string value, then Token_Name still contains Error_Name.
+
+      if Token_Name = Error_Name then
+         Token := Tok_String_Literal;
+         Token_Node := New_Node (N_String_Literal, Token_Ptr);
+         Set_Has_Wide_Character (Token_Node, Wide_Character_Found);
+
+      else
+         Token := Tok_Operator_Symbol;
+         Token_Node := New_Node (N_Operator_Symbol, Token_Ptr);
+         Set_Chars (Token_Node, Token_Name);
+      end if;
+
+      Set_Strval (Token_Node, String_Literal_Id);
+
+   end Set_String;
+
+----------
+-- Slit --
+----------
+
+begin
+   --  On entry, Scan_Ptr points to the opening character of the string which
+   --  is either a percent, double quote, or apostrophe (single quote). The
+   --  latter case is an error detected by the character literal circuit.
+
+   Delimiter := Source (Scan_Ptr);
+   Accumulate_Checksum (Delimiter);
+   Start_String;
+   Scan_Ptr := Scan_Ptr + 1;
+
+   --  Loop to scan out characters of string literal
+
+   loop
+      C := Source (Scan_Ptr);
+
+      if C = Delimiter then
+         Accumulate_Checksum (C);
+         Scan_Ptr := Scan_Ptr + 1;
+         exit when Source (Scan_Ptr) /= Delimiter;
+         Code := Get_Char_Code (C);
+         Accumulate_Checksum (C);
+         Scan_Ptr := Scan_Ptr + 1;
+
+      else
+         if C = '"' and then Delimiter = '%' then
+            Error_Msg_S ("quote not allowed in percent delimited string");
+            Code := Get_Char_Code (C);
+            Scan_Ptr := Scan_Ptr + 1;
+
+         elsif (C = ESC
+                 and then
+                Wide_Character_Encoding_Method in WC_ESC_Encoding_Method)
+           or else
+               (C in Upper_Half_Character
+                 and then
+                Upper_Half_Encoding)
+           or else
+               (C = '['
+                 and then
+                Source (Scan_Ptr + 1) = '"'
+                 and then
+                Identifier_Char (Source (Scan_Ptr + 2)))
+         then
+            Scan_Wide (Source, Scan_Ptr, Code, Err);
+            Accumulate_Checksum (Code);
+
+            if Err then
+               Error_Illegal_Wide_Character;
+               Code := Get_Char_Code (' ');
+            end if;
+
+         else
+            Accumulate_Checksum (C);
+
+            if C not in Graphic_Character then
+               if C in Line_Terminator then
+                  Error_Unterminated_String;
+                  exit;
+
+               elsif C in Upper_Half_Character then
+                  if Ada_83 then
+                     Error_Bad_String_Char;
+                  end if;
+
+               else
+                  Error_Bad_String_Char;
+               end if;
+            end if;
+
+            Code := Get_Char_Code (C);
+            Scan_Ptr := Scan_Ptr + 1;
+         end if;
+      end if;
+
+      Store_String_Char (Code);
+
+      if not In_Character_Range (Code) then
+         Wide_Character_Found := True;
+      end if;
+   end loop;
+
+   String_Literal_Id := End_String;
+   Set_String;
+   return;
+
+end Slit;
diff --git a/gcc/ada/scn.adb b/gcc/ada/scn.adb
new file mode 100644 (file)
index 0000000..146314d
--- /dev/null
@@ -0,0 +1,1570 @@
+------------------------------------------------------------------------------
+--                                                                          --
+--                         GNAT COMPILER COMPONENTS                         --
+--                                                                          --
+--                                  S C N                                   --
+--                                                                          --
+--                                 B o d y                                  --
+--                                                                          --
+--                            $Revision: 1.111 $
+--                                                                          --
+--          Copyright (C) 1992-2001 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- --
+-- ware  Foundation;  either version 2,  or (at your option) any later ver- --
+-- sion.  GNAT is distributed in the hope that it will be useful, but WITH- --
+-- OUT ANY WARRANTY;  without even the  implied warranty of MERCHANTABILITY --
+-- or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License --
+-- for  more details.  You should have  received  a copy of the GNU General --
+-- Public License  distributed with GNAT;  see file COPYING.  If not, write --
+-- to  the Free Software Foundation,  59 Temple Place - Suite 330,  Boston, --
+-- MA 02111-1307, USA.                                                      --
+--                                                                          --
+-- GNAT was originally developed  by the GNAT team at  New York University. --
+-- It is now maintained by Ada Core Technologies Inc (http://www.gnat.com). --
+--                                                                          --
+------------------------------------------------------------------------------
+
+with Atree;    use Atree;
+with Csets;    use Csets;
+with Errout;   use Errout;
+with Hostparm; use Hostparm;
+with Namet;    use Namet;
+with Opt;      use Opt;
+with Scans;    use Scans;
+with Sinput;   use Sinput;
+with Sinfo;    use Sinfo;
+with Snames;   use Snames;
+with Style;
+with Widechar; use Widechar;
+
+with System.WCh_Con; use System.WCh_Con;
+
+package body Scn is
+
+   use ASCII;
+   --  Make control characters visible
+
+   Used_As_Identifier : array (Token_Type) of Boolean;
+   --  Flags set True if a given keyword is used as an identifier (used to
+   --  make sure that we only post an error message for incorrect use of a
+   --  keyword as an identifier once for a given keyword).
+
+   -----------------------
+   -- Local Subprograms --
+   -----------------------
+
+   procedure Accumulate_Checksum (C : Character);
+   pragma Inline (Accumulate_Checksum);
+   --  This routine accumulates the checksum given character C. During the
+   --  scanning of a source file, this routine is called with every character
+   --  in the source, excluding blanks, and all control characters (except
+   --  that ESC is included in the checksum). Upper case letters not in string
+   --  literals are folded by the caller. See Sinput spec for the documentation
+   --  of the checksum algorithm. Note: checksum values are only used if we
+   --  generate code, so it is not necessary to worry about making the right
+   --  sequence of calls in any error situation.
+
+   procedure Accumulate_Checksum (C : Char_Code);
+   pragma Inline (Accumulate_Checksum);
+   --  This version is identical, except that the argument, C, is a character
+   --  code value instead of a character. This is used when wide characters
+   --  are scanned. We use the character code rather than the ASCII characters
+   --  so that the checksum is independent of wide character encoding method.
+
+   procedure Check_End_Of_Line;
+   --  Called when end of line encountered. Checks that line is not
+   --  too long, and that other style checks for the end of line are met.
+
+   function Determine_License return License_Type;
+   --  Scan header of file and check that it has an appropriate GNAT-style
+   --  header with a proper license statement. Returns GPL, Unrestricted,
+   --  or Modified_GPL depending on header. If none of these, returns Unknown.
+
+   function Double_Char_Token (C : Character) return Boolean;
+   --  This function is used for double character tokens like := or <>. It
+   --  checks if the character following Source (Scan_Ptr) is C, and if so
+   --  bumps Scan_Ptr past the pair of characters and returns True. A space
+   --  between the two characters is also recognized with an appropriate
+   --  error message being issued. If C is not present, False is returned.
+   --  Note that Double_Char_Token can only be used for tokens defined in
+   --  the Ada syntax (it's use for error cases like && is not appropriate
+   --  since we do not want a junk message for a case like &-space-&).
+
+   procedure Error_Illegal_Character;
+   --  Give illegal character error, Scan_Ptr points to character. On return,
+   --  Scan_Ptr is bumped past the illegal character.
+
+   procedure Error_Illegal_Wide_Character;
+   --  Give illegal wide character message. On return, Scan_Ptr is bumped
+   --  past the illegal character, which may still leave us pointing to
+   --  junk, not much we can do if the escape sequence is messed up!
+
+   procedure Error_Long_Line;
+   --  Signal error of excessively long line
+
+   procedure Error_No_Double_Underline;
+   --  Signal error of double underline character
+
+   procedure Nlit;
+   --  This is the procedure for scanning out numeric literals. On entry,
+   --  Scan_Ptr points to the digit that starts the numeric literal (the
+   --  checksum for this character has not been accumulated yet). On return
+   --  Scan_Ptr points past the last character of the numeric literal, Token
+   --  and Token_Node are set appropriately, and the checksum is updated.
+
+   function Set_Start_Column return Column_Number;
+   --  This routine is called with Scan_Ptr pointing to the first character
+   --  of a line. On exit, Scan_Ptr is advanced to the first non-blank
+   --  character of this line (or to the terminating format effector if the
+   --  line contains no non-blank characters), and the returned result is the
+   --  column number of this non-blank character (zero origin), which is the
+   --  value to be stored in the Start_Column scan variable.
+
+   procedure Slit;
+   --  This is the procedure for scanning out string literals. On entry,
+   --  Scan_Ptr points to the opening string quote (the checksum for this
+   --  character has not been accumulated yet). On return Scan_Ptr points
+   --  past the closing quote of the string literal, Token and Token_Node
+   --  are set appropriately, and the checksum is upated.
+
+   -------------------------
+   -- Accumulate_Checksum --
+   -------------------------
+
+   procedure Accumulate_Checksum (C : Character) is
+   begin
+      Checksum := Checksum + Checksum + Character'Pos (C);
+
+      if Checksum > 16#8000_0000# then
+         Checksum := (Checksum + 1) and 16#7FFF_FFFF#;
+      end if;
+   end Accumulate_Checksum;
+
+   procedure Accumulate_Checksum (C : Char_Code) is
+   begin
+      Checksum := Checksum + Checksum + Char_Code'Pos (C);
+
+      if Checksum > 16#8000_0000# then
+         Checksum := (Checksum + 1) and 16#7FFF_FFFF#;
+      end if;
+   end Accumulate_Checksum;
+
+   -----------------------
+   -- Check_End_Of_Line --
+   -----------------------
+
+   procedure Check_End_Of_Line is
+      Len : constant Int := Int (Scan_Ptr) - Int (Current_Line_Start);
+
+   begin
+      if Len > Hostparm.Max_Line_Length then
+         Error_Long_Line;
+
+      elsif Style_Check then
+         Style.Check_Line_Terminator (Len);
+      end if;
+   end Check_End_Of_Line;
+
+   -----------------------
+   -- Determine_License --
+   -----------------------
+
+   function Determine_License return License_Type is
+      GPL_Found : Boolean := False;
+
+      function Contains (S : String) return Boolean;
+      --  See if current comment contains successive non-blank characters
+      --  matching the contents of S. If so leave Scan_Ptr unchanged and
+      --  return True, otherwise leave Scan_Ptr unchanged and return False.
+
+      procedure Skip_EOL;
+      --  Skip to line terminator character
+
+      --------------
+      -- Contains --
+      --------------
+
+      function Contains (S : String) return Boolean is
+         CP : Natural;
+         SP : Source_Ptr;
+         SS : Source_Ptr;
+
+      begin
+         SP := Scan_Ptr;
+         while Source (SP) /= CR and then Source (SP) /= LF loop
+            if Source (SP) = S (S'First) then
+               SS := SP;
+               CP := S'First;
+
+               loop
+                  SS := SS + 1;
+                  CP := CP + 1;
+
+                  if CP > S'Last then
+                     return True;
+                  end if;
+
+                  while Source (SS) = ' ' loop
+                     SS := SS + 1;
+                  end loop;
+
+                  exit when Source (SS) /= S (CP);
+               end loop;
+            end if;
+
+            SP := SP + 1;
+         end loop;
+
+         return False;
+      end Contains;
+
+      --------------
+      -- Skip_EOL --
+      --------------
+
+      procedure Skip_EOL is
+      begin
+         while Source (Scan_Ptr) /= CR
+           and then Source (Scan_Ptr) /= LF
+         loop
+            Scan_Ptr := Scan_Ptr + 1;
+         end loop;
+      end Skip_EOL;
+
+   --  Start of processing for Determine_License
+
+   begin
+      loop
+         if Source (Scan_Ptr) /= '-'
+           or else Source (Scan_Ptr + 1) /= '-'
+         then
+            if GPL_Found then
+               return GPL;
+            else
+               return Unknown;
+            end if;
+
+         elsif Contains ("Asaspecialexception") then
+            if GPL_Found then
+               return Modified_GPL;
+            end if;
+
+         elsif Contains ("GNUGeneralPublicLicense") then
+            GPL_Found := True;
+
+         elsif
+             Contains
+               ("ThisspecificationisadaptedfromtheAdaSemanticInterface")
+           or else
+             Contains
+              ("ThisspecificationisderivedfromtheAdaReferenceManual")
+         then
+            return Unrestricted;
+         end if;
+
+         Skip_EOL;
+
+         Check_End_Of_Line;
+
+         declare
+            Physical : Boolean;
+
+         begin
+            Skip_Line_Terminators (Scan_Ptr, Physical);
+
+            --  If we are at start of physical line, update scan pointers
+            --  to reflect the start of the new line.
+
+            if Physical then
+               Current_Line_Start       := Scan_Ptr;
+               Start_Column             := Set_Start_Column;
+               First_Non_Blank_Location := Scan_Ptr;
+            end if;
+         end;
+      end loop;
+   end Determine_License;
+
+   ----------------------------
+   -- Determine_Token_Casing --
+   ----------------------------
+
+   function Determine_Token_Casing return Casing_Type is
+   begin
+      return Determine_Casing (Source (Token_Ptr .. Scan_Ptr - 1));
+   end Determine_Token_Casing;
+
+   -----------------------
+   -- Double_Char_Token --
+   -----------------------
+
+   function Double_Char_Token (C : Character) return Boolean is
+   begin
+      if Source (Scan_Ptr + 1) = C then
+         Accumulate_Checksum (C);
+         Scan_Ptr := Scan_Ptr + 2;
+         return True;
+
+      elsif Source (Scan_Ptr + 1) = ' '
+        and then Source (Scan_Ptr + 2) = C
+      then
+         Scan_Ptr := Scan_Ptr + 1;
+         Error_Msg_S ("no space allowed here");
+         Scan_Ptr := Scan_Ptr + 2;
+         return True;
+
+      else
+         return False;
+      end if;
+   end Double_Char_Token;
+
+   -----------------------------
+   -- Error_Illegal_Character --
+   -----------------------------
+
+   procedure Error_Illegal_Character is
+   begin
+      Error_Msg_S ("illegal character");
+      Scan_Ptr := Scan_Ptr + 1;
+   end Error_Illegal_Character;
+
+   ----------------------------------
+   -- Error_Illegal_Wide_Character --
+   ----------------------------------
+
+   procedure Error_Illegal_Wide_Character is
+   begin
+      if OpenVMS then
+         Error_Msg_S
+           ("illegal wide character, check " &
+            "'/'W'I'D'E'_'C'H'A'R'A'C'T'E'R'_'E'N'C'O'D'I'N'G qualifer");
+      else
+         Error_Msg_S
+           ("illegal wide character, check -gnatW switch");
+      end if;
+
+      Scan_Ptr := Scan_Ptr + 1;
+   end Error_Illegal_Wide_Character;
+
+   ---------------------
+   -- Error_Long_Line --
+   ---------------------
+
+   procedure Error_Long_Line is
+   begin
+      Error_Msg
+        ("this line is too long",
+         Current_Line_Start + Hostparm.Max_Line_Length);
+   end Error_Long_Line;
+
+   -------------------------------
+   -- Error_No_Double_Underline --
+   -------------------------------
+
+   procedure Error_No_Double_Underline is
+   begin
+      Error_Msg_S ("two consecutive underlines not permitted");
+   end Error_No_Double_Underline;
+
+   ------------------------
+   -- Initialize_Scanner --
+   ------------------------
+
+   procedure Initialize_Scanner
+     (Unit  : Unit_Number_Type;
+      Index : Source_File_Index)
+   is
+      GNAT_Hedr : constant Text_Buffer (1 .. 78) := (others => '-');
+
+   begin
+      --  Set up Token_Type values in Names Table entries for reserved keywords
+      --  We use the Pos value of the Token_Type value. Note we are relying on
+      --  the fact that Token_Type'Val (0) is not a reserved word!
+
+      Set_Name_Table_Byte (Name_Abort,      Token_Type'Pos (Tok_Abort));
+      Set_Name_Table_Byte (Name_Abs,        Token_Type'Pos (Tok_Abs));
+      Set_Name_Table_Byte (Name_Abstract,   Token_Type'Pos (Tok_Abstract));
+      Set_Name_Table_Byte (Name_Accept,     Token_Type'Pos (Tok_Accept));
+      Set_Name_Table_Byte (Name_Access,     Token_Type'Pos (Tok_Access));
+      Set_Name_Table_Byte (Name_And,        Token_Type'Pos (Tok_And));
+      Set_Name_Table_Byte (Name_Aliased,    Token_Type'Pos (Tok_Aliased));
+      Set_Name_Table_Byte (Name_All,        Token_Type'Pos (Tok_All));
+      Set_Name_Table_Byte (Name_Array,      Token_Type'Pos (Tok_Array));
+      Set_Name_Table_Byte (Name_At,         Token_Type'Pos (Tok_At));
+      Set_Name_Table_Byte (Name_Begin,      Token_Type'Pos (Tok_Begin));
+      Set_Name_Table_Byte (Name_Body,       Token_Type'Pos (Tok_Body));
+      Set_Name_Table_Byte (Name_Case,       Token_Type'Pos (Tok_Case));
+      Set_Name_Table_Byte (Name_Constant,   Token_Type'Pos (Tok_Constant));
+      Set_Name_Table_Byte (Name_Declare,    Token_Type'Pos (Tok_Declare));
+      Set_Name_Table_Byte (Name_Delay,      Token_Type'Pos (Tok_Delay));
+      Set_Name_Table_Byte (Name_Delta,      Token_Type'Pos (Tok_Delta));
+      Set_Name_Table_Byte (Name_Digits,     Token_Type'Pos (Tok_Digits));
+      Set_Name_Table_Byte (Name_Do,         Token_Type'Pos (Tok_Do));
+      Set_Name_Table_Byte (Name_Else,       Token_Type'Pos (Tok_Else));
+      Set_Name_Table_Byte (Name_Elsif,      Token_Type'Pos (Tok_Elsif));
+      Set_Name_Table_Byte (Name_End,        Token_Type'Pos (Tok_End));
+      Set_Name_Table_Byte (Name_Entry,      Token_Type'Pos (Tok_Entry));
+      Set_Name_Table_Byte (Name_Exception,  Token_Type'Pos (Tok_Exception));
+      Set_Name_Table_Byte (Name_Exit,       Token_Type'Pos (Tok_Exit));
+      Set_Name_Table_Byte (Name_For,        Token_Type'Pos (Tok_For));
+      Set_Name_Table_Byte (Name_Function,   Token_Type'Pos (Tok_Function));
+      Set_Name_Table_Byte (Name_Generic,    Token_Type'Pos (Tok_Generic));
+      Set_Name_Table_Byte (Name_Goto,       Token_Type'Pos (Tok_Goto));
+      Set_Name_Table_Byte (Name_If,         Token_Type'Pos (Tok_If));
+      Set_Name_Table_Byte (Name_In,         Token_Type'Pos (Tok_In));
+      Set_Name_Table_Byte (Name_Is,         Token_Type'Pos (Tok_Is));
+      Set_Name_Table_Byte (Name_Limited,    Token_Type'Pos (Tok_Limited));
+      Set_Name_Table_Byte (Name_Loop,       Token_Type'Pos (Tok_Loop));
+      Set_Name_Table_Byte (Name_Mod,        Token_Type'Pos (Tok_Mod));
+      Set_Name_Table_Byte (Name_New,        Token_Type'Pos (Tok_New));
+      Set_Name_Table_Byte (Name_Not,        Token_Type'Pos (Tok_Not));
+      Set_Name_Table_Byte (Name_Null,       Token_Type'Pos (Tok_Null));
+      Set_Name_Table_Byte (Name_Of,         Token_Type'Pos (Tok_Of));
+      Set_Name_Table_Byte (Name_Or,         Token_Type'Pos (Tok_Or));
+      Set_Name_Table_Byte (Name_Others,     Token_Type'Pos (Tok_Others));
+      Set_Name_Table_Byte (Name_Out,        Token_Type'Pos (Tok_Out));
+      Set_Name_Table_Byte (Name_Package,    Token_Type'Pos (Tok_Package));
+      Set_Name_Table_Byte (Name_Pragma,     Token_Type'Pos (Tok_Pragma));
+      Set_Name_Table_Byte (Name_Private,    Token_Type'Pos (Tok_Private));
+      Set_Name_Table_Byte (Name_Procedure,  Token_Type'Pos (Tok_Procedure));
+      Set_Name_Table_Byte (Name_Protected,  Token_Type'Pos (Tok_Protected));
+      Set_Name_Table_Byte (Name_Raise,      Token_Type'Pos (Tok_Raise));
+      Set_Name_Table_Byte (Name_Range,      Token_Type'Pos (Tok_Range));
+      Set_Name_Table_Byte (Name_Record,     Token_Type'Pos (Tok_Record));
+      Set_Name_Table_Byte (Name_Rem,        Token_Type'Pos (Tok_Rem));
+      Set_Name_Table_Byte (Name_Renames,    Token_Type'Pos (Tok_Renames));
+      Set_Name_Table_Byte (Name_Requeue,    Token_Type'Pos (Tok_Requeue));
+      Set_Name_Table_Byte (Name_Return,     Token_Type'Pos (Tok_Return));
+      Set_Name_Table_Byte (Name_Reverse,    Token_Type'Pos (Tok_Reverse));
+      Set_Name_Table_Byte (Name_Select,     Token_Type'Pos (Tok_Select));
+      Set_Name_Table_Byte (Name_Separate,   Token_Type'Pos (Tok_Separate));
+      Set_Name_Table_Byte (Name_Subtype,    Token_Type'Pos (Tok_Subtype));
+      Set_Name_Table_Byte (Name_Tagged,     Token_Type'Pos (Tok_Tagged));
+      Set_Name_Table_Byte (Name_Task,       Token_Type'Pos (Tok_Task));
+      Set_Name_Table_Byte (Name_Terminate,  Token_Type'Pos (Tok_Terminate));
+      Set_Name_Table_Byte (Name_Then,       Token_Type'Pos (Tok_Then));
+      Set_Name_Table_Byte (Name_Type,       Token_Type'Pos (Tok_Type));
+      Set_Name_Table_Byte (Name_Until,      Token_Type'Pos (Tok_Until));
+      Set_Name_Table_Byte (Name_Use,        Token_Type'Pos (Tok_Use));
+      Set_Name_Table_Byte (Name_When,       Token_Type'Pos (Tok_When));
+      Set_Name_Table_Byte (Name_While,      Token_Type'Pos (Tok_While));
+      Set_Name_Table_Byte (Name_With,       Token_Type'Pos (Tok_With));
+      Set_Name_Table_Byte (Name_Xor,        Token_Type'Pos (Tok_Xor));
+
+      --  Initialize scan control variables
+
+      Current_Source_File       := Index;
+      Source                    := Source_Text (Current_Source_File);
+      Current_Source_Unit       := Unit;
+      Scan_Ptr                  := Source_First (Current_Source_File);
+      Token                     := No_Token;
+      Token_Ptr                 := Scan_Ptr;
+      Current_Line_Start        := Scan_Ptr;
+      Token_Node                := Empty;
+      Token_Name                := No_Name;
+      Start_Column              := Set_Start_Column;
+      First_Non_Blank_Location  := Scan_Ptr;
+      Checksum                  := 0;
+
+      --  Set default for Comes_From_Source. All nodes built now until we
+      --  reenter the analyzer will have Comes_From_Source set to True
+
+      Set_Comes_From_Source_Default (True);
+
+      --  Check license if GNAT type header possibly present
+
+      if Source_Last (Index) - Scan_Ptr > 80
+        and then Source (Scan_Ptr .. Scan_Ptr + 77) = GNAT_Hedr
+      then
+         Set_License (Current_Source_File, Determine_License);
+      end if;
+
+      --  Scan initial token (note this initializes Prev_Token, Prev_Token_Ptr)
+
+      Scan;
+
+      --  Clear flags for reserved words used as indentifiers
+
+      for J in Token_Type loop
+         Used_As_Identifier (J) := False;
+      end loop;
+
+   end Initialize_Scanner;
+
+   ----------
+   -- Nlit --
+   ----------
+
+   procedure Nlit is separate;
+
+   ----------
+   -- Scan --
+   ----------
+
+   procedure Scan is
+   begin
+      Prev_Token := Token;
+      Prev_Token_Ptr := Token_Ptr;
+      Token_Name := Error_Name;
+
+      --  The following loop runs more than once only if a format effector
+      --  (tab, vertical tab, form  feed, line feed, carriage return) is
+      --  encountered and skipped, or some error situation, such as an
+      --  illegal character, is encountered.
+
+      loop
+         --  Skip past blanks, loop is opened up for speed
+
+         while Source (Scan_Ptr) = ' ' loop
+
+            if Source (Scan_Ptr + 1) /= ' ' then
+               Scan_Ptr := Scan_Ptr + 1;
+               exit;
+            end if;
+
+            if Source (Scan_Ptr + 2) /= ' ' then
+               Scan_Ptr := Scan_Ptr + 2;
+               exit;
+            end if;
+
+            if Source (Scan_Ptr + 3) /= ' ' then
+               Scan_Ptr := Scan_Ptr + 3;
+               exit;
+            end if;
+
+            if Source (Scan_Ptr + 4) /= ' ' then
+               Scan_Ptr := Scan_Ptr + 4;
+               exit;
+            end if;
+
+            if Source (Scan_Ptr + 5) /= ' ' then
+               Scan_Ptr := Scan_Ptr + 5;
+               exit;
+            end if;
+
+            if Source (Scan_Ptr + 6) /= ' ' then
+               Scan_Ptr := Scan_Ptr + 6;
+               exit;
+            end if;
+
+            if Source (Scan_Ptr + 7) /= ' ' then
+               Scan_Ptr := Scan_Ptr + 7;
+               exit;
+            end if;
+
+            Scan_Ptr := Scan_Ptr + 8;
+         end loop;
+
+         --  We are now at a non-blank character, which is the first character
+         --  of the token we will scan, and hence the value of Token_Ptr.
+
+         Token_Ptr := Scan_Ptr;
+
+         --  Here begins the main case statement which transfers control on
+         --  the basis of the non-blank character we have encountered.
+
+         case Source (Scan_Ptr) is
+
+         --  Line terminator characters
+
+         when CR | LF | FF | VT => Line_Terminator_Case : begin
+
+            --  Check line too long
+
+            Check_End_Of_Line;
+
+            declare
+               Physical : Boolean;
+
+            begin
+               Skip_Line_Terminators (Scan_Ptr, Physical);
+
+               --  If we are at start of physical line, update scan pointers
+               --  to reflect the start of the new line.
+
+               if Physical then
+                  Current_Line_Start       := Scan_Ptr;
+                  Start_Column             := Set_Start_Column;
+                  First_Non_Blank_Location := Scan_Ptr;
+               end if;
+            end;
+         end Line_Terminator_Case;
+
+         --  Horizontal tab, just skip past it
+
+         when HT =>
+            if Style_Check then Style.Check_HT; end if;
+            Scan_Ptr := Scan_Ptr + 1;
+
+         --  End of file character, treated as an end of file only if it
+         --  is the last character in the buffer, otherwise it is ignored.
+
+         when EOF =>
+            if Scan_Ptr = Source_Last (Current_Source_File) then
+               Check_End_Of_Line;
+               Token := Tok_EOF;
+               return;
+
+            else
+               Scan_Ptr := Scan_Ptr + 1;
+            end if;
+
+         --  Ampersand
+
+         when '&' =>
+            Accumulate_Checksum ('&');
+
+            if Source (Scan_Ptr + 1) = '&' then
+               Error_Msg_S ("'&'& should be `AND THEN`");
+               Scan_Ptr := Scan_Ptr + 2;
+               Token := Tok_And;
+               return;
+
+            else
+               Scan_Ptr := Scan_Ptr + 1;
+               Token := Tok_Ampersand;
+               return;
+            end if;
+
+         --  Asterisk (can be multiplication operator or double asterisk
+         --  which is the exponentiation compound delimtier).
+
+         when '*' =>
+            Accumulate_Checksum ('*');
+
+            if Source (Scan_Ptr + 1) = '*' then
+               Accumulate_Checksum ('*');
+               Scan_Ptr := Scan_Ptr + 2;
+               Token := Tok_Double_Asterisk;
+               return;
+
+            else
+               Scan_Ptr := Scan_Ptr + 1;
+               Token := Tok_Asterisk;
+               return;
+            end if;
+
+         --  Colon, which can either be an isolated colon, or part of an
+         --  assignment compound delimiter.
+
+         when ':' =>
+            Accumulate_Checksum (':');
+
+            if Double_Char_Token ('=') then
+               Token := Tok_Colon_Equal;
+               if Style_Check then Style.Check_Colon_Equal; end if;
+               return;
+
+            elsif Source (Scan_Ptr + 1) = '-'
+              and then Source (Scan_Ptr + 2) /= '-'
+            then
+               Token := Tok_Colon_Equal;
+               Error_Msg (":- should be :=", Scan_Ptr);
+               Scan_Ptr := Scan_Ptr + 2;
+               return;
+
+            else
+               Scan_Ptr := Scan_Ptr + 1;
+               Token := Tok_Colon;
+               if Style_Check then Style.Check_Colon; end if;
+               return;
+            end if;
+
+         --  Left parenthesis
+
+         when '(' =>
+            Accumulate_Checksum ('(');
+            Scan_Ptr := Scan_Ptr + 1;
+            Token := Tok_Left_Paren;
+            if Style_Check then Style.Check_Left_Paren; end if;
+            return;
+
+         --  Left bracket
+
+         when '[' =>
+            if Source (Scan_Ptr + 1) = '"' then
+               Name_Len := 0;
+               goto Scan_Identifier;
+
+            else
+               Error_Msg_S ("illegal character, replaced by ""(""");
+               Scan_Ptr := Scan_Ptr + 1;
+               Token := Tok_Left_Paren;
+               return;
+            end if;
+
+         --  Left brace
+
+         when '{' =>
+            Error_Msg_S ("illegal character, replaced by ""(""");
+            Scan_Ptr := Scan_Ptr + 1;
+            Token := Tok_Left_Paren;
+            return;
+
+         --  Comma
+
+         when ',' =>
+            Accumulate_Checksum (',');
+            Scan_Ptr := Scan_Ptr + 1;
+            Token := Tok_Comma;
+            if Style_Check then Style.Check_Comma; end if;
+            return;
+
+         --  Dot, which is either an isolated period, or part of a double
+         --  dot compound delimiter sequence. We also check for the case of
+         --  a digit following the period, to give a better error message.
+
+         when '.' =>
+            Accumulate_Checksum ('.');
+
+            if Double_Char_Token ('.') then
+               Token := Tok_Dot_Dot;
+               if Style_Check then Style.Check_Dot_Dot; end if;
+               return;
+
+            elsif Source (Scan_Ptr + 1) in '0' .. '9' then
+               Error_Msg_S ("numeric literal cannot start with point");
+               Scan_Ptr := Scan_Ptr + 1;
+
+            else
+               Scan_Ptr := Scan_Ptr + 1;
+               Token := Tok_Dot;
+               return;
+            end if;
+
+         --  Equal, which can either be an equality operator, or part of the
+         --  arrow (=>) compound delimiter.
+
+         when '=' =>
+            Accumulate_Checksum ('=');
+
+            if Double_Char_Token ('>') then
+               Token := Tok_Arrow;
+               if Style_Check then Style.Check_Arrow; end if;
+               return;
+
+            elsif Source (Scan_Ptr + 1) = '=' then
+               Error_Msg_S ("== should be =");
+               Scan_Ptr := Scan_Ptr + 1;
+            end if;
+
+            Scan_Ptr := Scan_Ptr + 1;
+            Token := Tok_Equal;
+            return;
+
+         --  Greater than, which can be a greater than operator, greater than
+         --  or equal operator, or first character of a right label bracket.
+
+         when '>' =>
+            Accumulate_Checksum ('>');
+
+            if Double_Char_Token ('=') then
+               Token := Tok_Greater_Equal;
+               return;
+
+            elsif Double_Char_Token ('>') then
+               Token := Tok_Greater_Greater;
+               return;
+
+            else
+               Scan_Ptr := Scan_Ptr + 1;
+               Token := Tok_Greater;
+               return;
+            end if;
+
+         --  Less than, which can be a less than operator, less than or equal
+         --  operator, or the first character of a left label bracket, or the
+         --  first character of a box (<>) compound delimiter.
+
+         when '<' =>
+            Accumulate_Checksum ('<');
+
+            if Double_Char_Token ('=') then
+               Token := Tok_Less_Equal;
+               return;
+
+            elsif Double_Char_Token ('>') then
+               Token := Tok_Box;
+               if Style_Check then Style.Check_Box; end if;
+               return;
+
+            elsif Double_Char_Token ('<') then
+               Token := Tok_Less_Less;
+               return;
+
+            else
+               Scan_Ptr := Scan_Ptr + 1;
+               Token := Tok_Less;
+               return;
+            end if;
+
+         --  Minus, which is either a subtraction operator, or the first
+         --  character of double minus starting a comment
+
+         when '-' => Minus_Case : begin
+            if Source (Scan_Ptr + 1) = '>' then
+               Error_Msg_S ("invalid token");
+               Scan_Ptr := Scan_Ptr + 2;
+               Token := Tok_Arrow;
+               return;
+
+            elsif Source (Scan_Ptr + 1) /= '-' then
+               Accumulate_Checksum ('-');
+               Scan_Ptr := Scan_Ptr + 1;
+               Token := Tok_Minus;
+               return;
+
+            --  Comment
+
+            else -- Source (Scan_Ptr + 1) = '-' then
+               if Style_Check then Style.Check_Comment; end if;
+               Scan_Ptr := Scan_Ptr + 2;
+
+               --  Loop to scan comment (this loop runs more than once only if
+               --  a horizontal tab or other non-graphic character is scanned)
+
+               loop
+                  --  Scan to non graphic character (opened up for speed)
+
+                  loop
+                     exit when Source (Scan_Ptr) not in Graphic_Character;
+                     Scan_Ptr := Scan_Ptr + 1;
+                     exit when Source (Scan_Ptr) not in Graphic_Character;
+                     Scan_Ptr := Scan_Ptr + 1;
+                     exit when Source (Scan_Ptr) not in Graphic_Character;
+                     Scan_Ptr := Scan_Ptr + 1;
+                     exit when Source (Scan_Ptr) not in Graphic_Character;
+                     Scan_Ptr := Scan_Ptr + 1;
+                     exit when Source (Scan_Ptr) not in Graphic_Character;
+                     Scan_Ptr := Scan_Ptr + 1;
+                  end loop;
+
+                  --  Keep going if horizontal tab
+
+                  if Source (Scan_Ptr) = HT then
+                     if Style_Check then Style.Check_HT; end if;
+                     Scan_Ptr := Scan_Ptr + 1;
+
+                  --  Terminate scan of comment if line terminator
+
+                  elsif Source (Scan_Ptr) in Line_Terminator then
+                     exit;
+
+                  --  Terminate scan of comment if end of file encountered
+                  --  (embedded EOF character or real last character in file)
+
+                  elsif Source (Scan_Ptr) = EOF then
+                     exit;
+
+                  --  Keep going if character in 80-FF range, or is ESC. These
+                  --  characters are allowed in comments by RM-2.1(1), 2.7(2).
+                  --  They are allowed even in Ada 83 mode according to the
+                  --  approved AI. ESC was added to the AI in June 93.
+
+                  elsif Source (Scan_Ptr) in Upper_Half_Character
+                    or else Source (Scan_Ptr) = ESC
+                  then
+                     Scan_Ptr := Scan_Ptr + 1;
+
+                  --  Otherwise we have an illegal comment character
+
+                  else
+                     Error_Illegal_Character;
+                  end if;
+
+               end loop;
+
+               --  Note that we do NOT execute a return here, instead we fall
+               --  through to reexecute the scan loop to look for a token.
+
+            end if;
+         end Minus_Case;
+
+         --  Double quote or percent starting a string literal
+
+         when '"' | '%' =>
+            Slit;
+            return;
+
+         --  Apostrophe. This can either be the start of a character literal,
+         --  or an isolated apostrophe used in a qualified expression or an
+         --  attribute. We treat it as a character literal if it does not
+         --  follow a right parenthesis, identifier, the keyword ALL or
+         --  a literal. This means that we correctly treat constructs like:
+
+         --    A := CHARACTER'('A');
+
+         --  Note that RM-2.2(7) does not require a separator between
+         --  "CHARACTER" and "'" in the above.
+
+         when ''' => Char_Literal_Case : declare
+            Code : Char_Code;
+            Err  : Boolean;
+
+         begin
+            Accumulate_Checksum (''');
+            Scan_Ptr := Scan_Ptr + 1;
+
+            --  Here is where we make the test to distinguish the cases. Treat
+            --  as apostrophe if previous token is an identifier, right paren
+            --  or the reserved word "all" (latter case as in A.all'Address)
+            --  Also treat it as apostrophe after a literal (this catches
+            --  some legitimate cases, like A."abs"'Address, and also gives
+            --  better error behavior for impossible cases like 123'xxx).
+
+            if Prev_Token = Tok_Identifier
+               or else Prev_Token = Tok_Right_Paren
+               or else Prev_Token = Tok_All
+               or else Prev_Token in Token_Class_Literal
+            then
+               Token := Tok_Apostrophe;
+               return;
+
+            --  Otherwise the apostrophe starts a character literal
+
+            else
+               --  Case of wide character literal with ESC or [ encoding
+
+               if (Source (Scan_Ptr) = ESC
+                     and then
+                    Wide_Character_Encoding_Method in WC_ESC_Encoding_Method)
+                 or else
+                   (Source (Scan_Ptr) in Upper_Half_Character
+                     and then
+                    Upper_Half_Encoding)
+                 or else
+                   (Source (Scan_Ptr) = '['
+                     and then
+                    Source (Scan_Ptr + 1) = '"')
+               then
+                  Scan_Wide (Source, Scan_Ptr, Code, Err);
+                  Accumulate_Checksum (Code);
+
+                  if Err then
+                     Error_Illegal_Wide_Character;
+                  end if;
+
+                  if Source (Scan_Ptr) /= ''' then
+                     Error_Msg_S ("missing apostrophe");
+                  else
+                     Scan_Ptr := Scan_Ptr + 1;
+                  end if;
+
+               --  If we do not find a closing quote in the expected place then
+               --  assume that we have a misguided attempt at a string literal.
+
+               --  However, if previous token is RANGE, then we return an
+               --  apostrophe instead since this gives better error recovery
+
+               elsif Source (Scan_Ptr + 1) /= ''' then
+
+                  if Prev_Token = Tok_Range then
+                     Token := Tok_Apostrophe;
+                     return;
+
+                  else
+                     Scan_Ptr := Scan_Ptr - 1;
+                     Error_Msg_S
+                       ("strings are delimited by double quote character");
+                     Scn.Slit;
+                     return;
+                  end if;
+
+               --  Otherwise we have a (non-wide) character literal
+
+               else
+                  Accumulate_Checksum (Source (Scan_Ptr));
+
+                  if Source (Scan_Ptr) not in Graphic_Character then
+                     if Source (Scan_Ptr) in Upper_Half_Character then
+                        if Ada_83 then
+                           Error_Illegal_Character;
+                        end if;
+
+                     else
+                        Error_Illegal_Character;
+                     end if;
+                  end if;
+
+                  Code := Get_Char_Code (Source (Scan_Ptr));
+                  Scan_Ptr := Scan_Ptr + 2;
+               end if;
+
+               --  Fall through here with Scan_Ptr updated past the closing
+               --  quote, and Code set to the Char_Code value for the literal
+
+               Accumulate_Checksum (''');
+               Token := Tok_Char_Literal;
+               Token_Node := New_Node (N_Character_Literal, Token_Ptr);
+               Set_Char_Literal_Value (Token_Node, Code);
+               Set_Character_Literal_Name (Code);
+               Token_Name := Name_Find;
+               Set_Chars (Token_Node, Token_Name);
+               return;
+            end if;
+         end Char_Literal_Case;
+
+         --  Right parenthesis
+
+         when ')' =>
+            Accumulate_Checksum (')');
+            Scan_Ptr := Scan_Ptr + 1;
+            Token := Tok_Right_Paren;
+            if Style_Check then Style.Check_Right_Paren; end if;
+            return;
+
+         --  Right bracket or right brace, treated as right paren
+
+         when ']' | '}' =>
+            Error_Msg_S ("illegal character, replaced by "")""");
+            Scan_Ptr := Scan_Ptr + 1;
+            Token := Tok_Right_Paren;
+            return;
+
+         --  Slash (can be division operator or first character of not equal)
+
+         when '/' =>
+            Accumulate_Checksum ('/');
+
+            if Double_Char_Token ('=') then
+               Token := Tok_Not_Equal;
+               return;
+            else
+               Scan_Ptr := Scan_Ptr + 1;
+               Token := Tok_Slash;
+               return;
+            end if;
+
+         --  Semicolon
+
+         when ';' =>
+            Accumulate_Checksum (';');
+            Scan_Ptr := Scan_Ptr + 1;
+            Token := Tok_Semicolon;
+            if Style_Check then Style.Check_Semicolon; end if;
+            return;
+
+         --  Vertical bar
+
+         when '|' => Vertical_Bar_Case : begin
+            Accumulate_Checksum ('|');
+
+            --  Special check for || to give nice message
+
+            if Source (Scan_Ptr + 1) = '|' then
+               Error_Msg_S ("""||"" should be `OR ELSE`");
+               Scan_Ptr := Scan_Ptr + 2;
+               Token := Tok_Or;
+               return;
+
+            else
+               Scan_Ptr := Scan_Ptr + 1;
+               Token := Tok_Vertical_Bar;
+               if Style_Check then Style.Check_Vertical_Bar; end if;
+               return;
+            end if;
+         end Vertical_Bar_Case;
+
+         --  Exclamation, replacement character for vertical bar
+
+         when '!' => Exclamation_Case : begin
+            Accumulate_Checksum ('!');
+
+            if Source (Scan_Ptr + 1) = '=' then
+               Error_Msg_S ("'!= should be /=");
+               Scan_Ptr := Scan_Ptr + 2;
+               Token := Tok_Not_Equal;
+               return;
+
+            else
+               Scan_Ptr := Scan_Ptr + 1;
+               Token := Tok_Vertical_Bar;
+               return;
+            end if;
+
+         end Exclamation_Case;
+
+         --  Plus
+
+         when '+' => Plus_Case : begin
+            Accumulate_Checksum ('+');
+            Scan_Ptr := Scan_Ptr + 1;
+            Token := Tok_Plus;
+            return;
+         end Plus_Case;
+
+         --  Digits starting a numeric literal
+
+         when '0' .. '9' =>
+            Nlit;
+
+            if Identifier_Char (Source (Scan_Ptr)) then
+               Error_Msg_S
+                 ("delimiter required between literal and identifier");
+            end if;
+
+            return;
+
+         --  Lower case letters
+
+         when 'a' .. 'z' =>
+            Name_Len := 1;
+            Name_Buffer (1) := Source (Scan_Ptr);
+            Accumulate_Checksum (Name_Buffer (1));
+            Scan_Ptr := Scan_Ptr + 1;
+            goto Scan_Identifier;
+
+         --  Upper case letters
+
+         when 'A' .. 'Z' =>
+            Name_Len := 1;
+            Name_Buffer (1) :=
+              Character'Val (Character'Pos (Source (Scan_Ptr)) + 32);
+            Accumulate_Checksum (Name_Buffer (1));
+            Scan_Ptr := Scan_Ptr + 1;
+            goto Scan_Identifier;
+
+         --  Underline character
+
+         when '_' =>
+            Error_Msg_S ("identifier cannot start with underline");
+            Name_Len := 1;
+            Name_Buffer (1) := '_';
+            Scan_Ptr := Scan_Ptr + 1;
+            goto Scan_Identifier;
+
+         --  Space (not possible, because we scanned past blanks)
+
+         when ' ' =>
+            raise Program_Error;
+
+         --  Characters in top half of ASCII 8-bit chart
+
+         when Upper_Half_Character =>
+
+            --  Wide character case. Note that Scan_Identifier will issue
+            --  an appropriate message if wide characters are not allowed
+            --  in identifiers.
+
+            if Upper_Half_Encoding then
+               Name_Len := 0;
+               goto Scan_Identifier;
+
+            --  Otherwise we have OK Latin-1 character
+
+            else
+               --  Upper half characters may possibly be identifier letters
+               --  but can never be digits, so Identifier_Character can be
+               --  used to test for a valid start of identifier character.
+
+               if Identifier_Char (Source (Scan_Ptr)) then
+                  Name_Len := 0;
+                  goto Scan_Identifier;
+               else
+                  Error_Illegal_Character;
+               end if;
+            end if;
+
+         when ESC =>
+
+            --  ESC character, possible start of identifier if wide characters
+            --  using ESC encoding are allowed in identifiers, which we can
+            --  tell by looking at the Identifier_Char flag for ESC, which is
+            --  only true if these conditions are met.
+
+            if Identifier_Char (ESC) then
+               Name_Len := 0;
+               goto Scan_Identifier;
+            else
+               Error_Illegal_Wide_Character;
+            end if;
+
+         --  Invalid control characters
+
+         when NUL | SOH | STX | ETX | EOT | ENQ | ACK | BEL | BS  | SO  |
+              SI  | DLE | DC1 | DC2 | DC3 | DC4 | NAK | SYN | ETB | CAN |
+              EM  | FS  | GS  | RS  | US  | DEL
+         =>
+            Error_Illegal_Character;
+
+         --  Invalid graphic characters
+
+         when '#' | '$' | '?' | '@' | '`' | '\' | '^' | '~' =>
+            Error_Illegal_Character;
+
+         --  End switch on non-blank character
+
+         end case;
+
+      --  End loop past format effectors. The exit from this loop is by
+      --  executing a return statement following completion of token scan
+      --  (control never falls out of this loop to the code which follows)
+
+      end loop;
+
+      --  Identifier scanning routine. On entry, some initial characters
+      --  of the identifier may have already been stored in Name_Buffer.
+      --  If so, Name_Len has the number of characters stored. otherwise
+      --  Name_Len is set to zero on entry.
+
+      <<Scan_Identifier>>
+
+         --  This loop scans as fast as possible past lower half letters
+         --  and digits, which we expect to be the most common characters.
+
+         loop
+            if Source (Scan_Ptr) in 'a' .. 'z'
+              or else Source (Scan_Ptr) in '0' .. '9'
+            then
+               Name_Buffer (Name_Len + 1) := Source (Scan_Ptr);
+               Accumulate_Checksum (Source (Scan_Ptr));
+
+            elsif Source (Scan_Ptr) in 'A' .. 'Z' then
+               Name_Buffer (Name_Len + 1) :=
+                 Character'Val (Character'Pos (Source (Scan_Ptr)) + 32);
+               Accumulate_Checksum (Name_Buffer (Name_Len + 1));
+            else
+               exit;
+            end if;
+
+            --  Open out the loop a couple of times for speed
+
+            if Source (Scan_Ptr + 1) in 'a' .. 'z'
+              or else Source (Scan_Ptr + 1) in '0' .. '9'
+            then
+               Name_Buffer (Name_Len + 2) := Source (Scan_Ptr + 1);
+               Accumulate_Checksum (Source (Scan_Ptr + 1));
+
+            elsif Source (Scan_Ptr + 1) in 'A' .. 'Z' then
+               Name_Buffer (Name_Len + 2) :=
+                 Character'Val (Character'Pos (Source (Scan_Ptr + 1)) + 32);
+               Accumulate_Checksum (Name_Buffer (Name_Len + 2));
+
+            else
+               Scan_Ptr := Scan_Ptr + 1;
+               Name_Len := Name_Len + 1;
+               exit;
+            end if;
+
+            if Source (Scan_Ptr + 2) in 'a' .. 'z'
+              or else Source (Scan_Ptr + 2) in '0' .. '9'
+            then
+               Name_Buffer (Name_Len + 3) := Source (Scan_Ptr + 2);
+               Accumulate_Checksum (Source (Scan_Ptr + 2));
+
+            elsif Source (Scan_Ptr + 2) in 'A' .. 'Z' then
+               Name_Buffer (Name_Len + 3) :=
+                 Character'Val (Character'Pos (Source (Scan_Ptr + 2)) + 32);
+               Accumulate_Checksum (Name_Buffer (Name_Len + 3));
+            else
+               Scan_Ptr := Scan_Ptr + 2;
+               Name_Len := Name_Len + 2;
+               exit;
+            end if;
+
+            if Source (Scan_Ptr + 3) in 'a' .. 'z'
+              or else Source (Scan_Ptr + 3) in '0' .. '9'
+            then
+               Name_Buffer (Name_Len + 4) := Source (Scan_Ptr + 3);
+               Accumulate_Checksum (Source (Scan_Ptr + 3));
+
+            elsif Source (Scan_Ptr + 3) in 'A' .. 'Z' then
+               Name_Buffer (Name_Len + 4) :=
+                 Character'Val (Character'Pos (Source (Scan_Ptr + 3)) + 32);
+               Accumulate_Checksum (Name_Buffer (Name_Len + 4));
+
+            else
+               Scan_Ptr := Scan_Ptr + 3;
+               Name_Len := Name_Len + 3;
+               exit;
+            end if;
+
+            Scan_Ptr := Scan_Ptr + 4;
+            Name_Len := Name_Len + 4;
+         end loop;
+
+         --  If we fall through, then we have encountered either an underline
+         --  character, or an extended identifier character (i.e. one from the
+         --  upper half), or a wide character, or an identifier terminator.
+         --  The initial test speeds us up in the most common case where we
+         --  have an identifier terminator. Note that ESC is an identifier
+         --  character only if a wide character encoding method that uses
+         --  ESC encoding is active, so if we find an ESC character we know
+         --  that we have a wide character.
+
+         if Identifier_Char (Source (Scan_Ptr)) then
+
+            --  Case of underline, check for error cases of double underline,
+            --  and for a trailing underline character
+
+            if Source (Scan_Ptr) = '_' then
+               Accumulate_Checksum ('_');
+               Name_Len := Name_Len + 1;
+               Name_Buffer (Name_Len) := '_';
+
+               if Identifier_Char (Source (Scan_Ptr + 1)) then
+                  Scan_Ptr := Scan_Ptr + 1;
+
+                  if Source (Scan_Ptr) = '_' then
+                     Error_No_Double_Underline;
+                  end if;
+
+               else
+                  Error_Msg_S ("identifier cannot end with underline");
+                  Scan_Ptr := Scan_Ptr + 1;
+               end if;
+
+               goto Scan_Identifier;
+
+            --  Upper half character
+
+            elsif Source (Scan_Ptr) in Upper_Half_Character
+              and then not Upper_Half_Encoding
+            then
+               Accumulate_Checksum (Source (Scan_Ptr));
+               Store_Encoded_Character
+                 (Get_Char_Code (Fold_Lower (Source (Scan_Ptr))));
+               Scan_Ptr := Scan_Ptr + 1;
+               goto Scan_Identifier;
+
+            --  Left bracket not followed by a quote terminates an identifier.
+            --  This is an error, but we don't want to give a junk error msg
+            --  about wide characters in this case!
+
+            elsif Source (Scan_Ptr) = '['
+              and then Source (Scan_Ptr + 1) /= '"'
+            then
+               null;
+
+            --  We know we have a wide character encoding here (the current
+            --  character is either ESC, left bracket, or an upper half
+            --  character depending on the encoding method).
+
+            else
+               --  Scan out the wide character and insert the appropriate
+               --  encoding into the name table entry for the identifier.
+
+               declare
+                  Sptr : constant Source_Ptr := Scan_Ptr;
+                  Code : Char_Code;
+                  Err  : Boolean;
+
+               begin
+                  Scan_Wide (Source, Scan_Ptr, Code, Err);
+                  Accumulate_Checksum (Code);
+
+                  if Err then
+                     Error_Illegal_Wide_Character;
+                  else
+                     Store_Encoded_Character (Code);
+                  end if;
+
+                  --  Make sure we are allowing wide characters in identifiers.
+                  --  Note that we allow wide character notation for an OK
+                  --  identifier character. This in particular allows bracket
+                  --  or other notation to be used for upper half letters.
+
+                  if Identifier_Character_Set /= 'w'
+                    and then
+                      (not In_Character_Range (Code)
+                         or else
+                       not Identifier_Char (Get_Character (Code)))
+                  then
+                     Error_Msg
+                       ("wide character not allowed in identifier", Sptr);
+                  end if;
+               end;
+
+               goto Scan_Identifier;
+            end if;
+         end if;
+
+         --  Scan of identifier is complete. The identifier is stored in
+         --  Name_Buffer, and Scan_Ptr points past the last character.
+
+         Token_Name := Name_Find;
+
+         --  Here is where we check if it was a keyword
+
+         if Get_Name_Table_Byte (Token_Name) /= 0
+           and then (Ada_95 or else Token_Name not in Ada_95_Reserved_Words)
+         then
+            Token := Token_Type'Val (Get_Name_Table_Byte (Token_Name));
+
+            --  Deal with possible style check for non-lower case keyword,
+            --  but we don't treat ACCESS, DELTA, DIGITS, RANGE as keywords
+            --  for this purpose if they appear as attribute designators.
+            --  Actually we only check the first character for speed.
+
+            if Style_Check
+              and then Source (Token_Ptr) <= 'Z'
+              and then (Prev_Token /= Tok_Apostrophe
+                          or else
+                            (Token /= Tok_Access
+                               and then Token /= Tok_Delta
+                               and then Token /= Tok_Digits
+                               and then Token /= Tok_Range))
+            then
+               Style.Non_Lower_Case_Keyword;
+            end if;
+
+            --  We must reset Token_Name since this is not an identifier
+            --  and if we leave Token_Name set, the parser gets confused
+            --  because it thinks it is dealing with an identifier instead
+            --  of the corresponding keyword.
+
+            Token_Name := No_Name;
+            return;
+
+         --  It is an identifier after all
+
+         else
+            Token_Node := New_Node (N_Identifier, Token_Ptr);
+            Set_Chars (Token_Node, Token_Name);
+            Token := Tok_Identifier;
+            return;
+         end if;
+   end Scan;
+
+   ---------------------
+   -- Scan_First_Char --
+   ---------------------
+
+   function Scan_First_Char return Source_Ptr is
+      Ptr : Source_Ptr := Current_Line_Start;
+
+   begin
+      loop
+         if Source (Ptr) = ' ' then
+            Ptr := Ptr + 1;
+
+         elsif Source (Ptr) = HT then
+            if Style_Check then Style.Check_HT; end if;
+            Ptr := Ptr + 1;
+
+         else
+            return Ptr;
+         end if;
+      end loop;
+   end Scan_First_Char;
+
+   ------------------------------
+   -- Scan_Reserved_Identifier --
+   ------------------------------
+
+   procedure Scan_Reserved_Identifier (Force_Msg : Boolean) is
+      Token_Chars : constant String := Token_Type'Image (Token);
+
+   begin
+      --  We have in Token_Chars the image of the Token name, i.e. Tok_xxx.
+      --  This code extracts the xxx and makes an identifier out of it.
+
+      Name_Len := 0;
+
+      for J in 5 .. Token_Chars'Length loop
+         Name_Len := Name_Len + 1;
+         Name_Buffer (Name_Len) := Fold_Lower (Token_Chars (J));
+      end loop;
+
+      Token_Name := Name_Find;
+
+      if not Used_As_Identifier (Token) or else Force_Msg then
+         Error_Msg_Name_1 := Token_Name;
+         Error_Msg_SC ("reserved word* cannot be used as identifier!");
+         Used_As_Identifier (Token) := True;
+      end if;
+
+      Token := Tok_Identifier;
+      Token_Node := New_Node (N_Identifier, Token_Ptr);
+      Set_Chars (Token_Node, Token_Name);
+   end Scan_Reserved_Identifier;
+
+   ----------------------
+   -- Set_Start_Column --
+   ----------------------
+
+   --  Note: it seems at first glance a little expensive to compute this value
+   --  for every source line (since it is certainly not used for all source
+   --  lines). On the other hand, it doesn't take much more work to skip past
+   --  the initial white space on the line counting the columns than it would
+   --  to scan past the white space using the standard scanning circuits.
+
+   function Set_Start_Column return Column_Number is
+      Start_Column : Column_Number := 0;
+
+   begin
+      --  Outer loop scans past horizontal tab characters
+
+      Tabs_Loop : loop
+
+         --  Inner loop scans past blanks as fast as possible, bumping Scan_Ptr
+         --  past the blanks and adjusting Start_Column to account for them.
+
+         Blanks_Loop : loop
+            if Source (Scan_Ptr) = ' ' then
+               if Source (Scan_Ptr + 1) = ' ' then
+                  if Source (Scan_Ptr + 2) = ' ' then
+                     if Source (Scan_Ptr + 3) = ' ' then
+                        if Source (Scan_Ptr + 4) = ' ' then
+                           if Source (Scan_Ptr + 5) = ' ' then
+                              if Source (Scan_Ptr + 6) = ' ' then
+                                 Scan_Ptr := Scan_Ptr + 7;
+                                 Start_Column := Start_Column + 7;
+                              else
+                                 Scan_Ptr := Scan_Ptr + 6;
+                                 Start_Column := Start_Column + 6;
+                                 exit Blanks_Loop;
+                              end if;
+                           else
+                              Scan_Ptr := Scan_Ptr + 5;
+                              Start_Column := Start_Column + 5;
+                              exit Blanks_Loop;
+                           end if;
+                        else
+                           Scan_Ptr := Scan_Ptr + 4;
+                           Start_Column := Start_Column + 4;
+                           exit Blanks_Loop;
+                        end if;
+                     else
+                        Scan_Ptr := Scan_Ptr + 3;
+                        Start_Column := Start_Column + 3;
+                        exit Blanks_Loop;
+                     end if;
+                  else
+                     Scan_Ptr := Scan_Ptr + 2;
+                     Start_Column := Start_Column + 2;
+                     exit Blanks_Loop;
+                  end if;
+               else
+                  Scan_Ptr := Scan_Ptr + 1;
+                  Start_Column := Start_Column + 1;
+                  exit Blanks_Loop;
+               end if;
+            else
+               exit Blanks_Loop;
+            end if;
+         end loop Blanks_Loop;
+
+         --  Outer loop keeps going only if a horizontal tab follows
+
+         if Source (Scan_Ptr) = HT then
+            if Style_Check then Style.Check_HT; end if;
+            Scan_Ptr := Scan_Ptr + 1;
+            Start_Column := (Start_Column / 8) * 8 + 8;
+         else
+            exit Tabs_Loop;
+         end if;
+
+      end loop Tabs_Loop;
+
+      return Start_Column;
+   end Set_Start_Column;
+
+   ----------
+   -- Slit --
+   ----------
+
+   procedure Slit is separate;
+
+end Scn;
diff --git a/gcc/ada/scn.ads b/gcc/ada/scn.ads
new file mode 100644 (file)
index 0000000..1fc5441
--- /dev/null
@@ -0,0 +1,69 @@
+------------------------------------------------------------------------------
+--                                                                          --
+--                         GNAT COMPILER COMPONENTS                         --
+--                                                                          --
+--                                  S C N                                   --
+--                                                                          --
+--                                 S p e c                                  --
+--                                                                          --
+--                            $Revision: 1.19 $
+--                                                                          --
+--          Copyright (C) 1992-2000 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- --
+-- ware  Foundation;  either version 2,  or (at your option) any later ver- --
+-- sion.  GNAT is distributed in the hope that it will be useful, but WITH- --
+-- OUT ANY WARRANTY;  without even the  implied warranty of MERCHANTABILITY --
+-- or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License --
+-- for  more details.  You should have  received  a copy of the GNU General --
+-- Public License  distributed with GNAT;  see file COPYING.  If not, write --
+-- to  the Free Software Foundation,  59 Temple Place - Suite 330,  Boston, --
+-- MA 02111-1307, USA.                                                      --
+--                                                                          --
+-- GNAT was originally developed  by the GNAT team at  New York University. --
+-- It is now maintained by Ada Core Technologies Inc (http://www.gnat.com). --
+--                                                                          --
+------------------------------------------------------------------------------
+
+--  This package contains the lexical analyzer routines. This is used both
+--  for scanning Ada source files and also for scanning Ada project files.
+
+with Casing; use Casing;
+with Types;  use Types;
+
+package Scn is
+
+   procedure Initialize_Scanner
+     (Unit  : Unit_Number_Type;
+      Index : Source_File_Index);
+   --  Initialize lexical scanner for scanning a new file. The caller has
+   --  completed the construction of the Units.Table entry for the specified
+   --  Unit and Index references the corresponding source file. A special
+   --  case is when Unit = No_Unit_Number, and Index corresponds to the
+   --  source index for reading the configuration pragma file.
+
+   procedure Scan;
+   --  Scan scans out the next token, and advances the scan state accordingly
+   --  (see package Scan_State for details). If the scan encounters an illegal
+   --  token, then an error message is issued pointing to the bad character,
+   --  and Scan returns a reasonable substitute token of some kind.
+
+   function Scan_First_Char return Source_Ptr;
+   --  This routine returns the position in Source of the first non-blank
+   --  character on the current line, used for certain error recovery actions.
+
+   procedure Scan_Reserved_Identifier (Force_Msg : Boolean);
+   --  This procedure is called to convert the current token, which the caller
+   --  has checked is for a reserved word, to an equivalent identifier. This is
+   --  of course only used in error situations where the parser can detect that
+   --  a reserved word is being used as an identifier. An appropriate error
+   --  message, pointing to the token, is also issued if either this is the
+   --  first occurrence of misuse of this identifier, or if Force_Msg is True.
+
+   function Determine_Token_Casing return Casing_Type;
+   pragma Inline (Determine_Token_Casing);
+   --  Determines the casing style of the current token, which is
+   --  either a keyword or an identifier. See also package Casing.
+
+end Scn;
diff --git a/gcc/ada/sdefault.ads b/gcc/ada/sdefault.ads
new file mode 100644 (file)
index 0000000..7d4cbc1
--- /dev/null
@@ -0,0 +1,40 @@
+------------------------------------------------------------------------------
+--                                                                          --
+--                         GNAT COMPILER COMPONENTS                         --
+--                                                                          --
+--                             S D E F A U L T                              --
+--                                                                          --
+--                                 S p e c                                  --
+--                                                                          --
+--                            $Revision: 1.8 $                              --
+--                                                                          --
+--          Copyright (C) 1992-1999 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- --
+-- ware  Foundation;  either version 2,  or (at your option) any later ver- --
+-- sion.  GNAT is distributed in the hope that it will be useful, but WITH- --
+-- OUT ANY WARRANTY;  without even the  implied warranty of MERCHANTABILITY --
+-- or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License --
+-- for  more details.  You should have  received  a copy of the GNU General --
+-- Public License  distributed with GNAT;  see file COPYING.  If not, write --
+-- to  the Free Software Foundation,  59 Temple Place - Suite 330,  Boston, --
+-- MA 02111-1307, USA.                                                      --
+--                                                                          --
+-- GNAT was originally developed  by the GNAT team at  New York University. --
+-- It is now maintained by Ada Core Technologies Inc (http://www.gnat.com). --
+--                                                                          --
+------------------------------------------------------------------------------
+
+with Types; use Types;
+package Sdefault is
+
+   --  This package contains functions that return the default values for
+   --  the include and object file directories, target name, and the default
+   --  library subdirectory (libsubdir) prefix.
+
+   function Include_Dir_Default_Name return String_Ptr;
+   function Object_Dir_Default_Name return String_Ptr;
+   function Target_Name return String_Ptr;
+   function Search_Dir_Prefix return String_Ptr;
+end Sdefault;
diff --git a/gcc/ada/sem.adb b/gcc/ada/sem.adb
new file mode 100644 (file)
index 0000000..1eb315d
--- /dev/null
@@ -0,0 +1,1184 @@
+------------------------------------------------------------------------------
+--                                                                          --
+--                         GNAT COMPILER COMPONENTS                         --
+--                                                                          --
+--                                  S E M                                   --
+--                                                                          --
+--                                 B o d y                                  --
+--                                                                          --
+--                            $Revision: 1.290 $
+--                                                                          --
+--          Copyright (C) 1992-2001, 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- --
+-- ware  Foundation;  either version 2,  or (at your option) any later ver- --
+-- sion.  GNAT is distributed in the hope that it will be useful, but WITH- --
+-- OUT ANY WARRANTY;  without even the  implied warranty of MERCHANTABILITY --
+-- or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License --
+-- for  more details.  You should have  received  a copy of the GNU General --
+-- Public License  distributed with GNAT;  see file COPYING.  If not, write --
+-- to  the Free Software Foundation,  59 Temple Place - Suite 330,  Boston, --
+-- MA 02111-1307, USA.                                                      --
+--                                                                          --
+-- GNAT was originally developed  by the GNAT team at  New York University. --
+-- It is now maintained by Ada Core Technologies Inc (http://www.gnat.com). --
+--                                                                          --
+------------------------------------------------------------------------------
+
+with Atree;    use Atree;
+with Debug;    use Debug;
+with Debug_A;  use Debug_A;
+with Einfo;    use Einfo;
+with Errout;   use Errout;
+with Expander; use Expander;
+with Fname;    use Fname;
+with HLO;      use HLO;
+with Lib;      use Lib;
+with Lib.Load; use Lib.Load;
+with Nlists;   use Nlists;
+with Opt;      use Opt;
+with Sem_Attr; use Sem_Attr;
+with Sem_Ch2;  use Sem_Ch2;
+with Sem_Ch3;  use Sem_Ch3;
+with Sem_Ch4;  use Sem_Ch4;
+with Sem_Ch5;  use Sem_Ch5;
+with Sem_Ch6;  use Sem_Ch6;
+with Sem_Ch7;  use Sem_Ch7;
+with Sem_Ch8;  use Sem_Ch8;
+with Sem_Ch9;  use Sem_Ch9;
+with Sem_Ch10; use Sem_Ch10;
+with Sem_Ch11; use Sem_Ch11;
+with Sem_Ch12; use Sem_Ch12;
+with Sem_Ch13; use Sem_Ch13;
+with Sem_Prag; use Sem_Prag;
+with Sem_Util; use Sem_Util;
+with Sinfo;    use Sinfo;
+with Stand;    use Stand;
+with Uintp;    use Uintp;
+
+pragma Warnings (Off, Sem_Util);
+--  Suppress warnings of unused with for Sem_Util (used only in asserts)
+
+package body Sem is
+
+   Outer_Generic_Scope : Entity_Id := Empty;
+   --  Global reference to the outer scope that is generic. In a non
+   --  generic context, it is empty. At the moment, it is only used
+   --  for avoiding freezing of external references in generics.
+
+   -------------
+   -- Analyze --
+   -------------
+
+   procedure Analyze (N : Node_Id) is
+   begin
+      Debug_A_Entry ("analyzing  ", N);
+
+      --  Immediate return if already analyzed
+
+      if Analyzed (N) then
+         Debug_A_Exit ("analyzing  ", N, "  (done, analyzed already)");
+         return;
+      end if;
+
+      Current_Error_Node := N;
+
+      --  Otherwise processing depends on the node kind
+
+      case Nkind (N) is
+
+         when N_Abort_Statement =>
+            Analyze_Abort_Statement (N);
+
+         when N_Abstract_Subprogram_Declaration =>
+            Analyze_Abstract_Subprogram_Declaration (N);
+
+         when N_Accept_Alternative =>
+            Analyze_Accept_Alternative (N);
+
+         when N_Accept_Statement =>
+            Analyze_Accept_Statement (N);
+
+         when N_Aggregate =>
+            Analyze_Aggregate (N);
+
+         when N_Allocator =>
+            Analyze_Allocator (N);
+
+         when N_And_Then =>
+            Analyze_Short_Circuit (N);
+
+         when N_Assignment_Statement =>
+            Analyze_Assignment (N);
+
+         when N_Asynchronous_Select =>
+            Analyze_Asynchronous_Select (N);
+
+         when N_At_Clause =>
+            Analyze_At_Clause (N);
+
+         when N_Attribute_Reference =>
+            Analyze_Attribute (N);
+
+         when N_Attribute_Definition_Clause   =>
+            Analyze_Attribute_Definition_Clause (N);
+
+         when N_Block_Statement =>
+            Analyze_Block_Statement (N);
+
+         when N_Case_Statement =>
+            Analyze_Case_Statement (N);
+
+         when N_Character_Literal =>
+            Analyze_Character_Literal (N);
+
+         when N_Code_Statement =>
+            Analyze_Code_Statement (N);
+
+         when N_Compilation_Unit =>
+            Analyze_Compilation_Unit (N);
+
+         when N_Component_Declaration =>
+            Analyze_Component_Declaration (N);
+
+         when N_Conditional_Expression =>
+            Analyze_Conditional_Expression (N);
+
+         when N_Conditional_Entry_Call =>
+            Analyze_Conditional_Entry_Call (N);
+
+         when N_Delay_Alternative =>
+            Analyze_Delay_Alternative (N);
+
+         when N_Delay_Relative_Statement =>
+            Analyze_Delay_Relative (N);
+
+         when N_Delay_Until_Statement =>
+            Analyze_Delay_Until (N);
+
+         when N_Entry_Body =>
+            Analyze_Entry_Body (N);
+
+         when N_Entry_Body_Formal_Part =>
+            Analyze_Entry_Body_Formal_Part (N);
+
+         when N_Entry_Call_Alternative =>
+            Analyze_Entry_Call_Alternative (N);
+
+         when N_Entry_Declaration =>
+            Analyze_Entry_Declaration (N);
+
+         when N_Entry_Index_Specification     =>
+            Analyze_Entry_Index_Specification (N);
+
+         when N_Enumeration_Representation_Clause =>
+            Analyze_Enumeration_Representation_Clause (N);
+
+         when N_Exception_Declaration =>
+            Analyze_Exception_Declaration (N);
+
+         when N_Exception_Renaming_Declaration =>
+            Analyze_Exception_Renaming (N);
+
+         when N_Exit_Statement =>
+            Analyze_Exit_Statement (N);
+
+         when N_Expanded_Name =>
+            Analyze_Expanded_Name (N);
+
+         when N_Explicit_Dereference =>
+            Analyze_Explicit_Dereference (N);
+
+         when N_Extension_Aggregate =>
+            Analyze_Aggregate (N);
+
+         when N_Formal_Object_Declaration =>
+            Analyze_Formal_Object_Declaration (N);
+
+         when N_Formal_Package_Declaration =>
+            Analyze_Formal_Package (N);
+
+         when N_Formal_Subprogram_Declaration =>
+            Analyze_Formal_Subprogram (N);
+
+         when N_Formal_Type_Declaration =>
+            Analyze_Formal_Type_Declaration (N);
+
+         when N_Free_Statement =>
+            Analyze_Free_Statement (N);
+
+         when N_Freeze_Entity =>
+            null;  -- no semantic processing required
+
+         when N_Full_Type_Declaration =>
+            Analyze_Type_Declaration (N);
+
+         when N_Function_Call =>
+            Analyze_Function_Call (N);
+
+         when N_Function_Instantiation =>
+            Analyze_Function_Instantiation (N);
+
+         when N_Generic_Function_Renaming_Declaration =>
+            Analyze_Generic_Function_Renaming (N);
+
+         when N_Generic_Package_Declaration =>
+            Analyze_Generic_Package_Declaration (N);
+
+         when N_Generic_Package_Renaming_Declaration =>
+            Analyze_Generic_Package_Renaming (N);
+
+         when N_Generic_Procedure_Renaming_Declaration =>
+            Analyze_Generic_Procedure_Renaming (N);
+
+         when N_Generic_Subprogram_Declaration =>
+            Analyze_Generic_Subprogram_Declaration (N);
+
+         when N_Goto_Statement =>
+            Analyze_Goto_Statement (N);
+
+         when N_Handled_Sequence_Of_Statements =>
+            Analyze_Handled_Statements (N);
+
+         when N_Identifier =>
+            Analyze_Identifier (N);
+
+         when N_If_Statement =>
+            Analyze_If_Statement (N);
+
+         when N_Implicit_Label_Declaration =>
+            Analyze_Implicit_Label_Declaration (N);
+
+         when N_In =>
+            Analyze_Membership_Op (N);
+
+         when N_Incomplete_Type_Declaration =>
+            Analyze_Incomplete_Type_Decl (N);
+
+         when N_Indexed_Component =>
+            Analyze_Indexed_Component_Form (N);
+
+         when N_Integer_Literal =>
+            Analyze_Integer_Literal (N);
+
+         when N_Itype_Reference =>
+            Analyze_Itype_Reference (N);
+
+         when N_Label =>
+            Analyze_Label (N);
+
+         when N_Loop_Statement =>
+            Analyze_Loop_Statement (N);
+
+         when N_Not_In =>
+            Analyze_Membership_Op (N);
+
+         when N_Null =>
+            Analyze_Null (N);
+
+         when N_Null_Statement =>
+            Analyze_Null_Statement (N);
+
+         when N_Number_Declaration =>
+            Analyze_Number_Declaration (N);
+
+         when N_Object_Declaration =>
+            Analyze_Object_Declaration (N);
+
+         when N_Object_Renaming_Declaration  =>
+            Analyze_Object_Renaming (N);
+
+         when N_Operator_Symbol =>
+            Analyze_Operator_Symbol (N);
+
+         when N_Op_Abs =>
+            Analyze_Unary_Op (N);
+
+         when N_Op_Add =>
+            Analyze_Arithmetic_Op (N);
+
+         when N_Op_And =>
+            Analyze_Logical_Op (N);
+
+         when N_Op_Concat =>
+            Analyze_Concatenation (N);
+
+         when N_Op_Divide =>
+            Analyze_Arithmetic_Op (N);
+
+         when N_Op_Eq =>
+            Analyze_Equality_Op (N);
+
+         when N_Op_Expon =>
+            Analyze_Arithmetic_Op (N);
+
+         when N_Op_Ge =>
+            Analyze_Comparison_Op (N);
+
+         when N_Op_Gt =>
+            Analyze_Comparison_Op (N);
+
+         when N_Op_Le =>
+            Analyze_Comparison_Op (N);
+
+         when N_Op_Lt =>
+            Analyze_Comparison_Op (N);
+
+         when N_Op_Minus =>
+            Analyze_Unary_Op (N);
+
+         when N_Op_Mod =>
+            Analyze_Arithmetic_Op (N);
+
+         when N_Op_Multiply =>
+            Analyze_Arithmetic_Op (N);
+
+         when N_Op_Ne =>
+            Analyze_Equality_Op (N);
+
+         when N_Op_Not =>
+            Analyze_Negation (N);
+
+         when N_Op_Or =>
+            Analyze_Logical_Op (N);
+
+         when N_Op_Plus =>
+            Analyze_Unary_Op (N);
+
+         when N_Op_Rem =>
+            Analyze_Arithmetic_Op (N);
+
+         when N_Op_Rotate_Left =>
+            Analyze_Arithmetic_Op (N);
+
+         when N_Op_Rotate_Right =>
+            Analyze_Arithmetic_Op (N);
+
+         when N_Op_Shift_Left =>
+            Analyze_Arithmetic_Op (N);
+
+         when N_Op_Shift_Right =>
+            Analyze_Arithmetic_Op (N);
+
+         when N_Op_Shift_Right_Arithmetic =>
+            Analyze_Arithmetic_Op (N);
+
+         when N_Op_Subtract =>
+            Analyze_Arithmetic_Op (N);
+
+         when N_Op_Xor =>
+            Analyze_Logical_Op (N);
+
+         when N_Or_Else =>
+            Analyze_Short_Circuit (N);
+
+         when N_Others_Choice =>
+            Analyze_Others_Choice (N);
+
+         when N_Package_Body =>
+            Analyze_Package_Body (N);
+
+         when N_Package_Body_Stub =>
+            Analyze_Package_Body_Stub (N);
+
+         when N_Package_Declaration =>
+            Analyze_Package_Declaration (N);
+
+         when N_Package_Instantiation =>
+            Analyze_Package_Instantiation (N);
+
+         when N_Package_Renaming_Declaration =>
+            Analyze_Package_Renaming (N);
+
+         when N_Package_Specification =>
+            Analyze_Package_Specification (N);
+
+         when N_Parameter_Association =>
+            Analyze_Parameter_Association (N);
+
+         when N_Pragma =>
+            Analyze_Pragma (N);
+
+         when N_Private_Extension_Declaration =>
+            Analyze_Private_Extension_Declaration (N);
+
+         when N_Private_Type_Declaration =>
+            Analyze_Private_Type_Declaration (N);
+
+         when N_Procedure_Call_Statement =>
+            Analyze_Procedure_Call (N);
+
+         when N_Procedure_Instantiation =>
+            Analyze_Procedure_Instantiation (N);
+
+         when N_Protected_Body =>
+            Analyze_Protected_Body (N);
+
+         when N_Protected_Body_Stub =>
+            Analyze_Protected_Body_Stub (N);
+
+         when N_Protected_Definition =>
+            Analyze_Protected_Definition (N);
+
+         when N_Protected_Type_Declaration =>
+            Analyze_Protected_Type (N);
+
+         when N_Qualified_Expression =>
+            Analyze_Qualified_Expression (N);
+
+         when N_Raise_Statement =>
+            Analyze_Raise_Statement (N);
+
+         when N_Raise_xxx_Error =>
+            Analyze_Raise_xxx_Error (N);
+
+         when N_Range =>
+            Analyze_Range (N);
+
+         when N_Range_Constraint =>
+            Analyze_Range (Range_Expression (N));
+
+         when N_Real_Literal =>
+            Analyze_Real_Literal (N);
+
+         when N_Record_Representation_Clause =>
+            Analyze_Record_Representation_Clause (N);
+
+         when N_Reference =>
+            Analyze_Reference (N);
+
+         when N_Requeue_Statement =>
+            Analyze_Requeue (N);
+
+         when N_Return_Statement =>
+            Analyze_Return_Statement (N);
+
+         when N_Selected_Component =>
+            Find_Selected_Component (N);
+            --  ??? why not Analyze_Selected_Component, needs comments
+
+         when N_Selective_Accept =>
+            Analyze_Selective_Accept (N);
+
+         when N_Single_Protected_Declaration =>
+            Analyze_Single_Protected (N);
+
+         when N_Single_Task_Declaration =>
+            Analyze_Single_Task (N);
+
+         when N_Slice =>
+            Analyze_Slice (N);
+
+         when N_String_Literal =>
+            Analyze_String_Literal (N);
+
+         when N_Subprogram_Body =>
+            Analyze_Subprogram_Body (N);
+
+         when N_Subprogram_Body_Stub =>
+            Analyze_Subprogram_Body_Stub (N);
+
+         when N_Subprogram_Declaration =>
+            Analyze_Subprogram_Declaration (N);
+
+         when N_Subprogram_Info =>
+            Analyze_Subprogram_Info (N);
+
+         when N_Subprogram_Renaming_Declaration =>
+            Analyze_Subprogram_Renaming (N);
+
+         when N_Subtype_Declaration =>
+            Analyze_Subtype_Declaration (N);
+
+         when N_Subtype_Indication =>
+            Analyze_Subtype_Indication (N);
+
+         when N_Subunit =>
+            Analyze_Subunit (N);
+
+         when N_Task_Body =>
+            Analyze_Task_Body (N);
+
+         when N_Task_Body_Stub =>
+            Analyze_Task_Body_Stub (N);
+
+         when N_Task_Definition =>
+            Analyze_Task_Definition (N);
+
+         when N_Task_Type_Declaration =>
+            Analyze_Task_Type (N);
+
+         when N_Terminate_Alternative =>
+            Analyze_Terminate_Alternative (N);
+
+         when N_Timed_Entry_Call =>
+            Analyze_Timed_Entry_Call (N);
+
+         when N_Triggering_Alternative =>
+            Analyze_Triggering_Alternative (N);
+
+         when N_Type_Conversion =>
+            Analyze_Type_Conversion (N);
+
+         when N_Unchecked_Expression =>
+            Analyze_Unchecked_Expression (N);
+
+         when N_Unchecked_Type_Conversion =>
+            Analyze_Unchecked_Type_Conversion (N);
+
+         when N_Use_Package_Clause =>
+            Analyze_Use_Package (N);
+
+         when N_Use_Type_Clause =>
+            Analyze_Use_Type (N);
+
+         when N_Validate_Unchecked_Conversion =>
+            null;
+
+         when N_Variant_Part =>
+            Analyze_Variant_Part (N);
+
+         when N_With_Clause =>
+            Analyze_With_Clause (N);
+
+         when N_With_Type_Clause =>
+            Analyze_With_Type_Clause (N);
+
+         --  A call to analyze the Empty node is an error, but most likely
+         --  it is an error caused by an attempt to analyze a malformed
+         --  piece of tree caused by some other error, so if there have
+         --  been any other errors, we just ignore it, otherwise it is
+         --  a real internal error which we complain about.
+
+         when N_Empty =>
+            pragma Assert (Errors_Detected /= 0);
+            null;
+
+         --  A call to analyze the error node is simply ignored, to avoid
+         --  causing cascaded errors (happens of course only in error cases)
+
+         when N_Error =>
+            null;
+
+         --  For the remaining node types, we generate compiler abort, because
+         --  these nodes are always analyzed within the Sem_Chn routines and
+         --  there should never be a case of making a call to the main Analyze
+         --  routine for these node kinds. For example, an N_Access_Definition
+         --  node appears only in the context of a type declaration, and is
+         --  processed by the analyze routine for type declarations.
+
+         when
+           N_Abortable_Part                         |
+           N_Access_Definition                      |
+           N_Access_Function_Definition             |
+           N_Access_Procedure_Definition            |
+           N_Access_To_Object_Definition            |
+           N_Case_Statement_Alternative             |
+           N_Compilation_Unit_Aux                   |
+           N_Component_Association                  |
+           N_Component_Clause                       |
+           N_Component_List                         |
+           N_Constrained_Array_Definition           |
+           N_Decimal_Fixed_Point_Definition         |
+           N_Defining_Character_Literal             |
+           N_Defining_Identifier                    |
+           N_Defining_Operator_Symbol               |
+           N_Defining_Program_Unit_Name             |
+           N_Delta_Constraint                       |
+           N_Derived_Type_Definition                |
+           N_Designator                             |
+           N_Digits_Constraint                      |
+           N_Discriminant_Association               |
+           N_Discriminant_Specification             |
+           N_Elsif_Part                             |
+           N_Entry_Call_Statement                   |
+           N_Enumeration_Type_Definition            |
+           N_Exception_Handler                      |
+           N_Floating_Point_Definition              |
+           N_Formal_Decimal_Fixed_Point_Definition  |
+           N_Formal_Derived_Type_Definition         |
+           N_Formal_Discrete_Type_Definition        |
+           N_Formal_Floating_Point_Definition       |
+           N_Formal_Modular_Type_Definition         |
+           N_Formal_Ordinary_Fixed_Point_Definition |
+           N_Formal_Private_Type_Definition         |
+           N_Formal_Signed_Integer_Type_Definition  |
+           N_Function_Specification                 |
+           N_Generic_Association                    |
+           N_Index_Or_Discriminant_Constraint       |
+           N_Iteration_Scheme                       |
+           N_Loop_Parameter_Specification           |
+           N_Mod_Clause                             |
+           N_Modular_Type_Definition                |
+           N_Ordinary_Fixed_Point_Definition        |
+           N_Parameter_Specification                |
+           N_Pragma_Argument_Association            |
+           N_Procedure_Specification                |
+           N_Real_Range_Specification               |
+           N_Record_Definition                      |
+           N_Signed_Integer_Type_Definition         |
+           N_Unconstrained_Array_Definition         |
+           N_Unused_At_Start                        |
+           N_Unused_At_End                          |
+           N_Variant                                =>
+
+            raise Program_Error;
+      end case;
+
+      Debug_A_Exit ("analyzing  ", N, "  (done)");
+
+      --  Now that we have analyzed the node, we call the expander to
+      --  perform possible expansion. This is done only for nodes that
+      --  are not subexpressions, because in the case of subexpressions,
+      --  we don't have the type yet, and the expander will need to know
+      --  the type before it can do its job. For subexpression nodes, the
+      --  call to the expander happens in the Sem_Res.Resolve.
+
+      --  The Analyzed flag is also set at this point for non-subexpression
+      --  nodes (in the case of subexpression nodes, we can't set the flag
+      --  yet, since resolution and expansion have not yet been completed)
+
+      if Nkind (N) not in N_Subexpr then
+         Expand (N);
+      end if;
+
+   end Analyze;
+
+   --  Version with check(s) suppressed
+
+   procedure Analyze (N : Node_Id; Suppress : Check_Id) is
+   begin
+      if Suppress = All_Checks then
+         declare
+            Svg : constant Suppress_Record := Scope_Suppress;
+
+         begin
+            Scope_Suppress := (others => True);
+            Analyze (N);
+            Scope_Suppress := Svg;
+         end;
+
+      else
+         declare
+            Svg : constant Boolean := Get_Scope_Suppress (Suppress);
+
+         begin
+            Set_Scope_Suppress (Suppress, True);
+            Analyze (N);
+            Set_Scope_Suppress (Suppress, Svg);
+         end;
+      end if;
+   end Analyze;
+
+   ------------------
+   -- Analyze_List --
+   ------------------
+
+   procedure Analyze_List (L : List_Id) is
+      Node : Node_Id;
+
+   begin
+      Node := First (L);
+      while Present (Node) loop
+         Analyze (Node);
+         Next (Node);
+      end loop;
+   end Analyze_List;
+
+   --  Version with check(s) suppressed
+
+   procedure Analyze_List (L : List_Id; Suppress : Check_Id) is
+   begin
+      if Suppress = All_Checks then
+         declare
+            Svg : constant Suppress_Record := Scope_Suppress;
+
+         begin
+            Scope_Suppress := (others => True);
+            Analyze_List (L);
+            Scope_Suppress := Svg;
+         end;
+
+      else
+         declare
+            Svg : constant Boolean := Get_Scope_Suppress (Suppress);
+
+         begin
+            Set_Scope_Suppress (Suppress, True);
+            Analyze_List (L);
+            Set_Scope_Suppress (Suppress, Svg);
+         end;
+      end if;
+   end Analyze_List;
+
+   -------------------------
+   -- Enter_Generic_Scope --
+   -------------------------
+
+   procedure Enter_Generic_Scope (S : Entity_Id) is
+   begin
+      if No (Outer_Generic_Scope) then
+         Outer_Generic_Scope := S;
+      end if;
+   end Enter_Generic_Scope;
+
+   ------------------------
+   -- Exit_Generic_Scope --
+   ------------------------
+
+   procedure Exit_Generic_Scope  (S : Entity_Id) is
+   begin
+      if S = Outer_Generic_Scope then
+         Outer_Generic_Scope := Empty;
+      end if;
+   end  Exit_Generic_Scope;
+
+   -----------------------------
+   -- External_Ref_In_Generic --
+   -----------------------------
+
+   function External_Ref_In_Generic (E : Entity_Id) return Boolean is
+   begin
+
+      --  Entity is global if defined outside of current outer_generic_scope:
+      --  Either the entity has a smaller depth that the outer generic, or it
+      --  is in a different compilation unit.
+
+      return Present (Outer_Generic_Scope)
+        and then (Scope_Depth (Scope (E)) < Scope_Depth (Outer_Generic_Scope)
+                   or else not In_Same_Source_Unit (E, Outer_Generic_Scope));
+   end External_Ref_In_Generic;
+
+   ------------------------
+   -- Get_Scope_Suppress --
+   ------------------------
+
+   function Get_Scope_Suppress (C : Check_Id) return Boolean is
+      S : Suppress_Record renames Scope_Suppress;
+
+   begin
+      case C is
+         when Access_Check        => return S.Access_Checks;
+         when Accessibility_Check => return S.Accessibility_Checks;
+         when Discriminant_Check  => return S.Discriminant_Checks;
+         when Division_Check      => return S.Division_Checks;
+         when Elaboration_Check   => return S.Discriminant_Checks;
+         when Index_Check         => return S.Elaboration_Checks;
+         when Length_Check        => return S.Discriminant_Checks;
+         when Overflow_Check      => return S.Overflow_Checks;
+         when Range_Check         => return S.Range_Checks;
+         when Storage_Check       => return S.Storage_Checks;
+         when Tag_Check           => return S.Tag_Checks;
+         when All_Checks =>
+            raise Program_Error;
+      end case;
+   end Get_Scope_Suppress;
+
+   ----------------
+   -- Initialize --
+   ----------------
+
+   procedure Initialize is
+   begin
+      Entity_Suppress.Init;
+      Scope_Stack.Init;
+      Unloaded_Subunits := False;
+   end Initialize;
+
+   ------------------------------
+   -- Insert_After_And_Analyze --
+   ------------------------------
+
+   procedure Insert_After_And_Analyze (N : Node_Id; M : Node_Id) is
+      Node : Node_Id;
+
+   begin
+      if Present (M) then
+
+         --  If we are not at the end of the list, then the easiest
+         --  coding is simply to insert before our successor
+
+         if Present (Next (N)) then
+            Insert_Before_And_Analyze (Next (N), M);
+
+         --  Case of inserting at the end of the list
+
+         else
+            --  Capture the Node_Id of the node to be inserted. This Node_Id
+            --  will still be the same after the insert operation.
+
+            Node := M;
+            Insert_After (N, M);
+
+            --  Now just analyze from the inserted node to the end of
+            --  the new list (note that this properly handles the case
+            --  where any of the analyze calls result in the insertion of
+            --  nodes after the analyzed node, expecting analysis).
+
+            while Present (Node) loop
+               Analyze (Node);
+               Mark_Rewrite_Insertion (Node);
+               Next (Node);
+            end loop;
+         end if;
+      end if;
+
+   end Insert_After_And_Analyze;
+
+   --  Version with check(s) suppressed
+
+   procedure Insert_After_And_Analyze
+     (N : Node_Id; M : Node_Id; Suppress : Check_Id)
+   is
+   begin
+      if Suppress = All_Checks then
+         declare
+            Svg : constant Suppress_Record := Scope_Suppress;
+
+         begin
+            Scope_Suppress := (others => True);
+            Insert_After_And_Analyze (N, M);
+            Scope_Suppress := Svg;
+         end;
+
+      else
+         declare
+            Svg : constant Boolean := Get_Scope_Suppress (Suppress);
+
+         begin
+            Set_Scope_Suppress (Suppress, True);
+            Insert_After_And_Analyze (N, M);
+            Set_Scope_Suppress (Suppress, Svg);
+         end;
+      end if;
+   end Insert_After_And_Analyze;
+
+   -------------------------------
+   -- Insert_Before_And_Analyze --
+   -------------------------------
+
+   procedure Insert_Before_And_Analyze (N : Node_Id; M : Node_Id) is
+      Node : Node_Id;
+
+   begin
+      if Present (M) then
+
+         --  Capture the Node_Id of the first list node to be inserted.
+         --  This will still be the first node after the insert operation,
+         --  since Insert_List_After does not modify the Node_Id values.
+
+         Node := M;
+         Insert_Before (N, M);
+
+         --  The insertion does not change the Id's of any of the nodes in
+         --  the list, and they are still linked, so we can simply loop from
+         --  the original first node until we meet the node before which the
+         --  insertion is occurring. Note that this properly handles the case
+         --  where any of the analyzed nodes insert nodes after themselves,
+         --  expecting them to get analyzed.
+
+         while Node /= N loop
+            Analyze (Node);
+            Mark_Rewrite_Insertion (Node);
+            Next (Node);
+         end loop;
+      end if;
+
+   end Insert_Before_And_Analyze;
+
+   --  Version with check(s) suppressed
+
+   procedure Insert_Before_And_Analyze
+     (N : Node_Id; M : Node_Id; Suppress : Check_Id)
+   is
+   begin
+      if Suppress = All_Checks then
+         declare
+            Svg : constant Suppress_Record := Scope_Suppress;
+
+         begin
+            Scope_Suppress := (others => True);
+            Insert_Before_And_Analyze (N, M);
+            Scope_Suppress := Svg;
+         end;
+
+      else
+         declare
+            Svg : constant Boolean := Get_Scope_Suppress (Suppress);
+
+         begin
+            Set_Scope_Suppress (Suppress, True);
+            Insert_Before_And_Analyze (N, M);
+            Set_Scope_Suppress (Suppress, Svg);
+         end;
+      end if;
+   end Insert_Before_And_Analyze;
+
+   -----------------------------------
+   -- Insert_List_After_And_Analyze --
+   -----------------------------------
+
+   procedure Insert_List_After_And_Analyze (N : Node_Id; L : List_Id) is
+      After : constant Node_Id := Next (N);
+      Node  : Node_Id;
+
+   begin
+      if Is_Non_Empty_List (L) then
+
+         --  Capture the Node_Id of the first list node to be inserted.
+         --  This will still be the first node after the insert operation,
+         --  since Insert_List_After does not modify the Node_Id values.
+
+         Node := First (L);
+         Insert_List_After (N, L);
+
+         --  Now just analyze from the original first node until we get to
+         --  the successor of the original insertion point (which may be
+         --  Empty if the insertion point was at the end of the list). Note
+         --  that this properly handles the case where any of the analyze
+         --  calls result in the insertion of nodes after the analyzed
+         --  node (possibly calling this routine recursively).
+
+         while Node /= After loop
+            Analyze (Node);
+            Mark_Rewrite_Insertion (Node);
+            Next (Node);
+         end loop;
+      end if;
+
+   end Insert_List_After_And_Analyze;
+
+   --  Version with check(s) suppressed
+
+   procedure Insert_List_After_And_Analyze
+     (N : Node_Id; L : List_Id; Suppress : Check_Id)
+   is
+   begin
+      if Suppress = All_Checks then
+         declare
+            Svg : constant Suppress_Record := Scope_Suppress;
+
+         begin
+            Scope_Suppress := (others => True);
+            Insert_List_After_And_Analyze (N, L);
+            Scope_Suppress := Svg;
+         end;
+
+      else
+         declare
+            Svg : constant Boolean := Get_Scope_Suppress (Suppress);
+
+         begin
+            Set_Scope_Suppress (Suppress, True);
+            Insert_List_After_And_Analyze (N, L);
+            Set_Scope_Suppress (Suppress, Svg);
+         end;
+      end if;
+   end Insert_List_After_And_Analyze;
+
+   ------------------------------------
+   -- Insert_List_Before_And_Analyze --
+   ------------------------------------
+
+   procedure Insert_List_Before_And_Analyze (N : Node_Id; L : List_Id) is
+      Node : Node_Id;
+
+   begin
+      if Is_Non_Empty_List (L) then
+
+         --  Capture the Node_Id of the first list node to be inserted.
+         --  This will still be the first node after the insert operation,
+         --  since Insert_List_After does not modify the Node_Id values.
+
+         Node := First (L);
+         Insert_List_Before (N, L);
+
+         --  The insertion does not change the Id's of any of the nodes in
+         --  the list, and they are still linked, so we can simply loop from
+         --  the original first node until we meet the node before which the
+         --  insertion is occurring. Note that this properly handles the case
+         --  where any of the analyzed nodes insert nodes after themselves,
+         --  expecting them to get analyzed.
+
+         while Node /= N loop
+            Analyze (Node);
+            Mark_Rewrite_Insertion (Node);
+            Next (Node);
+         end loop;
+      end if;
+
+   end Insert_List_Before_And_Analyze;
+
+   --  Version with check(s) suppressed
+
+   procedure Insert_List_Before_And_Analyze
+     (N : Node_Id; L : List_Id; Suppress : Check_Id)
+   is
+   begin
+      if Suppress = All_Checks then
+         declare
+            Svg : constant Suppress_Record := Scope_Suppress;
+
+         begin
+            Scope_Suppress := (others => True);
+            Insert_List_Before_And_Analyze (N, L);
+            Scope_Suppress := Svg;
+         end;
+
+      else
+         declare
+            Svg : constant Boolean := Get_Scope_Suppress (Suppress);
+
+         begin
+            Set_Scope_Suppress (Suppress, True);
+            Insert_List_Before_And_Analyze (N, L);
+            Set_Scope_Suppress (Suppress, Svg);
+         end;
+      end if;
+   end Insert_List_Before_And_Analyze;
+
+   ----------
+   -- Lock --
+   ----------
+
+   procedure Lock is
+   begin
+      Entity_Suppress.Locked := True;
+      Scope_Stack.Locked := True;
+      Entity_Suppress.Release;
+      Scope_Stack.Release;
+   end Lock;
+
+   ---------------
+   -- Semantics --
+   ---------------
+
+   procedure Semantics (Comp_Unit : Node_Id) is
+
+      --  The following locations save the corresponding global flags and
+      --  variables so that they can be restored on completion. This is
+      --  needed so that calls to Rtsfind start with the proper default
+      --  values for these variables, and also that such calls do not
+      --  disturb the settings for units being analyzed at a higher level.
+
+      S_Full_Analysis    : constant Boolean          := Full_Analysis;
+      S_In_Default_Expr  : constant Boolean          := In_Default_Expression;
+      S_Inside_A_Generic : constant Boolean          := Inside_A_Generic;
+      S_New_Nodes_OK     : constant Int              := New_Nodes_OK;
+      S_Outer_Gen_Scope  : constant Entity_Id        := Outer_Generic_Scope;
+      S_Sem_Unit         : constant Unit_Number_Type := Current_Sem_Unit;
+
+      Save_Config_Switches : Config_Switches_Type;
+      --  Variable used to save values of config switches while we analyze
+      --  the new unit, to be restored on exit for proper recursive behavior.
+
+      procedure Do_Analyze;
+      --  Procedure to analyze the compilation unit. This is called more
+      --  than once when the high level optimizer is activated.
+
+      procedure Do_Analyze is
+      begin
+         Save_Scope_Stack;
+         New_Scope (Standard_Standard);
+         Scope_Suppress := Suppress_Options;
+         Scope_Stack.Table
+           (Scope_Stack.Last).Component_Alignment_Default := Calign_Default;
+         Scope_Stack.Table
+           (Scope_Stack.Last).Is_Active_Stack_Base := True;
+         Outer_Generic_Scope := Empty;
+
+         --  Now analyze the top level compilation unit node
+
+         Analyze (Comp_Unit);
+
+         --  Check for scope mismatch on exit from compilation
+
+         pragma Assert (Current_Scope = Standard_Standard
+                          or else Comp_Unit = Cunit (Main_Unit));
+
+         --  Then pop entry for Standard, and pop implicit types
+
+         Pop_Scope;
+         Restore_Scope_Stack;
+      end Do_Analyze;
+
+   --  Start of processing for Sem
+
+   begin
+      Compiler_State        := Analyzing;
+      Current_Sem_Unit      := Get_Cunit_Unit_Number (Comp_Unit);
+
+      Expander_Mode_Save_And_Set
+        (Operating_Mode = Generate_Code or Debug_Flag_X);
+
+      Full_Analysis         := True;
+      Inside_A_Generic      := False;
+      In_Default_Expression := False;
+
+      Set_Comes_From_Source_Default (False);
+      Save_Opt_Config_Switches (Save_Config_Switches);
+      Set_Opt_Config_Switches
+        (Is_Internal_File_Name (Unit_File_Name (Current_Sem_Unit)));
+
+      --  Only do analysis of unit that has not already been analyzed
+
+      if not Analyzed (Comp_Unit) then
+         Initialize_Version (Current_Sem_Unit);
+         if HLO_Active then
+            Expander_Mode_Save_And_Set (False);
+            New_Nodes_OK := 1;
+            Do_Analyze;
+            Reset_Analyzed_Flags (Comp_Unit);
+            Expander_Mode_Restore;
+            High_Level_Optimize (Comp_Unit);
+            New_Nodes_OK := 0;
+         end if;
+
+         Do_Analyze;
+      end if;
+
+      --  Save indication of dynamic elaboration checks for ALI file
+
+      Set_Dynamic_Elab (Current_Sem_Unit, Dynamic_Elaboration_Checks);
+
+      --  Restore settings of saved switches to entry values
+
+      Current_Sem_Unit       := S_Sem_Unit;
+      Full_Analysis          := S_Full_Analysis;
+      In_Default_Expression  := S_In_Default_Expr;
+      Inside_A_Generic       := S_Inside_A_Generic;
+      New_Nodes_OK           := S_New_Nodes_OK;
+      Outer_Generic_Scope    := S_Outer_Gen_Scope;
+
+      Restore_Opt_Config_Switches (Save_Config_Switches);
+      Expander_Mode_Restore;
+
+   end Semantics;
+
+   ------------------------
+   -- Set_Scope_Suppress --
+   ------------------------
+
+   procedure Set_Scope_Suppress (C : Check_Id; B : Boolean) is
+      S : Suppress_Record renames Scope_Suppress;
+
+   begin
+      case C is
+         when Access_Check        => S.Access_Checks        := B;
+         when Accessibility_Check => S.Accessibility_Checks := B;
+         when Discriminant_Check  => S.Discriminant_Checks  := B;
+         when Division_Check      => S.Division_Checks      := B;
+         when Elaboration_Check   => S.Discriminant_Checks  := B;
+         when Index_Check         => S.Elaboration_Checks   := B;
+         when Length_Check        => S.Discriminant_Checks  := B;
+         when Overflow_Check      => S.Overflow_Checks      := B;
+         when Range_Check         => S.Range_Checks         := B;
+         when Storage_Check       => S.Storage_Checks       := B;
+         when Tag_Check           => S.Tag_Checks           := B;
+         when All_Checks =>
+            raise Program_Error;
+      end case;
+   end Set_Scope_Suppress;
+
+end Sem;
diff --git a/gcc/ada/sem.ads b/gcc/ada/sem.ads
new file mode 100644 (file)
index 0000000..a887616
--- /dev/null
@@ -0,0 +1,492 @@
+------------------------------------------------------------------------------
+--                                                                          --
+--                         GNAT COMPILER COMPONENTS                         --
+--                                                                          --
+--                                  S E M                                   --
+--                                                                          --
+--                                 S p e c                                  --
+--                                                                          --
+--                            $Revision: 1.101 $
+--                                                                          --
+--          Copyright (C) 1992-2001 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- --
+-- ware  Foundation;  either version 2,  or (at your option) any later ver- --
+-- sion.  GNAT is distributed in the hope that it will be useful, but WITH- --
+-- OUT ANY WARRANTY;  without even the  implied warranty of MERCHANTABILITY --
+-- or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License --
+-- for  more details.  You should have  received  a copy of the GNU General --
+-- Public License  distributed with GNAT;  see file COPYING.  If not, write --
+-- to  the Free Software Foundation,  59 Temple Place - Suite 330,  Boston, --
+-- MA 02111-1307, USA.                                                      --
+--                                                                          --
+-- GNAT was originally developed  by the GNAT team at  New York University. --
+-- It is now maintained by Ada Core Technologies Inc (http://www.gnat.com). --
+--                                                                          --
+------------------------------------------------------------------------------
+
+--------------------------------------
+-- Semantic Analysis: General Model --
+--------------------------------------
+
+--  Semantic processing involves 3 phases which are highly interwined
+--  (ie mutually recursive):
+--
+--    Analysis     implements the bulk of semantic analysis such as
+--                 name analysis and type resolution for declarations,
+--                 instructions and expressions.  The main routine
+--                 driving this process is procedure Analyze given below.
+--                 This analysis phase is really a bottom up pass that is
+--                 achieved during the recursive traversal performed by the
+--                 Analyze_... procedures implemented in the sem_* packages.
+--                 For expressions this phase determines unambiguous types
+--                 and collects sets of possible types where the
+--                 interpretation is potentially ambiguous.
+--
+--    Resolution   is carried out only for expressions to finish type
+--                 resolution that was initiated but not necessarily
+--                 completed during analysis (because of overloading
+--                 ambiguities). Specifically, after completing the bottom
+--                 up pass carried out during analysis for expressions, the
+--                 Resolve routine (see the spec of sem_res for more info)
+--                 is called to perform a top down resolution with
+--                 recursive calls to itself to resolve operands.
+--
+--    Expansion    if we are not generating code this phase is a no-op.
+--                 otherwise this phase expands, ie transforms, original
+--                 declaration, expressions or instructions into simpler
+--                 structures that can be handled by the back-end. This
+--                 phase is also in charge of generating code which is
+--                 implicit in the original source (for instance for
+--                 default initializations, controlled types, etc.)
+--                 There are two separate instances where expansion is
+--                 invoked. For declarations and instructions, expansion is
+--                 invoked just after analysis since no resolution needs
+--                 to be performed. For expressions, expansion is done just
+--                 after resolution. In both cases expansion is done from the
+--                 bottom up just before the end of Analyze for instructions
+--                 and declarations or the call to Resolve for expressions.
+--                 The main routine driving expansion is Expand.
+--                 See the spec of Expander for more details.
+--
+--  To summarize, in normal code generation mode we recursively traverse the
+--  abstract syntax tree top-down performing semantic analysis bottom
+--  up. For instructions and declarations, before the call to the Analyze
+--  routine completes we perform expansion since at that point we have all
+--  semantic information needed. For expression nodes, after the call to
+--  Analysis terminates we invoke the Resolve routine to transmit top-down
+--  the type that was gathered by Analyze which will resolve possible
+--  ambiguities in the expression. Just before the call to Resolve
+--  terminates, the expression can be expanded since all the semantic
+--  information is available at that point.
+--
+--  If we are not generating code then the expansion phase is a no-op.
+--
+--  When generating code there are a number of exceptions to the basic
+--  Analysis-Resolution-Expansion model for expressions. The most prominent
+--  examples are the handling of default expressions and aggregates.
+
+-------------------------------------
+-- Handling of Default Expressions --
+-------------------------------------
+
+--  The default expressions in component declarations and in procedure
+--  specifications (but not the ones in object declarations) are quite
+--  tricky to handle. The problem is that some processing is required
+--  at the point where the expression appears:
+--
+--    visibility analysis (including user defined operators)
+--    freezing of static expressions
+--
+--  but other processing must be deferred until the enclosing entity
+--  (record or procedure specification) is frozen:
+--
+--    freezing of any other types in the expression
+--    expansion
+--
+--  Expansion has to be deferred since you can't generate code for
+--  expressions that refernce types that have not been frozen yet. As an
+--  example, consider the following:
+--
+--      type x is delta 0.5 range -10.0 .. +10.0;
+--      ...
+--      type q is record
+--        xx : x := y * z;
+--      end record;
+--
+--      for x'small use 0.25
+--
+--  The expander is in charge of dealing with fixed-point, and of course
+--  the small declaration, which is not too late, since the declaration of
+--  type q does *not* freeze type x, definitely affects the expanded code.
+--
+--  Generally our model is to combine analysis resolution and expansion, but
+--  this is the one case where this model falls down. Here is how we patch
+--  it up without causing too much distortion to our basic model.
+--
+--  A switch (sede below) is set to indicate that we are in the initial
+--  occurence of a default expression. The analyzer is then called on this
+--  expression with the switch set true. Analysis and resolution proceed
+--  almost as usual, except that Freeze_Expression will not freeze
+--  non-static expressions if this switch is set, and the call to Expand at
+--  the end of resolution is skipped. This also skips the code that normally
+--  sets the Analyzed flag to True). The result is that when we are done the
+--  tree is still marked as unanalyzed, but all types for static expressions
+--  are frozen as required, and all entities of variables have been
+--  recorded.  We then turn off the switch, and later on reanalyze the
+--  expression with the switch off. The effect is that this second analysis
+--  freezes the rest of the types as required, and generates code but
+--  visibility analysis is not repeated since all the entities are marked.
+--
+--  The second analysis (the one that generates code) is in the context
+--  where the code is required. For a record field default, this is in
+--  the initialization procedure for the record and for a subprogram
+--  default parameter, it is at the point the subprogram is frozen.
+
+------------------
+-- Pre-Analysis --
+------------------
+
+--  For certain kind of expressions, such as aggregates, we need to defer
+--  expansion of the aggregate and its inner expressions after the whole
+--  set of expressions appearing inside the aggregate have been analyzed.
+--  Consider, for instance the following example:
+--
+--     (1 .. 100 => new Thing (Function_Call))
+--
+--  The normal Analysis-Resolution-Expansion mechanism where expansion
+--  of the children is performed before expansion of the parent does not
+--  work if the code generated for the children by the expander needs
+--  to be evaluated repeatdly (for instance in the above aggregate
+--  "new Thing (Function_Call)" needs to be called 100 times.)
+--  The reason why this mecanism does not work is that, the expanded code
+--  for the children is typically inserted above the parent and thus
+--  when the father gets expanded no re-evaluation takes place. For instance
+--  in the case of aggregates if "new Thing (Function_Call)" is expanded
+--  before of the aggregate the expanded code will be placed outside
+--  of the aggregate and when expanding the aggregate the loop from 1 to 100
+--  will not surround the expanded code for "new Thing (Function_Call)".
+--
+--  To remedy this situation we introduce a new flag which signals whether
+--  we want a full analysis (ie expansion is enabled) or a pre-analysis
+--  which performs Analysis and Resolution but no expansion.
+--
+--  After the complete pre-analysis of an expression has been carried out
+--  we can transform the expression and then carry out the full
+--  Analyze-Resolve-Expand cycle on the transformed expression top-down
+--  so that the expansion of inner expressions happens inside the newly
+--  generated node for the parent expression.
+--
+--  Note that the difference between processing of default expressions and
+--  pre-analysis of other expressions is that we do carry out freezing in
+--  the latter but not in the former (except for static scalar expressions).
+--  The routine that performs pre-analysis is called Pre_Analyze_And_Resolve
+--  and is in Sem_Res.
+
+with Alloc;
+with Einfo;  use Einfo;
+with Opt;    use Opt;
+with Snames; use Snames;
+with Table;
+with Types;  use Types;
+
+package Sem is
+
+   New_Nodes_OK : Int := 1;
+   --  Temporary flag for use in checking out HLO. Set non-zero if it is
+   --  OK to generate new nodes.
+
+   -----------------------------
+   -- Semantic Analysis Flags --
+   -----------------------------
+
+   Full_Analysis : Boolean := True;
+   --  Switch to indicate whether we are doing a full analysis or a
+   --  pre-analysis. In normal analysis mode (Analysis-Expansion for
+   --  instructions or declarations) or (Analysis-Resolution-Expansion for
+   --  expressions) this flag is set. Note that if we are not generating
+   --  code the expansion phase merely sets the Analyzed flag to True in
+   --  this case. If we are in Pre-Analysis mode (see above) this flag is
+   --  set to False then the expansion phase is skipped.
+   --  When this flag is False the flag Expander_Active is also False
+   --  (the Expander_Activer flag defined in the spec of package Expander
+   --  tells you whether expansion is currently enabled).
+   --  You should really regard this as a read only flag.
+
+   In_Default_Expression : Boolean := False;
+   --  Switch to indicate that we are in a default expression, as described
+   --  above. Note that this must be recursively saved on a Semantics call
+   --  since it is possible for the analysis of an expression to result in
+   --  a recursive call (e.g. to get the entity for System.Address as part
+   --  of the processing of an Address attribute reference).
+   --  When this switch is True then Full_Analysis above must be False.
+   --  You should really regard this as a read only flag.
+
+   In_Inlined_Body : Boolean := False;
+   --  Switch to indicate that we are analyzing and resolving an inlined
+   --  body. Type checking is disabled in this context, because types are
+   --  known to be compatible. This avoids problems with private types whose
+   --  full view is derived from private types.
+
+   Inside_A_Generic : Boolean := False;
+   --  This flag is set if we are processing a generic specification,
+   --  generic definition, or generic body. When this flag is True the
+   --  Expander_Active flag is False to disable any code expansion (see
+   --  package Expander). Only the generic processing can modify the
+   --  status of this flag, any other client should regard it as read-only.
+
+   Unloaded_Subunits : Boolean := False;
+   --  This flag is set True if we have subunits that are not loaded. This
+   --  occurs when the main unit is a subunit, and contains lower level
+   --  subunits that are not loaded. We use this flag to suppress warnings
+   --  about unused variables, since these warnings are unreliable in this
+   --  case. We could perhaps do a more accurate job and retain some of the
+   --  warnings, but it is quite a tricky job. See test 4323-002.
+
+   -----------------
+   -- Scope Stack --
+   -----------------
+
+   Scope_Suppress : Suppress_Record := Suppress_Options;
+   --  This record contains the current scope based settings of the suppress
+   --  switches. It is initialized from the options as shown, and then modified
+   --  by pragma Suppress. On entry to each scope, the current setting is saved
+   --  the scope stack, and then restored on exit from the scope.
+
+   --  The scope stack holds all entries of the scope table. As in the parser,
+   --  we use Last as the stack pointer, so that we can always find the scope
+   --  that is currently open in Scope_Stack.Table (Scope_Stack.Last). The
+   --  oldest entry, at Scope_Stack (0) is Standard. The entries in the table
+   --  include the entity for the referenced scope, together with information
+   --  used to restore the proper setting of check suppressions on scope exit.
+
+   --  There are two kinds of suppress checks, scope based suppress checks
+   --  (from initial command line arguments, or from Suppress pragmas not
+   --  including an entity name). The scope based suppress checks are recorded
+   --  in the Sem.Supress variable, and all that is necessary is to save the
+   --  state of this variable on scope entry, and restore it on scope exit.
+
+   --  The other kind of suppress check is entity based suppress checks, from
+   --  Suppress pragmas giving an Entity_Id. These checks are reflected by the
+   --  appropriate bit being set in the corresponding entity, and restoring the
+   --  setting of these bits is a little trickier. In particular a given pragma
+   --  Suppress may or may not affect the current state. If it sets a check for
+   --  an entity that is already checked, then it is important that this check
+   --  not be restored on scope exit. The situation is made more complicated
+   --  by the fact that a given suppress pragma can specify multiple entities
+   --  (in the overloaded case), and multiple checks (by using All_Checks), so
+   --  that it may be partially effective. On exit only checks that were in
+   --  fact effective must be removed. Logically we could do this by saving
+   --  the entire state of the entity flags on scope entry and restoring them
+   --  on scope exit, but that would be ludicrous, so what we do instead is to
+   --  maintain the following differential structure that shows what checks
+   --  were installed for the current scope.
+
+   --  Note: Suppress pragmas that specify entities defined in a package
+   --  spec do not make entries in this table, since such checks suppress
+   --  requests are valid for the entire life of the entity.
+
+   type Entity_Check_Suppress_Record is record
+      Entity : Entity_Id;
+      --  Entity to which the check applies
+
+      Check : Check_Id;
+      --  Check which is set (note this cannot be All_Checks, if the All_Checks
+      --  case, a sequence of eentries appears for the individual checks.
+   end record;
+
+   --  Entity_Suppress is a stack, to which new entries are added as they
+   --  are processed (see pragma Suppress circuit in Sem_Prag). The scope
+   --  stack entry simply saves the stack pointer on entry, and restores
+   --  it on exit by reversing the checks one by one.
+
+   package Entity_Suppress is new Table.Table (
+     Table_Component_Type => Entity_Check_Suppress_Record,
+     Table_Index_Type     => Int,
+     Table_Low_Bound      => 0,
+     Table_Initial        => Alloc.Entity_Suppress_Initial,
+     Table_Increment      => Alloc.Entity_Suppress_Increment,
+     Table_Name           => "Entity_Suppress");
+
+   --  Here is the scope stack itself
+
+   type Scope_Stack_Entry is record
+      Entity : Entity_Id;
+      --  Entity representing the scope
+
+      Last_Subprogram_Name : String_Ptr;
+      --  Pointer to name of last subprogram body in this scope. Used for
+      --  testing proper alpha ordering of subprogram bodies in scope.
+
+      Save_Scope_Suppress  : Suppress_Record;
+      --  Save contents of Scope_Suppress on entry
+
+      Save_Entity_Suppress : Int;
+      --  Save contents of Entity_Suppress.Last on entry
+
+      Is_Transient : Boolean;
+      --  Marks Transient Scopes (See Exp_Ch7 body for details)
+
+      Previous_Visibility : Boolean;
+      --  Used when installing the parent (s) of the current compilation
+      --  unit. The parent may already be visible because of an ongoing
+      --  compilation, and the proper visibility must be restored on exit.
+
+      Node_To_Be_Wrapped : Node_Id;
+      --  Only used in transient scopes. Records the node which will
+      --  be wrapped by the transient block.
+
+      Actions_To_Be_Wrapped_Before : List_Id;
+      Actions_To_Be_Wrapped_After  : List_Id;
+      --  Actions that have to be inserted at the start or at the end of a
+      --  transient block. Used to temporarily hold these actions until the
+      --  block is created, at which time the actions are moved to the
+      --  block.
+
+      Pending_Freeze_Actions : List_Id;
+      --  Used to collect freeze entity nodes and associated actions that
+      --  are generated in a inner context but need to be analyzed outside,
+      --  such as records and initialization procedures. On exit from the
+      --  scope, this list of actions is inserted before the scope construct
+      --  and analyzed to generate the corresponding freeze processing and
+      --  elaboration of other associated actions.
+
+      First_Use_Clause : Node_Id;
+      --  Head of list of Use_Clauses in current scope. The list is built
+      --  when the declarations in the scope are processed. The list is
+      --  traversed on scope exit to undo the effect of the use clauses.
+
+      Component_Alignment_Default : Component_Alignment_Kind;
+      --  Component alignment to be applied to any record or array types
+      --  that are declared for which a specific component alignment pragma
+      --  does not set the alignment.
+
+      Is_Active_Stack_Base : Boolean;
+      --  Set to true only when entering the scope for Standard_Standard from
+      --  from within procedure Semantics. Indicates the base of the current
+      --  active set of scopes. Needed by In_Open_Scopes to handle cases
+      --  where Standard_Standard can be pushed in the middle of the active
+      --  set of scopes (occurs for instantiations of generic child units).
+   end record;
+
+   package Scope_Stack is new Table.Table (
+     Table_Component_Type => Scope_Stack_Entry,
+     Table_Index_Type     => Int,
+     Table_Low_Bound      => 0,
+     Table_Initial        => Alloc.Scope_Stack_Initial,
+     Table_Increment      => Alloc.Scope_Stack_Increment,
+     Table_Name           => "Sem.Scope_Stack");
+
+   function Get_Scope_Suppress (C : Check_Id) return Boolean;
+   --  Get suppress status of check C for the current scope
+
+   procedure Set_Scope_Suppress (C : Check_Id; B : Boolean);
+   --  Set suppress status of check C for the current scope
+
+   -----------------
+   -- Subprograms --
+   -----------------
+
+   procedure Initialize;
+   --  Initialize internal tables
+
+   procedure Lock;
+   --  Lock internal tables before calling back end
+
+   procedure Semantics (Comp_Unit : Node_Id);
+   --  This procedure is called to perform semantic analysis on the specified
+   --  node which is the N_Compilation_Unit node for the unit.
+
+   procedure Analyze (N : Node_Id);
+   procedure Analyze (N : Node_Id; Suppress : Check_Id);
+   --  This is the recursive procedure which is applied to individual nodes
+   --  of the tree, starting at the top level node (compilation unit node)
+   --  and then moving down the tree in a top down traversal. It calls
+   --  individual routines with names Analyze_xxx to analyze node xxx. Each
+   --  of these routines is responsible for calling Analyze on the components
+   --  of the subtree.
+   --
+   --  Note: In the case of expression components (nodes whose Nkind is in
+   --  N_Subexpr), the call to Analyze does not complete the semantic analysis
+   --  of the node, since the type resolution cannot be completed until the
+   --  complete context is analyzed. The completion of the type analysis occurs
+   --  in the corresponding Resolve routine (see Sem_Res).
+   --
+   --  Note: for integer and real literals, the analyzer sets the flag to
+   --  indicate that the result is a static expression. If the expander
+   --  generates a literal that does NOT correspond to a static expression,
+   --  e.g. by folding an expression whose value is known at compile-time,
+   --  but is not technically static, then the caller should reset the
+   --  Is_Static_Expression flag after analyzing but before resolving.
+   --
+   --  If the Suppress argument is present, then the analysis is done
+   --  with the specified check suppressed (can be All_Checks to suppress
+   --  all checks).
+
+   procedure Analyze_List (L : List_Id);
+   procedure Analyze_List (L : List_Id; Suppress : Check_Id);
+   --  Analyzes each element of a list. If the Suppress argument is present,
+   --  then the analysis is done with the specified check suppressed (can
+   --  be All_Checks to suppress all checks).
+
+   procedure Insert_List_After_And_Analyze
+     (N : Node_Id; L : List_Id);
+   procedure Insert_List_After_And_Analyze
+     (N : Node_Id; L : List_Id; Suppress : Check_Id);
+   --  Inserts list L after node N using Nlists.Insert_List_After, and then,
+   --  after this insertion is complete, analyzes all the nodes in the list,
+   --  including any additional nodes generated by this analysis. If the list
+   --  is empty or be No_List, the call has no effect. If the Suppress
+   --  argument is present, then the analysis is done with the specified
+   --  check suppressed (can be All_Checks to suppress all checks).
+
+   procedure Insert_List_Before_And_Analyze
+     (N : Node_Id; L : List_Id);
+   procedure Insert_List_Before_And_Analyze
+     (N : Node_Id; L : List_Id; Suppress : Check_Id);
+   --  Inserts list L before node N using Nlists.Insert_List_Before, and then,
+   --  after this insertion is complete, analyzes all the nodes in the list,
+   --  including any additional nodes generated by this analysis. If the list
+   --  is empty or be No_List, the call has no effect. If the Suppress
+   --  argument is present, then the analysis is done with the specified
+   --  check suppressed (can be All_Checks to suppress all checks).
+
+   procedure Insert_After_And_Analyze
+     (N : Node_Id; M : Node_Id);
+   procedure Insert_After_And_Analyze
+     (N : Node_Id; M : Node_Id; Suppress : Check_Id);
+   --  Inserts node M after node N and then after the insertion is complete,
+   --  analyzes the inserted node and all nodes that are generated by
+   --  this analysis. If the node is empty, the call has no effect. If the
+   --  Suppress argument is present, then the analysis is done with the
+   --  specified check suppressed (can be All_Checks to suppress all checks).
+
+   procedure Insert_Before_And_Analyze
+     (N : Node_Id; M : Node_Id);
+   procedure Insert_Before_And_Analyze
+     (N : Node_Id; M : Node_Id; Suppress : Check_Id);
+   --  Inserts node M before node N and then after the insertion is complete,
+   --  analyzes the inserted node and all nodes that could be generated by
+   --  this analysis. If the node is empty, the call has no effect. If the
+   --  Suppress argument is present, then the analysis is done with the
+   --  specified check suppressed (can be All_Checks to suppress all checks).
+
+   function External_Ref_In_Generic (E : Entity_Id) return Boolean;
+   --  Return True if we are in the context of a generic and E is
+   --  external (more global) to it.
+
+   procedure Enter_Generic_Scope (S : Entity_Id);
+   --  Shall be called each time a Generic subprogram or package scope is
+   --  entered.  S is the entity of the scope.
+   --  ??? At the moment, only called for package specs because this mechanism
+   --  is only used for avoiding freezing of external references in generics
+   --  and this can only be an issue if the outer generic scope is a package
+   --  spec (otherwise all external entities are already frozen)
+
+   procedure Exit_Generic_Scope  (S : Entity_Id);
+   --  Shall be called each time a Generic subprogram or package scope is
+   --  exited.  S is the entity of the scope.
+   --  ??? At the moment, only called for package specs exit.
+
+end Sem;
diff --git a/gcc/ada/sem_aggr.adb b/gcc/ada/sem_aggr.adb
new file mode 100644 (file)
index 0000000..29778ff
--- /dev/null
@@ -0,0 +1,2848 @@
+------------------------------------------------------------------------------
+--                                                                          --
+--                         GNAT COMPILER COMPONENTS                         --
+--                                                                          --
+--                             S E M _ A G G R                              --
+--                                                                          --
+--                                 B o d y                                  --
+--                                                                          --
+--                            $Revision: 1.232 $
+--                                                                          --
+--          Copyright (C) 1992-2001 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- --
+-- ware  Foundation;  either version 2,  or (at your option) any later ver- --
+-- sion.  GNAT is distributed in the hope that it will be useful, but WITH- --
+-- OUT ANY WARRANTY;  without even the  implied warranty of MERCHANTABILITY --
+-- or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License --
+-- for  more details.  You should have  received  a copy of the GNU General --
+-- Public License  distributed with GNAT;  see file COPYING.  If not, write --
+-- to  the Free Software Foundation,  59 Temple Place - Suite 330,  Boston, --
+-- MA 02111-1307, USA.                                                      --
+--                                                                          --
+-- GNAT was originally developed  by the GNAT team at  New York University. --
+-- It is now maintained by Ada Core Technologies Inc (http://www.gnat.com). --
+--                                                                          --
+------------------------------------------------------------------------------
+
+with Atree;    use Atree;
+with Checks;   use Checks;
+with Einfo;    use Einfo;
+with Elists;   use Elists;
+with Errout;   use Errout;
+with Exp_Util; use Exp_Util;
+with Freeze;   use Freeze;
+with Itypes;   use Itypes;
+with Namet;    use Namet;
+with Nmake;    use Nmake;
+with Nlists;   use Nlists;
+with Opt;      use Opt;
+with Sem;      use Sem;
+with Sem_Cat;  use Sem_Cat;
+with Sem_Ch8;  use Sem_Ch8;
+with Sem_Ch13; use Sem_Ch13;
+with Sem_Eval; use Sem_Eval;
+with Sem_Res;  use Sem_Res;
+with Sem_Util; use Sem_Util;
+with Sem_Type; use Sem_Type;
+with Sinfo;    use Sinfo;
+with Snames;   use Snames;
+with Stringt;  use Stringt;
+with Stand;    use Stand;
+with Tbuild;   use Tbuild;
+with Uintp;    use Uintp;
+
+with GNAT.Spelling_Checker; use GNAT.Spelling_Checker;
+
+package body Sem_Aggr is
+
+   type Case_Bounds is record
+     Choice_Lo   : Node_Id;
+     Choice_Hi   : Node_Id;
+     Choice_Node : Node_Id;
+   end record;
+
+   type Case_Table_Type is array (Nat range <>) of Case_Bounds;
+   --  Table type used by Check_Case_Choices procedure
+
+   -----------------------
+   -- Local Subprograms --
+   -----------------------
+
+   procedure Sort_Case_Table (Case_Table : in out Case_Table_Type);
+   --  Sort the Case Table using the Lower Bound of each Choice as the key.
+   --  A simple insertion sort is used since the number of choices in a case
+   --  statement of variant part will usually be small and probably in near
+   --  sorted order.
+
+   ------------------------------------------------------
+   -- Subprograms used for RECORD AGGREGATE Processing --
+   ------------------------------------------------------
+
+   procedure Resolve_Record_Aggregate (N : Node_Id; Typ : Entity_Id);
+   --  This procedure performs all the semantic checks required for record
+   --  aggregates. Note that for aggregates analysis and resolution go
+   --  hand in hand. Aggregate analysis has been delayed up to here and
+   --  it is done while resolving the aggregate.
+   --
+   --    N is the N_Aggregate node.
+   --    Typ is the record type for the aggregate resolution
+   --
+   --  While performing the semantic checks, this procedure
+   --  builds a new Component_Association_List where each record field
+   --  appears alone in a Component_Choice_List along with its corresponding
+   --  expression. The record fields in the Component_Association_List
+   --  appear in the same order in which they appear in the record type Typ.
+   --
+   --  Once this new Component_Association_List is built and all the
+   --  semantic checks performed, the original aggregate subtree is replaced
+   --  with the new named record aggregate just built. Note that the subtree
+   --  substitution is performed with Rewrite so as to be
+   --  able to retrieve the original aggregate.
+   --
+   --  The aggregate subtree manipulation performed by Resolve_Record_Aggregate
+   --  yields the aggregate format expected by Gigi. Typically, this kind of
+   --  tree manipulations are done in the expander. However, because the
+   --  semantic checks that need to be performed on record aggregates really
+   --  go hand in hand with the record aggreagate normalization, the aggregate
+   --  subtree transformation is performed during resolution rather than
+   --  expansion. Had we decided otherwise we would have had to duplicate
+   --  most of the code in the expansion procedure Expand_Record_Aggregate.
+   --  Note, however, that all the expansion concerning aggegates for tagged
+   --  records is done in Expand_Record_Aggregate.
+   --
+   --  The algorithm of Resolve_Record_Aggregate proceeds as follows:
+   --
+   --  1. Make sure that the record type against which the record aggregate
+   --     has to be resolved is not abstract. Furthermore if the type is
+   --     a null aggregate make sure the input aggregate N is also null.
+   --
+   --  2. Verify that the structure of the aggregate is that of a record
+   --     aggregate. Specifically, look for component associations and ensure
+   --     that each choice list only has identifiers or the N_Others_Choice
+   --     node. Also make sure that if present, the N_Others_Choice occurs
+   --     last and by itself.
+   --
+   --  3. If Typ contains discriminants, the values for each discriminant
+   --     is looked for. If the record type Typ has variants, we check
+   --     that the expressions corresponding to each discriminant ruling
+   --     the (possibly nested) variant parts of Typ, are static. This
+   --     allows us to determine the variant parts to which the rest of
+   --     the aggregate must conform. The names of discriminants with their
+   --     values are saved in a new association list, New_Assoc_List which
+   --     is later augmented with the names and values of the remaining
+   --     components in the record type.
+   --
+   --     During this phase we also make sure that every discriminant is
+   --     assigned exactly one value. Note that when several values
+   --     for a given discriminant are found, semantic processing continues
+   --     looking for further errors. In this case it's the first
+   --     discriminant value found which we will be recorded.
+   --
+   --     IMPORTANT NOTE: For derived tagged types this procedure expects
+   --     First_Discriminant and Next_Discriminant to give the correct list
+   --     of discriminants, in the correct order.
+   --
+   --  4. After all the discriminant values have been gathered, we can
+   --     set the Etype of the record aggregate. If Typ contains no
+   --     discriminants this is straightforward: the Etype of N is just
+   --     Typ, otherwise a new implicit constrained subtype of Typ is
+   --     built to be the Etype of N.
+   --
+   --  5. Gather the remaining record components according to the discriminant
+   --     values. This involves recursively traversing the record type
+   --     structure to see what variants are selected by the given discriminant
+   --     values. This processing is a little more convoluted if Typ is a
+   --     derived tagged types since we need to retrieve the record structure
+   --     of all the ancestors of Typ.
+   --
+   --  6. After gathering the record components we look for their values
+   --     in the record aggregate and emit appropriate error messages
+   --     should we not find such values or should they be duplicated.
+   --
+   --  7. We then make sure no illegal component names appear in the
+   --     record aggegate and make sure that the type of the record
+   --     components appearing in a same choice list is the same.
+   --     Finally we ensure that the others choice, if present, is
+   --     used to provide the value of at least a record component.
+   --
+   --  8. The original aggregate node is replaced with the new named
+   --     aggregate built in steps 3 through 6, as explained earlier.
+   --
+   --  Given the complexity of record aggregate resolution, the primary
+   --  goal of this routine is clarity and simplicity rather than execution
+   --  and storage efficiency. If there are only positional components in the
+   --  aggregate the running time is linear. If there are associations
+   --  the running time is still linear as long as the order of the
+   --  associations is not too far off the order of the components in the
+   --  record type. If this is not the case the running time is at worst
+   --  quadratic in the size of the association list.
+
+   procedure Check_Misspelled_Component
+     (Elements      : Elist_Id;
+      Component     : Node_Id);
+   --  Give possible misspelling diagnostic if Component is likely to be
+   --  a misspelling of one of the components of the Assoc_List.
+   --  This is called by Resolv_Aggr_Expr after producing
+   --  an invalid component error message.
+
+   procedure Check_Static_Discriminated_Subtype (T : Entity_Id; V : Node_Id);
+   --  An optimization: determine whether a discriminated subtype has a
+   --  static constraint, and contains array components whose length is also
+   --  static, either because they are constrained by the discriminant, or
+   --  because the original component bounds are static.
+
+   -----------------------------------------------------
+   -- Subprograms used for ARRAY AGGREGATE Processing --
+   -----------------------------------------------------
+
+   function Resolve_Array_Aggregate
+     (N              : Node_Id;
+      Index          : Node_Id;
+      Index_Constr   : Node_Id;
+      Component_Typ  : Entity_Id;
+      Others_Allowed : Boolean)
+      return           Boolean;
+   --  This procedure performs the semantic checks for an array aggregate.
+   --  True is returned if the aggregate resolution succeeds.
+   --  The procedure works by recursively checking each nested aggregate.
+   --  Specifically, after checking a sub-aggreate nested at the i-th level
+   --  we recursively check all the subaggregates at the i+1-st level (if any).
+   --  Note that for aggregates analysis and resolution go hand in hand.
+   --  Aggregate analysis has been delayed up to here and it is done while
+   --  resolving the aggregate.
+   --
+   --    N is the current N_Aggregate node to be checked.
+   --
+   --    Index is the index node corresponding to the array sub-aggregate that
+   --    we are currently checking (RM 4.3.3 (8)). Its Etype is the
+   --    corresponding index type (or subtype).
+   --
+   --    Index_Constr is the node giving the applicable index constraint if
+   --    any (RM 4.3.3 (10)). It "is a constraint provided by certain
+   --    contexts [...] that can be used to determine the bounds of the array
+   --    value specified by the aggregate". If Others_Allowed below is False
+   --    there is no applicable index constraint and this node is set to Index.
+   --
+   --    Component_Typ is the array component type.
+   --
+   --    Others_Allowed indicates whether an others choice is allowed
+   --    in the context where the top-level aggregate appeared.
+   --
+   --  The algorithm of Resolve_Array_Aggregate proceeds as follows:
+   --
+   --  1. Make sure that the others choice, if present, is by itself and
+   --     appears last in the sub-aggregate. Check that we do not have
+   --     positional and named components in the array sub-aggregate (unless
+   --     the named association is an others choice). Finally if an others
+   --     choice is present, make sure it is allowed in the aggregate contex.
+   --
+   --  2. If the array sub-aggregate contains discrete_choices:
+   --
+   --     (A) Verify their validity. Specifically verify that:
+   --
+   --        (a) If a null range is present it must be the only possible
+   --            choice in the array aggregate.
+   --
+   --        (b) Ditto for a non static range.
+   --
+   --        (c) Ditto for a non static expression.
+   --
+   --        In addition this step analyzes and resolves each discrete_choice,
+   --        making sure that its type is the type of the corresponding Index.
+   --        If we are not at the lowest array aggregate level (in the case of
+   --        multi-dimensional aggregates) then invoke Resolve_Array_Aggregate
+   --        recursively on each component expression. Otherwise, resolve the
+   --        bottom level component expressions against the expected component
+   --        type ONLY IF the component corresponds to a single discrete choice
+   --        which is not an others choice (to see why read the DELAYED
+   --        COMPONENT RESOLUTION below).
+   --
+   --     (B) Determine the bounds of the sub-aggregate and lowest and
+   --         highest choice values.
+   --
+   --  3. For positional aggregates:
+   --
+   --     (A) Loop over the component expressions either recursively invoking
+   --         Resolve_Array_Aggregate on each of these for multi-dimensional
+   --         array aggregates or resolving the bottom level component
+   --         expressions against the expected component type.
+   --
+   --     (B) Determine the bounds of the positional sub-aggregates.
+   --
+   --  4. Try to determine statically whether the evaluation of the array
+   --     sub-aggregate raises Constraint_Error. If yes emit proper
+   --     warnings. The precise checks are the following:
+   --
+   --     (A) Check that the index range defined by aggregate bounds is
+   --         compatible with corresponding index subtype.
+   --         We also check against the base type. In fact it could be that
+   --         Low/High bounds of the base type are static whereas those of
+   --         the index subtype are not. Thus if we can statically catch
+   --         a problem with respect to the base type we are guaranteed
+   --         that the same problem will arise with the index subtype
+   --
+   --     (B) If we are dealing with a named aggregate containing an others
+   --         choice and at least one discrete choice then make sure the range
+   --         specified by the discrete choices does not overflow the
+   --         aggregate bounds. We also check against the index type and base
+   --         type bounds for the same reasons given in (A).
+   --
+   --     (C) If we are dealing with a positional aggregate with an others
+   --         choice make sure the number of positional elements specified
+   --         does not overflow the aggregate bounds. We also check against
+   --         the index type and base type bounds as mentioned in (A).
+   --
+   --     Finally construct an N_Range node giving the sub-aggregate bounds.
+   --     Set the Aggregate_Bounds field of the sub-aggregate to be this
+   --     N_Range. The routine Array_Aggr_Subtype below uses such N_Ranges
+   --     to build the appropriate aggregate subtype. Aggregate_Bounds
+   --     information is needed during expansion.
+   --
+   --  DELAYED COMPONENT RESOLUTION: The resolution of bottom level component
+   --  expressions in an array aggregate may call Duplicate_Subexpr or some
+   --  other routine that inserts code just outside the outermost aggregate.
+   --  If the array aggregate contains discrete choices or an others choice,
+   --  this may be wrong. Consider for instance the following example.
+   --
+   --    type Rec is record
+   --       V : Integer := 0;
+   --    end record;
+   --
+   --    type Acc_Rec is access Rec;
+   --    Arr : array (1..3) of Acc_Rec := (1 .. 3 => new Rec);
+   --
+   --  Then the transformation of "new Rec" that occurs during resolution
+   --  entails the following code modifications
+   --
+   --    P7b : constant Acc_Rec := new Rec;
+   --    Rec_init_proc (P7b.all);
+   --    Arr : array (1..3) of Acc_Rec := (1 .. 3 => P7b);
+   --
+   --  This code transformation is clearly wrong, since we need to call
+   --  "new Rec" for each of the 3 array elements. To avoid this problem we
+   --  delay resolution of the components of non positional array aggregates
+   --  to the expansion phase. As an optimization, if the discrete choice
+   --  specifies a single value we do not delay resolution.
+
+   function Array_Aggr_Subtype (N : Node_Id; Typ : Node_Id) return Entity_Id;
+   --  This routine returns the type or subtype of an array aggregate.
+   --
+   --    N is the array aggregate node whose type we return.
+   --
+   --    Typ is the context type in which N occurs.
+   --
+   --  This routine creates an implicit array subtype whose bouds are
+   --  those defined by the aggregate. When this routine is invoked
+   --  Resolve_Array_Aggregate has already processed aggregate N. Thus the
+   --  Aggregate_Bounds of each sub-aggregate, is an N_Range node giving the
+   --  sub-aggregate bounds. When building the aggegate itype, this function
+   --  traverses the array aggregate N collecting such Aggregate_Bounds and
+   --  constructs the proper array aggregate itype.
+   --
+   --  Note that in the case of multidimensional aggregates each inner
+   --  sub-aggregate corresponding to a given array dimension, may provide a
+   --  different bounds. If it is possible to determine statically that
+   --  some sub-aggregates corresponding to the same index do not have the
+   --  same bounds, then a warning is emitted. If such check is not possible
+   --  statically (because some sub-aggregate bounds are dynamic expressions)
+   --  then this job is left to the expander. In all cases the particular
+   --  bounds that this function will chose for a given dimension is the first
+   --  N_Range node for a sub-aggregate corresponding to that dimension.
+   --
+   --  Note that the Raises_Constraint_Error flag of an array aggregate
+   --  whose evaluation is determined to raise CE by Resolve_Array_Aggregate,
+   --  is set in Resolve_Array_Aggregate but the aggregate is not
+   --  immediately replaced with a raise CE. In fact, Array_Aggr_Subtype must
+   --  first construct the proper itype for the aggregate (Gigi needs
+   --  this). After constructing the proper itype we will eventually  replace
+   --  the top-level aggregate with a raise CE (done in Resolve_Aggregate).
+   --  Of course in cases such as:
+   --
+   --     type Arr is array (integer range <>) of Integer;
+   --     A : Arr := (positive range -1 .. 2 => 0);
+   --
+   --  The bounds of the aggregate itype are cooked up to look reasonable
+   --  (in this particular case the bounds will be 1 .. 2).
+
+   procedure Aggregate_Constraint_Checks
+     (Exp       : Node_Id;
+      Check_Typ : Entity_Id);
+   --  Checks expression Exp against subtype Check_Typ. If Exp is an
+   --  aggregate and Check_Typ a constrained record type with discriminants,
+   --  we generate the appropriate discriminant checks. If Exp is an array
+   --  aggregate then emit the appropriate length checks. If Exp is a scalar
+   --  type, or a string literal, Exp is changed into Check_Typ'(Exp) to
+   --  ensure that range checks are performed at run time.
+
+   procedure Make_String_Into_Aggregate (N : Node_Id);
+   --  A string literal can appear in  a context in  which a one dimensional
+   --  array of characters is expected. This procedure simply rewrites the
+   --  string as an aggregate, prior to resolution.
+
+   ---------------------------------
+   -- Aggregate_Constraint_Checks --
+   ---------------------------------
+
+   procedure Aggregate_Constraint_Checks
+     (Exp       : Node_Id;
+      Check_Typ : Entity_Id)
+   is
+      Exp_Typ : constant Entity_Id  := Etype (Exp);
+
+   begin
+      if Raises_Constraint_Error (Exp) then
+         return;
+      end if;
+
+      --  This is really expansion activity, so make sure that expansion
+      --  is on and is allowed.
+
+      if not Expander_Active or else In_Default_Expression then
+         return;
+      end if;
+
+      --  First check if we have to insert discriminant checks
+
+      if Has_Discriminants (Exp_Typ) then
+         Apply_Discriminant_Check (Exp, Check_Typ);
+
+      --  Next emit length checks for array aggregates
+
+      elsif Is_Array_Type (Exp_Typ) then
+         Apply_Length_Check (Exp, Check_Typ);
+
+      --  Finally emit scalar and string checks. If we are dealing with a
+      --  scalar literal we need to check by hand because the Etype of
+      --  literals is not necessarily correct.
+
+      elsif Is_Scalar_Type (Exp_Typ)
+        and then Compile_Time_Known_Value (Exp)
+      then
+         if Is_Out_Of_Range (Exp, Base_Type (Check_Typ)) then
+            Apply_Compile_Time_Constraint_Error
+              (Exp, "value not in range of}?",
+               Ent => Base_Type (Check_Typ),
+               Typ => Base_Type (Check_Typ));
+
+         elsif Is_Out_Of_Range (Exp, Check_Typ) then
+            Apply_Compile_Time_Constraint_Error
+              (Exp, "value not in range of}?",
+               Ent => Check_Typ,
+               Typ => Check_Typ);
+
+         elsif not Range_Checks_Suppressed (Check_Typ) then
+            Apply_Scalar_Range_Check (Exp, Check_Typ);
+         end if;
+
+      elsif (Is_Scalar_Type (Exp_Typ)
+             or else Nkind (Exp) = N_String_Literal)
+        and then Exp_Typ /= Check_Typ
+      then
+         if Is_Entity_Name (Exp)
+           and then Ekind (Entity (Exp)) = E_Constant
+         then
+            --  If expression is a constant, it is worthwhile checking whether
+            --  it is a bound of the type.
+
+            if (Is_Entity_Name (Type_Low_Bound (Check_Typ))
+                 and then Entity (Exp) = Entity (Type_Low_Bound (Check_Typ)))
+              or else (Is_Entity_Name (Type_High_Bound (Check_Typ))
+                and then Entity (Exp) = Entity (Type_High_Bound (Check_Typ)))
+            then
+               return;
+
+            else
+               Rewrite (Exp, Convert_To (Check_Typ, Relocate_Node (Exp)));
+               Analyze_And_Resolve (Exp, Check_Typ);
+            end if;
+         else
+            Rewrite (Exp, Convert_To (Check_Typ, Relocate_Node (Exp)));
+            Analyze_And_Resolve (Exp, Check_Typ);
+         end if;
+
+      end if;
+   end Aggregate_Constraint_Checks;
+
+   ------------------------
+   -- Array_Aggr_Subtype --
+   ------------------------
+
+   function Array_Aggr_Subtype
+     (N    : Node_Id;
+      Typ  : Entity_Id)
+      return Entity_Id
+   is
+      Aggr_Dimension : constant Pos := Number_Dimensions (Typ);
+      --  Number of aggregate index dimensions.
+
+      Aggr_Range : array (1 .. Aggr_Dimension) of Node_Id := (others => Empty);
+      --  Constrained N_Range of each index dimension in our aggregate itype.
+
+      Aggr_Low   : array (1 .. Aggr_Dimension) of Node_Id := (others => Empty);
+      Aggr_High  : array (1 .. Aggr_Dimension) of Node_Id := (others => Empty);
+      --  Low and High bounds for each index dimension in our aggregate itype.
+
+      Is_Fully_Positional : Boolean := True;
+
+      procedure Collect_Aggr_Bounds (N : Node_Id; Dim : Pos);
+      --  N is an array (sub-)aggregate. Dim is the dimension corresponding to
+      --  (sub-)aggregate N. This procedure collects the constrained N_Range
+      --  nodes corresponding to each index dimension of our aggregate itype.
+      --  These N_Range nodes are collected in Aggr_Range above.
+      --  Likewise collect in Aggr_Low & Aggr_High above the low and high
+      --  bounds of each index dimension. If, when collecting, two bounds
+      --  corresponding to the same dimension are static and found to differ,
+      --  then emit a warning, and mark N as raising Constraint_Error.
+
+      -------------------------
+      -- Collect_Aggr_Bounds --
+      -------------------------
+
+      procedure Collect_Aggr_Bounds (N : Node_Id; Dim : Pos) is
+         This_Range : constant Node_Id := Aggregate_Bounds (N);
+         --  The aggregate range node of this specific sub-aggregate.
+
+         This_Low  : constant Node_Id := Low_Bound (Aggregate_Bounds (N));
+         This_High : constant Node_Id := High_Bound (Aggregate_Bounds (N));
+         --  The aggregate bounds of this specific sub-aggregate.
+
+         Assoc : Node_Id;
+         Expr  : Node_Id;
+
+      begin
+         --  Collect the first N_Range for a given dimension that you find.
+         --  For a given dimension they must be all equal anyway.
+
+         if No (Aggr_Range (Dim)) then
+            Aggr_Low (Dim)   := This_Low;
+            Aggr_High (Dim)  := This_High;
+            Aggr_Range (Dim) := This_Range;
+
+         else
+            if Compile_Time_Known_Value (This_Low) then
+               if not Compile_Time_Known_Value (Aggr_Low (Dim)) then
+                  Aggr_Low (Dim)  := This_Low;
+
+               elsif Expr_Value (This_Low) /= Expr_Value (Aggr_Low (Dim)) then
+                  Set_Raises_Constraint_Error (N);
+                  Error_Msg_N ("Sub-aggregate low bound mismatch?", N);
+                  Error_Msg_N ("Constraint_Error will be raised at run-time?",
+                               N);
+               end if;
+            end if;
+
+            if Compile_Time_Known_Value (This_High) then
+               if not Compile_Time_Known_Value (Aggr_High (Dim)) then
+                  Aggr_High (Dim)  := This_High;
+
+               elsif
+                 Expr_Value (This_High) /= Expr_Value (Aggr_High (Dim))
+               then
+                  Set_Raises_Constraint_Error (N);
+                  Error_Msg_N ("Sub-aggregate high bound mismatch?", N);
+                  Error_Msg_N ("Constraint_Error will be raised at run-time?",
+                               N);
+               end if;
+            end if;
+         end if;
+
+         if Dim < Aggr_Dimension then
+
+            --  Process positional components
+
+            if Present (Expressions (N)) then
+               Expr := First (Expressions (N));
+               while Present (Expr) loop
+                  Collect_Aggr_Bounds (Expr, Dim + 1);
+                  Next (Expr);
+               end loop;
+            end if;
+
+            --  Process component associations
+
+            if Present (Component_Associations (N)) then
+               Is_Fully_Positional := False;
+
+               Assoc := First (Component_Associations (N));
+               while Present (Assoc) loop
+                  Expr := Expression (Assoc);
+                  Collect_Aggr_Bounds (Expr, Dim + 1);
+                  Next (Assoc);
+               end loop;
+            end if;
+         end if;
+      end Collect_Aggr_Bounds;
+
+      --  Array_Aggr_Subtype variables
+
+      Itype : Entity_Id;
+      --  the final itype of the overall aggregate
+
+      Index_Constraints : List_Id := New_List;
+      --  The list of index constraints of the aggregate itype.
+
+   --  Start of processing for Array_Aggr_Subtype
+
+   begin
+      --  Make sure that the list of index constraints is properly attached
+      --  to the tree, and then collect the aggregate bounds.
+
+      Set_Parent (Index_Constraints, N);
+      Collect_Aggr_Bounds (N, 1);
+
+      --  Build the list of constrained indices of our aggregate itype.
+
+      for J in 1 .. Aggr_Dimension loop
+         Create_Index : declare
+            Index_Base : Entity_Id := Base_Type (Etype (Aggr_Range (J)));
+            Index_Typ  : Entity_Id;
+
+         begin
+            --  Construct the Index subtype
+
+            Index_Typ := Create_Itype (Subtype_Kind (Ekind (Index_Base)), N);
+
+            Set_Etype (Index_Typ, Index_Base);
+
+            if Is_Character_Type (Index_Base) then
+               Set_Is_Character_Type (Index_Typ);
+            end if;
+
+            Set_Size_Info      (Index_Typ,                (Index_Base));
+            Set_RM_Size        (Index_Typ, RM_Size        (Index_Base));
+            Set_First_Rep_Item (Index_Typ, First_Rep_Item (Index_Base));
+            Set_Scalar_Range   (Index_Typ, Aggr_Range (J));
+
+            if Is_Discrete_Or_Fixed_Point_Type (Index_Typ) then
+               Set_RM_Size (Index_Typ, UI_From_Int (Minimum_Size (Index_Typ)));
+            end if;
+
+            Set_Etype (Aggr_Range (J), Index_Typ);
+
+            Append (Aggr_Range (J), To => Index_Constraints);
+         end Create_Index;
+      end loop;
+
+      --  Now build the Itype
+
+      Itype := Create_Itype (E_Array_Subtype, N);
+
+      Set_First_Rep_Item         (Itype, First_Rep_Item         (Typ));
+      Set_Component_Type         (Itype, Component_Type         (Typ));
+      Set_Convention             (Itype, Convention             (Typ));
+      Set_Depends_On_Private     (Itype, Has_Private_Component  (Typ));
+      Set_Etype                  (Itype, Base_Type              (Typ));
+      Set_Has_Alignment_Clause   (Itype, Has_Alignment_Clause   (Typ));
+      Set_Is_Aliased             (Itype, Is_Aliased             (Typ));
+      Set_Suppress_Index_Checks  (Itype, Suppress_Index_Checks  (Typ));
+      Set_Suppress_Length_Checks (Itype, Suppress_Length_Checks (Typ));
+      Set_Depends_On_Private     (Itype, Depends_On_Private     (Typ));
+
+      Set_First_Index    (Itype, First (Index_Constraints));
+      Set_Is_Constrained (Itype, True);
+      Set_Is_Internal    (Itype, True);
+      Init_Size_Align    (Itype);
+
+      --  A simple optimization: purely positional aggregates of static
+      --  components should be passed to gigi unexpanded whenever possible,
+      --  and regardless of the staticness of the bounds themselves. Subse-
+      --  quent checks in exp_aggr verify that type is not packed, etc.
+
+      Set_Size_Known_At_Compile_Time (Itype,
+         Is_Fully_Positional
+           and then Comes_From_Source (N)
+           and then Size_Known_At_Compile_Time (Component_Type (Typ)));
+
+      --  We always need a freeze node for a packed array subtype, so that
+      --  we can build the Packed_Array_Type corresponding to the subtype.
+      --  If expansion is disabled, the packed array subtype is not built,
+      --  and we must not generate a freeze node for the type, or else it
+      --  will appear incomplete to gigi.
+
+      if Is_Packed (Itype) and then not In_Default_Expression
+        and then Expander_Active
+      then
+         Freeze_Itype (Itype, N);
+      end if;
+
+      return Itype;
+   end Array_Aggr_Subtype;
+
+   --------------------------------
+   -- Check_Misspelled_Component --
+   --------------------------------
+
+   procedure Check_Misspelled_Component
+     (Elements      : Elist_Id;
+      Component     : Node_Id)
+   is
+      Max_Suggestions   : constant := 2;
+
+      Nr_Of_Suggestions : Natural := 0;
+      Suggestion_1      : Entity_Id := Empty;
+      Suggestion_2      : Entity_Id := Empty;
+      Component_Elmt    : Elmt_Id;
+
+   begin
+      --  All the components of List are matched against Component and
+      --  a count is maintained of possible misspellings. When at the
+      --  end of the analysis there are one or two (not more!) possible
+      --  misspellings, these misspellings will be suggested as
+      --  possible correction.
+
+      Get_Name_String (Chars (Component));
+
+      declare
+         S  : constant String (1 .. Name_Len) :=
+                Name_Buffer (1 .. Name_Len);
+
+      begin
+
+         Component_Elmt := First_Elmt (Elements);
+
+         while Nr_Of_Suggestions <= Max_Suggestions
+            and then Present (Component_Elmt)
+         loop
+
+            Get_Name_String (Chars (Node (Component_Elmt)));
+
+            if Is_Bad_Spelling_Of (Name_Buffer (1 .. Name_Len), S) then
+               Nr_Of_Suggestions := Nr_Of_Suggestions + 1;
+
+               case Nr_Of_Suggestions is
+                  when 1      => Suggestion_1 := Node (Component_Elmt);
+                  when 2      => Suggestion_2 := Node (Component_Elmt);
+                  when others => exit;
+               end case;
+            end if;
+
+            Next_Elmt (Component_Elmt);
+         end loop;
+
+         --  Report at most two suggestions
+
+         if Nr_Of_Suggestions = 1 then
+            Error_Msg_NE ("\possible misspelling of&",
+               Component, Suggestion_1);
+
+         elsif Nr_Of_Suggestions = 2 then
+            Error_Msg_Node_2 := Suggestion_2;
+            Error_Msg_NE ("\possible misspelling of& or&",
+              Component, Suggestion_1);
+         end if;
+      end;
+   end Check_Misspelled_Component;
+
+   ----------------------------------------
+   -- Check_Static_Discriminated_Subtype --
+   ----------------------------------------
+
+   procedure Check_Static_Discriminated_Subtype (T : Entity_Id; V : Node_Id) is
+      Disc : constant Entity_Id := First_Discriminant (T);
+      Comp : Entity_Id;
+      Ind  : Entity_Id;
+
+   begin
+      if Has_Record_Rep_Clause (Base_Type (T)) then
+         return;
+
+      elsif Present (Next_Discriminant (Disc)) then
+         return;
+
+      elsif Nkind (V) /= N_Integer_Literal then
+         return;
+      end if;
+
+      Comp := First_Component (T);
+
+      while Present (Comp) loop
+
+         if Is_Scalar_Type (Etype (Comp)) then
+            null;
+
+         elsif Is_Private_Type (Etype (Comp))
+           and then Present (Full_View (Etype (Comp)))
+           and then Is_Scalar_Type (Full_View (Etype (Comp)))
+         then
+            null;
+
+         elsif Is_Array_Type (Etype (Comp)) then
+
+            if Is_Bit_Packed_Array (Etype (Comp)) then
+               return;
+            end if;
+
+            Ind := First_Index (Etype (Comp));
+
+            while Present (Ind) loop
+
+               if Nkind (Ind) /= N_Range
+                 or else Nkind (Low_Bound (Ind)) /= N_Integer_Literal
+                 or else Nkind (High_Bound (Ind)) /= N_Integer_Literal
+               then
+                  return;
+               end if;
+
+               Next_Index (Ind);
+            end loop;
+
+         else
+            return;
+         end if;
+
+         Next_Component (Comp);
+      end loop;
+
+      --  On exit, all components have statically known sizes.
+
+      Set_Size_Known_At_Compile_Time (T);
+   end Check_Static_Discriminated_Subtype;
+
+   --------------------------------
+   -- Make_String_Into_Aggregate --
+   --------------------------------
+
+   procedure Make_String_Into_Aggregate (N : Node_Id) is
+      C      : Char_Code;
+      C_Node : Node_Id;
+      Exprs  : List_Id := New_List;
+      Loc    : constant Source_Ptr := Sloc (N);
+      New_N  : Node_Id;
+      P      : Source_Ptr := Loc + 1;
+      Str    : constant String_Id  := Strval (N);
+      Strlen : constant Nat        := String_Length (Str);
+
+   begin
+      for J in  1 .. Strlen loop
+         C := Get_String_Char (Str, J);
+         Set_Character_Literal_Name (C);
+
+         C_Node :=  Make_Character_Literal (P, Name_Find, C);
+         Set_Etype (C_Node, Any_Character);
+         Set_Analyzed (C_Node);
+         Append_To (Exprs, C_Node);
+
+         P := P + 1;
+         --  something special for wide strings ?
+      end loop;
+
+      New_N := Make_Aggregate (Loc, Expressions => Exprs);
+      Set_Analyzed (New_N);
+      Set_Etype (New_N, Any_Composite);
+
+      Rewrite (N, New_N);
+   end Make_String_Into_Aggregate;
+
+   -----------------------
+   -- Resolve_Aggregate --
+   -----------------------
+
+   procedure Resolve_Aggregate (N : Node_Id; Typ : Entity_Id) is
+      Pkind : constant Node_Kind := Nkind (Parent (N));
+
+      Aggr_Subtyp : Entity_Id;
+      --  The actual aggregate subtype. This is not necessarily the same as Typ
+      --  which is the subtype of the context in which the aggregate was found.
+
+   begin
+      if Is_Limited_Type (Typ) then
+         Error_Msg_N ("aggregate type cannot be limited", N);
+
+      elsif Is_Limited_Composite (Typ) then
+         Error_Msg_N ("aggregate type cannot have limited component", N);
+
+      elsif Is_Class_Wide_Type (Typ) then
+         Error_Msg_N ("type of aggregate cannot be class-wide", N);
+
+      elsif Typ = Any_String
+        or else Typ = Any_Composite
+      then
+         Error_Msg_N ("no unique type for aggregate", N);
+         Set_Etype (N, Any_Composite);
+
+      elsif Is_Array_Type (Typ) and then Null_Record_Present (N) then
+         Error_Msg_N ("null record forbidden in array aggregate", N);
+
+      elsif Is_Record_Type (Typ) then
+         Resolve_Record_Aggregate (N, Typ);
+
+      elsif Is_Array_Type (Typ) then
+
+         --  First a special test, for the case of a positional aggregate
+         --  of characters which can be replaced by a string literal.
+         --  Do not perform this transformation if this was a string literal
+         --  to start with, whose components needed constraint checks, or if
+         --  the component type is non-static, because it will require those
+         --  checks and be transformed back into an aggregate.
+
+         if Number_Dimensions (Typ) = 1
+           and then
+             (Root_Type (Component_Type (Typ)) = Standard_Character
+               or else
+              Root_Type (Component_Type (Typ)) = Standard_Wide_Character)
+           and then No (Component_Associations (N))
+           and then not Is_Limited_Composite (Typ)
+           and then not Is_Private_Composite (Typ)
+           and then not Is_Bit_Packed_Array (Typ)
+           and then Nkind (Original_Node (Parent (N))) /= N_String_Literal
+           and then Is_Static_Subtype (Component_Type (Typ))
+         then
+            declare
+               Expr : Node_Id;
+
+            begin
+               Expr := First (Expressions (N));
+               while Present (Expr) loop
+                  exit when Nkind (Expr) /= N_Character_Literal;
+                  Next (Expr);
+               end loop;
+
+               if No (Expr) then
+                  Start_String;
+
+                  Expr := First (Expressions (N));
+                  while Present (Expr) loop
+                     Store_String_Char (Char_Literal_Value (Expr));
+                     Next (Expr);
+                  end loop;
+
+                  Rewrite (N,
+                    Make_String_Literal (Sloc (N), End_String));
+
+                  Analyze_And_Resolve (N, Typ);
+                  return;
+               end if;
+            end;
+         end if;
+
+         --  Here if we have a real aggregate to deal with
+
+         Array_Aggregate : declare
+            Aggr_Resolved : Boolean;
+            Aggr_Typ      : Entity_Id := Etype (Typ);
+            --  This is the unconstrained array type, which is the type
+            --  against which the aggregate is to be resoved. Typ itself
+            --  is the array type of the context which may not be the same
+            --  subtype as the subtype for the final aggregate.
+
+         begin
+            --  In the following we determine whether an others choice is
+            --  allowed inside the array aggregate. The test checks the context
+            --  in which the array aggregate occurs. If the context does not
+            --  permit it, or the aggregate type is unconstrained, an others
+            --  choice is not allowed.
+            --
+            --  Note that there is no node for Explicit_Actual_Parameter.
+            --  To test for this context we therefore have to test for node
+            --  N_Parameter_Association which itself appears only if there is a
+            --  formal parameter. Consequently we also need to test for
+            --  N_Procedure_Call_Statement or N_Function_Call.
+
+            if Is_Constrained (Typ) and then
+              (Pkind = N_Assignment_Statement      or else
+               Pkind = N_Parameter_Association     or else
+               Pkind = N_Function_Call             or else
+               Pkind = N_Procedure_Call_Statement  or else
+               Pkind = N_Generic_Association       or else
+               Pkind = N_Formal_Object_Declaration or else
+               Pkind = N_Return_Statement          or else
+               Pkind = N_Object_Declaration        or else
+               Pkind = N_Component_Declaration     or else
+               Pkind = N_Parameter_Specification   or else
+               Pkind = N_Qualified_Expression      or else
+               Pkind = N_Aggregate                 or else
+               Pkind = N_Extension_Aggregate       or else
+               Pkind = N_Component_Association)
+            then
+               Aggr_Resolved :=
+                 Resolve_Array_Aggregate
+                   (N,
+                    Index          => First_Index (Aggr_Typ),
+                    Index_Constr   => First_Index (Typ),
+                    Component_Typ  => Component_Type (Typ),
+                    Others_Allowed => True);
+
+            else
+               Aggr_Resolved :=
+                 Resolve_Array_Aggregate
+                   (N,
+                    Index          => First_Index (Aggr_Typ),
+                    Index_Constr   => First_Index (Aggr_Typ),
+                    Component_Typ  => Component_Type (Typ),
+                    Others_Allowed => False);
+            end if;
+
+            if not Aggr_Resolved then
+               Aggr_Subtyp := Any_Composite;
+            else
+               Aggr_Subtyp := Array_Aggr_Subtype (N, Typ);
+            end if;
+
+            Set_Etype (N, Aggr_Subtyp);
+         end Array_Aggregate;
+
+      else
+         Error_Msg_N ("illegal context for aggregate", N);
+
+      end if;
+
+      --  If we can determine statically that the evaluation of the
+      --  aggregate raises Constraint_Error, then replace the
+      --  aggregate with an N_Raise_Constraint_Error node, but set the
+      --  Etype to the right aggregate subtype. Gigi needs this.
+
+      if Raises_Constraint_Error (N) then
+         Aggr_Subtyp := Etype (N);
+         Rewrite (N, Make_Raise_Constraint_Error (Sloc (N)));
+         Set_Raises_Constraint_Error (N);
+         Set_Etype (N, Aggr_Subtyp);
+         Set_Analyzed (N);
+      end if;
+
+   end Resolve_Aggregate;
+
+   -----------------------------
+   -- Resolve_Array_Aggregate --
+   -----------------------------
+
+   function Resolve_Array_Aggregate
+     (N              : Node_Id;
+      Index          : Node_Id;
+      Index_Constr   : Node_Id;
+      Component_Typ  : Entity_Id;
+      Others_Allowed : Boolean)
+      return           Boolean
+   is
+      Loc : constant Source_Ptr := Sloc (N);
+
+      Failure : constant Boolean := False;
+      Success : constant Boolean := True;
+
+      Index_Typ      : constant Entity_Id := Etype (Index);
+      Index_Typ_Low  : constant Node_Id   := Type_Low_Bound  (Index_Typ);
+      Index_Typ_High : constant Node_Id   := Type_High_Bound (Index_Typ);
+      --  The type of the index corresponding to the array sub-aggregate
+      --  along with its low and upper bounds
+
+      Index_Base      : constant Entity_Id := Base_Type (Index_Typ);
+      Index_Base_Low  : constant Node_Id   := Type_Low_Bound (Index_Base);
+      Index_Base_High : constant Node_Id   := Type_High_Bound (Index_Base);
+      --  ditto for the base type
+
+      function Add (Val : Uint; To : Node_Id) return Node_Id;
+      --  Creates a new expression node where Val is added to expression To.
+      --  Tries to constant fold whenever possible. To must be an already
+      --  analyzed expression.
+
+      procedure Check_Bound (BH : Node_Id; AH : in out Node_Id);
+      --  Checks that AH (the upper bound of an array aggregate) is <= BH
+      --  (the upper bound of the index base type). If the check fails a
+      --  warning is emitted, the Raises_Constraint_Error Flag of N is set,
+      --  and AH is replaced with a duplicate of BH.
+
+      procedure Check_Bounds (L, H : Node_Id; AL, AH : Node_Id);
+      --  Checks that range AL .. AH is compatible with range L .. H. Emits a
+      --  warning if not and sets the Raises_Constraint_Error Flag in N.
+
+      procedure Check_Length (L, H : Node_Id; Len : Uint);
+      --  Checks that range L .. H contains at least Len elements. Emits a
+      --  warning if not and sets the Raises_Constraint_Error Flag in N.
+
+      function Dynamic_Or_Null_Range (L, H : Node_Id) return Boolean;
+      --  Returns True if range L .. H is dynamic or null.
+
+      procedure Get (Value : out Uint; From : Node_Id; OK : out Boolean);
+      --  Given expression node From, this routine sets OK to False if it
+      --  cannot statically evaluate From. Otherwise it stores this static
+      --  value into Value.
+
+      function Resolve_Aggr_Expr
+        (Expr        : Node_Id;
+         Single_Elmt : Boolean)
+         return        Boolean;
+      --  Resolves aggregate expression Expr. Returs False if resolution
+      --  fails. If Single_Elmt is set to False, the expression Expr may be
+      --  used to initialize several array aggregate elements (this can
+      --  happen for discrete choices such as "L .. H => Expr" or the others
+      --  choice). In this event we do not resolve Expr unless expansion is
+      --  disabled. To know why, see the DELAYED COMPONENT RESOLUTION
+      --  note above.
+
+      ---------
+      -- Add --
+      ---------
+
+      function Add (Val : Uint; To : Node_Id) return Node_Id is
+         Expr_Pos : Node_Id;
+         Expr     : Node_Id;
+         To_Pos   : Node_Id;
+
+      begin
+         if Raises_Constraint_Error (To) then
+            return To;
+         end if;
+
+         --  First test if we can do constant folding
+
+         if Compile_Time_Known_Value (To)
+           or else Nkind (To) = N_Integer_Literal
+         then
+            Expr_Pos := Make_Integer_Literal (Loc, Expr_Value (To) + Val);
+            Set_Is_Static_Expression (Expr_Pos);
+            Set_Etype (Expr_Pos, Etype (To));
+            Set_Analyzed (Expr_Pos, Analyzed (To));
+
+            if not Is_Enumeration_Type (Index_Typ) then
+               Expr := Expr_Pos;
+
+            --  If we are dealing with enumeration return
+            --     Index_Typ'Val (Expr_Pos)
+
+            else
+               Expr :=
+                 Make_Attribute_Reference
+                   (Loc,
+                    Prefix         => New_Reference_To (Index_Typ, Loc),
+                    Attribute_Name => Name_Val,
+                    Expressions    => New_List (Expr_Pos));
+            end if;
+
+            return Expr;
+         end if;
+
+         --  If we are here no constant folding possible
+
+         if not Is_Enumeration_Type (Index_Base) then
+            Expr :=
+              Make_Op_Add (Loc,
+                           Left_Opnd  => Duplicate_Subexpr (To),
+                           Right_Opnd => Make_Integer_Literal (Loc, Val));
+
+         --  If we are dealing with enumeration return
+         --    Index_Typ'Val (Index_Typ'Pos (To) + Val)
+
+         else
+            To_Pos :=
+              Make_Attribute_Reference
+                (Loc,
+                 Prefix         => New_Reference_To (Index_Typ, Loc),
+                 Attribute_Name => Name_Pos,
+                 Expressions    => New_List (Duplicate_Subexpr (To)));
+
+            Expr_Pos :=
+              Make_Op_Add (Loc,
+                           Left_Opnd  => To_Pos,
+                           Right_Opnd => Make_Integer_Literal (Loc, Val));
+
+            Expr :=
+              Make_Attribute_Reference
+                (Loc,
+                 Prefix         => New_Reference_To (Index_Typ, Loc),
+                 Attribute_Name => Name_Val,
+                 Expressions    => New_List (Expr_Pos));
+         end if;
+
+         return Expr;
+      end Add;
+
+      -----------------
+      -- Check_Bound --
+      -----------------
+
+      procedure Check_Bound (BH : Node_Id; AH : in out Node_Id) is
+         Val_BH : Uint;
+         Val_AH : Uint;
+
+         OK_BH : Boolean;
+         OK_AH : Boolean;
+
+      begin
+         Get (Value => Val_BH, From => BH, OK => OK_BH);
+         Get (Value => Val_AH, From => AH, OK => OK_AH);
+
+         if OK_BH and then OK_AH and then Val_BH < Val_AH then
+            Set_Raises_Constraint_Error (N);
+            Error_Msg_N ("upper bound out of range?", AH);
+            Error_Msg_N ("Constraint_Error will be raised at run-time?", AH);
+
+            --  You need to set AH to BH or else in the case of enumerations
+            --  indices we will not be able to resolve the aggregate bounds.
+
+            AH := Duplicate_Subexpr (BH);
+         end if;
+      end Check_Bound;
+
+      ------------------
+      -- Check_Bounds --
+      ------------------
+
+      procedure Check_Bounds (L, H : Node_Id; AL, AH : Node_Id) is
+         Val_L  : Uint;
+         Val_H  : Uint;
+         Val_AL : Uint;
+         Val_AH : Uint;
+
+         OK_L  : Boolean;
+         OK_H  : Boolean;
+         OK_AL : Boolean;
+         OK_AH : Boolean;
+
+      begin
+         if Raises_Constraint_Error (N)
+           or else Dynamic_Or_Null_Range (AL, AH)
+         then
+            return;
+         end if;
+
+         Get (Value => Val_L, From => L, OK => OK_L);
+         Get (Value => Val_H, From => H, OK => OK_H);
+
+         Get (Value => Val_AL, From => AL, OK => OK_AL);
+         Get (Value => Val_AH, From => AH, OK => OK_AH);
+
+         if OK_L and then Val_L > Val_AL then
+            Set_Raises_Constraint_Error (N);
+            Error_Msg_N ("lower bound of aggregate out of range?", N);
+            Error_Msg_N ("Constraint_Error will be raised at run-time?", N);
+         end if;
+
+         if OK_H and then Val_H < Val_AH then
+            Set_Raises_Constraint_Error (N);
+            Error_Msg_N ("upper bound of aggregate out of range?", N);
+            Error_Msg_N ("Constraint_Error will be raised at run-time?", N);
+         end if;
+      end Check_Bounds;
+
+      ------------------
+      -- Check_Length --
+      ------------------
+
+      procedure Check_Length (L, H : Node_Id; Len : Uint) is
+         Val_L  : Uint;
+         Val_H  : Uint;
+
+         OK_L  : Boolean;
+         OK_H  : Boolean;
+
+         Range_Len : Uint;
+
+      begin
+         if Raises_Constraint_Error (N) then
+            return;
+         end if;
+
+         Get (Value => Val_L, From => L, OK => OK_L);
+         Get (Value => Val_H, From => H, OK => OK_H);
+
+         if not OK_L or else not OK_H then
+            return;
+         end if;
+
+         --  If null range length is zero
+
+         if Val_L > Val_H then
+            Range_Len := Uint_0;
+         else
+            Range_Len := Val_H - Val_L + 1;
+         end if;
+
+         if Range_Len < Len then
+            Set_Raises_Constraint_Error (N);
+            Error_Msg_N ("Too many elements?", N);
+            Error_Msg_N ("Constraint_Error will be raised at run-time?", N);
+         end if;
+      end Check_Length;
+
+      ---------------------------
+      -- Dynamic_Or_Null_Range --
+      ---------------------------
+
+      function Dynamic_Or_Null_Range (L, H : Node_Id) return Boolean is
+         Val_L : Uint;
+         Val_H : Uint;
+
+         OK_L  : Boolean;
+         OK_H  : Boolean;
+
+      begin
+         Get (Value => Val_L, From => L, OK => OK_L);
+         Get (Value => Val_H, From => H, OK => OK_H);
+
+         return not OK_L or else not OK_H
+           or else not Is_OK_Static_Expression (L)
+           or else not Is_OK_Static_Expression (H)
+           or else Val_L > Val_H;
+      end Dynamic_Or_Null_Range;
+
+      ---------
+      -- Get --
+      ---------
+
+      procedure Get (Value : out Uint; From : Node_Id; OK : out Boolean) is
+      begin
+         OK := True;
+
+         if Compile_Time_Known_Value (From) then
+            Value := Expr_Value (From);
+
+         --  If expression From is something like Some_Type'Val (10) then
+         --  Value = 10
+
+         elsif Nkind (From) = N_Attribute_Reference
+           and then Attribute_Name (From) = Name_Val
+           and then Compile_Time_Known_Value (First (Expressions (From)))
+         then
+            Value := Expr_Value (First (Expressions (From)));
+
+         else
+            Value := Uint_0;
+            OK := False;
+         end if;
+      end Get;
+
+      -----------------------
+      -- Resolve_Aggr_Expr --
+      -----------------------
+
+      function Resolve_Aggr_Expr
+        (Expr        : Node_Id;
+         Single_Elmt : Boolean)
+         return        Boolean
+      is
+         Nxt_Ind        : Node_Id := Next_Index (Index);
+         Nxt_Ind_Constr : Node_Id := Next_Index (Index_Constr);
+         --  Index is the current index corresponding to the expresion.
+
+         Resolution_OK : Boolean := True;
+         --  Set to False if resolution of the expression failed.
+
+      begin
+         --  If the array type against which we are resolving the aggregate
+         --  has several dimensions, the expressions nested inside the
+         --  aggregate must be further aggregates (or strings).
+
+         if Present (Nxt_Ind) then
+            if Nkind (Expr) /= N_Aggregate then
+
+               --  A string literal can appear where a one-dimensional array
+               --  of characters is expected. If the literal looks like an
+               --  operator, it is still an operator symbol, which will be
+               --  transformed into a string when analyzed.
+
+               if Is_Character_Type (Component_Typ)
+                 and then No (Next_Index (Nxt_Ind))
+                 and then (Nkind (Expr) = N_String_Literal
+                            or else Nkind (Expr) = N_Operator_Symbol)
+               then
+                  --  A string literal used in a multidimensional array
+                  --  aggregate in place of the final one-dimensional
+                  --  aggregate must not be enclosed in parentheses.
+
+                  if Paren_Count (Expr) /= 0 then
+                     Error_Msg_N ("No parenthesis allowed here", Expr);
+                  end if;
+
+                  Make_String_Into_Aggregate (Expr);
+
+               else
+                  Error_Msg_N ("nested array aggregate expected", Expr);
+                  return Failure;
+               end if;
+            end if;
+
+            Resolution_OK := Resolve_Array_Aggregate
+              (Expr, Nxt_Ind, Nxt_Ind_Constr, Component_Typ, Others_Allowed);
+
+         --  Do not resolve the expressions of discrete or others choices
+         --  unless the expression covers a single component, or the expander
+         --  is inactive.
+
+         elsif Single_Elmt
+           or else not Expander_Active
+           or else In_Default_Expression
+         then
+            Analyze_And_Resolve (Expr, Component_Typ);
+            Check_Non_Static_Context (Expr);
+            Aggregate_Constraint_Checks (Expr, Component_Typ);
+         end if;
+
+         if Raises_Constraint_Error (Expr)
+           and then Nkind (Parent (Expr)) /= N_Component_Association
+         then
+            Set_Raises_Constraint_Error (N);
+         end if;
+
+         return Resolution_OK;
+      end Resolve_Aggr_Expr;
+
+      --  Variables local to Resolve_Array_Aggregate
+
+      Assoc   : Node_Id;
+      Choice  : Node_Id;
+      Expr    : Node_Id;
+
+      Who_Cares : Node_Id;
+
+      Aggr_Low  : Node_Id := Empty;
+      Aggr_High : Node_Id := Empty;
+      --  The actual low and high bounds of this sub-aggegate
+
+      Choices_Low  : Node_Id := Empty;
+      Choices_High : Node_Id := Empty;
+      --  The lowest and highest discrete choices values for a named aggregate
+
+      Nb_Elements : Uint := Uint_0;
+      --  The number of elements in a positional aggegate
+
+      Others_Present : Boolean := False;
+
+      Nb_Choices : Nat := 0;
+      --  Contains the overall number of named choices in this sub-aggregate
+
+      Nb_Discrete_Choices : Nat := 0;
+      --  The overall number of discrete choices (not counting others choice)
+
+      Case_Table_Size : Nat;
+      --  Contains the size of the case table needed to sort aggregate choices
+
+   --  Start of processing for Resolve_Array_Aggregate
+
+   begin
+      --  STEP 1: make sure the aggregate is correctly formatted
+
+      if Present (Component_Associations (N)) then
+         Assoc := First (Component_Associations (N));
+         while Present (Assoc) loop
+            Choice := First (Choices (Assoc));
+            while Present (Choice) loop
+               if Nkind (Choice) = N_Others_Choice then
+                  Others_Present := True;
+
+                  if Choice /= First (Choices (Assoc))
+                    or else Present (Next (Choice))
+                  then
+                     Error_Msg_N
+                       ("OTHERS must appear alone in a choice list", Choice);
+                     return Failure;
+                  end if;
+
+                  if Present (Next (Assoc)) then
+                     Error_Msg_N
+                       ("OTHERS must appear last in an aggregate", Choice);
+                     return Failure;
+                  end if;
+
+                  if Ada_83
+                    and then Assoc /= First (Component_Associations (N))
+                    and then (Nkind (Parent (N)) = N_Assignment_Statement
+                               or else
+                                 Nkind (Parent (N)) = N_Object_Declaration)
+                  then
+                     Error_Msg_N
+                       ("(Ada 83) illegal context for OTHERS choice", N);
+                  end if;
+               end if;
+
+               Nb_Choices := Nb_Choices + 1;
+               Next (Choice);
+            end loop;
+
+            Next (Assoc);
+         end loop;
+      end if;
+
+      --  At this point we know that the others choice, if present, is by
+      --  itself and appears last in the aggregate. Check if we have mixed
+      --  positional and discrete associations (other than the others choice).
+
+      if Present (Expressions (N))
+        and then (Nb_Choices > 1
+                   or else (Nb_Choices = 1 and then not Others_Present))
+      then
+         Error_Msg_N
+           ("named association cannot follow positional association",
+            First (Choices (First (Component_Associations (N)))));
+         return Failure;
+      end if;
+
+      --  Test for the validity of an others choice if present
+
+      if Others_Present and then not Others_Allowed then
+         Error_Msg_N
+           ("OTHERS choice not allowed here",
+            First (Choices (First (Component_Associations (N)))));
+         return Failure;
+      end if;
+
+      --  STEP 2: Process named components
+
+      if No (Expressions (N)) then
+
+         if Others_Present then
+            Case_Table_Size := Nb_Choices - 1;
+         else
+            Case_Table_Size := Nb_Choices;
+         end if;
+
+         Step_2 : declare
+            Low  : Node_Id;
+            High : Node_Id;
+            --  Denote the lowest and highest values in an aggregate choice
+
+            Hi_Val : Uint;
+            Lo_Val : Uint;
+            --  High end of one range and Low end of the next. Should be
+            --  contiguous if there is no hole in the list of values.
+
+            Missing_Values : Boolean;
+            --  Set True if missing index values
+
+            S_Low  : Node_Id := Empty;
+            S_High : Node_Id := Empty;
+            --  if a choice in an aggregate is a subtype indication these
+            --  denote the lowest and highest values of the subtype
+
+            Table : Case_Table_Type (1 .. Case_Table_Size);
+            --  Used to sort all the different choice values
+
+            Single_Choice : Boolean;
+            --  Set to true every time there is a single discrete choice in a
+            --  discrete association
+
+            Prev_Nb_Discrete_Choices : Nat;
+            --  Used to keep track of the number of discrete choices
+            --  in the current association.
+
+         begin
+            --  STEP 2 (A): Check discrete choices validity.
+
+            Assoc := First (Component_Associations (N));
+            while Present (Assoc) loop
+
+               Prev_Nb_Discrete_Choices := Nb_Discrete_Choices;
+               Choice := First (Choices (Assoc));
+               loop
+                  Analyze (Choice);
+
+                  if Nkind (Choice) = N_Others_Choice then
+                     Single_Choice := False;
+                     exit;
+
+                  --  Test for subtype mark without constraint
+
+                  elsif Is_Entity_Name (Choice) and then
+                    Is_Type (Entity (Choice))
+                  then
+                     if Base_Type (Entity (Choice)) /= Index_Base then
+                        Error_Msg_N
+                          ("invalid subtype mark in aggregate choice",
+                           Choice);
+                        return Failure;
+                     end if;
+
+                  elsif Nkind (Choice) = N_Subtype_Indication then
+                     Resolve_Discrete_Subtype_Indication (Choice, Index_Base);
+
+                     --  Does the subtype indication evaluation raise CE ?
+
+                     Get_Index_Bounds (Subtype_Mark (Choice), S_Low, S_High);
+                     Get_Index_Bounds (Choice, Low, High);
+                     Check_Bounds (S_Low, S_High, Low, High);
+
+                  else  --  Choice is a range or an expression
+                     Resolve (Choice, Index_Base);
+                     Check_Non_Static_Context (Choice);
+
+                     --  Do not range check a choice. This check is redundant
+                     --  since this test is already performed when we check
+                     --  that the bounds of the array aggregate are within
+                     --  range.
+
+                     Set_Do_Range_Check (Choice, False);
+                  end if;
+
+                  --  If we could not resolve the discrete choice stop here
+
+                  if Etype (Choice) = Any_Type then
+                     return Failure;
+
+                  --  If the discrete choice raises CE get its original bounds.
+
+                  elsif Nkind (Choice) = N_Raise_Constraint_Error then
+                     Set_Raises_Constraint_Error (N);
+                     Get_Index_Bounds (Original_Node (Choice), Low, High);
+
+                  --  Otherwise get its bounds as usual
+
+                  else
+                     Get_Index_Bounds (Choice, Low, High);
+                  end if;
+
+                  if (Dynamic_Or_Null_Range (Low, High)
+                       or else (Nkind (Choice) = N_Subtype_Indication
+                                 and then
+                                   Dynamic_Or_Null_Range (S_Low, S_High)))
+                    and then Nb_Choices /= 1
+                  then
+                     Error_Msg_N
+                       ("dynamic or empty choice in aggregate " &
+                        "must be the only choice", Choice);
+                     return Failure;
+                  end if;
+
+                  Nb_Discrete_Choices := Nb_Discrete_Choices + 1;
+                  Table (Nb_Discrete_Choices).Choice_Lo := Low;
+                  Table (Nb_Discrete_Choices).Choice_Hi := High;
+
+                  Next (Choice);
+
+                  if No (Choice) then
+                     --  Check if we have a single discrete choice and whether
+                     --  this discrete choice specifies a single value.
+
+                     Single_Choice :=
+                       (Nb_Discrete_Choices = Prev_Nb_Discrete_Choices + 1)
+                         and then (Low = High);
+
+                     exit;
+                  end if;
+               end loop;
+
+               if not
+                 Resolve_Aggr_Expr
+                   (Expression (Assoc), Single_Elmt => Single_Choice)
+               then
+                  return Failure;
+               end if;
+
+               Next (Assoc);
+            end loop;
+
+            --  If aggregate contains more than one choice then these must be
+            --  static. Sort them and check that they are contiguous
+
+            if Nb_Discrete_Choices > 1 then
+               Sort_Case_Table (Table);
+               Missing_Values := False;
+
+               Outer : for J in 1 .. Nb_Discrete_Choices - 1 loop
+                  if Expr_Value (Table (J).Choice_Hi) >=
+                       Expr_Value (Table (J + 1).Choice_Lo)
+                  then
+                     Error_Msg_N
+                       ("duplicate choice values in array aggregate",
+                        Table (J).Choice_Hi);
+                     return Failure;
+
+                  elsif not Others_Present then
+
+                     Hi_Val := Expr_Value (Table (J).Choice_Hi);
+                     Lo_Val := Expr_Value (Table (J + 1).Choice_Lo);
+
+                     --  If missing values, output error messages
+
+                     if Lo_Val - Hi_Val > 1 then
+
+                        --  Header message if not first missing value
+
+                        if not Missing_Values then
+                           Error_Msg_N
+                             ("missing index value(s) in array aggregate", N);
+                           Missing_Values := True;
+                        end if;
+
+                        --  Output values of missing indexes
+
+                        Lo_Val := Lo_Val - 1;
+                        Hi_Val := Hi_Val + 1;
+
+                        --  Enumeration type case
+
+                        if Is_Enumeration_Type (Index_Typ) then
+                           Error_Msg_Name_1 :=
+                             Chars
+                               (Get_Enum_Lit_From_Pos
+                                 (Index_Typ, Hi_Val, Loc));
+
+                           if Lo_Val = Hi_Val then
+                              Error_Msg_N ("\  %", N);
+                           else
+                              Error_Msg_Name_2 :=
+                                Chars
+                                  (Get_Enum_Lit_From_Pos
+                                    (Index_Typ, Lo_Val, Loc));
+                              Error_Msg_N ("\  % .. %", N);
+                           end if;
+
+                        --  Integer types case
+
+                        else
+                           Error_Msg_Uint_1 := Hi_Val;
+
+                           if Lo_Val = Hi_Val then
+                              Error_Msg_N ("\  ^", N);
+                           else
+                              Error_Msg_Uint_2 := Lo_Val;
+                              Error_Msg_N ("\  ^ .. ^", N);
+                           end if;
+                        end if;
+                     end if;
+                  end if;
+               end loop Outer;
+
+               if Missing_Values then
+                  Set_Etype (N, Any_Composite);
+                  return Failure;
+               end if;
+            end if;
+
+            --  STEP 2 (B): Compute aggregate bounds and min/max choices values
+
+            if Nb_Discrete_Choices > 0 then
+               Choices_Low  := Table (1).Choice_Lo;
+               Choices_High := Table (Nb_Discrete_Choices).Choice_Hi;
+            end if;
+
+            if Others_Present then
+               Get_Index_Bounds (Index_Constr, Aggr_Low, Aggr_High);
+
+            else
+               Aggr_Low  := Choices_Low;
+               Aggr_High := Choices_High;
+            end if;
+         end Step_2;
+
+      --  STEP 3: Process positional components
+
+      else
+         --  STEP 3 (A): Process positional elements
+
+         Expr := First (Expressions (N));
+         Nb_Elements := Uint_0;
+         while Present (Expr) loop
+            Nb_Elements := Nb_Elements + 1;
+
+            if not Resolve_Aggr_Expr (Expr, Single_Elmt => True) then
+               return Failure;
+            end if;
+
+            Next (Expr);
+         end loop;
+
+         if Others_Present then
+            Assoc := Last (Component_Associations (N));
+            if not Resolve_Aggr_Expr (Expression (Assoc),
+                                      Single_Elmt => False)
+            then
+               return Failure;
+            end if;
+         end if;
+
+         --  STEP 3 (B): Compute the aggregate bounds
+
+         if Others_Present then
+            Get_Index_Bounds (Index_Constr, Aggr_Low, Aggr_High);
+
+         else
+            if Others_Allowed then
+               Get_Index_Bounds (Index_Constr, Aggr_Low, Who_Cares);
+            else
+               Aggr_Low := Index_Typ_Low;
+            end if;
+
+            Aggr_High := Add (Nb_Elements - 1, To => Aggr_Low);
+            Check_Bound (Index_Base_High, Aggr_High);
+         end if;
+      end if;
+
+      --  STEP 4: Perform static aggregate checks and save the bounds
+
+      --  Check (A)
+
+      Check_Bounds (Index_Typ_Low, Index_Typ_High, Aggr_Low, Aggr_High);
+      Check_Bounds (Index_Base_Low, Index_Base_High, Aggr_Low, Aggr_High);
+
+      --  Check (B)
+
+      if Others_Present and then Nb_Discrete_Choices > 0 then
+         Check_Bounds (Aggr_Low, Aggr_High, Choices_Low, Choices_High);
+         Check_Bounds (Index_Typ_Low, Index_Typ_High,
+                       Choices_Low, Choices_High);
+         Check_Bounds (Index_Base_Low, Index_Base_High,
+                       Choices_Low, Choices_High);
+
+      --  Check (C)
+
+      elsif Others_Present and then Nb_Elements > 0 then
+         Check_Length (Aggr_Low, Aggr_High, Nb_Elements);
+         Check_Length (Index_Typ_Low, Index_Typ_High, Nb_Elements);
+         Check_Length (Index_Base_Low, Index_Base_High, Nb_Elements);
+
+      end if;
+
+      if Raises_Constraint_Error (Aggr_Low)
+        or else Raises_Constraint_Error (Aggr_High)
+      then
+         Set_Raises_Constraint_Error (N);
+      end if;
+
+      Aggr_Low := Duplicate_Subexpr (Aggr_Low);
+
+      --  Do not duplicate Aggr_High if Aggr_High = Aggr_Low + Nb_Elements
+      --  since the addition node returned by Add is not yet analyzed. Attach
+      --  to tree and analyze first. Reset analyzed flag to insure it will get
+      --  analyzed when it is a literal bound whose type must be properly
+      --  set.
+
+      if Others_Present or else Nb_Discrete_Choices > 0 then
+         Aggr_High := Duplicate_Subexpr (Aggr_High);
+
+         if Etype (Aggr_High) = Universal_Integer then
+            Set_Analyzed (Aggr_High, False);
+         end if;
+      end if;
+
+      Set_Aggregate_Bounds
+        (N, Make_Range (Loc, Low_Bound => Aggr_Low, High_Bound => Aggr_High));
+
+      --  The bounds may contain expressions that must be inserted upwards.
+      --  Attach them fully to the tree. After analysis, remove side effects
+      --  from upper bound, if still needed.
+
+      Set_Parent (Aggregate_Bounds (N), N);
+      Analyze_And_Resolve (Aggregate_Bounds (N), Index_Typ);
+
+      if not Others_Present and then Nb_Discrete_Choices = 0 then
+         Set_High_Bound (Aggregate_Bounds (N),
+             Duplicate_Subexpr (High_Bound (Aggregate_Bounds (N))));
+      end if;
+
+      return Success;
+   end Resolve_Array_Aggregate;
+
+   ---------------------------------
+   -- Resolve_Extension_Aggregate --
+   ---------------------------------
+
+   --  There are two cases to consider:
+
+   --  a) If the ancestor part is a type mark, the components needed are
+   --  the difference between the components of the expected type and the
+   --  components of the given type mark.
+
+   --  b) If the ancestor part is an expression, it must be unambiguous,
+   --  and once we have its type we can also compute the needed  components
+   --  as in the previous case. In both cases, if the ancestor type is not
+   --  the immediate ancestor, we have to build this ancestor recursively.
+
+   --  In both cases discriminants of the ancestor type do not play a
+   --  role in the resolution of the needed components, because inherited
+   --  discriminants cannot be used in a type extension. As a result we can
+   --  compute independently the list of components of the ancestor type and
+   --  of the expected type.
+
+   procedure Resolve_Extension_Aggregate (N : Node_Id; Typ : Entity_Id) is
+      A        : constant Node_Id := Ancestor_Part (N);
+      A_Type   : Entity_Id;
+      I        : Interp_Index;
+      It       : Interp;
+      Imm_Type : Entity_Id;
+
+      function Valid_Ancestor_Type return Boolean;
+      --  Verify that the type of the ancestor part is a non-private ancestor
+      --  of the expected type.
+
+      function Valid_Ancestor_Type return Boolean is
+         Imm_Type : Entity_Id;
+
+      begin
+         Imm_Type := Base_Type (Typ);
+         while Is_Derived_Type (Imm_Type)
+           and then Etype (Imm_Type) /= Base_Type (A_Type)
+         loop
+            Imm_Type := Etype (Base_Type (Imm_Type));
+         end loop;
+
+         if Etype (Imm_Type) /= Base_Type (A_Type) then
+            Error_Msg_NE ("expect ancestor type of &", A, Typ);
+            return False;
+         else
+            return True;
+         end if;
+      end Valid_Ancestor_Type;
+
+   --  Start of processing for Resolve_Extension_Aggregate
+
+   begin
+      Analyze (A);
+
+      if not Is_Tagged_Type (Typ) then
+         Error_Msg_N ("type of extension aggregate must be tagged", N);
+         return;
+
+      elsif Is_Limited_Type (Typ) then
+         Error_Msg_N ("aggregate type cannot be limited", N);
+         return;
+
+      elsif Is_Class_Wide_Type (Typ) then
+         Error_Msg_N ("aggregate cannot be of a class-wide type", N);
+         return;
+      end if;
+
+      if Is_Entity_Name (A)
+        and then Is_Type (Entity (A))
+      then
+         A_Type   := Get_Full_View (Entity (A));
+         Imm_Type := Base_Type (Typ);
+
+         if Valid_Ancestor_Type then
+            Set_Entity (A, A_Type);
+            Set_Etype  (A, A_Type);
+
+            Validate_Ancestor_Part (N);
+            Resolve_Record_Aggregate (N, Typ);
+         end if;
+
+      elsif Nkind (A) /= N_Aggregate then
+         if Is_Overloaded (A) then
+            A_Type := Any_Type;
+            Get_First_Interp (A, I, It);
+
+            while Present (It.Typ) loop
+
+               if Is_Tagged_Type (It.Typ)
+                  and then not Is_Limited_Type (It.Typ)
+               then
+                  if A_Type /= Any_Type then
+                     Error_Msg_N ("cannot resolve expression", A);
+                     return;
+                  else
+                     A_Type := It.Typ;
+                  end if;
+               end if;
+
+               Get_Next_Interp (I, It);
+            end loop;
+
+            if A_Type = Any_Type then
+               Error_Msg_N
+                 ("ancestor part must be non-limited tagged type", A);
+               return;
+            end if;
+
+         else
+            A_Type := Etype (A);
+         end if;
+
+         if Valid_Ancestor_Type then
+            Resolve (A, A_Type);
+            Check_Non_Static_Context (A);
+            Resolve_Record_Aggregate (N, Typ);
+         end if;
+
+      else
+         Error_Msg_N (" No unique type for this aggregate",  A);
+      end if;
+
+   end Resolve_Extension_Aggregate;
+
+   ------------------------------
+   -- Resolve_Record_Aggregate --
+   ------------------------------
+
+   procedure Resolve_Record_Aggregate (N : Node_Id; Typ : Entity_Id) is
+      Regular_Aggr    : constant Boolean := Nkind (N) /= N_Extension_Aggregate;
+
+      New_Assoc_List  : List_Id := New_List;
+      New_Assoc       : Node_Id;
+      --  New_Assoc_List is the newly built list of N_Component_Association
+      --  nodes. New_Assoc is one such N_Component_Association node in it.
+      --  Please note that while Assoc and New_Assoc contain the same
+      --  kind of nodes, they are used to iterate over two different
+      --  N_Component_Association lists.
+
+      Others_Etype : Entity_Id := Empty;
+      --  This variable is used to save the Etype of the last record component
+      --  that takes its value from the others choice. Its purpose is:
+      --
+      --    (a) make sure the others choice is useful
+      --
+      --    (b) make sure the type of all the components whose value is
+      --        subsumed by the others choice are the same.
+      --
+      --  This variable is updated as a side effect of function Get_Value
+
+      procedure Add_Association (Component : Entity_Id; Expr : Node_Id);
+      --  Builds a new N_Component_Association node which associates
+      --  Component to expression Expr and adds it to the new association
+      --  list New_Assoc_List being built.
+
+      function Discr_Present (Discr : Entity_Id) return Boolean;
+      --  If aggregate N is a regular aggregate this routine will return True.
+      --  Otherwise, if N is an extension aggreagte, Discr is a discriminant
+      --  whose value may already have been specified by N's ancestor part,
+      --  this routine checks whether this is indeed the case and if so
+      --  returns False, signaling that no value for Discr should appear in the
+      --  N's aggregate part. Also, in this case, the routine appends to
+      --  New_Assoc_List Discr the discriminant value specified in the ancestor
+      --  part.
+
+      function Get_Value
+        (Compon                 : Node_Id;
+         From                   : List_Id;
+         Consider_Others_Choice : Boolean := False)
+         return                   Node_Id;
+      --  Given a record component stored in parameter Compon, the
+      --  following function returns its value as it appears in the list
+      --  From, which is a list of N_Component_Association nodes. If no
+      --  component association has a choice for the searched component,
+      --  the value provided by the others choice is returned, if there
+      --  is  one and Consider_Others_Choice is set to true. Otherwise
+      --  Empty is returned. If there is more than one component association
+      --  giving a value for the searched record component, an error message
+      --  is emitted and the first found value is returned.
+      --
+      --  If Consider_Others_Choice is set and the returned expression comes
+      --  from the others choice, then Others_Etype is set as a side effect.
+      --  An error message is emitted if the components taking their value
+      --  from the others choice do not have same type.
+
+      procedure Resolve_Aggr_Expr (Expr : Node_Id; Component : Node_Id);
+      --  Analyzes and resolves expression Expr against the Etype of the
+      --  Component. This routine also applies all appropiate checks to Expr.
+      --  It finally saves a Expr in the newly created association list that
+      --  will be attached to the final record aggregate. Note that if the
+      --  Parent pointer of Expr is not set then Expr was produced with a
+      --  New_copy_Tree or some such.
+
+      ---------------------
+      -- Add_Association --
+      ---------------------
+
+      procedure Add_Association (Component : Entity_Id; Expr : Node_Id) is
+         New_Assoc   : Node_Id;
+         Choice_List : List_Id := New_List;
+
+      begin
+         Append (New_Occurrence_Of (Component, Sloc (Expr)), Choice_List);
+         New_Assoc :=
+           Make_Component_Association (Sloc (Expr),
+             Choices    => Choice_List,
+             Expression => Expr);
+         Append (New_Assoc, New_Assoc_List);
+      end Add_Association;
+
+      -------------------
+      -- Discr_Present --
+      -------------------
+
+      function Discr_Present (Discr : Entity_Id) return Boolean is
+         Loc : Source_Ptr;
+
+         Ancestor     : Node_Id;
+         Discr_Expr   : Node_Id;
+
+         Ancestor_Typ : Entity_Id;
+         Orig_Discr   : Entity_Id;
+         D            : Entity_Id;
+         D_Val        : Elmt_Id := No_Elmt; -- stop junk warning
+
+         Ancestor_Is_Subtyp : Boolean;
+
+      begin
+         if Regular_Aggr then
+            return True;
+         end if;
+
+         Ancestor     := Ancestor_Part (N);
+         Ancestor_Typ := Etype (Ancestor);
+         Loc          := Sloc (Ancestor);
+
+         Ancestor_Is_Subtyp :=
+           Is_Entity_Name (Ancestor) and then Is_Type (Entity (Ancestor));
+
+         --  If the ancestor part has no discriminants clearly N's aggregate
+         --  part must provide a value for Discr.
+
+         if not Has_Discriminants (Ancestor_Typ) then
+            return True;
+
+         --  If the ancestor part is an unconstrained subtype mark then the
+         --  Discr must be present in N's aggregate part.
+
+         elsif Ancestor_Is_Subtyp
+           and then not Is_Constrained (Entity (Ancestor))
+         then
+            return True;
+         end if;
+
+         --  Now look to see if Discr was specified in the ancestor part.
+
+         Orig_Discr := Original_Record_Component (Discr);
+         D          := First_Discriminant (Ancestor_Typ);
+
+         if Ancestor_Is_Subtyp then
+            D_Val := First_Elmt (Discriminant_Constraint (Entity (Ancestor)));
+         end if;
+
+         while Present (D) loop
+            --  If Ancestor has already specified Disc value than
+            --  insert its value in the final aggregate.
+
+            if Original_Record_Component (D) = Orig_Discr then
+               if Ancestor_Is_Subtyp then
+                  Discr_Expr := New_Copy_Tree (Node (D_Val));
+               else
+                  Discr_Expr :=
+                    Make_Selected_Component (Loc,
+                      Prefix        => Duplicate_Subexpr (Ancestor),
+                      Selector_Name => New_Occurrence_Of (Discr, Loc));
+               end if;
+
+               Resolve_Aggr_Expr (Discr_Expr, Discr);
+               return False;
+            end if;
+
+            Next_Discriminant (D);
+
+            if Ancestor_Is_Subtyp then
+               Next_Elmt (D_Val);
+            end if;
+         end loop;
+
+         return True;
+      end Discr_Present;
+
+      ---------------
+      -- Get_Value --
+      ---------------
+
+      function Get_Value
+        (Compon                 : Node_Id;
+         From                   : List_Id;
+         Consider_Others_Choice : Boolean := False)
+         return                   Node_Id
+      is
+         Assoc         : Node_Id;
+         Expr          : Node_Id := Empty;
+         Selector_Name : Node_Id;
+
+      begin
+         if Present (From) then
+            Assoc := First (From);
+         else
+            return Empty;
+         end if;
+
+         while Present (Assoc) loop
+            Selector_Name := First (Choices (Assoc));
+            while Present (Selector_Name) loop
+               if Nkind (Selector_Name) = N_Others_Choice then
+                  if Consider_Others_Choice and then No (Expr) then
+                     if Present (Others_Etype) and then
+                        Base_Type (Others_Etype) /= Base_Type (Etype (Compon))
+                     then
+                        Error_Msg_N ("components in OTHERS choice must " &
+                                     "have same type", Selector_Name);
+                     end if;
+
+                     Others_Etype := Etype (Compon);
+
+                     --  We need to duplicate the expression for each
+                     --  successive component covered by the others choice.
+                     --  If the expression is itself an array aggregate with
+                     --  "others", its subtype must be obtained from the
+                     --  current component, and therefore it must be (at least
+                     --  partly) reanalyzed.
+
+                     if Analyzed (Expression (Assoc)) then
+                        Expr := New_Copy_Tree (Expression (Assoc));
+
+                        if Nkind (Expr) = N_Aggregate
+                          and then Is_Array_Type (Etype (Expr))
+                          and then No (Expressions (Expr))
+                          and then
+                            Nkind (First (Choices
+                              (First (Component_Associations (Expr)))))
+                                = N_Others_Choice
+                        then
+                           Set_Analyzed (Expr, False);
+                        end if;
+
+                        return Expr;
+
+                     else
+                        return Expression (Assoc);
+                     end if;
+                  end if;
+
+               elsif Chars (Compon) = Chars (Selector_Name) then
+                  if No (Expr) then
+                     --  We need to duplicate the expression when several
+                     --  components are grouped together with a "|" choice.
+                     --  For instance "filed1 | filed2 => Expr"
+
+                     if Present (Next (Selector_Name)) then
+                        Expr := New_Copy_Tree (Expression (Assoc));
+                     else
+                        Expr := Expression (Assoc);
+                     end if;
+
+                  else
+                     Error_Msg_NE
+                       ("more than one value supplied for &",
+                        Selector_Name, Compon);
+
+                  end if;
+               end if;
+
+               Next (Selector_Name);
+            end loop;
+
+            Next (Assoc);
+         end loop;
+
+         return Expr;
+      end Get_Value;
+
+      -----------------------
+      -- Resolve_Aggr_Expr --
+      -----------------------
+
+      procedure Resolve_Aggr_Expr (Expr : Node_Id; Component : Node_Id) is
+         New_C     : Entity_Id := Component;
+         Expr_Type : Entity_Id := Empty;
+
+         function Has_Expansion_Delayed (Expr : Node_Id) return Boolean;
+         --  If the expression is an aggregate (possibly qualified) then its
+         --  expansion is delayed until the enclosing aggregate is expanded
+         --  into assignments. In that case, do not generate checks on the
+         --  expression, because they will be generated later, and will other-
+         --  wise force a copy (to remove side-effects) that would leave a
+         --  dynamic-sized aggregate in the code, something that gigi cannot
+         --  handle.
+
+         Relocate  : Boolean;
+         --  Set to True if the resolved Expr node needs to be relocated
+         --  when attached to the newly created association list. This node
+         --  need not be relocated if its parent pointer is not set.
+         --  In fact in this case Expr is the output of a New_Copy_Tree call.
+         --  if Relocate is True then we have analyzed the expression node
+         --  in the original aggregate and hence it needs to be relocated
+         --  when moved over the new association list.
+
+         function Has_Expansion_Delayed (Expr : Node_Id) return Boolean is
+            Kind : constant Node_Kind := Nkind (Expr);
+
+         begin
+            return ((Kind = N_Aggregate
+                       or else Kind = N_Extension_Aggregate)
+                     and then Present (Etype (Expr))
+                     and then Is_Record_Type (Etype (Expr))
+                     and then Expansion_Delayed (Expr))
+
+              or else (Kind = N_Qualified_Expression
+                        and then Has_Expansion_Delayed (Expression (Expr)));
+         end Has_Expansion_Delayed;
+
+      --  Start of processing for  Resolve_Aggr_Expr
+
+      begin
+         --  If the type of the component is elementary or the type of the
+         --  aggregate does not contain discriminants, use the type of the
+         --  component to resolve Expr.
+
+         if Is_Elementary_Type (Etype (Component))
+           or else not Has_Discriminants (Etype (N))
+         then
+            Expr_Type := Etype (Component);
+
+         --  Otherwise we have to pick up the new type of the component from
+         --  the new costrained subtype of the aggregate. In fact components
+         --  which are of a composite type might be constrained by a
+         --  discriminant, and we want to resolve Expr against the subtype were
+         --  all discriminant occurrences are replaced with their actual value.
+
+         else
+            New_C := First_Component (Etype (N));
+            while Present (New_C) loop
+               if Chars (New_C) = Chars (Component) then
+                  Expr_Type := Etype (New_C);
+                  exit;
+               end if;
+
+               Next_Component (New_C);
+            end loop;
+
+            pragma Assert (Present (Expr_Type));
+
+            --  For each range in an array type where a discriminant has been
+            --  replaced with the constraint, check that this range is within
+            --  the range of the base type. This checks is done in the
+            --  _init_proc for regular objects, but has to be done here for
+            --  aggregates since no _init_proc is called for them.
+
+            if Is_Array_Type (Expr_Type) then
+               declare
+                  Index          : Node_Id := First_Index (Expr_Type);
+                  --  Range of the current constrained index in the array.
+
+                  Orig_Index     : Node_Id := First_Index (Etype (Component));
+                  --  Range corresponding to the range Index above in the
+                  --  original unconstrained record type. The bounds of this
+                  --  range may be governed by discriminants.
+
+                  Unconstr_Index : Node_Id := First_Index (Etype (Expr_Type));
+                  --  Range corresponding to the range Index above for the
+                  --  unconstrained array type. This range is needed to apply
+                  --  range checks.
+
+               begin
+                  while Present (Index) loop
+                     if Depends_On_Discriminant (Orig_Index) then
+                        Apply_Range_Check (Index, Etype (Unconstr_Index));
+                     end if;
+
+                     Next_Index (Index);
+                     Next_Index (Orig_Index);
+                     Next_Index (Unconstr_Index);
+                  end loop;
+               end;
+            end if;
+         end if;
+
+         --  If the Parent pointer of Expr is not set, Expr is an expression
+         --  duplicated by New_Tree_Copy (this happens for record aggregates
+         --  that look like (Field1 | Filed2 => Expr) or (others => Expr)).
+         --  Such a duplicated expression must be attached to the tree
+         --  before analysis and resolution to enforce the rule that a tree
+         --  fragment should never be analyzed or resolved unless it is
+         --  attached to the current compilation unit.
+
+         if No (Parent (Expr)) then
+            Set_Parent (Expr, N);
+            Relocate := False;
+         else
+            Relocate := True;
+         end if;
+
+         Analyze_And_Resolve (Expr, Expr_Type);
+         Check_Non_Static_Context (Expr);
+
+         if not Has_Expansion_Delayed (Expr) then
+            Aggregate_Constraint_Checks (Expr, Expr_Type);
+         end if;
+
+         if Raises_Constraint_Error (Expr) then
+            Set_Raises_Constraint_Error (N);
+         end if;
+
+         if Relocate then
+            Add_Association (New_C, Relocate_Node (Expr));
+         else
+            Add_Association (New_C, Expr);
+         end if;
+
+      end Resolve_Aggr_Expr;
+
+      --  Resolve_Record_Aggregate local variables
+
+      Assoc : Node_Id;
+      --  N_Component_Association node belonging to the input aggregate N
+
+      Expr            : Node_Id;
+      Positional_Expr : Node_Id;
+
+      Component      : Entity_Id;
+      Component_Elmt : Elmt_Id;
+      Components     : Elist_Id := New_Elmt_List;
+      --  Components is the list of the record components whose value must
+      --  be provided in the aggregate. This list does include discriminants.
+
+   --  Start of processing for Resolve_Record_Aggregate
+
+   begin
+      --  We may end up calling Duplicate_Subexpr on expressions that are
+      --  attached to New_Assoc_List. For this reason we need to attach it
+      --  to the tree by setting its parent pointer to N. This parent point
+      --  will change in STEP 8 below.
+
+      Set_Parent (New_Assoc_List, N);
+
+      --  STEP 1: abstract type and null record verification
+
+      if Is_Abstract (Typ) then
+         Error_Msg_N ("type of aggregate cannot be abstract",  N);
+      end if;
+
+      if No (First_Entity (Typ)) and then Null_Record_Present (N) then
+         Set_Etype (N, Typ);
+         return;
+
+      elsif Present (First_Entity (Typ))
+        and then Null_Record_Present (N)
+        and then not Is_Tagged_Type (Typ)
+      then
+         Error_Msg_N ("record aggregate cannot be null", N);
+         return;
+
+      elsif No (First_Entity (Typ)) then
+         Error_Msg_N ("record aggregate must be null", N);
+         return;
+      end if;
+
+      --  STEP 2: Verify aggregate structure
+
+      Step_2 : declare
+         Selector_Name : Node_Id;
+         Bad_Aggregate : Boolean := False;
+
+      begin
+         if Present (Component_Associations (N)) then
+            Assoc := First (Component_Associations (N));
+         else
+            Assoc := Empty;
+         end if;
+
+         while Present (Assoc) loop
+            Selector_Name := First (Choices (Assoc));
+            while Present (Selector_Name) loop
+               if Nkind (Selector_Name) = N_Identifier then
+                  null;
+
+               elsif Nkind (Selector_Name) = N_Others_Choice then
+                  if Selector_Name /= First (Choices (Assoc))
+                    or else Present (Next (Selector_Name))
+                  then
+                     Error_Msg_N ("OTHERS must appear alone in a choice list",
+                                  Selector_Name);
+                     return;
+
+                  elsif Present (Next (Assoc)) then
+                     Error_Msg_N ("OTHERS must appear last in an aggregate",
+                                  Selector_Name);
+                     return;
+                  end if;
+
+               else
+                  Error_Msg_N
+                    ("selector name should be identifier or OTHERS",
+                     Selector_Name);
+                  Bad_Aggregate := True;
+               end if;
+
+               Next (Selector_Name);
+            end loop;
+
+            Next (Assoc);
+         end loop;
+
+         if Bad_Aggregate then
+            return;
+         end if;
+      end Step_2;
+
+      --  STEP 3: Find discriminant Values
+
+      Step_3 : declare
+         Discrim               : Entity_Id;
+         Missing_Discriminants : Boolean := False;
+
+      begin
+         if Present (Expressions (N)) then
+            Positional_Expr := First (Expressions (N));
+         else
+            Positional_Expr := Empty;
+         end if;
+
+         if Has_Discriminants (Typ) then
+            Discrim := First_Discriminant (Typ);
+         else
+            Discrim := Empty;
+         end if;
+
+         --  First find the discriminant values in the positional components
+
+         while Present (Discrim) and then Present (Positional_Expr) loop
+            if Discr_Present (Discrim) then
+               Resolve_Aggr_Expr (Positional_Expr, Discrim);
+               Next (Positional_Expr);
+            end if;
+
+            if Present (Get_Value (Discrim, Component_Associations (N))) then
+               Error_Msg_NE
+                 ("more than one value supplied for discriminant&",
+                  N, Discrim);
+            end if;
+
+            Next_Discriminant (Discrim);
+         end loop;
+
+         --  Find remaining discriminant values, if any, among named components
+
+         while Present (Discrim) loop
+            Expr := Get_Value (Discrim, Component_Associations (N), True);
+
+            if not Discr_Present (Discrim) then
+               if Present (Expr) then
+                  Error_Msg_NE
+                    ("more than one value supplied for discriminant&",
+                     N, Discrim);
+               end if;
+
+            elsif No (Expr) then
+               Error_Msg_NE
+                 ("no value supplied for discriminant &", N, Discrim);
+               Missing_Discriminants := True;
+
+            else
+               Resolve_Aggr_Expr (Expr, Discrim);
+            end if;
+
+            Next_Discriminant (Discrim);
+         end loop;
+
+         if Missing_Discriminants then
+            return;
+         end if;
+
+         --  At this point and until the beginning of STEP 6, New_Assoc_List
+         --  contains only the discriminants and their values.
+
+      end Step_3;
+
+      --  STEP 4: Set the Etype of the record aggregate
+
+      --  ??? This code is pretty much a copy of Sem_Ch3.Build_Subtype. That
+      --  routine should really be exported in sem_util or some such and used
+      --  in sem_ch3 and here rather than have a copy of the code which is a
+      --  maintenance nightmare.
+
+      --  ??? Performace WARNING. The current implementation creates a new
+      --  itype for all aggregates whose base type is discriminated.
+      --  This means that for record aggregates nested inside an array
+      --  aggregate we will create a new itype for each record aggregate
+      --  if the array cmponent type has discriminants. For large aggregates
+      --  this may be a problem. What should be done in this case is
+      --  to reuse itypes as much as possible.
+
+      if Has_Discriminants (Typ) then
+         Build_Constrained_Itype : declare
+            Loc         : constant Source_Ptr := Sloc (N);
+            Indic       : Node_Id;
+            Subtyp_Decl : Node_Id;
+            Def_Id      : Entity_Id;
+
+            C : List_Id := New_List;
+
+         begin
+            New_Assoc := First (New_Assoc_List);
+            while Present (New_Assoc) loop
+               Append (Duplicate_Subexpr (Expression (New_Assoc)), To => C);
+               Next (New_Assoc);
+            end loop;
+
+            Indic :=
+              Make_Subtype_Indication (Loc,
+                Subtype_Mark => New_Occurrence_Of (Base_Type (Typ), Loc),
+                Constraint  => Make_Index_Or_Discriminant_Constraint (Loc, C));
+
+            Def_Id := Create_Itype (Ekind (Typ), N);
+
+            Subtyp_Decl :=
+              Make_Subtype_Declaration (Loc,
+                Defining_Identifier => Def_Id,
+                Subtype_Indication  => Indic);
+            Set_Parent (Subtyp_Decl, Parent (N));
+
+            --  Itypes must be analyzed with checks off (see itypes.ads).
+
+            Analyze (Subtyp_Decl, Suppress => All_Checks);
+
+            Set_Etype (N, Def_Id);
+            Check_Static_Discriminated_Subtype
+              (Def_Id, Expression (First (New_Assoc_List)));
+         end Build_Constrained_Itype;
+
+      else
+         Set_Etype (N, Typ);
+      end if;
+
+      --  STEP 5: Get remaining components according to discriminant values
+
+      Step_5 : declare
+         Record_Def      : Node_Id;
+         Parent_Typ      : Entity_Id;
+         Root_Typ        : Entity_Id;
+         Parent_Typ_List : Elist_Id;
+         Parent_Elmt     : Elmt_Id;
+         Errors_Found    : Boolean := False;
+         Dnode           : Node_Id;
+
+      begin
+         if Is_Derived_Type (Typ) and then Is_Tagged_Type (Typ) then
+            Parent_Typ_List := New_Elmt_List;
+
+            --  If this is an extension aggregate, the component list must
+            --  include all components that are not in the given ancestor
+            --  type. Otherwise, the component list must include components
+            --  of all ancestors.
+
+            if Nkind (N) = N_Extension_Aggregate then
+               Root_Typ := Base_Type (Etype (Ancestor_Part (N)));
+            else
+               Root_Typ := Root_Type (Typ);
+
+               if Nkind (Parent (Base_Type (Root_Typ)))
+                    = N_Private_Type_Declaration
+               then
+                  Error_Msg_NE
+                    ("type of aggregate has private ancestor&!",
+                     N, Root_Typ);
+                  Error_Msg_N  ("must use extension aggregate!", N);
+                  return;
+               end if;
+
+               Dnode := Declaration_Node (Base_Type (Root_Typ));
+
+               --  If we don't get a full declaration, then we have some
+               --  error which will get signalled later so skip this part.
+
+               if Nkind (Dnode) = N_Full_Type_Declaration then
+                  Record_Def := Type_Definition (Dnode);
+                  Gather_Components (Typ,
+                    Component_List (Record_Def),
+                    Governed_By   => New_Assoc_List,
+                    Into          => Components,
+                    Report_Errors => Errors_Found);
+               end if;
+            end if;
+
+            Parent_Typ  := Base_Type (Typ);
+            while Parent_Typ /= Root_Typ loop
+
+               Prepend_Elmt (Parent_Typ, To => Parent_Typ_List);
+               Parent_Typ := Etype (Parent_Typ);
+
+               if (Nkind (Parent (Base_Type (Parent_Typ))) =
+                                        N_Private_Type_Declaration
+                    or else Nkind (Parent (Base_Type (Parent_Typ))) =
+                                        N_Private_Extension_Declaration)
+               then
+                  if Nkind (N) /= N_Extension_Aggregate then
+                     Error_Msg_NE
+                       ("type of aggregate has private ancestor&!",
+                        N, Parent_Typ);
+                     Error_Msg_N  ("must use extension aggregate!", N);
+                     return;
+
+                  elsif Parent_Typ /= Root_Typ then
+                     Error_Msg_NE
+                       ("ancestor part of aggregate must be private type&",
+                         Ancestor_Part (N), Parent_Typ);
+                     return;
+                  end if;
+               end if;
+            end loop;
+
+            --  Now collect components from all other ancestors.
+
+            Parent_Elmt := First_Elmt (Parent_Typ_List);
+            while Present (Parent_Elmt) loop
+               Parent_Typ := Node (Parent_Elmt);
+               Record_Def := Type_Definition (Parent (Base_Type (Parent_Typ)));
+               Gather_Components (Empty,
+                 Component_List (Record_Extension_Part (Record_Def)),
+                 Governed_By   => New_Assoc_List,
+                 Into          => Components,
+                 Report_Errors => Errors_Found);
+
+               Next_Elmt (Parent_Elmt);
+            end loop;
+
+         else
+            Record_Def := Type_Definition (Parent (Base_Type (Typ)));
+
+            if Null_Present (Record_Def) then
+               null;
+            else
+               Gather_Components (Typ,
+                 Component_List (Record_Def),
+                 Governed_By   => New_Assoc_List,
+                 Into          => Components,
+                 Report_Errors => Errors_Found);
+            end if;
+         end if;
+
+         if Errors_Found then
+            return;
+         end if;
+      end Step_5;
+
+      --  STEP 6: Find component Values
+
+      Component := Empty;
+      Component_Elmt := First_Elmt (Components);
+
+      --  First scan the remaining positional associations in the aggregate.
+      --  Remember that at this point Positional_Expr contains the current
+      --  positional association if any is left after looking for discriminant
+      --  values in step 3.
+
+      while Present (Positional_Expr) and then Present (Component_Elmt) loop
+         Component := Node (Component_Elmt);
+         Resolve_Aggr_Expr (Positional_Expr, Component);
+
+         if Present (Get_Value (Component, Component_Associations (N))) then
+            Error_Msg_NE
+              ("more than one value supplied for Component &", N, Component);
+         end if;
+
+         Next (Positional_Expr);
+         Next_Elmt (Component_Elmt);
+      end loop;
+
+      if Present (Positional_Expr) then
+         Error_Msg_N
+           ("too many components for record aggregate", Positional_Expr);
+      end if;
+
+      --  Now scan for the named arguments of the aggregate
+
+      while Present (Component_Elmt) loop
+         Component := Node (Component_Elmt);
+         Expr := Get_Value (Component, Component_Associations (N), True);
+
+         if No (Expr) then
+            Error_Msg_NE ("no value supplied for component &!", N, Component);
+         else
+            Resolve_Aggr_Expr (Expr, Component);
+         end if;
+
+         Next_Elmt (Component_Elmt);
+      end loop;
+
+      --  STEP 7: check for invalid components + check type in choice list
+
+      Step_7 : declare
+         Selectr : Node_Id;
+         --  Selector name
+
+         Typech  : Entity_Id;
+         --  Type of first component in choice list
+
+      begin
+         if Present (Component_Associations (N)) then
+            Assoc := First (Component_Associations (N));
+         else
+            Assoc := Empty;
+         end if;
+
+         Verification : while Present (Assoc) loop
+            Selectr := First (Choices (Assoc));
+            Typech := Empty;
+
+            if Nkind (Selectr) = N_Others_Choice then
+               if No (Others_Etype) then
+                  Error_Msg_N
+                    ("OTHERS must represent at least one component", Selectr);
+               end if;
+
+               exit Verification;
+            end if;
+
+            while Present (Selectr) loop
+               New_Assoc := First (New_Assoc_List);
+               while Present (New_Assoc) loop
+                  Component := First (Choices (New_Assoc));
+                  exit when Chars (Selectr) = Chars (Component);
+                  Next (New_Assoc);
+               end loop;
+
+               --  If no association, this is not a legal component of
+               --  of the type in question,  except if this is an internal
+               --  component supplied by a previous expansion.
+
+               if No (New_Assoc) then
+
+                  if Chars (Selectr) /= Name_uTag
+                    and then Chars (Selectr) /= Name_uParent
+                    and then Chars (Selectr) /= Name_uController
+                  then
+                     if not Has_Discriminants (Typ) then
+                        Error_Msg_Node_2 := Typ;
+                        Error_Msg_N
+                          ("& is not a component of}",
+                            Selectr);
+                     else
+                        Error_Msg_N
+                          ("& is not a component of the aggregate subtype",
+                            Selectr);
+                     end if;
+
+                     Check_Misspelled_Component (Components, Selectr);
+                  end if;
+
+               elsif No (Typech) then
+                  Typech := Base_Type (Etype (Component));
+
+               elsif Typech /= Base_Type (Etype (Component)) then
+                  Error_Msg_N
+                    ("components in choice list must have same type", Selectr);
+               end if;
+
+               Next (Selectr);
+            end loop;
+
+            Next (Assoc);
+         end loop Verification;
+      end Step_7;
+
+      --  STEP 8: replace the original aggregate
+
+      Step_8 : declare
+         New_Aggregate : Node_Id := New_Copy (N);
+
+      begin
+         Set_Expressions            (New_Aggregate, No_List);
+         Set_Etype                  (New_Aggregate, Etype (N));
+         Set_Component_Associations (New_Aggregate, New_Assoc_List);
+
+         Rewrite (N, New_Aggregate);
+      end Step_8;
+   end Resolve_Record_Aggregate;
+
+   ---------------------
+   -- Sort_Case_Table --
+   ---------------------
+
+   procedure Sort_Case_Table (Case_Table : in out Case_Table_Type) is
+      L : Int := Case_Table'First;
+      U : Int := Case_Table'Last;
+      K : Int;
+      J : Int;
+      T : Case_Bounds;
+
+   begin
+      K := L;
+
+      while K /= U loop
+         T := Case_Table (K + 1);
+         J := K + 1;
+
+         while J /= L
+           and then Expr_Value (Case_Table (J - 1).Choice_Lo) >
+                    Expr_Value (T.Choice_Lo)
+         loop
+            Case_Table (J) := Case_Table (J - 1);
+            J := J - 1;
+         end loop;
+
+         Case_Table (J) := T;
+         K := K + 1;
+      end loop;
+   end Sort_Case_Table;
+
+end Sem_Aggr;
diff --git a/gcc/ada/sem_aggr.ads b/gcc/ada/sem_aggr.ads
new file mode 100644 (file)
index 0000000..41a4bd7
--- /dev/null
@@ -0,0 +1,39 @@
+------------------------------------------------------------------------------
+--                                                                          --
+--                         GNAT COMPILER COMPONENTS                         --
+--                                                                          --
+--                             S E M _ A G G R                              --
+--                                                                          --
+--                                 S p e c                                  --
+--                                                                          --
+--                            $Revision: 1.3 $                              --
+--                                                                          --
+--        Copyright (C) 1992,1993,1994 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- --
+-- ware  Foundation;  either version 2,  or (at your option) any later ver- --
+-- sion.  GNAT is distributed in the hope that it will be useful, but WITH- --
+-- OUT ANY WARRANTY;  without even the  implied warranty of MERCHANTABILITY --
+-- or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License --
+-- for  more details.  You should have  received  a copy of the GNU General --
+-- Public License  distributed with GNAT;  see file COPYING.  If not, write --
+-- to  the Free Software Foundation,  59 Temple Place - Suite 330,  Boston, --
+-- MA 02111-1307, USA.                                                      --
+--                                                                          --
+-- GNAT was originally developed  by the GNAT team at  New York University. --
+-- It is now maintained by Ada Core Technologies Inc (http://www.gnat.com). --
+--                                                                          --
+------------------------------------------------------------------------------
+
+--  This package contains the resolution code for aggregates. It is logically
+--  part of Sem_Res, but is split off since the aggregate code is so complex.
+
+with Types; use Types;
+
+package Sem_Aggr is
+
+   procedure Resolve_Aggregate           (N : Node_Id; Typ : Entity_Id);
+   procedure Resolve_Extension_Aggregate (N : Node_Id; Typ : Entity_Id);
+
+end Sem_Aggr;
diff --git a/gcc/ada/sem_attr.adb b/gcc/ada/sem_attr.adb
new file mode 100644 (file)
index 0000000..4574315
--- /dev/null
@@ -0,0 +1,6822 @@
+------------------------------------------------------------------------------
+--                                                                          --
+--                         GNAT COMPILER COMPONENTS                         --
+--                                                                          --
+--                             S E M _ A T T R                              --
+--                                                                          --
+--                                 B o d y                                  --
+--                                                                          --
+--                            $Revision: 1.552 $
+--                                                                          --
+--          Copyright (C) 1992-2001, 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- --
+-- ware  Foundation;  either version 2,  or (at your option) any later ver- --
+-- sion.  GNAT is distributed in the hope that it will be useful, but WITH- --
+-- OUT ANY WARRANTY;  without even the  implied warranty of MERCHANTABILITY --
+-- or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License --
+-- for  more details.  You should have  received  a copy of the GNU General --
+-- Public License  distributed with GNAT;  see file COPYING.  If not, write --
+-- to  the Free Software Foundation,  59 Temple Place - Suite 330,  Boston, --
+-- MA 02111-1307, USA.                                                      --
+--                                                                          --
+-- GNAT was originally developed  by the GNAT team at  New York University. --
+-- It is now maintained by Ada Core Technologies Inc (http://www.gnat.com). --
+--                                                                          --
+------------------------------------------------------------------------------
+
+with Ada.Characters.Latin_1; use Ada.Characters.Latin_1;
+
+with Atree;    use Atree;
+with Checks;   use Checks;
+with Einfo;    use Einfo;
+with Errout;   use Errout;
+with Eval_Fat;
+with Exp_Tss;  use Exp_Tss;
+with Exp_Util; use Exp_Util;
+with Expander; use Expander;
+with Freeze;   use Freeze;
+with Lib.Xref; use Lib.Xref;
+with Namet;    use Namet;
+with Nlists;   use Nlists;
+with Nmake;    use Nmake;
+with Opt;      use Opt;
+with Restrict; use Restrict;
+with Rtsfind;  use Rtsfind;
+with Sem;      use Sem;
+with Sem_Cat;  use Sem_Cat;
+with Sem_Ch6;  use Sem_Ch6;
+with Sem_Ch8;  use Sem_Ch8;
+with Sem_Ch13; use Sem_Ch13;
+with Sem_Dist; use Sem_Dist;
+with Sem_Eval; use Sem_Eval;
+with Sem_Res;  use Sem_Res;
+with Sem_Type; use Sem_Type;
+with Sem_Util; use Sem_Util;
+with Stand;    use Stand;
+with Sinfo;    use Sinfo;
+with Sinput;   use Sinput;
+with Snames;   use Snames;
+with Stand;
+with Stringt;  use Stringt;
+with Targparm; use Targparm;
+with Ttypes;   use Ttypes;
+with Ttypef;   use Ttypef;
+with Tbuild;   use Tbuild;
+with Uintp;    use Uintp;
+with Urealp;   use Urealp;
+with Widechar; use Widechar;
+
+package body Sem_Attr is
+
+   True_Value  : constant Uint := Uint_1;
+   False_Value : constant Uint := Uint_0;
+   --  Synonyms to be used when these constants are used as Boolean values
+
+   Bad_Attribute : exception;
+   --  Exception raised if an error is detected during attribute processing,
+   --  used so that we can abandon the processing so we don't run into
+   --  trouble with cascaded errors.
+
+   --  The following array is the list of attributes defined in the Ada 83 RM
+
+   Attribute_83 : Attribute_Class_Array := Attribute_Class_Array'(
+      Attribute_Address           |
+      Attribute_Aft               |
+      Attribute_Alignment         |
+      Attribute_Base              |
+      Attribute_Callable          |
+      Attribute_Constrained       |
+      Attribute_Count             |
+      Attribute_Delta             |
+      Attribute_Digits            |
+      Attribute_Emax              |
+      Attribute_Epsilon           |
+      Attribute_First             |
+      Attribute_First_Bit         |
+      Attribute_Fore              |
+      Attribute_Image             |
+      Attribute_Large             |
+      Attribute_Last              |
+      Attribute_Last_Bit          |
+      Attribute_Leading_Part      |
+      Attribute_Length            |
+      Attribute_Machine_Emax      |
+      Attribute_Machine_Emin      |
+      Attribute_Machine_Mantissa  |
+      Attribute_Machine_Overflows |
+      Attribute_Machine_Radix     |
+      Attribute_Machine_Rounds    |
+      Attribute_Mantissa          |
+      Attribute_Pos               |
+      Attribute_Position          |
+      Attribute_Pred              |
+      Attribute_Range             |
+      Attribute_Safe_Emax         |
+      Attribute_Safe_Large        |
+      Attribute_Safe_Small        |
+      Attribute_Size              |
+      Attribute_Small             |
+      Attribute_Storage_Size      |
+      Attribute_Succ              |
+      Attribute_Terminated        |
+      Attribute_Val               |
+      Attribute_Value             |
+      Attribute_Width             => True,
+      others                      => False);
+
+   -----------------------
+   -- Local_Subprograms --
+   -----------------------
+
+   procedure Eval_Attribute (N : Node_Id);
+   --  Performs compile time evaluation of attributes where possible, leaving
+   --  the Is_Static_Expression/Raises_Constraint_Error flags appropriately
+   --  set, and replacing the node with a literal node if the value can be
+   --  computed at compile time. All static attribute references are folded,
+   --  as well as a number of cases of non-static attributes that can always
+   --  be computed at compile time (e.g. floating-point model attributes that
+   --  are applied to non-static subtypes). Of course in such cases, the
+   --  Is_Static_Expression flag will not be set on the resulting literal.
+   --  Note that the only required action of this procedure is to catch the
+   --  static expression cases as described in the RM. Folding of other cases
+   --  is done where convenient, but some additional non-static folding is in
+   --  N_Expand_Attribute_Reference in cases where this is more convenient.
+
+   function Is_Anonymous_Tagged_Base
+     (Anon : Entity_Id;
+      Typ  : Entity_Id)
+      return Boolean;
+   --  For derived tagged types that constrain parent discriminants we build
+   --  an anonymous unconstrained base type. We need to recognize the relation
+   --  between the two when analyzing an access attribute for a constrained
+   --  component, before the full declaration for Typ has been analyzed, and
+   --  where therefore the prefix of the attribute does not match the enclosing
+   --  scope.
+
+   -----------------------
+   -- Analyze_Attribute --
+   -----------------------
+
+   procedure Analyze_Attribute (N : Node_Id) is
+      Loc     : constant Source_Ptr   := Sloc (N);
+      Aname   : constant Name_Id      := Attribute_Name (N);
+      P       : constant Node_Id      := Prefix (N);
+      Exprs   : constant List_Id      := Expressions (N);
+      Attr_Id : constant Attribute_Id := Get_Attribute_Id (Aname);
+      E1      : Node_Id;
+      E2      : Node_Id;
+
+      P_Type : Entity_Id;
+      --  Type of prefix after analysis
+
+      P_Base_Type : Entity_Id;
+      --  Base type of prefix after analysis
+
+      P_Root_Type : Entity_Id;
+      --  Root type of prefix after analysis
+
+      Unanalyzed  : Node_Id;
+
+      -----------------------
+      -- Local Subprograms --
+      -----------------------
+
+      procedure Access_Attribute;
+      --  Used for Access, Unchecked_Access, Unrestricted_Access attributes.
+      --  Internally, Id distinguishes which of the three cases is involved.
+
+      procedure Check_Array_Or_Scalar_Type;
+      --  Common procedure used by First, Last, Range attribute to check
+      --  that the prefix is a constrained array or scalar type, or a name
+      --  of an array object, and that an argument appears only if appropriate
+      --  (i.e. only in the array case).
+
+      procedure Check_Array_Type;
+      --  Common semantic checks for all array attributes. Checks that the
+      --  prefix is a constrained array type or the name of an array object.
+      --  The error message for non-arrays is specialized appropriately.
+
+      procedure Check_Asm_Attribute;
+      --  Common semantic checks for Asm_Input and Asm_Output attributes
+
+      procedure Check_Component;
+      --  Common processing for Bit_Position, First_Bit, Last_Bit, and
+      --  Position. Checks prefix is an appropriate selected component.
+
+      procedure Check_Decimal_Fixed_Point_Type;
+      --  Check that prefix of attribute N is a decimal fixed-point type
+
+      procedure Check_Dereference;
+      --  If the prefix of attribute is an object of an access type, then
+      --  introduce an explicit deference, and adjust P_Type accordingly.
+
+      procedure Check_Discrete_Type;
+      --  Verify that prefix of attribute N is a discrete type
+
+      procedure Check_E0;
+      --  Check that no attribute arguments are present
+
+      procedure Check_Either_E0_Or_E1;
+      --  Check that there are zero or one attribute arguments present
+
+      procedure Check_E1;
+      --  Check that exactly one attribute argument is present
+
+      procedure Check_E2;
+      --  Check that two attribute arguments are present
+
+      procedure Check_Enum_Image;
+      --  If the prefix type is an enumeration type, set all its literals
+      --  as referenced, since the image function could possibly end up
+      --  referencing any of the literals indirectly.
+
+      procedure Check_Enumeration_Type;
+      --  Verify that prefix of attribute N is an enumeration type
+
+      procedure Check_Fixed_Point_Type;
+      --  Verify that prefix of attribute N is a fixed type
+
+      procedure Check_Fixed_Point_Type_0;
+      --  Verify that prefix of attribute N is a fixed type and that
+      --  no attribute expressions are present
+
+      procedure Check_Floating_Point_Type;
+      --  Verify that prefix of attribute N is a float type
+
+      procedure Check_Floating_Point_Type_0;
+      --  Verify that prefix of attribute N is a float type and that
+      --  no attribute expressions are present
+
+      procedure Check_Floating_Point_Type_1;
+      --  Verify that prefix of attribute N is a float type and that
+      --  exactly one attribute expression is present
+
+      procedure Check_Floating_Point_Type_2;
+      --  Verify that prefix of attribute N is a float type and that
+      --  two attribute expressions are present
+
+      procedure Legal_Formal_Attribute;
+      --  Common processing for attributes Definite, and Has_Discriminants
+
+      procedure Check_Integer_Type;
+      --  Verify that prefix of attribute N is an integer type
+
+      procedure Check_Library_Unit;
+      --  Verify that prefix of attribute N is a library unit
+
+      procedure Check_Not_Incomplete_Type;
+      --  Check that P (the prefix of the attribute) is not an incomplete
+      --  type or a private type for which no full view has been given.
+
+      procedure Check_Object_Reference (P : Node_Id);
+      --  Check that P (the prefix of the attribute) is an object reference
+
+      procedure Check_Program_Unit;
+      --  Verify that prefix of attribute N is a program unit
+
+      procedure Check_Real_Type;
+      --  Verify that prefix of attribute N is fixed or float type
+
+      procedure Check_Scalar_Type;
+      --  Verify that prefix of attribute N is a scalar type
+
+      procedure Check_Standard_Prefix;
+      --  Verify that prefix of attribute N is package Standard
+
+      procedure Check_Stream_Attribute (Nam : Name_Id);
+      --  Validity checking for stream attribute. Nam is the name of the
+      --  corresponding possible defined attribute function (e.g. for the
+      --  Read attribute, Nam will be Name_uRead).
+
+      procedure Check_Task_Prefix;
+      --  Verify that prefix of attribute N is a task or task type
+
+      procedure Check_Type;
+      --  Verify that the prefix of attribute N is a type
+
+      procedure Check_Unit_Name (Nod : Node_Id);
+      --  Check that Nod is of the form of a library unit name, i.e that
+      --  it is an identifier, or a selected component whose prefix is
+      --  itself of the form of a library unit name. Note that this is
+      --  quite different from Check_Program_Unit, since it only checks
+      --  the syntactic form of the name, not the semantic identity. This
+      --  is because it is used with attributes (Elab_Body, Elab_Spec, and
+      --  UET_Address) which can refer to non-visible unit.
+
+      procedure Error_Attr (Msg : String; Error_Node : Node_Id);
+      pragma No_Return (Error_Attr);
+      --  Posts error using Error_Msg_N at given node, sets type of attribute
+      --  node to Any_Type, and then raises Bad_Attribute to avoid any further
+      --  semantic processing. The message typically contains a % insertion
+      --  character which is replaced by the attribute name.
+
+      procedure Standard_Attribute (Val : Int);
+      --  Used to process attributes whose prefix is package Standard which
+      --  yield values of type Universal_Integer. The attribute reference
+      --  node is rewritten with an integer literal of the given value.
+
+      procedure Unexpected_Argument (En : Node_Id);
+      --  Signal unexpected attribute argument (En is the argument)
+
+      procedure Validate_Non_Static_Attribute_Function_Call;
+      --  Called when processing an attribute that is a function call to a
+      --  non-static function, i.e. an attribute function that either takes
+      --  non-scalar arguments or returns a non-scalar result. Verifies that
+      --  such a call does not appear in a preelaborable context.
+
+      ----------------------
+      -- Access_Attribute --
+      ----------------------
+
+      procedure Access_Attribute is
+         Acc_Type : Entity_Id;
+
+         Scop : Entity_Id;
+         Typ  : Entity_Id;
+
+         function Build_Access_Object_Type (DT : Entity_Id) return Entity_Id;
+         --  Build an access-to-object type whose designated type is DT,
+         --  and whose Ekind is appropriate to the attribute type. The
+         --  type that is constructed is returned as the result.
+
+         procedure Build_Access_Subprogram_Type (P : Node_Id);
+         --  Build an access to subprogram whose designated type is
+         --  the type of the prefix. If prefix is overloaded, so it the
+         --  node itself. The result is stored in Acc_Type.
+
+         ------------------------------
+         -- Build_Access_Object_Type --
+         ------------------------------
+
+         function Build_Access_Object_Type (DT : Entity_Id) return Entity_Id is
+            Typ : Entity_Id;
+
+         begin
+            if Aname = Name_Unrestricted_Access then
+               Typ :=
+                 New_Internal_Entity
+                   (E_Allocator_Type, Current_Scope, Loc, 'A');
+            else
+               Typ :=
+                 New_Internal_Entity
+                   (E_Access_Attribute_Type, Current_Scope, Loc, 'A');
+            end if;
+
+            Set_Etype                     (Typ, Typ);
+            Init_Size_Align               (Typ);
+            Set_Is_Itype                  (Typ);
+            Set_Associated_Node_For_Itype (Typ, N);
+            Set_Directly_Designated_Type  (Typ, DT);
+            return Typ;
+         end Build_Access_Object_Type;
+
+         ----------------------------------
+         -- Build_Access_Subprogram_Type --
+         ----------------------------------
+
+         procedure Build_Access_Subprogram_Type (P : Node_Id) is
+            Index    : Interp_Index;
+            It       : Interp;
+
+            function Get_Kind (E : Entity_Id) return Entity_Kind;
+            --  Distinguish between access to regular and protected
+            --  subprograms.
+
+            function Get_Kind (E : Entity_Id) return Entity_Kind is
+            begin
+               if Convention (E) = Convention_Protected then
+                  return E_Access_Protected_Subprogram_Type;
+               else
+                  return E_Access_Subprogram_Type;
+               end if;
+            end Get_Kind;
+
+         --  Start of processing for Build_Access_Subprogram_Type
+
+         begin
+            if not Is_Overloaded (P) then
+               Acc_Type :=
+                 New_Internal_Entity
+                   (Get_Kind (Entity (P)), Current_Scope, Loc, 'A');
+               Set_Etype (Acc_Type, Acc_Type);
+               Set_Directly_Designated_Type (Acc_Type, Entity (P));
+               Set_Etype (N, Acc_Type);
+
+            else
+               Get_First_Interp (P, Index, It);
+               Set_Etype (N, Any_Type);
+
+               while Present (It.Nam) loop
+
+                  if not Is_Intrinsic_Subprogram (It.Nam) then
+                     Acc_Type :=
+                       New_Internal_Entity
+                         (Get_Kind (It.Nam), Current_Scope, Loc, 'A');
+                     Set_Etype (Acc_Type, Acc_Type);
+                     Set_Directly_Designated_Type (Acc_Type, It.Nam);
+                     Add_One_Interp (N, Acc_Type, Acc_Type);
+                  end if;
+
+                  Get_Next_Interp (Index, It);
+               end loop;
+
+               if Etype (N) = Any_Type then
+                  Error_Attr ("prefix of % attribute cannot be intrinsic", P);
+               end if;
+            end if;
+         end Build_Access_Subprogram_Type;
+
+      --  Start of processing for Access_Attribute
+
+      begin
+         Check_E0;
+
+         if Nkind (P) = N_Character_Literal then
+            Error_Attr
+              ("prefix of % attribute cannot be enumeration literal", P);
+
+         --  In the case of an access to subprogram, use the name of the
+         --  subprogram itself as the designated type. Type-checking in
+         --  this case compares the signatures of the designated types.
+
+         elsif Is_Entity_Name (P)
+           and then Is_Overloadable (Entity (P))
+         then
+            Build_Access_Subprogram_Type (P);
+            return;
+
+         --  Component is an operation of a protected type.
+
+         elsif (Nkind (P) = N_Selected_Component
+           and then Is_Overloadable (Entity (Selector_Name (P))))
+         then
+            if Ekind (Entity (Selector_Name (P))) = E_Entry then
+               Error_Attr ("Prefix of % attribute must be subprogram", P);
+            end if;
+
+            Build_Access_Subprogram_Type (Selector_Name (P));
+            return;
+         end if;
+
+         --  Deal with incorrect reference to a type, but note that some
+         --  accesses are allowed (references to the current type instance).
+
+         if Is_Entity_Name (P) then
+            Scop := Current_Scope;
+            Typ := Entity (P);
+
+            if Is_Type (Typ) then
+
+               --  OK if we are within the scope of a limited type
+               --  let's mark the component as having per object constraint
+
+               if Is_Anonymous_Tagged_Base (Scop, Typ) then
+                  Typ := Scop;
+                  Set_Entity (P, Typ);
+                  Set_Etype  (P, Typ);
+               end if;
+
+               if Typ = Scop then
+                  declare
+                     Q : Node_Id := Parent (N);
+
+                  begin
+                     while Present (Q)
+                       and then Nkind (Q) /= N_Component_Declaration
+                     loop
+                        Q := Parent (Q);
+                     end loop;
+                     if Present (Q) then
+                        Set_Has_Per_Object_Constraint (
+                          Defining_Identifier (Q), True);
+                     end if;
+                  end;
+
+                  if Nkind (P) = N_Expanded_Name then
+                     Error_Msg_N
+                       ("current instance prefix must be a direct name", P);
+                  end if;
+
+                  --  If a current instance attribute appears within a
+                  --  a component constraint it must appear alone; other
+                  --  contexts (default expressions, within a task body)
+                  --  are not subject to this restriction.
+
+                  if not In_Default_Expression
+                    and then not Has_Completion (Scop)
+                    and then
+                      Nkind (Parent (N)) /= N_Discriminant_Association
+                    and then
+                      Nkind (Parent (N)) /= N_Index_Or_Discriminant_Constraint
+                  then
+                     Error_Msg_N
+                       ("current instance attribute must appear alone", N);
+                  end if;
+
+               --  OK if we are in initialization procedure for the type
+               --  in question, in which case the reference to the type
+               --  is rewritten as a reference to the current object.
+
+               elsif Ekind (Scop) = E_Procedure
+                 and then Chars (Scop) = Name_uInit_Proc
+                 and then Etype (First_Formal (Scop)) = Typ
+               then
+                  Rewrite (N,
+                    Make_Attribute_Reference (Loc,
+                      Prefix         => Make_Identifier (Loc, Name_uInit),
+                      Attribute_Name => Name_Unrestricted_Access));
+                  Analyze (N);
+                  return;
+
+               --  OK if a task type, this test needs sharpening up ???
+
+               elsif Is_Task_Type (Typ) then
+                  null;
+
+               --  Otherwise we have an error case
+
+               else
+                  Error_Attr ("% attribute cannot be applied to type", P);
+                  return;
+               end if;
+            end if;
+         end if;
+
+         --  If we fall through, we have a normal access to object case.
+         --  Unrestricted_Access is legal wherever an allocator would be
+         --  legal, so its Etype is set to E_Allocator. The expected type
+         --  of the other attributes is a general access type, and therefore
+         --  we label them with E_Access_Attribute_Type.
+
+         if not Is_Overloaded (P) then
+            Acc_Type := Build_Access_Object_Type (P_Type);
+            Set_Etype (N, Acc_Type);
+         else
+            declare
+               Index : Interp_Index;
+               It    : Interp;
+
+            begin
+               Set_Etype (N, Any_Type);
+               Get_First_Interp (P, Index, It);
+
+               while Present (It.Typ) loop
+                  Acc_Type := Build_Access_Object_Type (It.Typ);
+                  Add_One_Interp (N, Acc_Type, Acc_Type);
+                  Get_Next_Interp (Index, It);
+               end loop;
+            end;
+         end if;
+
+         --  Check for aliased view unless unrestricted case. We allow
+         --  a nonaliased prefix when within an instance because the
+         --  prefix may have been a tagged formal object, which is
+         --  defined to be aliased even when the actual might not be
+         --  (other instance cases will have been caught in the generic).
+
+         if Aname /= Name_Unrestricted_Access
+           and then not Is_Aliased_View (P)
+           and then not In_Instance
+         then
+            Error_Attr ("prefix of % attribute must be aliased", P);
+         end if;
+
+      end Access_Attribute;
+
+      --------------------------------
+      -- Check_Array_Or_Scalar_Type --
+      --------------------------------
+
+      procedure Check_Array_Or_Scalar_Type is
+         Index : Entity_Id;
+
+         D : Int;
+         --  Dimension number for array attributes.
+
+      begin
+         --  Case of string literal or string literal subtype. These cases
+         --  cannot arise from legal Ada code, but the expander is allowed
+         --  to generate them. They require special handling because string
+         --  literal subtypes do not have standard bounds (the whole idea
+         --  of these subtypes is to avoid having to generate the bounds)
+
+         if Ekind (P_Type) = E_String_Literal_Subtype then
+            Set_Etype (N, Etype (First_Index (P_Base_Type)));
+            return;
+
+         --  Scalar types
+
+         elsif Is_Scalar_Type (P_Type) then
+            Check_Type;
+
+            if Present (E1) then
+               Error_Attr ("invalid argument in % attribute", E1);
+            else
+               Set_Etype (N, P_Base_Type);
+               return;
+            end if;
+
+         --  The following is a special test to allow 'First to apply to
+         --  private scalar types if the attribute comes from generated
+         --  code. This occurs in the case of Normalize_Scalars code.
+
+         elsif Is_Private_Type (P_Type)
+           and then Present (Full_View (P_Type))
+           and then Is_Scalar_Type (Full_View (P_Type))
+           and then not Comes_From_Source (N)
+         then
+            Set_Etype (N, Implementation_Base_Type (P_Type));
+
+         --  Array types other than string literal subtypes handled above
+
+         else
+            Check_Array_Type;
+
+            --  We know prefix is an array type, or the name of an array
+            --  object, and that the expression, if present, is static
+            --  and within the range of the dimensions of the type.
+
+            if Is_Array_Type (P_Type) then
+               Index := First_Index (P_Base_Type);
+
+            else pragma Assert (Is_Access_Type (P_Type));
+               Index := First_Index (Base_Type (Designated_Type (P_Type)));
+            end if;
+
+            if No (E1) then
+
+               --  First dimension assumed
+
+               Set_Etype (N, Base_Type (Etype (Index)));
+
+            else
+               D := UI_To_Int (Intval (E1));
+
+               for J in 1 .. D - 1 loop
+                  Next_Index (Index);
+               end loop;
+
+               Set_Etype (N, Base_Type (Etype (Index)));
+               Set_Etype (E1, Standard_Integer);
+            end if;
+         end if;
+      end Check_Array_Or_Scalar_Type;
+
+      ----------------------
+      -- Check_Array_Type --
+      ----------------------
+
+      procedure Check_Array_Type is
+         D : Int;
+         --  Dimension number for array attributes.
+
+      begin
+         --  If the type is a string literal type, then this must be generated
+         --  internally, and no further check is required on its legality.
+
+         if Ekind (P_Type) = E_String_Literal_Subtype then
+            return;
+
+         --  If the type is a composite, it is an illegal aggregate, no point
+         --  in going on.
+
+         elsif P_Type = Any_Composite then
+            raise Bad_Attribute;
+         end if;
+
+         --  Normal case of array type or subtype
+
+         Check_Either_E0_Or_E1;
+
+         if Is_Array_Type (P_Type) then
+            if not Is_Constrained (P_Type)
+              and then Is_Entity_Name (P)
+              and then Is_Type (Entity (P))
+            then
+               --  Note: we do not call Error_Attr here, since we prefer to
+               --  continue, using the relevant index type of the array,
+               --  even though it is unconstrained. This gives better error
+               --  recovery behavior.
+
+               Error_Msg_Name_1 := Aname;
+               Error_Msg_N
+                 ("prefix for % attribute must be constrained array", P);
+            end if;
+
+            D := Number_Dimensions (P_Type);
+
+         elsif Is_Access_Type (P_Type)
+           and then Is_Array_Type (Designated_Type (P_Type))
+         then
+            if Is_Entity_Name (P) and then Is_Type (Entity (P)) then
+               Error_Attr ("prefix of % attribute cannot be access type", P);
+            end if;
+
+            D := Number_Dimensions (Designated_Type (P_Type));
+
+            --  If there is an implicit dereference, then we must freeze
+            --  the designated type of the access type, since the type of
+            --  the referenced array is this type (see AI95-00106).
+
+            Freeze_Before (N, Designated_Type (P_Type));
+
+         else
+            if Is_Private_Type (P_Type) then
+               Error_Attr
+                 ("prefix for % attribute may not be private type", P);
+
+            elsif Attr_Id = Attribute_First
+                    or else
+                  Attr_Id = Attribute_Last
+            then
+               Error_Attr ("invalid prefix for % attribute", P);
+
+            else
+               Error_Attr ("prefix for % attribute must be array", P);
+            end if;
+         end if;
+
+         if Present (E1) then
+            Resolve (E1, Any_Integer);
+            Set_Etype (E1, Standard_Integer);
+
+            if not Is_Static_Expression (E1)
+              or else Raises_Constraint_Error (E1)
+            then
+               Error_Attr ("expression for dimension must be static", E1);
+
+            elsif  UI_To_Int (Expr_Value (E1)) > D
+              or else UI_To_Int (Expr_Value (E1)) < 1
+            then
+               Error_Attr ("invalid dimension number for array type", E1);
+            end if;
+         end if;
+      end Check_Array_Type;
+
+      -------------------------
+      -- Check_Asm_Attribute --
+      -------------------------
+
+      procedure Check_Asm_Attribute is
+      begin
+         Check_Type;
+         Check_E2;
+
+         --  Check first argument is static string expression
+
+         Analyze_And_Resolve (E1, Standard_String);
+
+         if Etype (E1) = Any_Type then
+            return;
+
+         elsif not Is_OK_Static_Expression (E1) then
+            Error_Attr
+              ("constraint argument must be static string expression", E1);
+         end if;
+
+         --  Check second argument is right type
+
+         Analyze_And_Resolve (E2, Entity (P));
+
+         --  Note: that is all we need to do, we don't need to check
+         --  that it appears in a correct context. The Ada type system
+         --  will do that for us.
+
+      end Check_Asm_Attribute;
+
+      ---------------------
+      -- Check_Component --
+      ---------------------
+
+      procedure Check_Component is
+      begin
+         Check_E0;
+
+         if Nkind (P) /= N_Selected_Component
+           or else
+             (Ekind (Entity (Selector_Name (P))) /= E_Component
+               and then
+              Ekind (Entity (Selector_Name (P))) /= E_Discriminant)
+         then
+            Error_Attr
+              ("prefix for % attribute must be selected component", P);
+         end if;
+      end Check_Component;
+
+      ------------------------------------
+      -- Check_Decimal_Fixed_Point_Type --
+      ------------------------------------
+
+      procedure Check_Decimal_Fixed_Point_Type is
+      begin
+         Check_Type;
+
+         if not Is_Decimal_Fixed_Point_Type (P_Type) then
+            Error_Attr
+              ("prefix of % attribute must be decimal type", P);
+         end if;
+      end Check_Decimal_Fixed_Point_Type;
+
+      -----------------------
+      -- Check_Dereference --
+      -----------------------
+
+      procedure Check_Dereference is
+      begin
+         if Is_Object_Reference (P)
+           and then Is_Access_Type (P_Type)
+         then
+            Rewrite (P,
+              Make_Explicit_Dereference (Sloc (P),
+                Prefix => Relocate_Node (P)));
+
+            Analyze_And_Resolve (P);
+            P_Type := Etype (P);
+
+            if P_Type = Any_Type then
+               raise Bad_Attribute;
+            end if;
+
+            P_Base_Type := Base_Type (P_Type);
+            P_Root_Type := Root_Type (P_Base_Type);
+         end if;
+      end Check_Dereference;
+
+      -------------------------
+      -- Check_Discrete_Type --
+      -------------------------
+
+      procedure Check_Discrete_Type is
+      begin
+         Check_Type;
+
+         if not Is_Discrete_Type (P_Type) then
+            Error_Attr ("prefix of % attribute must be discrete type", P);
+         end if;
+      end Check_Discrete_Type;
+
+      --------------
+      -- Check_E0 --
+      --------------
+
+      procedure Check_E0 is
+      begin
+         if Present (E1) then
+            Unexpected_Argument (E1);
+         end if;
+      end Check_E0;
+
+      --------------
+      -- Check_E1 --
+      --------------
+
+      procedure Check_E1 is
+      begin
+         Check_Either_E0_Or_E1;
+
+         if No (E1) then
+
+            --  Special-case attributes that are functions and that appear as
+            --  the prefix of another attribute. Error is posted on parent.
+
+            if Nkind (Parent (N)) = N_Attribute_Reference
+              and then (Attribute_Name (Parent (N)) = Name_Address
+                          or else
+                        Attribute_Name (Parent (N)) = Name_Code_Address
+                          or else
+                        Attribute_Name (Parent (N)) = Name_Access)
+            then
+               Error_Msg_Name_1 := Attribute_Name (Parent (N));
+               Error_Msg_N ("illegal prefix for % attribute", Parent (N));
+               Set_Etype (Parent (N), Any_Type);
+               Set_Entity (Parent (N), Any_Type);
+               raise Bad_Attribute;
+
+            else
+               Error_Attr ("missing argument for % attribute", N);
+            end if;
+         end if;
+      end Check_E1;
+
+      --------------
+      -- Check_E2 --
+      --------------
+
+      procedure Check_E2 is
+      begin
+         if No (E1) then
+            Error_Attr ("missing arguments for % attribute (2 required)", N);
+         elsif No (E2) then
+            Error_Attr ("missing argument for % attribute (2 required)", N);
+         end if;
+      end Check_E2;
+
+      ---------------------------
+      -- Check_Either_E0_Or_E1 --
+      ---------------------------
+
+      procedure Check_Either_E0_Or_E1 is
+      begin
+         if Present (E2) then
+            Unexpected_Argument (E2);
+         end if;
+      end Check_Either_E0_Or_E1;
+
+      ----------------------
+      -- Check_Enum_Image --
+      ----------------------
+
+      procedure Check_Enum_Image is
+         Lit : Entity_Id;
+
+      begin
+         if Is_Enumeration_Type (P_Base_Type) then
+            Lit := First_Literal (P_Base_Type);
+            while Present (Lit) loop
+               Set_Referenced (Lit);
+               Next_Literal (Lit);
+            end loop;
+         end if;
+      end Check_Enum_Image;
+
+      ----------------------------
+      -- Check_Enumeration_Type --
+      ----------------------------
+
+      procedure Check_Enumeration_Type is
+      begin
+         Check_Type;
+
+         if not Is_Enumeration_Type (P_Type) then
+            Error_Attr ("prefix of % attribute must be enumeration type", P);
+         end if;
+      end Check_Enumeration_Type;
+
+      ----------------------------
+      -- Check_Fixed_Point_Type --
+      ----------------------------
+
+      procedure Check_Fixed_Point_Type is
+      begin
+         Check_Type;
+
+         if not Is_Fixed_Point_Type (P_Type) then
+            Error_Attr ("prefix of % attribute must be fixed point type", P);
+         end if;
+      end Check_Fixed_Point_Type;
+
+      ------------------------------
+      -- Check_Fixed_Point_Type_0 --
+      ------------------------------
+
+      procedure Check_Fixed_Point_Type_0 is
+      begin
+         Check_Fixed_Point_Type;
+         Check_E0;
+      end Check_Fixed_Point_Type_0;
+
+      -------------------------------
+      -- Check_Floating_Point_Type --
+      -------------------------------
+
+      procedure Check_Floating_Point_Type is
+      begin
+         Check_Type;
+
+         if not Is_Floating_Point_Type (P_Type) then
+            Error_Attr ("prefix of % attribute must be float type", P);
+         end if;
+      end Check_Floating_Point_Type;
+
+      ---------------------------------
+      -- Check_Floating_Point_Type_0 --
+      ---------------------------------
+
+      procedure Check_Floating_Point_Type_0 is
+      begin
+         Check_Floating_Point_Type;
+         Check_E0;
+      end Check_Floating_Point_Type_0;
+
+      ---------------------------------
+      -- Check_Floating_Point_Type_1 --
+      ---------------------------------
+
+      procedure Check_Floating_Point_Type_1 is
+      begin
+         Check_Floating_Point_Type;
+         Check_E1;
+      end Check_Floating_Point_Type_1;
+
+      ---------------------------------
+      -- Check_Floating_Point_Type_2 --
+      ---------------------------------
+
+      procedure Check_Floating_Point_Type_2 is
+      begin
+         Check_Floating_Point_Type;
+         Check_E2;
+      end Check_Floating_Point_Type_2;
+
+      ------------------------
+      -- Check_Integer_Type --
+      ------------------------
+
+      procedure Check_Integer_Type is
+      begin
+         Check_Type;
+
+         if not Is_Integer_Type (P_Type) then
+            Error_Attr ("prefix of % attribute must be integer type", P);
+         end if;
+      end Check_Integer_Type;
+
+      ------------------------
+      -- Check_Library_Unit --
+      ------------------------
+
+      procedure Check_Library_Unit is
+      begin
+         if not Is_Compilation_Unit (Entity (P)) then
+            Error_Attr ("prefix of % attribute must be library unit", P);
+         end if;
+      end Check_Library_Unit;
+
+      -------------------------------
+      -- Check_Not_Incomplete_Type --
+      -------------------------------
+
+      procedure Check_Not_Incomplete_Type is
+      begin
+         if not Is_Entity_Name (P)
+           or else not Is_Type (Entity (P))
+           or else In_Default_Expression
+         then
+            return;
+
+         else
+            Check_Fully_Declared (P_Type, P);
+         end if;
+      end Check_Not_Incomplete_Type;
+
+      ----------------------------
+      -- Check_Object_Reference --
+      ----------------------------
+
+      procedure Check_Object_Reference (P : Node_Id) is
+         Rtyp : Entity_Id;
+
+      begin
+         --  If we need an object, and we have a prefix that is the name of
+         --  a function entity, convert it into a function call.
+
+         if Is_Entity_Name (P)
+           and then Ekind (Entity (P)) = E_Function
+         then
+            Rtyp := Etype (Entity (P));
+
+            Rewrite (P,
+              Make_Function_Call (Sloc (P),
+                Name => Relocate_Node (P)));
+
+            Analyze_And_Resolve (P, Rtyp);
+
+         --  Otherwise we must have an object reference
+
+         elsif not Is_Object_Reference (P) then
+            Error_Attr ("prefix of % attribute must be object", P);
+         end if;
+      end Check_Object_Reference;
+
+      ------------------------
+      -- Check_Program_Unit --
+      ------------------------
+
+      procedure Check_Program_Unit is
+      begin
+         if Is_Entity_Name (P) then
+            declare
+               K : constant Entity_Kind := Ekind (Entity (P));
+               T : constant Entity_Id   := Etype (Entity (P));
+
+            begin
+               if K in Subprogram_Kind
+                 or else K in Task_Kind
+                 or else K in Protected_Kind
+                 or else K = E_Package
+                 or else K in Generic_Unit_Kind
+                 or else (K = E_Variable
+                            and then
+                              (Is_Task_Type (T)
+                                 or else
+                               Is_Protected_Type (T)))
+               then
+                  return;
+               end if;
+            end;
+         end if;
+
+         Error_Attr ("prefix of % attribute must be program unit", P);
+      end Check_Program_Unit;
+
+      ---------------------
+      -- Check_Real_Type --
+      ---------------------
+
+      procedure Check_Real_Type is
+      begin
+         Check_Type;
+
+         if not Is_Real_Type (P_Type) then
+            Error_Attr ("prefix of % attribute must be real type", P);
+         end if;
+      end Check_Real_Type;
+
+      -----------------------
+      -- Check_Scalar_Type --
+      -----------------------
+
+      procedure Check_Scalar_Type is
+      begin
+         Check_Type;
+
+         if not Is_Scalar_Type (P_Type) then
+            Error_Attr ("prefix of % attribute must be scalar type", P);
+         end if;
+      end Check_Scalar_Type;
+
+      ---------------------------
+      -- Check_Standard_Prefix --
+      ---------------------------
+
+      procedure Check_Standard_Prefix is
+      begin
+         Check_E0;
+
+         if Nkind (P) /= N_Identifier
+           or else Chars (P) /= Name_Standard
+         then
+            Error_Attr ("only allowed prefix for % attribute is Standard", P);
+         end if;
+
+      end Check_Standard_Prefix;
+
+      ----------------------------
+      -- Check_Stream_Attribute --
+      ----------------------------
+
+      procedure Check_Stream_Attribute (Nam : Name_Id) is
+         Etyp : Entity_Id;
+         Btyp : Entity_Id;
+
+      begin
+         Validate_Non_Static_Attribute_Function_Call;
+
+         --  With the exception of 'Input, Stream attributes are procedures,
+         --  and can only appear at the position of procedure calls. We check
+         --  for this here, before they are rewritten, to give a more precise
+         --  diagnostic.
+
+         if Nam = Name_uInput then
+            null;
+
+         elsif Is_List_Member (N)
+           and then Nkind (Parent (N)) /= N_Procedure_Call_Statement
+           and then Nkind (Parent (N)) /= N_Aggregate
+         then
+            null;
+
+         else
+            Error_Attr
+              ("invalid context for attribute %, which is a procedure", N);
+         end if;
+
+         Check_Type;
+         Btyp := Implementation_Base_Type (P_Type);
+
+         --  Stream attributes not allowed on limited types unless the
+         --  special OK_For_Stream flag is set.
+
+         if Is_Limited_Type (P_Type)
+           and then Comes_From_Source (N)
+           and then not Present (TSS (Btyp, Nam))
+           and then No (Get_Rep_Pragma (Btyp, Name_Stream_Convert))
+         then
+            --  Special case the message if we are compiling the stub version
+            --  of a remote operation. One error on the type is sufficient.
+
+            if (Is_Remote_Types (Current_Scope)
+                 or else Is_Remote_Call_Interface (Current_Scope))
+              and then not Error_Posted (Btyp)
+            then
+               Error_Msg_Node_2 := Current_Scope;
+               Error_Msg_NE
+                 ("limited type& used in& has no stream attributes", P, Btyp);
+               Set_Error_Posted (Btyp);
+
+            elsif not Error_Posted (Btyp) then
+               Error_Msg_NE
+                 ("limited type& has no stream attributes", P, Btyp);
+            end if;
+         end if;
+
+         --  Here we must check that the first argument is an access type
+         --  that is compatible with Ada.Streams.Root_Stream_Type'Class.
+
+         Analyze_And_Resolve (E1);
+         Etyp := Etype (E1);
+
+         --  Note: the double call to Root_Type here is needed because the
+         --  root type of a class-wide type is the corresponding type (e.g.
+         --  X for X'Class, and we really want to go to the root.
+
+         if not Is_Access_Type (Etyp)
+           or else Root_Type (Root_Type (Designated_Type (Etyp))) /=
+                     RTE (RE_Root_Stream_Type)
+         then
+            Error_Attr
+              ("expected access to Ada.Streams.Root_Stream_Type''Class", E1);
+         end if;
+
+         --  Check that the second argument is of the right type if there is
+         --  one (the Input attribute has only one argument so this is skipped)
+
+         if Present (E2) then
+            Analyze (E2);
+
+            if Nam = Name_uRead
+              and then not Is_OK_Variable_For_Out_Formal (E2)
+            then
+               Error_Attr
+                 ("second argument of % attribute must be a variable", E2);
+            end if;
+
+            Resolve (E2, P_Type);
+         end if;
+      end Check_Stream_Attribute;
+
+      -----------------------
+      -- Check_Task_Prefix --
+      -----------------------
+
+      procedure Check_Task_Prefix is
+      begin
+         Analyze (P);
+
+         if Is_Task_Type (Etype (P))
+           or else (Is_Access_Type (Etype (P))
+              and then Is_Task_Type (Designated_Type (Etype (P))))
+         then
+            Resolve (P, Etype (P));
+         else
+            Error_Attr ("prefix of % attribute must be a task", P);
+         end if;
+      end Check_Task_Prefix;
+
+      ----------------
+      -- Check_Type --
+      ----------------
+
+      --  The possibilities are an entity name denoting a type, or an
+      --  attribute reference that denotes a type (Base or Class). If
+      --  the type is incomplete, replace it with its full view.
+
+      procedure Check_Type is
+      begin
+         if not Is_Entity_Name (P)
+           or else not Is_Type (Entity (P))
+         then
+            Error_Attr ("prefix of % attribute must be a type", P);
+
+         elsif Ekind (Entity (P)) = E_Incomplete_Type
+            and then Present (Full_View (Entity (P)))
+         then
+            P_Type := Full_View (Entity (P));
+            Set_Entity (P, P_Type);
+         end if;
+      end Check_Type;
+
+      ---------------------
+      -- Check_Unit_Name --
+      ---------------------
+
+      procedure Check_Unit_Name (Nod : Node_Id) is
+      begin
+         if Nkind (Nod) = N_Identifier then
+            return;
+
+         elsif Nkind (Nod) = N_Selected_Component then
+            Check_Unit_Name (Prefix (Nod));
+
+            if Nkind (Selector_Name (Nod)) = N_Identifier then
+               return;
+            end if;
+         end if;
+
+         Error_Attr ("argument for % attribute must be unit name", P);
+      end Check_Unit_Name;
+
+      ----------------
+      -- Error_Attr --
+      ----------------
+
+      procedure Error_Attr (Msg : String; Error_Node : Node_Id) is
+      begin
+         Error_Msg_Name_1 := Aname;
+         Error_Msg_N (Msg, Error_Node);
+         Set_Etype (N, Any_Type);
+         Set_Entity (N, Any_Type);
+         raise Bad_Attribute;
+      end Error_Attr;
+
+      ----------------------------
+      -- Legal_Formal_Attribute --
+      ----------------------------
+
+      procedure Legal_Formal_Attribute is
+      begin
+         Check_E0;
+
+         if not Is_Entity_Name (P)
+           or else not Is_Type (Entity (P))
+         then
+            Error_Attr (" prefix of % attribute must be generic type", N);
+
+         elsif Is_Generic_Actual_Type (Entity (P))
+           or In_Instance
+         then
+            null;
+
+         elsif Is_Generic_Type (Entity (P)) then
+            if not Is_Indefinite_Subtype (Entity (P)) then
+               Error_Attr
+                 (" prefix of % attribute must be indefinite generic type", N);
+            end if;
+
+         else
+            Error_Attr
+              (" prefix of % attribute must be indefinite generic type", N);
+         end if;
+
+         Set_Etype (N, Standard_Boolean);
+      end Legal_Formal_Attribute;
+
+      ------------------------
+      -- Standard_Attribute --
+      ------------------------
+
+      procedure Standard_Attribute (Val : Int) is
+      begin
+         Check_Standard_Prefix;
+         Rewrite (N,
+           Make_Integer_Literal (Loc, Val));
+         Analyze (N);
+      end Standard_Attribute;
+
+      -------------------------
+      -- Unexpected Argument --
+      -------------------------
+
+      procedure Unexpected_Argument (En : Node_Id) is
+      begin
+         Error_Attr ("unexpected argument for % attribute", En);
+      end Unexpected_Argument;
+
+      -------------------------------------------------
+      -- Validate_Non_Static_Attribute_Function_Call --
+      -------------------------------------------------
+
+      --  This function should be moved to Sem_Dist ???
+
+      procedure Validate_Non_Static_Attribute_Function_Call is
+      begin
+         if In_Preelaborated_Unit
+           and then not In_Subprogram_Or_Concurrent_Unit
+         then
+            Error_Msg_N ("non-static function call in preelaborated unit", N);
+         end if;
+      end Validate_Non_Static_Attribute_Function_Call;
+
+   -----------------------------------------------
+   -- Start of Processing for Analyze_Attribute --
+   -----------------------------------------------
+
+   begin
+      --  Immediate return if unrecognized attribute (already diagnosed
+      --  by parser, so there is nothing more that we need to do)
+
+      if not Is_Attribute_Name (Aname) then
+         raise Bad_Attribute;
+      end if;
+
+      --  Deal with Ada 83 and Features issues
+
+      if not Attribute_83 (Attr_Id) then
+         if Ada_83 and then Comes_From_Source (N) then
+            Error_Msg_Name_1 := Aname;
+            Error_Msg_N ("(Ada 83) attribute% is not standard?", N);
+         end if;
+
+         if Attribute_Impl_Def (Attr_Id) then
+            Check_Restriction (No_Implementation_Attributes, N);
+         end if;
+      end if;
+
+      --   Remote access to subprogram type access attribute reference needs
+      --   unanalyzed copy for tree transformation. The analyzed copy is used
+      --   for its semantic information (whether prefix is a remote subprogram
+      --   name), the unanalyzed copy is used to construct new subtree rooted
+      --   with N_aggregate which represents a fat pointer aggregate.
+
+      if Aname = Name_Access then
+         Unanalyzed := Copy_Separate_Tree (N);
+      end if;
+
+      --  Analyze prefix and exit if error in analysis. If the prefix is an
+      --  incomplete type, use full view if available. A special case is
+      --  that we never analyze the prefix of an Elab_Body or Elab_Spec
+      --  or UET_Address attribute.
+
+      if Aname /= Name_Elab_Body
+           and then
+         Aname /= Name_Elab_Spec
+           and then
+         Aname /= Name_UET_Address
+      then
+         Analyze (P);
+         P_Type := Etype (P);
+
+         if Is_Entity_Name (P)
+           and then Present (Entity (P))
+           and then Is_Type (Entity (P))
+           and then Ekind (Entity (P)) = E_Incomplete_Type
+         then
+            P_Type := Get_Full_View (P_Type);
+            Set_Entity (P, P_Type);
+            Set_Etype  (P, P_Type);
+         end if;
+
+         if P_Type = Any_Type then
+            raise Bad_Attribute;
+         end if;
+
+         P_Base_Type := Base_Type (P_Type);
+         P_Root_Type := Root_Type (P_Base_Type);
+      end if;
+
+      --  Analyze expressions that may be present, exiting if an error occurs
+
+      if No (Exprs) then
+         E1 := Empty;
+         E2 := Empty;
+
+      else
+         E1 := First (Exprs);
+         Analyze (E1);
+
+         if Etype (E1) = Any_Type then
+            raise Bad_Attribute;
+         end if;
+
+         E2 := Next (E1);
+
+         if Present (E2) then
+            Analyze (E2);
+
+            if Etype (E2) = Any_Type then
+               raise Bad_Attribute;
+            end if;
+
+            if Present (Next (E2)) then
+               Unexpected_Argument (Next (E2));
+            end if;
+         end if;
+      end if;
+
+      if Is_Overloaded (P)
+        and then Aname /= Name_Access
+        and then Aname /= Name_Address
+        and then Aname /= Name_Code_Address
+        and then Aname /= Name_Count
+        and then Aname /= Name_Unchecked_Access
+      then
+         Error_Attr ("ambiguous prefix for % attribute", P);
+      end if;
+
+      --  Remaining processing depends on attribute
+
+      case Attr_Id is
+
+      ------------------
+      -- Abort_Signal --
+      ------------------
+
+      when Attribute_Abort_Signal =>
+         Check_Standard_Prefix;
+         Rewrite (N,
+           New_Reference_To (Stand.Abort_Signal, Loc));
+         Analyze (N);
+
+      ------------
+      -- Access --
+      ------------
+
+      when Attribute_Access =>
+         Access_Attribute;
+
+      -------------
+      -- Address --
+      -------------
+
+      when Attribute_Address =>
+         Check_E0;
+
+         --  Check for some junk cases, where we have to allow the address
+         --  attribute but it does not make much sense, so at least for now
+         --  just replace with Null_Address.
+
+         --  We also do this if the prefix is a reference to the AST_Entry
+         --  attribute. If expansion is active, the attribute will be
+         --  replaced by a function call, and address will work fine and
+         --  get the proper value, but if expansion is not active, then
+         --  the check here allows proper semantic analysis of the reference.
+
+         if (Is_Entity_Name (P)
+           and then
+             (((Ekind (Entity (P)) = E_Task_Type
+                 or else Ekind (Entity (P)) = E_Protected_Type)
+                   and then Etype (Entity (P)) = Base_Type (Entity (P)))
+               or else Ekind (Entity (P)) = E_Package
+               or else Is_Generic_Unit (Entity (P))))
+           or else
+            (Nkind (P) = N_Attribute_Reference
+              and then
+             Attribute_Name (P) = Name_AST_Entry)
+         then
+            Rewrite (N,
+              New_Occurrence_Of (RTE (RE_Null_Address), Sloc (N)));
+
+         --  The following logic is obscure, needs explanation ???
+
+         elsif Nkind (P) = N_Attribute_Reference
+           or else (Is_Entity_Name (P)
+                      and then not Is_Subprogram (Entity (P))
+                      and then not Is_Object (Entity (P))
+                      and then Ekind (Entity (P)) /= E_Label)
+         then
+            Error_Attr ("invalid prefix for % attribute", P);
+
+         elsif Is_Entity_Name (P) then
+            Set_Address_Taken (Entity (P));
+         end if;
+
+         Set_Etype (N, RTE (RE_Address));
+
+      ------------------
+      -- Address_Size --
+      ------------------
+
+      when Attribute_Address_Size =>
+         Standard_Attribute (System_Address_Size);
+
+      --------------
+      -- Adjacent --
+      --------------
+
+      when Attribute_Adjacent =>
+         Check_Floating_Point_Type_2;
+         Set_Etype (N, P_Base_Type);
+         Resolve (E1, P_Base_Type);
+         Resolve (E2, P_Base_Type);
+
+      ---------
+      -- Aft --
+      ---------
+
+      when Attribute_Aft =>
+         Check_Fixed_Point_Type_0;
+         Set_Etype (N, Universal_Integer);
+
+      ---------------
+      -- Alignment --
+      ---------------
+
+      when Attribute_Alignment =>
+
+         --  Don't we need more checking here, cf Size ???
+
+         Check_E0;
+         Check_Not_Incomplete_Type;
+         Set_Etype (N, Universal_Integer);
+
+      ---------------
+      -- Asm_Input --
+      ---------------
+
+      when Attribute_Asm_Input =>
+         Check_Asm_Attribute;
+         Set_Etype (N, RTE (RE_Asm_Input_Operand));
+
+      ----------------
+      -- Asm_Output --
+      ----------------
+
+      when Attribute_Asm_Output =>
+         Check_Asm_Attribute;
+
+         if Etype (E2) = Any_Type then
+            return;
+
+         elsif Aname = Name_Asm_Output then
+            if not Is_Variable (E2) then
+               Error_Attr
+                 ("second argument for Asm_Output is not variable", E2);
+            end if;
+         end if;
+
+         Note_Possible_Modification (E2);
+         Set_Etype (N, RTE (RE_Asm_Output_Operand));
+
+      ---------------
+      -- AST_Entry --
+      ---------------
+
+      when Attribute_AST_Entry => AST_Entry : declare
+         Ent  : Entity_Id;
+         Pref : Node_Id;
+         Ptyp : Entity_Id;
+
+         Indexed : Boolean;
+         --  Indicates if entry family index is present. Note the coding
+         --  here handles the entry family case, but in fact it cannot be
+         --  executed currently, because pragma AST_Entry does not permit
+         --  the specification of an entry family.
+
+         procedure Bad_AST_Entry;
+         --  Signal a bad AST_Entry pragma
+
+         function OK_Entry (E : Entity_Id) return Boolean;
+         --  Checks that E is of an appropriate entity kind for an entry
+         --  (i.e. E_Entry if Index is False, or E_Entry_Family if Index
+         --  is set True for the entry family case). In the True case,
+         --  makes sure that Is_AST_Entry is set on the entry.
+
+         procedure Bad_AST_Entry is
+         begin
+            Error_Attr ("prefix for % attribute must be task entry", P);
+         end Bad_AST_Entry;
+
+         function OK_Entry (E : Entity_Id) return Boolean is
+            Result : Boolean;
+
+         begin
+            if Indexed then
+               Result := (Ekind (E) = E_Entry_Family);
+            else
+               Result := (Ekind (E) = E_Entry);
+            end if;
+
+            if Result then
+               if not Is_AST_Entry (E) then
+                  Error_Msg_Name_2 := Aname;
+                  Error_Attr
+                    ("% attribute requires previous % pragma", P);
+               end if;
+            end if;
+
+            return Result;
+         end OK_Entry;
+
+      --  Start of processing for AST_Entry
+
+      begin
+         Check_VMS (N);
+         Check_E0;
+
+         --  Deal with entry family case
+
+         if Nkind (P) = N_Indexed_Component then
+            Pref := Prefix (P);
+            Indexed := True;
+         else
+            Pref := P;
+            Indexed := False;
+         end if;
+
+         Ptyp := Etype (Pref);
+
+         if Ptyp = Any_Type or else Error_Posted (Pref) then
+            return;
+         end if;
+
+         --  If the prefix is a selected component whose prefix is of an
+         --  access type, then introduce an explicit dereference.
+
+         if Nkind (Pref) = N_Selected_Component
+           and then Is_Access_Type (Ptyp)
+         then
+            Rewrite (Pref,
+              Make_Explicit_Dereference (Sloc (Pref),
+                Relocate_Node (Pref)));
+            Analyze_And_Resolve (Pref, Designated_Type (Ptyp));
+         end if;
+
+         --  Prefix can be of the form a.b, where a is a task object
+         --  and b is one of the entries of the corresponding task type.
+
+         if Nkind (Pref) = N_Selected_Component
+           and then OK_Entry (Entity (Selector_Name (Pref)))
+           and then Is_Object_Reference (Prefix (Pref))
+           and then Is_Task_Type (Etype (Prefix (Pref)))
+         then
+            null;
+
+         --  Otherwise the prefix must be an entry of a containing task,
+         --  or of a variable of the enclosing task type.
+
+         else
+            if Nkind (Pref) = N_Identifier
+              or else Nkind (Pref) = N_Expanded_Name
+            then
+               Ent := Entity (Pref);
+
+               if not OK_Entry (Ent)
+                 or else not In_Open_Scopes (Scope (Ent))
+               then
+                  Bad_AST_Entry;
+               end if;
+
+            else
+               Bad_AST_Entry;
+            end if;
+         end if;
+
+         Set_Etype (N, RTE (RE_AST_Handler));
+      end AST_Entry;
+
+      ----------
+      -- Base --
+      ----------
+
+      when Attribute_Base => Base : declare
+         Typ : Entity_Id;
+
+      begin
+         Check_Either_E0_Or_E1;
+         Find_Type (P);
+         Typ := Entity (P);
+
+         if Sloc (Typ) = Standard_Location
+           and then Base_Type (Typ) = Typ
+           and then Warn_On_Redundant_Constructs
+         then
+            Error_Msg_NE
+              ("?redudant attribute, & is its own base type", N, Typ);
+         end if;
+
+         Set_Etype (N, Base_Type (Entity (P)));
+
+         --  If we have an expression present, then really this is a conversion
+         --  and the tree must be reformed. Note that this is one of the cases
+         --  in which we do a replace rather than a rewrite, because the
+         --  original tree is junk.
+
+         if Present (E1) then
+            Replace (N,
+              Make_Type_Conversion (Loc,
+                Subtype_Mark =>
+                  Make_Attribute_Reference (Loc,
+                    Prefix => Prefix (N),
+                    Attribute_Name => Name_Base),
+                Expression => Relocate_Node (E1)));
+
+            --  E1 may be overloaded, and its interpretations preserved.
+
+            Save_Interps (E1, Expression (N));
+            Analyze (N);
+
+         --  For other cases, set the proper type as the entity of the
+         --  attribute reference, and then rewrite the node to be an
+         --  occurrence of the referenced base type. This way, no one
+         --  else in the compiler has to worry about the base attribute.
+
+         else
+            Set_Entity (N, Base_Type (Entity (P)));
+            Rewrite (N,
+              New_Reference_To (Entity (N), Loc));
+            Analyze (N);
+         end if;
+      end Base;
+
+      ---------
+      -- Bit --
+      ---------
+
+      when Attribute_Bit => Bit :
+      begin
+         Check_E0;
+
+         if not Is_Object_Reference (P) then
+            Error_Attr ("prefix for % attribute must be object", P);
+
+         --  What about the access object cases ???
+
+         else
+            null;
+         end if;
+
+         Set_Etype (N, Universal_Integer);
+      end Bit;
+
+      ---------------
+      -- Bit_Order --
+      ---------------
+
+      when Attribute_Bit_Order => Bit_Order :
+      begin
+         Check_E0;
+         Check_Type;
+
+         if not Is_Record_Type (P_Type) then
+            Error_Attr ("prefix of % attribute must be record type", P);
+         end if;
+
+         if Bytes_Big_Endian xor Reverse_Bit_Order (P_Type) then
+            Rewrite (N,
+              New_Occurrence_Of (RTE (RE_High_Order_First), Loc));
+         else
+            Rewrite (N,
+              New_Occurrence_Of (RTE (RE_Low_Order_First), Loc));
+         end if;
+
+         Set_Etype (N, RTE (RE_Bit_Order));
+         Resolve (N, Etype (N));
+
+         --  Reset incorrect indication of staticness
+
+         Set_Is_Static_Expression (N, False);
+      end Bit_Order;
+
+      ------------------
+      -- Bit_Position --
+      ------------------
+
+      --  Note: in generated code, we can have a Bit_Position attribute
+      --  applied to a (naked) record component (i.e. the prefix is an
+      --  identifier that references an E_Component or E_Discriminant
+      --  entity directly, and this is interpreted as expected by Gigi.
+      --  The following code will not tolerate such usage, but when the
+      --  expander creates this special case, it marks it as analyzed
+      --  immediately and sets an appropriate type.
+
+      when Attribute_Bit_Position =>
+
+         if Comes_From_Source (N) then
+            Check_Component;
+         end if;
+
+         Set_Etype (N, Universal_Integer);
+
+      ------------------
+      -- Body_Version --
+      ------------------
+
+      when Attribute_Body_Version =>
+         Check_E0;
+         Check_Program_Unit;
+         Set_Etype (N, RTE (RE_Version_String));
+
+      --------------
+      -- Callable --
+      --------------
+
+      when Attribute_Callable =>
+         Check_E0;
+         Set_Etype (N, Standard_Boolean);
+         Check_Task_Prefix;
+
+      ------------
+      -- Caller --
+      ------------
+
+      when Attribute_Caller => Caller : declare
+         Ent        : Entity_Id;
+         S          : Entity_Id;
+
+      begin
+         Check_E0;
+
+         if Nkind (P) = N_Identifier
+           or else Nkind (P) = N_Expanded_Name
+         then
+            Ent := Entity (P);
+
+            if not Is_Entry (Ent) then
+               Error_Attr ("invalid entry name", N);
+            end if;
+
+         else
+            Error_Attr ("invalid entry name", N);
+            return;
+         end if;
+
+         for J in reverse 0 .. Scope_Stack.Last loop
+            S := Scope_Stack.Table (J).Entity;
+
+            if S = Scope (Ent) then
+               Error_Attr ("Caller must appear in matching accept or body", N);
+            elsif S = Ent then
+               exit;
+            end if;
+         end loop;
+
+         Set_Etype (N, RTE (RO_AT_Task_ID));
+      end Caller;
+
+      -------------
+      -- Ceiling --
+      -------------
+
+      when Attribute_Ceiling =>
+         Check_Floating_Point_Type_1;
+         Set_Etype (N, P_Base_Type);
+         Resolve (E1, P_Base_Type);
+
+      -----------
+      -- Class --
+      -----------
+
+      when Attribute_Class => Class : declare
+      begin
+         Check_Restriction (No_Dispatch, N);
+         Check_Either_E0_Or_E1;
+
+         --  If we have an expression present, then really this is a conversion
+         --  and the tree must be reformed into a proper conversion. This is a
+         --  Replace rather than a Rewrite, because the original tree is junk.
+         --  If expression is overloaded, propagate interpretations to new one.
+
+         if Present (E1) then
+            Replace (N,
+              Make_Type_Conversion (Loc,
+                Subtype_Mark =>
+                  Make_Attribute_Reference (Loc,
+                    Prefix => Prefix (N),
+                    Attribute_Name => Name_Class),
+                Expression => Relocate_Node (E1)));
+
+            Save_Interps (E1, Expression (N));
+            Analyze (N);
+
+         --  Otherwise we just need to find the proper type
+
+         else
+            Find_Type (N);
+         end if;
+
+      end Class;
+
+      ------------------
+      -- Code_Address --
+      ------------------
+
+      when Attribute_Code_Address =>
+         Check_E0;
+
+         if Nkind (P) = N_Attribute_Reference
+           and then (Attribute_Name (P) = Name_Elab_Body
+                       or else
+                     Attribute_Name (P) = Name_Elab_Spec)
+         then
+            null;
+
+         elsif not Is_Entity_Name (P)
+           or else (Ekind (Entity (P)) /= E_Function
+                      and then
+                    Ekind (Entity (P)) /= E_Procedure)
+         then
+            Error_Attr ("invalid prefix for % attribute", P);
+            Set_Address_Taken (Entity (P));
+         end if;
+
+         Set_Etype (N, RTE (RE_Address));
+
+      --------------------
+      -- Component_Size --
+      --------------------
+
+      when Attribute_Component_Size =>
+         Check_E0;
+         Set_Etype (N, Universal_Integer);
+
+         --  Note: unlike other array attributes, unconstrained arrays are OK
+
+         if Is_Array_Type (P_Type) and then not Is_Constrained (P_Type) then
+            null;
+         else
+            Check_Array_Type;
+         end if;
+
+      -------------
+      -- Compose --
+      -------------
+
+      when Attribute_Compose =>
+         Check_Floating_Point_Type_2;
+         Set_Etype (N, P_Base_Type);
+         Resolve (E1, P_Base_Type);
+         Resolve (E2, Any_Integer);
+
+      -----------------
+      -- Constrained --
+      -----------------
+
+      when Attribute_Constrained =>
+         Check_E0;
+         Set_Etype (N, Standard_Boolean);
+
+         --  Case from RM J.4(2) of constrained applied to private type
+
+         if Is_Entity_Name (P) and then Is_Type (Entity (P)) then
+
+            --  If we are within an instance, the attribute must be legal
+            --  because it was valid in the generic unit.
+
+            if In_Instance then
+               return;
+
+            --  For sure OK if we have a real private type itself, but must
+            --  be completed, cannot apply Constrained to incomplete type.
+
+            elsif Is_Private_Type (Entity (P)) then
+               Check_Not_Incomplete_Type;
+               return;
+            end if;
+
+         else
+            Check_Object_Reference (P);
+
+            --  If N does not come from source, then we allow the
+            --  the attribute prefix to be of a private type whose
+            --  full type has discriminants. This occurs in cases
+            --  involving expanded calls to stream attributes.
+
+            if not Comes_From_Source (N) then
+               P_Type := Underlying_Type (P_Type);
+            end if;
+
+            --  Must have discriminants or be an access type designating
+            --  a type with discriminants. If it is a classwide type is
+            --  has unknown discriminants.
+
+            if Has_Discriminants (P_Type)
+               or else Has_Unknown_Discriminants (P_Type)
+               or else
+                 (Is_Access_Type (P_Type)
+                   and then Has_Discriminants (Designated_Type (P_Type)))
+            then
+               return;
+
+            --  Also allow an object of a generic type if extensions allowed
+            --  and allow this for any type at all.
+
+            elsif (Is_Generic_Type (P_Type)
+                     or else Is_Generic_Actual_Type (P_Type))
+              and then Extensions_Allowed
+            then
+               return;
+            end if;
+         end if;
+
+         --  Fall through if bad prefix
+
+         Error_Attr
+           ("prefix of % attribute must be object of discriminated type", P);
+
+      ---------------
+      -- Copy_Sign --
+      ---------------
+
+      when Attribute_Copy_Sign =>
+         Check_Floating_Point_Type_2;
+         Set_Etype (N, P_Base_Type);
+         Resolve (E1, P_Base_Type);
+         Resolve (E2, P_Base_Type);
+
+      -----------
+      -- Count --
+      -----------
+
+      when Attribute_Count => Count :
+      declare
+         Ent : Entity_Id;
+         S   : Entity_Id;
+         Tsk : Entity_Id;
+
+      begin
+         Check_E0;
+
+         if Nkind (P) = N_Identifier
+           or else Nkind (P) = N_Expanded_Name
+         then
+            Ent := Entity (P);
+
+            if Ekind (Ent) /= E_Entry then
+               Error_Attr ("invalid entry name", N);
+            end if;
+
+         elsif Nkind (P) = N_Indexed_Component then
+            Ent := Entity (Prefix (P));
+
+            if Ekind (Ent) /= E_Entry_Family then
+               Error_Attr ("invalid entry family name", P);
+               return;
+            end if;
+
+         else
+            Error_Attr ("invalid entry name", N);
+            return;
+         end if;
+
+         for J in reverse 0 .. Scope_Stack.Last loop
+            S := Scope_Stack.Table (J).Entity;
+
+            if S = Scope (Ent) then
+               if Nkind (P) = N_Expanded_Name then
+                  Tsk := Entity (Prefix (P));
+
+                  --  The prefix denotes either the task type, or else a
+                  --  single task whose task type is being analyzed.
+
+                  if (Is_Type (Tsk)
+                      and then Tsk = S)
+
+                    or else (not Is_Type (Tsk)
+                      and then Etype (Tsk) = S
+                      and then not (Comes_From_Source (S)))
+                  then
+                     null;
+                  else
+                     Error_Msg_N
+                       ("Count must apply to entry of current task", N);
+                  end if;
+               end if;
+
+               exit;
+
+            elsif Ekind (Scope (Ent)) in Task_Kind
+              and then Ekind (S) /= E_Loop
+              and then Ekind (S) /= E_Block
+              and then Ekind (S) /= E_Entry
+              and then Ekind (S) /= E_Entry_Family
+            then
+               Error_Attr ("Count cannot appear in inner unit", N);
+
+            elsif Ekind (Scope (Ent)) = E_Protected_Type
+              and then not Has_Completion (Scope (Ent))
+            then
+               Error_Attr ("attribute % can only be used inside body", N);
+            end if;
+         end loop;
+
+         if Is_Overloaded (P) then
+            declare
+               Index : Interp_Index;
+               It    : Interp;
+
+            begin
+               Get_First_Interp (P, Index, It);
+
+               while Present (It.Nam) loop
+                  if It.Nam = Ent then
+                     null;
+
+                  elsif Scope (It.Nam) = Scope (Ent) then
+                     Error_Attr ("ambiguous entry name", N);
+
+                  else
+                     --  For now make this into a warning. Will become an
+                     --  error after the 3.15 release.
+
+                     Error_Msg_N
+                       ("ambiguous name, resolved to entry?", N);
+                     Error_Msg_N
+                       ("\(this will become an error in a later release)?", N);
+                  end if;
+
+                  Get_Next_Interp (Index, It);
+               end loop;
+            end;
+         end if;
+
+         Set_Etype (N, Universal_Integer);
+      end Count;
+
+      -----------------------
+      -- Default_Bit_Order --
+      -----------------------
+
+      when Attribute_Default_Bit_Order => Default_Bit_Order :
+      begin
+         Check_Standard_Prefix;
+         Check_E0;
+
+         if Bytes_Big_Endian then
+            Rewrite (N,
+              Make_Integer_Literal (Loc, False_Value));
+         else
+            Rewrite (N,
+              Make_Integer_Literal (Loc, True_Value));
+         end if;
+
+         Set_Etype (N, Universal_Integer);
+         Set_Is_Static_Expression (N);
+      end Default_Bit_Order;
+
+      --------------
+      -- Definite --
+      --------------
+
+      when Attribute_Definite =>
+         Legal_Formal_Attribute;
+
+      -----------
+      -- Delta --
+      -----------
+
+      when Attribute_Delta =>
+         Check_Fixed_Point_Type_0;
+         Set_Etype (N, Universal_Real);
+
+      ------------
+      -- Denorm --
+      ------------
+
+      when Attribute_Denorm =>
+         Check_Floating_Point_Type_0;
+         Set_Etype (N, Standard_Boolean);
+
+      ------------
+      -- Digits --
+      ------------
+
+      when Attribute_Digits =>
+         Check_E0;
+         Check_Type;
+
+         if not Is_Floating_Point_Type (P_Type)
+           and then not Is_Decimal_Fixed_Point_Type (P_Type)
+         then
+            Error_Attr
+              ("prefix of % attribute must be float or decimal type", P);
+         end if;
+
+         Set_Etype (N, Universal_Integer);
+
+      ---------------
+      -- Elab_Body --
+      ---------------
+
+      --  Also handles processing for Elab_Spec
+
+      when Attribute_Elab_Body | Attribute_Elab_Spec =>
+         Check_E0;
+         Check_Unit_Name (P);
+         Set_Etype (N, Standard_Void_Type);
+
+         --  We have to manually call the expander in this case to get
+         --  the necessary expansion (normally attributes that return
+         --  entities are not expanded).
+
+         Expand (N);
+
+      ---------------
+      -- Elab_Spec --
+      ---------------
+
+      --  Shares processing with Elab_Body
+
+      ----------------
+      -- Elaborated --
+      ----------------
+
+      when Attribute_Elaborated =>
+         Check_E0;
+         Check_Library_Unit;
+         Set_Etype (N, Standard_Boolean);
+
+      ----------
+      -- Emax --
+      ----------
+
+      when Attribute_Emax =>
+         Check_Floating_Point_Type_0;
+         Set_Etype (N, Universal_Integer);
+
+      --------------
+      -- Enum_Rep --
+      --------------
+
+      when Attribute_Enum_Rep => Enum_Rep : declare
+      begin
+         if Present (E1) then
+            Check_E1;
+            Check_Discrete_Type;
+            Resolve (E1, P_Base_Type);
+
+         else
+            if not Is_Entity_Name (P)
+              or else (not Is_Object (Entity (P))
+                         and then
+                       Ekind (Entity (P)) /= E_Enumeration_Literal)
+            then
+               Error_Attr
+                 ("prefix of %attribute must be " &
+                  "discrete type/object or enum literal", P);
+            end if;
+         end if;
+
+         Set_Etype (N, Universal_Integer);
+      end Enum_Rep;
+
+      -------------
+      -- Epsilon --
+      -------------
+
+      when Attribute_Epsilon =>
+         Check_Floating_Point_Type_0;
+         Set_Etype (N, Universal_Real);
+
+      --------------
+      -- Exponent --
+      --------------
+
+      when Attribute_Exponent =>
+         Check_Floating_Point_Type_1;
+         Set_Etype (N, Universal_Integer);
+         Resolve (E1, P_Base_Type);
+
+      ------------------
+      -- External_Tag --
+      ------------------
+
+      when Attribute_External_Tag =>
+         Check_E0;
+         Check_Type;
+
+         Set_Etype (N, Standard_String);
+
+         if not Is_Tagged_Type (P_Type) then
+            Error_Attr ("prefix of % attribute must be tagged", P);
+         end if;
+
+      -----------
+      -- First --
+      -----------
+
+      when Attribute_First =>
+         Check_Array_Or_Scalar_Type;
+
+      ---------------
+      -- First_Bit --
+      ---------------
+
+      when Attribute_First_Bit =>
+         Check_Component;
+         Set_Etype (N, Universal_Integer);
+
+      -----------------
+      -- Fixed_Value --
+      -----------------
+
+      when Attribute_Fixed_Value =>
+         Check_E1;
+         Check_Fixed_Point_Type;
+         Resolve (E1, Any_Integer);
+         Set_Etype (N, P_Base_Type);
+
+      -----------
+      -- Floor --
+      -----------
+
+      when Attribute_Floor =>
+         Check_Floating_Point_Type_1;
+         Set_Etype (N, P_Base_Type);
+         Resolve (E1, P_Base_Type);
+
+      ----------
+      -- Fore --
+      ----------
+
+      when Attribute_Fore =>
+         Check_Fixed_Point_Type_0;
+         Set_Etype (N, Universal_Integer);
+
+      --------------
+      -- Fraction --
+      --------------
+
+      when Attribute_Fraction =>
+         Check_Floating_Point_Type_1;
+         Set_Etype (N, P_Base_Type);
+         Resolve (E1, P_Base_Type);
+
+      -----------------------
+      -- Has_Discriminants --
+      -----------------------
+
+      when Attribute_Has_Discriminants =>
+         Legal_Formal_Attribute;
+
+      --------------
+      -- Identity --
+      --------------
+
+      when Attribute_Identity =>
+         Check_E0;
+         Analyze (P);
+
+         if Etype (P) =  Standard_Exception_Type then
+            Set_Etype (N, RTE (RE_Exception_Id));
+
+         elsif Is_Task_Type (Etype (P))
+           or else (Is_Access_Type (Etype (P))
+              and then Is_Task_Type (Designated_Type (Etype (P))))
+         then
+            Resolve (P, Etype (P));
+            Set_Etype (N, RTE (RO_AT_Task_ID));
+
+         else
+            Error_Attr ("prefix of % attribute must be a task or an "
+              & "exception", P);
+         end if;
+
+      -----------
+      -- Image --
+      -----------
+
+      when Attribute_Image => Image :
+      begin
+         Set_Etype (N, Standard_String);
+         Check_Scalar_Type;
+
+         if Is_Real_Type (P_Type) then
+            if Ada_83 and then Comes_From_Source (N) then
+               Error_Msg_Name_1 := Aname;
+               Error_Msg_N
+                 ("(Ada 83) % attribute not allowed for real types", N);
+            end if;
+         end if;
+
+         if Is_Enumeration_Type (P_Type) then
+            Check_Restriction (No_Enumeration_Maps, N);
+         end if;
+
+         Check_E1;
+         Resolve (E1, P_Base_Type);
+         Check_Enum_Image;
+         Validate_Non_Static_Attribute_Function_Call;
+      end Image;
+
+      ---------
+      -- Img --
+      ---------
+
+      when Attribute_Img => Img :
+      begin
+         Set_Etype (N, Standard_String);
+
+         if not Is_Scalar_Type (P_Type)
+           or else (Is_Entity_Name (P) and then Is_Type (Entity (P)))
+         then
+            Error_Attr
+              ("prefix of % attribute must be scalar object name", N);
+         end if;
+
+         Check_Enum_Image;
+      end Img;
+
+      -----------
+      -- Input --
+      -----------
+
+      when Attribute_Input =>
+         Check_E1;
+         Check_Stream_Attribute (Name_uInput);
+         Disallow_In_No_Run_Time_Mode (N);
+         Set_Etype (N, P_Base_Type);
+
+      -------------------
+      -- Integer_Value --
+      -------------------
+
+      when Attribute_Integer_Value =>
+         Check_E1;
+         Check_Integer_Type;
+         Resolve (E1, Any_Fixed);
+         Set_Etype (N, P_Base_Type);
+
+      -----------
+      -- Large --
+      -----------
+
+      when Attribute_Large =>
+         Check_E0;
+         Check_Real_Type;
+         Set_Etype (N, Universal_Real);
+
+      ----------
+      -- Last --
+      ----------
+
+      when Attribute_Last =>
+         Check_Array_Or_Scalar_Type;
+
+      --------------
+      -- Last_Bit --
+      --------------
+
+      when Attribute_Last_Bit =>
+         Check_Component;
+         Set_Etype (N, Universal_Integer);
+
+      ------------------
+      -- Leading_Part --
+      ------------------
+
+      when Attribute_Leading_Part =>
+         Check_Floating_Point_Type_2;
+         Set_Etype (N, P_Base_Type);
+         Resolve (E1, P_Base_Type);
+         Resolve (E2, Any_Integer);
+
+      ------------
+      -- Length --
+      ------------
+
+      when Attribute_Length =>
+         Check_Array_Type;
+         Set_Etype (N, Universal_Integer);
+
+      -------------
+      -- Machine --
+      -------------
+
+      when Attribute_Machine =>
+         Check_Floating_Point_Type_1;
+         Set_Etype (N, P_Base_Type);
+         Resolve (E1, P_Base_Type);
+
+      ------------------
+      -- Machine_Emax --
+      ------------------
+
+      when Attribute_Machine_Emax =>
+         Check_Floating_Point_Type_0;
+         Set_Etype (N, Universal_Integer);
+
+      ------------------
+      -- Machine_Emin --
+      ------------------
+
+      when Attribute_Machine_Emin =>
+         Check_Floating_Point_Type_0;
+         Set_Etype (N, Universal_Integer);
+
+      ----------------------
+      -- Machine_Mantissa --
+      ----------------------
+
+      when Attribute_Machine_Mantissa =>
+         Check_Floating_Point_Type_0;
+         Set_Etype (N, Universal_Integer);
+
+      -----------------------
+      -- Machine_Overflows --
+      -----------------------
+
+      when Attribute_Machine_Overflows =>
+         Check_Real_Type;
+         Check_E0;
+         Set_Etype (N, Standard_Boolean);
+
+      -------------------
+      -- Machine_Radix --
+      -------------------
+
+      when Attribute_Machine_Radix =>
+         Check_Real_Type;
+         Check_E0;
+         Set_Etype (N, Universal_Integer);
+
+      --------------------
+      -- Machine_Rounds --
+      --------------------
+
+      when Attribute_Machine_Rounds =>
+         Check_Real_Type;
+         Check_E0;
+         Set_Etype (N, Standard_Boolean);
+
+      ------------------
+      -- Machine_Size --
+      ------------------
+
+      when Attribute_Machine_Size =>
+         Check_E0;
+         Check_Type;
+         Check_Not_Incomplete_Type;
+         Set_Etype (N, Universal_Integer);
+
+      --------------
+      -- Mantissa --
+      --------------
+
+      when Attribute_Mantissa =>
+         Check_E0;
+         Check_Real_Type;
+         Set_Etype (N, Universal_Integer);
+
+      ---------
+      -- Max --
+      ---------
+
+      when Attribute_Max =>
+         Check_E2;
+         Check_Scalar_Type;
+         Resolve (E1, P_Base_Type);
+         Resolve (E2, P_Base_Type);
+         Set_Etype (N, P_Base_Type);
+
+      ----------------------------
+      -- Max_Interrupt_Priority --
+      ----------------------------
+
+      when Attribute_Max_Interrupt_Priority =>
+         Standard_Attribute
+           (UI_To_Int
+             (Expr_Value
+               (Expression
+                 (Parent (RTE (RE_Max_Interrupt_Priority))))));
+
+      ------------------
+      -- Max_Priority --
+      ------------------
+
+      when Attribute_Max_Priority =>
+         Standard_Attribute
+           (UI_To_Int
+             (Expr_Value
+               (Expression
+                 (Parent (RTE (RE_Max_Priority))))));
+
+      ----------------------------------
+      -- Max_Size_In_Storage_Elements --
+      ----------------------------------
+
+      when Attribute_Max_Size_In_Storage_Elements =>
+         Check_E0;
+         Check_Type;
+         Check_Not_Incomplete_Type;
+         Set_Etype (N, Universal_Integer);
+
+      -----------------------
+      -- Maximum_Alignment --
+      -----------------------
+
+      when Attribute_Maximum_Alignment =>
+         Standard_Attribute (Ttypes.Maximum_Alignment);
+
+      --------------------
+      -- Mechanism_Code --
+      --------------------
+
+      when Attribute_Mechanism_Code =>
+
+         if not Is_Entity_Name (P)
+           or else not Is_Subprogram (Entity (P))
+         then
+            Error_Attr ("prefix of % attribute must be subprogram", P);
+         end if;
+
+         Check_Either_E0_Or_E1;
+
+         if Present (E1) then
+            Resolve (E1, Any_Integer);
+            Set_Etype (E1, Standard_Integer);
+
+            if not Is_Static_Expression (E1) then
+               Error_Attr
+                 ("expression for parameter number must be static", E1);
+
+            elsif UI_To_Int (Intval (E1)) > Number_Formals (Entity (P))
+              or else UI_To_Int (Intval (E1)) < 0
+            then
+               Error_Attr ("invalid parameter number for %attribute", E1);
+            end if;
+         end if;
+
+         Set_Etype (N, Universal_Integer);
+
+      ---------
+      -- Min --
+      ---------
+
+      when Attribute_Min =>
+         Check_E2;
+         Check_Scalar_Type;
+         Resolve (E1, P_Base_Type);
+         Resolve (E2, P_Base_Type);
+         Set_Etype (N, P_Base_Type);
+
+      -----------
+      -- Model --
+      -----------
+
+      when Attribute_Model =>
+         Check_Floating_Point_Type_1;
+         Set_Etype (N, P_Base_Type);
+         Resolve (E1, P_Base_Type);
+
+      ----------------
+      -- Model_Emin --
+      ----------------
+
+      when Attribute_Model_Emin =>
+         Check_Floating_Point_Type_0;
+         Set_Etype (N, Universal_Integer);
+
+      -------------------
+      -- Model_Epsilon --
+      -------------------
+
+      when Attribute_Model_Epsilon =>
+         Check_Floating_Point_Type_0;
+         Set_Etype (N, Universal_Real);
+
+      --------------------
+      -- Model_Mantissa --
+      --------------------
+
+      when Attribute_Model_Mantissa =>
+         Check_Floating_Point_Type_0;
+         Set_Etype (N, Universal_Integer);
+
+      -----------------
+      -- Model_Small --
+      -----------------
+
+      when Attribute_Model_Small =>
+         Check_Floating_Point_Type_0;
+         Set_Etype (N, Universal_Real);
+
+      -------------
+      -- Modulus --
+      -------------
+
+      when Attribute_Modulus =>
+         Check_E0;
+         Check_Type;
+
+         if not Is_Modular_Integer_Type (P_Type) then
+            Error_Attr ("prefix of % attribute must be modular type", P);
+         end if;
+
+         Set_Etype (N, Universal_Integer);
+
+      --------------------
+      -- Null_Parameter --
+      --------------------
+
+      when Attribute_Null_Parameter => Null_Parameter : declare
+         Parnt  : constant Node_Id := Parent (N);
+         GParnt : constant Node_Id := Parent (Parnt);
+
+         procedure Bad_Null_Parameter (Msg : String);
+         --  Used if bad Null parameter attribute node is found. Issues
+         --  given error message, and also sets the type to Any_Type to
+         --  avoid blowups later on from dealing with a junk node.
+
+         procedure Must_Be_Imported (Proc_Ent : Entity_Id);
+         --  Called to check that Proc_Ent is imported subprogram
+
+         ------------------------
+         -- Bad_Null_Parameter --
+         ------------------------
+
+         procedure Bad_Null_Parameter (Msg : String) is
+         begin
+            Error_Msg_N (Msg, N);
+            Set_Etype (N, Any_Type);
+         end Bad_Null_Parameter;
+
+         ----------------------
+         -- Must_Be_Imported --
+         ----------------------
+
+         procedure Must_Be_Imported (Proc_Ent : Entity_Id) is
+            Pent : Entity_Id := Proc_Ent;
+
+         begin
+            while Present (Alias (Pent)) loop
+               Pent := Alias (Pent);
+            end loop;
+
+            --  Ignore check if procedure not frozen yet (we will get
+            --  another chance when the default parameter is reanalyzed)
+
+            if not Is_Frozen (Pent) then
+               return;
+
+            elsif not Is_Imported (Pent) then
+               Bad_Null_Parameter
+                 ("Null_Parameter can only be used with imported subprogram");
+
+            else
+               return;
+            end if;
+         end Must_Be_Imported;
+
+      --  Start of processing for Null_Parameter
+
+      begin
+         Check_Type;
+         Check_E0;
+         Set_Etype (N, P_Type);
+
+         --  Case of attribute used as default expression
+
+         if Nkind (Parnt) = N_Parameter_Specification then
+            Must_Be_Imported (Defining_Entity (GParnt));
+
+         --  Case of attribute used as actual for subprogram (positional)
+
+         elsif (Nkind (Parnt) = N_Procedure_Call_Statement
+                 or else
+                Nkind (Parnt) = N_Function_Call)
+            and then Is_Entity_Name (Name (Parnt))
+         then
+            Must_Be_Imported (Entity (Name (Parnt)));
+
+         --  Case of attribute used as actual for subprogram (named)
+
+         elsif Nkind (Parnt) = N_Parameter_Association
+           and then (Nkind (GParnt) = N_Procedure_Call_Statement
+                       or else
+                     Nkind (GParnt) = N_Function_Call)
+           and then Is_Entity_Name (Name (GParnt))
+         then
+            Must_Be_Imported (Entity (Name (GParnt)));
+
+         --  Not an allowed case
+
+         else
+            Bad_Null_Parameter
+              ("Null_Parameter must be actual or default parameter");
+         end if;
+
+      end Null_Parameter;
+
+      -----------------
+      -- Object_Size --
+      -----------------
+
+      when Attribute_Object_Size =>
+         Check_E0;
+         Check_Type;
+         Check_Not_Incomplete_Type;
+         Set_Etype (N, Universal_Integer);
+
+      ------------
+      -- Output --
+      ------------
+
+      when Attribute_Output =>
+         Check_E2;
+         Check_Stream_Attribute (Name_uInput);
+         Set_Etype (N, Standard_Void_Type);
+         Disallow_In_No_Run_Time_Mode (N);
+         Resolve (N, Standard_Void_Type);
+
+      ------------------
+      -- Partition_ID --
+      ------------------
+
+      when Attribute_Partition_ID =>
+         Check_E0;
+
+         if P_Type /= Any_Type then
+            if not Is_Library_Level_Entity (Entity (P)) then
+               Error_Attr
+                 ("prefix of % attribute must be library-level entity", P);
+
+            --  The defining entity of prefix should not be declared inside
+            --  a Pure unit. RM E.1(8).
+            --  The Is_Pure flag has been set during declaration.
+
+            elsif Is_Entity_Name (P)
+              and then Is_Pure (Entity (P))
+            then
+               Error_Attr
+                 ("prefix of % attribute must not be declared pure", P);
+            end if;
+         end if;
+
+         Set_Etype (N, Universal_Integer);
+
+      -------------------------
+      -- Passed_By_Reference --
+      -------------------------
+
+      when Attribute_Passed_By_Reference =>
+         Check_E0;
+         Check_Type;
+         Set_Etype (N, Standard_Boolean);
+
+      ---------
+      -- Pos --
+      ---------
+
+      when Attribute_Pos =>
+         Check_Discrete_Type;
+         Check_E1;
+         Resolve (E1, P_Base_Type);
+         Set_Etype (N, Universal_Integer);
+
+      --------------
+      -- Position --
+      --------------
+
+      when Attribute_Position =>
+         Check_Component;
+         Set_Etype (N, Universal_Integer);
+
+      ----------
+      -- Pred --
+      ----------
+
+      when Attribute_Pred =>
+         Check_Scalar_Type;
+         Check_E1;
+         Resolve (E1, P_Base_Type);
+         Set_Etype (N, P_Base_Type);
+
+         --  Nothing to do for real type case
+
+         if Is_Real_Type (P_Type) then
+            null;
+
+         --  If not modular type, test for overflow check required
+
+         else
+            if not Is_Modular_Integer_Type (P_Type)
+              and then not Range_Checks_Suppressed (P_Base_Type)
+            then
+               Enable_Range_Check (E1);
+            end if;
+         end if;
+
+      -----------
+      -- Range --
+      -----------
+
+      when Attribute_Range =>
+         Check_Array_Or_Scalar_Type;
+
+         if Ada_83
+           and then Is_Scalar_Type (P_Type)
+           and then Comes_From_Source (N)
+         then
+            Error_Attr
+              ("(Ada 83) % attribute not allowed for scalar type", P);
+         end if;
+
+      ------------------
+      -- Range_Length --
+      ------------------
+
+      when Attribute_Range_Length =>
+         Check_Discrete_Type;
+         Set_Etype (N, Universal_Integer);
+
+      ----------
+      -- Read --
+      ----------
+
+      when Attribute_Read =>
+         Check_E2;
+         Check_Stream_Attribute (Name_uRead);
+         Set_Etype (N, Standard_Void_Type);
+         Resolve (N, Standard_Void_Type);
+         Disallow_In_No_Run_Time_Mode (N);
+         Note_Possible_Modification (E2);
+
+      ---------------
+      -- Remainder --
+      ---------------
+
+      when Attribute_Remainder =>
+         Check_Floating_Point_Type_2;
+         Set_Etype (N, P_Base_Type);
+         Resolve (E1, P_Base_Type);
+         Resolve (E2, P_Base_Type);
+
+      -----------
+      -- Round --
+      -----------
+
+      when Attribute_Round =>
+         Check_E1;
+         Check_Decimal_Fixed_Point_Type;
+         Set_Etype (N, P_Base_Type);
+
+         --  Because the context is universal_real (3.5.10(12)) it is a legal
+         --  context for a universal fixed expression. This is the only
+         --  attribute whose functional description involves U_R.
+
+         if Etype (E1) = Universal_Fixed then
+            declare
+               Conv : constant Node_Id := Make_Type_Conversion (Loc,
+                  Subtype_Mark => New_Occurrence_Of (Universal_Real, Loc),
+                  Expression   => Relocate_Node (E1));
+
+            begin
+               Rewrite (E1, Conv);
+               Analyze (E1);
+            end;
+         end if;
+
+         Resolve (E1, Any_Real);
+
+      --------------
+      -- Rounding --
+      --------------
+
+      when Attribute_Rounding =>
+         Check_Floating_Point_Type_1;
+         Set_Etype (N, P_Base_Type);
+         Resolve (E1, P_Base_Type);
+
+      ---------------
+      -- Safe_Emax --
+      ---------------
+
+      when Attribute_Safe_Emax =>
+         Check_Floating_Point_Type_0;
+         Set_Etype (N, Universal_Integer);
+
+      ----------------
+      -- Safe_First --
+      ----------------
+
+      when Attribute_Safe_First =>
+         Check_Floating_Point_Type_0;
+         Set_Etype (N, Universal_Real);
+
+      ----------------
+      -- Safe_Large --
+      ----------------
+
+      when Attribute_Safe_Large =>
+         Check_E0;
+         Check_Real_Type;
+         Set_Etype (N, Universal_Real);
+
+      ---------------
+      -- Safe_Last --
+      ---------------
+
+      when Attribute_Safe_Last =>
+         Check_Floating_Point_Type_0;
+         Set_Etype (N, Universal_Real);
+
+      ----------------
+      -- Safe_Small --
+      ----------------
+
+      when Attribute_Safe_Small =>
+         Check_E0;
+         Check_Real_Type;
+         Set_Etype (N, Universal_Real);
+
+      -----------
+      -- Scale --
+      -----------
+
+      when Attribute_Scale =>
+         Check_E0;
+         Check_Decimal_Fixed_Point_Type;
+         Set_Etype (N, Universal_Integer);
+
+      -------------
+      -- Scaling --
+      -------------
+
+      when Attribute_Scaling =>
+         Check_Floating_Point_Type_2;
+         Set_Etype (N, P_Base_Type);
+         Resolve (E1, P_Base_Type);
+
+      ------------------
+      -- Signed_Zeros --
+      ------------------
+
+      when Attribute_Signed_Zeros =>
+         Check_Floating_Point_Type_0;
+         Set_Etype (N, Standard_Boolean);
+
+      ----------
+      -- Size --
+      ----------
+
+      when Attribute_Size | Attribute_VADS_Size =>
+         Check_E0;
+
+         if Is_Object_Reference (P)
+           or else (Is_Entity_Name (P)
+                      and then
+                    Ekind (Entity (P)) = E_Function)
+         then
+            Check_Object_Reference (P);
+
+         elsif Nkind (P) = N_Attribute_Reference
+           or else
+             (Nkind (P) = N_Selected_Component
+               and then (Is_Entry (Entity (Selector_Name (P)))
+                           or else
+                         Is_Subprogram (Entity (Selector_Name (P)))))
+           or else
+             (Is_Entity_Name (P)
+               and then not Is_Type (Entity (P))
+               and then not Is_Object (Entity (P)))
+         then
+            Error_Attr ("invalid prefix for % attribute", P);
+         end if;
+
+         Check_Not_Incomplete_Type;
+         Set_Etype (N, Universal_Integer);
+
+      -----------
+      -- Small --
+      -----------
+
+      when Attribute_Small =>
+         Check_E0;
+         Check_Real_Type;
+         Set_Etype (N, Universal_Real);
+
+      ------------------
+      -- Storage_Pool --
+      ------------------
+
+      when Attribute_Storage_Pool =>
+         if Is_Access_Type (P_Type) then
+            Check_E0;
+
+            --  Set appropriate entity
+
+            if Present (Associated_Storage_Pool (Root_Type (P_Type))) then
+               Set_Entity (N, Associated_Storage_Pool (Root_Type (P_Type)));
+            else
+               Set_Entity (N, RTE (RE_Global_Pool_Object));
+            end if;
+
+            Set_Etype (N, Class_Wide_Type (RTE (RE_Root_Storage_Pool)));
+
+            --  Validate_Remote_Access_To_Class_Wide_Type for attribute
+            --  Storage_Pool since this attribute is not defined for such
+            --  types (RM E.2.3(22)).
+
+            Validate_Remote_Access_To_Class_Wide_Type (N);
+
+         else
+            Error_Attr ("prefix of % attribute must be access type", P);
+         end if;
+
+      ------------------
+      -- Storage_Size --
+      ------------------
+
+      when Attribute_Storage_Size =>
+
+         if Is_Task_Type (P_Type) then
+            Check_E0;
+            Set_Etype (N, Universal_Integer);
+
+         elsif Is_Access_Type (P_Type) then
+            if Is_Entity_Name (P)
+              and then Is_Type (Entity (P))
+            then
+               Check_E0;
+               Check_Type;
+               Set_Etype (N, Universal_Integer);
+
+               --   Validate_Remote_Access_To_Class_Wide_Type for attribute
+               --   Storage_Size since this attribute is not defined for
+               --   such types (RM E.2.3(22)).
+
+               Validate_Remote_Access_To_Class_Wide_Type (N);
+
+            --  The prefix is allowed to be an implicit dereference
+            --  of an access value designating a task.
+
+            else
+               Check_E0;
+               Check_Task_Prefix;
+               Set_Etype (N, Universal_Integer);
+            end if;
+
+         else
+            Error_Attr
+              ("prefix of % attribute must be access or task type", P);
+         end if;
+
+      ------------------
+      -- Storage_Unit --
+      ------------------
+
+      when Attribute_Storage_Unit =>
+         Standard_Attribute (Ttypes.System_Storage_Unit);
+
+      ----------
+      -- Succ --
+      ----------
+
+      when Attribute_Succ =>
+         Check_Scalar_Type;
+         Check_E1;
+         Resolve (E1, P_Base_Type);
+         Set_Etype (N, P_Base_Type);
+
+         --  Nothing to do for real type case
+
+         if Is_Real_Type (P_Type) then
+            null;
+
+         --  If not modular type, test for overflow check required.
+
+         else
+            if not Is_Modular_Integer_Type (P_Type)
+              and then not Range_Checks_Suppressed (P_Base_Type)
+            then
+               Enable_Range_Check (E1);
+            end if;
+         end if;
+
+      ---------
+      -- Tag --
+      ---------
+
+      when Attribute_Tag =>
+         Check_E0;
+         Check_Dereference;
+
+         if not Is_Tagged_Type (P_Type) then
+            Error_Attr ("prefix of % attribute must be tagged", P);
+
+         --  Next test does not apply to generated code
+         --  why not, and what does the illegal reference mean???
+
+         elsif Is_Object_Reference (P)
+           and then not Is_Class_Wide_Type (P_Type)
+           and then Comes_From_Source (N)
+         then
+            Error_Attr
+              ("% attribute can only be applied to objects of class-wide type",
+               P);
+         end if;
+
+         Set_Etype (N, RTE (RE_Tag));
+
+      ----------------
+      -- Terminated --
+      ----------------
+
+      when Attribute_Terminated =>
+         Check_E0;
+         Set_Etype (N, Standard_Boolean);
+         Check_Task_Prefix;
+
+      ----------
+      -- Tick --
+      ----------
+
+      when Attribute_Tick =>
+         Check_Standard_Prefix;
+         Rewrite (N,
+           Make_Real_Literal (Loc,
+             UR_From_Components (
+               Num   => UI_From_Int (Ttypes.System_Tick_Nanoseconds),
+               Den   => UI_From_Int (9),
+               Rbase => 10)));
+         Analyze (N);
+
+      ----------------
+      -- To_Address --
+      ----------------
+
+      when Attribute_To_Address =>
+         Check_E1;
+         Analyze (P);
+
+         if Nkind (P) /= N_Identifier
+           or else Chars (P) /= Name_System
+         then
+            Error_Attr ("prefix of %attribute must be System", P);
+         end if;
+
+         Generate_Reference (RTE (RE_Address), P);
+         Analyze_And_Resolve (E1, Any_Integer);
+         Set_Etype (N, RTE (RE_Address));
+
+      ----------------
+      -- Truncation --
+      ----------------
+
+      when Attribute_Truncation =>
+         Check_Floating_Point_Type_1;
+         Resolve (E1, P_Base_Type);
+         Set_Etype (N, P_Base_Type);
+
+      ----------------
+      -- Type_Class --
+      ----------------
+
+      when Attribute_Type_Class =>
+         Check_E0;
+         Check_Type;
+         Check_Not_Incomplete_Type;
+         Set_Etype (N, RTE (RE_Type_Class));
+
+      -----------------
+      -- UET_Address --
+      -----------------
+
+      when Attribute_UET_Address =>
+         Check_E0;
+         Check_Unit_Name (P);
+         Set_Etype (N, RTE (RE_Address));
+
+      -----------------------
+      -- Unbiased_Rounding --
+      -----------------------
+
+      when Attribute_Unbiased_Rounding =>
+         Check_Floating_Point_Type_1;
+         Set_Etype (N, P_Base_Type);
+         Resolve (E1, P_Base_Type);
+
+      ----------------------
+      -- Unchecked_Access --
+      ----------------------
+
+      when Attribute_Unchecked_Access =>
+         if Comes_From_Source (N) then
+            Check_Restriction (No_Unchecked_Access, N);
+         end if;
+
+         Access_Attribute;
+
+      ------------------------------
+      -- Universal_Literal_String --
+      ------------------------------
+
+      --  This is a GNAT specific attribute whose prefix must be a named
+      --  number where the expression is either a single numeric literal,
+      --  or a numeric literal immediately preceded by a minus sign. The
+      --  result is equivalent to a string literal containing the text of
+      --  the literal as it appeared in the source program with a possible
+      --  leading minus sign.
+
+      when Attribute_Universal_Literal_String => Universal_Literal_String :
+      begin
+         Check_E0;
+
+         if not Is_Entity_Name (P)
+           or else Ekind (Entity (P)) not in Named_Kind
+         then
+            Error_Attr ("prefix for % attribute must be named number", P);
+
+         else
+            declare
+               Expr     : Node_Id;
+               Negative : Boolean;
+               S        : Source_Ptr;
+               Src      : Source_Buffer_Ptr;
+
+            begin
+               Expr := Original_Node (Expression (Parent (Entity (P))));
+
+               if Nkind (Expr) = N_Op_Minus then
+                  Negative := True;
+                  Expr := Original_Node (Right_Opnd (Expr));
+               else
+                  Negative := False;
+               end if;
+
+               if Nkind (Expr) /= N_Integer_Literal
+                 and then Nkind (Expr) /= N_Real_Literal
+               then
+                  Error_Attr
+                    ("named number for % attribute must be simple literal", N);
+               end if;
+
+               --  Build string literal corresponding to source literal text
+
+               Start_String;
+
+               if Negative then
+                  Store_String_Char (Get_Char_Code ('-'));
+               end if;
+
+               S := Sloc (Expr);
+               Src := Source_Text (Get_Source_File_Index (S));
+
+               while Src (S) /= ';' and then Src (S) /= ' ' loop
+                  Store_String_Char (Get_Char_Code (Src (S)));
+                  S := S + 1;
+               end loop;
+
+               --  Now we rewrite the attribute with the string literal
+
+               Rewrite (N,
+                 Make_String_Literal (Loc, End_String));
+               Analyze (N);
+            end;
+         end if;
+      end Universal_Literal_String;
+
+      -------------------------
+      -- Unrestricted_Access --
+      -------------------------
+
+      --  This is a GNAT specific attribute which is like Access except that
+      --  all scope checks and checks for aliased views are omitted.
+
+      when Attribute_Unrestricted_Access =>
+         if Comes_From_Source (N) then
+            Check_Restriction (No_Unchecked_Access, N);
+         end if;
+
+         if Is_Entity_Name (P) then
+            Set_Address_Taken (Entity (P));
+         end if;
+
+         Access_Attribute;
+
+      ---------
+      -- Val --
+      ---------
+
+      when Attribute_Val => Val : declare
+      begin
+         Check_E1;
+         Check_Discrete_Type;
+         Resolve (E1, Any_Integer);
+         Set_Etype (N, P_Base_Type);
+
+         --  Note, we need a range check in general, but we wait for the
+         --  Resolve call to do this, since we want to let Eval_Attribute
+         --  have a chance to find an static illegality first!
+      end Val;
+
+      -----------
+      -- Valid --
+      -----------
+
+      when Attribute_Valid =>
+         Check_E0;
+
+         --  Ignore check for object if we have a 'Valid reference generated
+         --  by the expanded code, since in some cases valid checks can occur
+         --  on items that are names, but are not objects (e.g. attributes).
+
+         if Comes_From_Source (N) then
+            Check_Object_Reference (P);
+         end if;
+
+         if not Is_Scalar_Type (P_Type) then
+            Error_Attr ("object for % attribute must be of scalar type", P);
+         end if;
+
+         Set_Etype (N, Standard_Boolean);
+
+      -----------
+      -- Value --
+      -----------
+
+      when Attribute_Value => Value :
+      begin
+         Check_E1;
+         Check_Scalar_Type;
+
+         if Is_Enumeration_Type (P_Type) then
+            Check_Restriction (No_Enumeration_Maps, N);
+         end if;
+
+         --  Set Etype before resolving expression because expansion
+         --  of expression may require enclosing type.
+
+         Set_Etype (N, P_Type);
+         Validate_Non_Static_Attribute_Function_Call;
+      end Value;
+
+      ----------------
+      -- Value_Size --
+      ----------------
+
+      when Attribute_Value_Size =>
+         Check_E0;
+         Check_Type;
+         Check_Not_Incomplete_Type;
+         Set_Etype (N, Universal_Integer);
+
+      -------------
+      -- Version --
+      -------------
+
+      when Attribute_Version =>
+         Check_E0;
+         Check_Program_Unit;
+         Set_Etype (N, RTE (RE_Version_String));
+
+      ------------------
+      -- Wchar_T_Size --
+      ------------------
+
+      when Attribute_Wchar_T_Size =>
+         Standard_Attribute (Interfaces_Wchar_T_Size);
+
+      ----------------
+      -- Wide_Image --
+      ----------------
+
+      when Attribute_Wide_Image => Wide_Image :
+      begin
+         Check_Scalar_Type;
+         Set_Etype (N, Standard_Wide_String);
+         Check_E1;
+         Resolve (E1, P_Base_Type);
+         Validate_Non_Static_Attribute_Function_Call;
+      end Wide_Image;
+
+      ----------------
+      -- Wide_Value --
+      ----------------
+
+      when Attribute_Wide_Value => Wide_Value :
+      begin
+         Check_E1;
+         Check_Scalar_Type;
+
+         --  Set Etype before resolving expression because expansion
+         --  of expression may require enclosing type.
+
+         Set_Etype (N, P_Type);
+         Validate_Non_Static_Attribute_Function_Call;
+      end Wide_Value;
+
+      ----------------
+      -- Wide_Width --
+      ----------------
+
+      when Attribute_Wide_Width =>
+         Check_E0;
+         Check_Scalar_Type;
+         Set_Etype (N, Universal_Integer);
+
+      -----------
+      -- Width --
+      -----------
+
+      when Attribute_Width =>
+         Check_E0;
+         Check_Scalar_Type;
+         Set_Etype (N, Universal_Integer);
+
+      ---------------
+      -- Word_Size --
+      ---------------
+
+      when Attribute_Word_Size =>
+         Standard_Attribute (System_Word_Size);
+
+      -----------
+      -- Write --
+      -----------
+
+      when Attribute_Write =>
+         Check_E2;
+         Check_Stream_Attribute (Name_uWrite);
+         Set_Etype (N, Standard_Void_Type);
+         Disallow_In_No_Run_Time_Mode (N);
+         Resolve (N, Standard_Void_Type);
+
+      end case;
+
+   --  All errors raise Bad_Attribute, so that we get out before any further
+   --  damage occurs when an error is detected (for example, if we check for
+   --  one attribute expression, and the check succeeds, we want to be able
+   --  to proceed securely assuming that an expression is in fact present.
+
+   exception
+      when Bad_Attribute =>
+         Set_Etype (N, Any_Type);
+         return;
+
+   end Analyze_Attribute;
+
+   --------------------
+   -- Eval_Attribute --
+   --------------------
+
+   procedure Eval_Attribute (N : Node_Id) is
+      Loc   : constant Source_Ptr   := Sloc (N);
+      Aname : constant Name_Id      := Attribute_Name (N);
+      Id    : constant Attribute_Id := Get_Attribute_Id (Aname);
+      P     : constant Node_Id      := Prefix (N);
+
+      C_Type : constant Entity_Id := Etype (N);
+      --  The type imposed by the context.
+
+      E1 : Node_Id;
+      --  First expression, or Empty if none
+
+      E2 : Node_Id;
+      --  Second expression, or Empty if none
+
+      P_Entity : Entity_Id;
+      --  Entity denoted by prefix
+
+      P_Type : Entity_Id;
+      --  The type of the prefix
+
+      P_Base_Type : Entity_Id;
+      --  The base type of the prefix type
+
+      P_Root_Type : Entity_Id;
+      --  The root type of the prefix type
+
+      Static : Boolean;
+      --  True if prefix type is static
+
+      Lo_Bound, Hi_Bound : Node_Id;
+      --  Expressions for low and high bounds of type or array index referenced
+      --  by First, Last, or Length attribute for array, set by Set_Bounds.
+
+      CE_Node : Node_Id;
+      --  Constraint error node used if we have an attribute reference has
+      --  an argument that raises a constraint error. In this case we replace
+      --  the attribute with a raise constraint_error node. This is important
+      --  processing, since otherwise gigi might see an attribute which it is
+      --  unprepared to deal with.
+
+      function Aft_Value return Nat;
+      --  Computes Aft value for current attribute prefix (used by Aft itself
+      --  and also by Width for computing the Width of a fixed point type).
+
+      procedure Check_Expressions;
+      --  In case where the attribute is not foldable, the expressions, if
+      --  any, of the attribute, are in a non-static context. This procedure
+      --  performs the required additional checks.
+
+      procedure Float_Attribute_Universal_Integer
+        (IEEES_Val : Int;
+         IEEEL_Val : Int;
+         IEEEX_Val : Int;
+         VAXFF_Val : Int;
+         VAXDF_Val : Int;
+         VAXGF_Val : Int);
+      --  This procedure evaluates a float attribute with no arguments that
+      --  returns a universal integer result. The parameters give the values
+      --  for the possible floating-point root types. See ttypef for details.
+      --  The prefix type is a float type (and is thus not a generic type).
+
+      procedure Float_Attribute_Universal_Real
+        (IEEES_Val : String;
+         IEEEL_Val : String;
+         IEEEX_Val : String;
+         VAXFF_Val : String;
+         VAXDF_Val : String;
+         VAXGF_Val : String);
+      --  This procedure evaluates a float attribute with no arguments that
+      --  returns a universal real result. The parameters give the values
+      --  required for the possible floating-point root types in string
+      --  format as real literals with a possible leading minus sign.
+      --  The prefix type is a float type (and is thus not a generic type).
+
+      function Fore_Value return Nat;
+      --  Computes the Fore value for the current attribute prefix, which is
+      --  known to be a static fixed-point type. Used by Fore and Width.
+
+      function Mantissa return Uint;
+      --  Returns the Mantissa value for the prefix type
+
+      procedure Set_Bounds;
+      --  Used for First, Last and Length attributes applied to an array or
+      --  array subtype. Sets the variables Index_Lo and Index_Hi to the low
+      --  and high bound expressions for the index referenced by the attribute
+      --  designator (i.e. the first index if no expression is present, and
+      --  the N'th index if the value N is present as an expression).
+
+      ---------------
+      -- Aft_Value --
+      ---------------
+
+      function Aft_Value return Nat is
+         Result    : Nat;
+         Delta_Val : Ureal;
+
+      begin
+         Result := 1;
+         Delta_Val := Delta_Value (P_Type);
+
+         while Delta_Val < Ureal_Tenth loop
+            Delta_Val := Delta_Val * Ureal_10;
+            Result := Result + 1;
+         end loop;
+
+         return Result;
+      end Aft_Value;
+
+      -----------------------
+      -- Check_Expressions --
+      -----------------------
+
+      procedure Check_Expressions is
+         E : Node_Id := E1;
+
+      begin
+         while Present (E) loop
+            Check_Non_Static_Context (E);
+            Next (E);
+         end loop;
+      end Check_Expressions;
+
+      ---------------------------------------
+      -- Float_Attribute_Universal_Integer --
+      ---------------------------------------
+
+      procedure Float_Attribute_Universal_Integer
+        (IEEES_Val : Int;
+         IEEEL_Val : Int;
+         IEEEX_Val : Int;
+         VAXFF_Val : Int;
+         VAXDF_Val : Int;
+         VAXGF_Val : Int)
+      is
+         Val  : Int;
+         Digs : constant Nat := UI_To_Int (Digits_Value (P_Base_Type));
+
+      begin
+         if not Vax_Float (P_Base_Type) then
+            if Digs = IEEES_Digits then
+               Val := IEEES_Val;
+            elsif Digs = IEEEL_Digits then
+               Val := IEEEL_Val;
+            else pragma Assert (Digs = IEEEX_Digits);
+               Val := IEEEX_Val;
+            end if;
+
+         else
+            if Digs = VAXFF_Digits then
+               Val := VAXFF_Val;
+            elsif Digs = VAXDF_Digits then
+               Val := VAXDF_Val;
+            else pragma Assert (Digs = VAXGF_Digits);
+               Val := VAXGF_Val;
+            end if;
+         end if;
+
+         Fold_Uint (N, UI_From_Int (Val));
+      end Float_Attribute_Universal_Integer;
+
+      ------------------------------------
+      -- Float_Attribute_Universal_Real --
+      ------------------------------------
+
+      procedure Float_Attribute_Universal_Real
+        (IEEES_Val : String;
+         IEEEL_Val : String;
+         IEEEX_Val : String;
+         VAXFF_Val : String;
+         VAXDF_Val : String;
+         VAXGF_Val : String)
+      is
+         Val  : Node_Id;
+         Digs : constant Nat := UI_To_Int (Digits_Value (P_Base_Type));
+
+      begin
+         if not Vax_Float (P_Base_Type) then
+            if Digs = IEEES_Digits then
+               Val := Real_Convert (IEEES_Val);
+            elsif Digs = IEEEL_Digits then
+               Val := Real_Convert (IEEEL_Val);
+            else pragma Assert (Digs = IEEEX_Digits);
+               Val := Real_Convert (IEEEX_Val);
+            end if;
+
+         else
+            if Digs = VAXFF_Digits then
+               Val := Real_Convert (VAXFF_Val);
+            elsif Digs = VAXDF_Digits then
+               Val := Real_Convert (VAXDF_Val);
+            else pragma Assert (Digs = VAXGF_Digits);
+               Val := Real_Convert (VAXGF_Val);
+            end if;
+         end if;
+
+         Set_Sloc (Val, Loc);
+         Rewrite (N, Val);
+         Analyze_And_Resolve (N, C_Type);
+      end Float_Attribute_Universal_Real;
+
+      ----------------
+      -- Fore_Value --
+      ----------------
+
+      --  Note that the Fore calculation is based on the actual values
+      --  of the bounds, and does not take into account possible rounding.
+
+      function Fore_Value return Nat is
+         Lo      : constant Uint  := Expr_Value (Type_Low_Bound (P_Type));
+         Hi      : constant Uint  := Expr_Value (Type_High_Bound (P_Type));
+         Small   : constant Ureal := Small_Value (P_Type);
+         Lo_Real : constant Ureal := Lo * Small;
+         Hi_Real : constant Ureal := Hi * Small;
+         T       : Ureal;
+         R       : Nat;
+
+      begin
+         --  Bounds are given in terms of small units, so first compute
+         --  proper values as reals.
+
+         T := UR_Max (abs Lo_Real, abs Hi_Real);
+         R := 2;
+
+         --  Loop to compute proper value if more than one digit required
+
+         while T >= Ureal_10 loop
+            R := R + 1;
+            T := T / Ureal_10;
+         end loop;
+
+         return R;
+      end Fore_Value;
+
+      --------------
+      -- Mantissa --
+      --------------
+
+      --  Table of mantissa values accessed by function  Computed using
+      --  the relation:
+
+      --    T'Mantissa = integer next above (D * log(10)/log(2)) + 1)
+
+      --  where D is T'Digits (RM83 3.5.7)
+
+      Mantissa_Value : constant array (Nat range 1 .. 40) of Nat := (
+          1 =>   5,
+          2 =>   8,
+          3 =>  11,
+          4 =>  15,
+          5 =>  18,
+          6 =>  21,
+          7 =>  25,
+          8 =>  28,
+          9 =>  31,
+         10 =>  35,
+         11 =>  38,
+         12 =>  41,
+         13 =>  45,
+         14 =>  48,
+         15 =>  51,
+         16 =>  55,
+         17 =>  58,
+         18 =>  61,
+         19 =>  65,
+         20 =>  68,
+         21 =>  71,
+         22 =>  75,
+         23 =>  78,
+         24 =>  81,
+         25 =>  85,
+         26 =>  88,
+         27 =>  91,
+         28 =>  95,
+         29 =>  98,
+         30 => 101,
+         31 => 104,
+         32 => 108,
+         33 => 111,
+         34 => 114,
+         35 => 118,
+         36 => 121,
+         37 => 124,
+         38 => 128,
+         39 => 131,
+         40 => 134);
+
+      function Mantissa return Uint is
+      begin
+         return
+           UI_From_Int (Mantissa_Value (UI_To_Int (Digits_Value (P_Type))));
+      end Mantissa;
+
+      ----------------
+      -- Set_Bounds --
+      ----------------
+
+      procedure Set_Bounds is
+         Ndim : Nat;
+         Indx : Node_Id;
+         Ityp : Entity_Id;
+
+      begin
+         --  For a string literal subtype, we have to construct the bounds.
+         --  Valid Ada code never applies attributes to string literals, but
+         --  it is convenient to allow the expander to generate attribute
+         --  references of this type (e.g. First and Last applied to a string
+         --  literal).
+
+         --  Note that the whole point of the E_String_Literal_Subtype is to
+         --  avoid this construction of bounds, but the cases in which we
+         --  have to materialize them are rare enough that we don't worry!
+
+         --  The low bound is simply the low bound of the base type. The
+         --  high bound is computed from the length of the string and this
+         --  low bound.
+
+         if Ekind (P_Type) = E_String_Literal_Subtype then
+            Lo_Bound :=
+              Type_Low_Bound (Etype (First_Index (Base_Type (P_Type))));
+
+            Hi_Bound :=
+              Make_Integer_Literal (Sloc (P),
+                Intval =>
+                  Expr_Value (Lo_Bound) + String_Literal_Length (P_Type) - 1);
+
+            Set_Parent (Hi_Bound, P);
+            Analyze_And_Resolve (Hi_Bound, Etype (Lo_Bound));
+            return;
+
+         --  For non-array case, just get bounds of scalar type
+
+         elsif Is_Scalar_Type (P_Type) then
+            Ityp := P_Type;
+
+         --  For array case, get type of proper index
+
+         else
+            if No (E1) then
+               Ndim := 1;
+            else
+               Ndim := UI_To_Int (Expr_Value (E1));
+            end if;
+
+            Indx := First_Index (P_Type);
+            for J in 1 .. Ndim - 1 loop
+               Next_Index (Indx);
+            end loop;
+
+            --  If no index type, get out (some other error occurred, and
+            --  we don't have enough information to complete the job!)
+
+            if No (Indx) then
+               Lo_Bound := Error;
+               Hi_Bound := Error;
+               return;
+            end if;
+
+            Ityp := Etype (Indx);
+         end if;
+
+         --  A discrete range in an index constraint is allowed to be a
+         --  subtype indication. This is syntactically a pain, but should
+         --  not propagate to the entity for the corresponding index subtype.
+         --  After checking that the subtype indication is legal, the range
+         --  of the subtype indication should be transfered to the entity.
+         --  The attributes for the bounds should remain the simple retrievals
+         --  that they are now.
+
+         Lo_Bound := Type_Low_Bound (Ityp);
+         Hi_Bound := Type_High_Bound (Ityp);
+
+      end Set_Bounds;
+
+   --  Start of processing for Eval_Attribute
+
+   begin
+      --  Acquire first two expressions (at the moment, no attributes
+      --  take more than two expressions in any case).
+
+      if Present (Expressions (N)) then
+         E1 := First (Expressions (N));
+         E2 := Next (E1);
+      else
+         E1 := Empty;
+         E2 := Empty;
+      end if;
+
+      --  Special processing for cases where the prefix is an object
+
+      if Is_Object_Reference (P) then
+
+         --  For Component_Size, the prefix is an array object, and we apply
+         --  the attribute to the type of the object. This is allowed for
+         --  both unconstrained and constrained arrays, since the bounds
+         --  have no influence on the value of this attribute.
+
+         if Id = Attribute_Component_Size then
+            P_Entity := Etype (P);
+
+         --  For First and Last, the prefix is an array object, and we apply
+         --  the attribute to the type of the array, but we need a constrained
+         --  type for this, so we use the actual subtype if available.
+
+         elsif Id = Attribute_First
+                 or else
+               Id = Attribute_Last
+                 or else
+               Id = Attribute_Length
+         then
+            declare
+               AS : constant Entity_Id := Get_Actual_Subtype_If_Available (P);
+
+            begin
+               if Present (AS) then
+                  P_Entity := AS;
+
+               --  If no actual subtype, cannot fold
+
+               else
+                  Check_Expressions;
+                  return;
+               end if;
+            end;
+
+         --  For Size, give size of object if available, otherwise we
+         --  cannot fold Size.
+
+         elsif Id = Attribute_Size then
+
+            if Is_Entity_Name (P)
+              and then Known_Esize (Entity (P))
+            then
+               Fold_Uint (N, Esize (Entity (P)));
+               Set_Is_Static_Expression (N, False);
+               return;
+
+            else
+               Check_Expressions;
+               return;
+            end if;
+
+         --  For Alignment, give size of object if available, otherwise we
+         --  cannot fold Alignment.
+
+         elsif Id = Attribute_Alignment then
+
+            if Is_Entity_Name (P)
+              and then Known_Alignment (Entity (P))
+            then
+               Fold_Uint (N, Alignment (Entity (P)));
+               Set_Is_Static_Expression (N, False);
+               return;
+
+            else
+               Check_Expressions;
+               return;
+            end if;
+
+         --  No other attributes for objects are folded
+
+         else
+            Check_Expressions;
+            return;
+         end if;
+
+      --  Cases where P is not an object. Cannot do anything if P is
+      --  not the name of an entity.
+
+      elsif not Is_Entity_Name (P) then
+         Check_Expressions;
+         return;
+
+      --  Otherwise get prefix entity
+
+      else
+         P_Entity := Entity (P);
+      end if;
+
+      --  At this stage P_Entity is the entity to which the attribute
+      --  is to be applied. This is usually simply the entity of the
+      --  prefix, except in some cases of attributes for objects, where
+      --  as described above, we apply the attribute to the object type.
+
+      --  First foldable possibility is a scalar or array type (RM 4.9(7))
+      --  that is not generic (generic types are eliminated by RM 4.9(25)).
+      --  Note we allow non-static non-generic types at this stage as further
+      --  described below.
+
+      if Is_Type (P_Entity)
+        and then (Is_Scalar_Type (P_Entity) or Is_Array_Type (P_Entity))
+        and then (not Is_Generic_Type (P_Entity))
+      then
+         P_Type := P_Entity;
+
+      --  Second foldable possibility is an array object (RM 4.9(8))
+
+      elsif (Ekind (P_Entity) = E_Variable
+               or else
+             Ekind (P_Entity) = E_Constant)
+        and then Is_Array_Type (Etype (P_Entity))
+        and then (not Is_Generic_Type (Etype (P_Entity)))
+      then
+         P_Type := Etype (P_Entity);
+
+         --  If the entity is an array constant with an unconstrained
+         --  nominal subtype then get the type from the initial value.
+         --  If the value has been expanded into assignments, the expression
+         --  is not present and the attribute reference remains dynamic.
+         --  We could do better here and retrieve the type ???
+
+         if Ekind (P_Entity) = E_Constant
+           and then not Is_Constrained (P_Type)
+         then
+            if No (Constant_Value (P_Entity)) then
+               return;
+            else
+               P_Type := Etype (Constant_Value (P_Entity));
+            end if;
+         end if;
+
+      --  Definite must be folded if the prefix is not a generic type,
+      --  that is to say if we are within an instantiation. Same processing
+      --  applies to the GNAT attributes Has_Discriminants and Type_Class
+
+      elsif (Id = Attribute_Definite
+               or else
+             Id = Attribute_Has_Discriminants
+               or else
+             Id = Attribute_Type_Class)
+        and then not Is_Generic_Type (P_Entity)
+      then
+         P_Type := P_Entity;
+
+      --  We can fold 'Size applied to a type if the size is known
+      --  (as happens for a size from an attribute definition clause).
+      --  At this stage, this can happen only for types (e.g. record
+      --  types) for which the size is always non-static. We exclude
+      --  generic types from consideration (since they have bogus
+      --  sizes set within templates).
+
+      elsif Id = Attribute_Size
+        and then Is_Type (P_Entity)
+        and then (not Is_Generic_Type (P_Entity))
+        and then Known_Static_RM_Size (P_Entity)
+      then
+         Fold_Uint (N, RM_Size (P_Entity));
+         Set_Is_Static_Expression (N, False);
+         return;
+
+      --  No other cases are foldable (they certainly aren't static, and at
+      --  the moment we don't try to fold any cases other than the two above)
+
+      else
+         Check_Expressions;
+         return;
+      end if;
+
+      --  If either attribute or the prefix is Any_Type, then propagate
+      --  Any_Type to the result and don't do anything else at all.
+
+      if P_Type = Any_Type
+        or else (Present (E1) and then Etype (E1) = Any_Type)
+        or else (Present (E2) and then Etype (E2) = Any_Type)
+      then
+         Set_Etype (N, Any_Type);
+         return;
+      end if;
+
+      --  Scalar subtype case. We have not yet enforced the static requirement
+      --  of (RM 4.9(7)) and we don't intend to just yet, since there are cases
+      --  of non-static attribute references (e.g. S'Digits for a non-static
+      --  floating-point type, which we can compute at compile time).
+
+      --  Note: this folding of non-static attributes is not simply a case of
+      --  optimization. For many of the attributes affected, Gigi cannot handle
+      --  the attribute and depends on the front end having folded them away.
+
+      --  Note: although we don't require staticness at this stage, we do set
+      --  the Static variable to record the staticness, for easy reference by
+      --  those attributes where it matters (e.g. Succ and Pred), and also to
+      --  be used to ensure that non-static folded things are not marked as
+      --  being static (a check that is done right at the end).
+
+      P_Root_Type := Root_Type (P_Type);
+      P_Base_Type := Base_Type (P_Type);
+
+      --  If the root type or base type is generic, then we cannot fold. This
+      --  test is needed because subtypes of generic types are not always
+      --  marked as being generic themselves (which seems odd???)
+
+      if Is_Generic_Type (P_Root_Type)
+        or else Is_Generic_Type (P_Base_Type)
+      then
+         return;
+      end if;
+
+      if Is_Scalar_Type (P_Type) then
+         Static := Is_OK_Static_Subtype (P_Type);
+
+      --  Array case. We enforce the constrained requirement of (RM 4.9(7-8))
+      --  since we can't do anything with unconstrained arrays. In addition,
+      --  only the First, Last and Length attributes are possibly static.
+      --  In addition Component_Size is possibly foldable, even though it
+      --  can never be static.
+
+      --  Definite, Has_Discriminants and Type_Class are again exceptions,
+      --  because they apply as well to unconstrained types.
+
+      elsif Id = Attribute_Definite
+              or else
+            Id = Attribute_Has_Discriminants
+              or else
+            Id = Attribute_Type_Class
+      then
+         Static := False;
+
+      else
+         if not Is_Constrained (P_Type)
+           or else (Id /= Attribute_Component_Size and then
+                    Id /= Attribute_First          and then
+                    Id /= Attribute_Last           and then
+                    Id /= Attribute_Length)
+         then
+            Check_Expressions;
+            return;
+         end if;
+
+         --  The rules in (RM 4.9(7,8)) require a static array, but as in the
+         --  scalar case, we hold off on enforcing staticness, since there are
+         --  cases which we can fold at compile time even though they are not
+         --  static (e.g. 'Length applied to a static index, even though other
+         --  non-static indexes make the array type non-static). This is only
+         --  ab optimization, but it falls out essentially free, so why not.
+         --  Again we compute the variable Static for easy reference later
+         --  (note that no array attributes are static in Ada 83).
+
+         Static := Ada_95;
+
+         declare
+            N : Node_Id;
+
+         begin
+            N := First_Index (P_Type);
+            while Present (N) loop
+               Static := Static and Is_Static_Subtype (Etype (N));
+               Next_Index (N);
+            end loop;
+         end;
+      end if;
+
+      --  Check any expressions that are present. Note that these expressions,
+      --  depending on the particular attribute type, are either part of the
+      --  attribute designator, or they are arguments in a case where the
+      --  attribute reference returns a function. In the latter case, the
+      --  rule in (RM 4.9(22)) applies and in particular requires the type
+      --  of the expressions to be scalar in order for the attribute to be
+      --  considered to be static.
+
+      declare
+         E : Node_Id;
+
+      begin
+         E := E1;
+         while Present (E) loop
+
+            --  If expression is not static, then the attribute reference
+            --  certainly is neither foldable nor static, so we can quit
+            --  after calling Apply_Range_Check for 'Pos attributes.
+
+            --  We can also quit if the expression is not of a scalar type
+            --  as noted above.
+
+            if not Is_Static_Expression (E)
+              or else not Is_Scalar_Type (Etype (E))
+            then
+               if Id = Attribute_Pos then
+                  if Is_Integer_Type (Etype (E)) then
+                     Apply_Range_Check (E, Etype (N));
+                  end if;
+               end if;
+
+               Check_Expressions;
+               return;
+
+            --  If the expression raises a constraint error, then so does
+            --  the attribute reference. We keep going in this case because
+            --  we are still interested in whether the attribute reference
+            --  is static even if it is not static.
+
+            elsif Raises_Constraint_Error (E) then
+               Set_Raises_Constraint_Error (N);
+            end if;
+
+            Next (E);
+         end loop;
+
+         if Raises_Constraint_Error (Prefix (N)) then
+            return;
+         end if;
+      end;
+
+      --  Deal with the case of a static attribute reference that raises
+      --  constraint error. The Raises_Constraint_Error flag will already
+      --  have been set, and the Static flag shows whether the attribute
+      --  reference is static. In any case we certainly can't fold such an
+      --  attribute reference.
+
+      --  Note that the rewriting of the attribute node with the constraint
+      --  error node is essential in this case, because otherwise Gigi might
+      --  blow up on one of the attributes it never expects to see.
+
+      --  The constraint_error node must have the type imposed by the context,
+      --  to avoid spurious errors in the enclosing expression.
+
+      if Raises_Constraint_Error (N) then
+         CE_Node :=
+           Make_Raise_Constraint_Error (Sloc (N));
+         Set_Etype (CE_Node, Etype (N));
+         Set_Raises_Constraint_Error (CE_Node);
+         Check_Expressions;
+         Rewrite (N, Relocate_Node (CE_Node));
+         Set_Is_Static_Expression (N, Static);
+         return;
+      end if;
+
+      --  At this point we have a potentially foldable attribute reference.
+      --  If Static is set, then the attribute reference definitely obeys
+      --  the requirements in (RM 4.9(7,8,22)), and it definitely can be
+      --  folded. If Static is not set, then the attribute may or may not
+      --  be foldable, and the individual attribute processing routines
+      --  test Static as required in cases where it makes a difference.
+
+      case Id is
+
+      --------------
+      -- Adjacent --
+      --------------
+
+      when Attribute_Adjacent =>
+         if Static then
+            Fold_Ureal (N,
+              Eval_Fat.Adjacent
+                (P_Root_Type, Expr_Value_R (E1), Expr_Value_R (E2)));
+         end if;
+
+      ---------
+      -- Aft --
+      ---------
+
+      when Attribute_Aft =>
+         Fold_Uint (N, UI_From_Int (Aft_Value));
+
+      ---------------
+      -- Alignment --
+      ---------------
+
+      when Attribute_Alignment => Alignment_Block : declare
+         P_TypeA : constant Entity_Id := Underlying_Type (P_Type);
+
+      begin
+         --  Fold if alignment is set and not otherwise
+
+         if Known_Alignment (P_TypeA) then
+            Fold_Uint (N, Alignment (P_TypeA));
+         end if;
+      end Alignment_Block;
+
+      ---------------
+      -- AST_Entry --
+      ---------------
+
+      --  Can only be folded in No_Ast_Handler case
+
+      when Attribute_AST_Entry =>
+         if not Is_AST_Entry (P_Entity) then
+            Rewrite (N,
+              New_Occurrence_Of (RTE (RE_No_AST_Handler), Loc));
+         else
+            null;
+         end if;
+
+      ---------
+      -- Bit --
+      ---------
+
+      --  Bit can never be folded
+
+      when Attribute_Bit =>
+         null;
+
+      ------------------
+      -- Body_Version --
+      ------------------
+
+      --  Body_version can never be static
+
+      when Attribute_Body_Version =>
+         null;
+
+      -------------
+      -- Ceiling --
+      -------------
+
+      when Attribute_Ceiling =>
+         if Static then
+            Fold_Ureal (N,
+              Eval_Fat.Ceiling (P_Root_Type, Expr_Value_R (E1)));
+         end if;
+
+      --------------------
+      -- Component_Size --
+      --------------------
+
+      when Attribute_Component_Size =>
+         if Component_Size (P_Type) /= 0 then
+            Fold_Uint (N, Component_Size (P_Type));
+         end if;
+
+      -------------
+      -- Compose --
+      -------------
+
+      when Attribute_Compose =>
+         if Static then
+            Fold_Ureal (N,
+              Eval_Fat.Compose
+                (P_Root_Type, Expr_Value_R (E1), Expr_Value (E2)));
+         end if;
+
+      -----------------
+      -- Constrained --
+      -----------------
+
+      --  Constrained is never folded for now, there may be cases that
+      --  could be handled at compile time. to be looked at later.
+
+      when Attribute_Constrained =>
+         null;
+
+      ---------------
+      -- Copy_Sign --
+      ---------------
+
+      when Attribute_Copy_Sign =>
+         if Static then
+            Fold_Ureal (N,
+              Eval_Fat.Copy_Sign
+                (P_Root_Type, Expr_Value_R (E1), Expr_Value_R (E2)));
+         end if;
+
+      -----------
+      -- Delta --
+      -----------
+
+      when Attribute_Delta =>
+         Fold_Ureal (N, Delta_Value (P_Type));
+
+      --------------
+      -- Definite --
+      --------------
+
+      when Attribute_Definite =>
+         declare
+            Result : Node_Id;
+
+         begin
+            if Is_Indefinite_Subtype (P_Entity) then
+               Result := New_Occurrence_Of (Standard_False, Loc);
+            else
+               Result := New_Occurrence_Of (Standard_True, Loc);
+            end if;
+
+            Rewrite (N, Result);
+            Analyze_And_Resolve (N, Standard_Boolean);
+         end;
+
+      ------------
+      -- Denorm --
+      ------------
+
+      when Attribute_Denorm =>
+         Fold_Uint
+           (N, UI_From_Int (Boolean'Pos (Denorm_On_Target)));
+
+      ------------
+      -- Digits --
+      ------------
+
+      when Attribute_Digits =>
+         Fold_Uint (N, Digits_Value (P_Type));
+
+      ----------
+      -- Emax --
+      ----------
+
+      when Attribute_Emax =>
+
+         --  Ada 83 attribute is defined as (RM83 3.5.8)
+
+         --    T'Emax = 4 * T'Mantissa
+
+         Fold_Uint (N, 4 * Mantissa);
+
+      --------------
+      -- Enum_Rep --
+      --------------
+
+      when Attribute_Enum_Rep =>
+         if Static then
+
+            --  For an enumeration type with a non-standard representation
+            --  use the Enumeration_Rep field of the proper constant. Note
+            --  that this would not work for types Character/Wide_Character,
+            --  since no real entities are created for the enumeration
+            --  literals, but that does not matter since these two types
+            --  do not have non-standard representations anyway.
+
+            if Is_Enumeration_Type (P_Type)
+              and then Has_Non_Standard_Rep (P_Type)
+            then
+               Fold_Uint (N, Enumeration_Rep (Expr_Value_E (E1)));
+
+            --  For enumeration types with standard representations and all
+            --  other cases (i.e. all integer and modular types), Enum_Rep
+            --  is equivalent to Pos.
+
+            else
+               Fold_Uint (N, Expr_Value (E1));
+            end if;
+         end if;
+
+      -------------
+      -- Epsilon --
+      -------------
+
+      when Attribute_Epsilon =>
+
+         --  Ada 83 attribute is defined as (RM83 3.5.8)
+
+         --    T'Epsilon = 2.0**(1 - T'Mantissa)
+
+         Fold_Ureal (N, Ureal_2 ** (1 - Mantissa));
+
+      --------------
+      -- Exponent --
+      --------------
+
+      when Attribute_Exponent =>
+         if Static then
+            Fold_Uint (N,
+              Eval_Fat.Exponent (P_Root_Type, Expr_Value_R (E1)));
+         end if;
+
+      -----------
+      -- First --
+      -----------
+
+      when Attribute_First => First_Attr :
+      begin
+         Set_Bounds;
+
+         if Compile_Time_Known_Value (Lo_Bound) then
+            if Is_Real_Type (P_Type) then
+               Fold_Ureal (N, Expr_Value_R (Lo_Bound));
+            else
+               Fold_Uint  (N, Expr_Value (Lo_Bound));
+            end if;
+         end if;
+      end First_Attr;
+
+      -----------------
+      -- Fixed_Value --
+      -----------------
+
+      when Attribute_Fixed_Value =>
+         null;
+
+      -----------
+      -- Floor --
+      -----------
+
+      when Attribute_Floor =>
+         if Static then
+            Fold_Ureal (N,
+              Eval_Fat.Floor (P_Root_Type, Expr_Value_R (E1)));
+         end if;
+
+      ----------
+      -- Fore --
+      ----------
+
+      when Attribute_Fore =>
+         if Static then
+            Fold_Uint (N, UI_From_Int (Fore_Value));
+         end if;
+
+      --------------
+      -- Fraction --
+      --------------
+
+      when Attribute_Fraction =>
+         if Static then
+            Fold_Ureal (N,
+              Eval_Fat.Fraction (P_Root_Type, Expr_Value_R (E1)));
+         end if;
+
+      -----------------------
+      -- Has_Discriminants --
+      -----------------------
+
+      when Attribute_Has_Discriminants =>
+         declare
+            Result : Node_Id;
+
+         begin
+            if Has_Discriminants (P_Entity) then
+               Result := New_Occurrence_Of (Standard_True, Loc);
+            else
+               Result := New_Occurrence_Of (Standard_False, Loc);
+            end if;
+
+            Rewrite (N, Result);
+            Analyze_And_Resolve (N, Standard_Boolean);
+         end;
+
+      --------------
+      -- Identity --
+      --------------
+
+      when Attribute_Identity =>
+         null;
+
+      -----------
+      -- Image --
+      -----------
+
+      --  Image is a scalar attribute, but is never static, because it is
+      --  not a static function (having a non-scalar argument (RM 4.9(22))
+
+      when Attribute_Image =>
+         null;
+
+      ---------
+      -- Img --
+      ---------
+
+      --  Img is a scalar attribute, but is never static, because it is
+      --  not a static function (having a non-scalar argument (RM 4.9(22))
+
+      when Attribute_Img =>
+         null;
+
+      -------------------
+      -- Integer_Value --
+      -------------------
+
+      when Attribute_Integer_Value =>
+         null;
+
+      -----------
+      -- Large --
+      -----------
+
+      when Attribute_Large =>
+
+         --  For fixed-point, we use the identity:
+
+         --    T'Large = (2.0**T'Mantissa - 1.0) * T'Small
+
+         if Is_Fixed_Point_Type (P_Type) then
+            Rewrite (N,
+              Make_Op_Multiply (Loc,
+                Left_Opnd =>
+                  Make_Op_Subtract (Loc,
+                    Left_Opnd =>
+                      Make_Op_Expon (Loc,
+                        Left_Opnd =>
+                          Make_Real_Literal (Loc, Ureal_2),
+                        Right_Opnd =>
+                          Make_Attribute_Reference (Loc,
+                            Prefix => P,
+                            Attribute_Name => Name_Mantissa)),
+                    Right_Opnd => Make_Real_Literal (Loc, Ureal_1)),
+
+                Right_Opnd =>
+                  Make_Real_Literal (Loc, Small_Value (Entity (P)))));
+
+            Analyze_And_Resolve (N, C_Type);
+
+         --  Floating-point (Ada 83 compatibility)
+
+         else
+            --  Ada 83 attribute is defined as (RM83 3.5.8)
+
+            --    T'Large = 2.0**T'Emax * (1.0 - 2.0**(-T'Mantissa))
+
+            --  where
+
+            --    T'Emax = 4 * T'Mantissa
+
+            Fold_Ureal (N,
+              Ureal_2 ** (4 * Mantissa) *
+              (Ureal_1 - Ureal_2 ** (-Mantissa)));
+         end if;
+
+      ----------
+      -- Last --
+      ----------
+
+      when Attribute_Last => Last :
+      begin
+         Set_Bounds;
+
+         if Compile_Time_Known_Value (Hi_Bound) then
+            if Is_Real_Type (P_Type) then
+               Fold_Ureal (N, Expr_Value_R (Hi_Bound));
+            else
+               Fold_Uint  (N, Expr_Value (Hi_Bound));
+            end if;
+         end if;
+      end Last;
+
+      ------------------
+      -- Leading_Part --
+      ------------------
+
+      when Attribute_Leading_Part =>
+         if Static then
+            Fold_Ureal (N,
+              Eval_Fat.Leading_Part
+                (P_Root_Type, Expr_Value_R (E1), Expr_Value (E2)));
+         end if;
+
+      ------------
+      -- Length --
+      ------------
+
+      when Attribute_Length => Length :
+      begin
+         Set_Bounds;
+
+         if Compile_Time_Known_Value (Lo_Bound)
+           and then Compile_Time_Known_Value (Hi_Bound)
+         then
+            Fold_Uint (N,
+              UI_Max (0, 1 + (Expr_Value (Hi_Bound) - Expr_Value (Lo_Bound))));
+         end if;
+      end Length;
+
+      -------------
+      -- Machine --
+      -------------
+
+      when Attribute_Machine =>
+         if Static then
+            Fold_Ureal (N,
+              Eval_Fat.Machine (P_Root_Type, Expr_Value_R (E1),
+                Eval_Fat.Round));
+         end if;
+
+      ------------------
+      -- Machine_Emax --
+      ------------------
+
+      when Attribute_Machine_Emax =>
+         Float_Attribute_Universal_Integer (
+           IEEES_Machine_Emax,
+           IEEEL_Machine_Emax,
+           IEEEX_Machine_Emax,
+           VAXFF_Machine_Emax,
+           VAXDF_Machine_Emax,
+           VAXGF_Machine_Emax);
+
+      ------------------
+      -- Machine_Emin --
+      ------------------
+
+      when Attribute_Machine_Emin =>
+         Float_Attribute_Universal_Integer (
+           IEEES_Machine_Emin,
+           IEEEL_Machine_Emin,
+           IEEEX_Machine_Emin,
+           VAXFF_Machine_Emin,
+           VAXDF_Machine_Emin,
+           VAXGF_Machine_Emin);
+
+      ----------------------
+      -- Machine_Mantissa --
+      ----------------------
+
+      when Attribute_Machine_Mantissa =>
+         Float_Attribute_Universal_Integer (
+           IEEES_Machine_Mantissa,
+           IEEEL_Machine_Mantissa,
+           IEEEX_Machine_Mantissa,
+           VAXFF_Machine_Mantissa,
+           VAXDF_Machine_Mantissa,
+           VAXGF_Machine_Mantissa);
+
+      -----------------------
+      -- Machine_Overflows --
+      -----------------------
+
+      when Attribute_Machine_Overflows =>
+
+         --  Always true for fixed-point
+
+         if Is_Fixed_Point_Type (P_Type) then
+            Fold_Uint (N, True_Value);
+
+         --  Floating point case
+
+         else
+            Fold_Uint
+              (N, UI_From_Int (Boolean'Pos (Machine_Overflows_On_Target)));
+         end if;
+
+      -------------------
+      -- Machine_Radix --
+      -------------------
+
+      when Attribute_Machine_Radix =>
+         if Is_Fixed_Point_Type (P_Type) then
+            if Is_Decimal_Fixed_Point_Type (P_Type)
+              and then Machine_Radix_10 (P_Type)
+            then
+               Fold_Uint (N, Uint_10);
+            else
+               Fold_Uint (N, Uint_2);
+            end if;
+
+         --  All floating-point type always have radix 2
+
+         else
+            Fold_Uint (N, Uint_2);
+         end if;
+
+      --------------------
+      -- Machine_Rounds --
+      --------------------
+
+      when Attribute_Machine_Rounds =>
+
+         --  Always False for fixed-point
+
+         if Is_Fixed_Point_Type (P_Type) then
+            Fold_Uint (N, False_Value);
+
+         --  Else yield proper floating-point result
+
+         else
+            Fold_Uint
+              (N, UI_From_Int (Boolean'Pos (Machine_Rounds_On_Target)));
+         end if;
+
+      ------------------
+      -- Machine_Size --
+      ------------------
+
+      --  Note: Machine_Size is identical to Object_Size
+
+      when Attribute_Machine_Size => Machine_Size : declare
+         P_TypeA : constant Entity_Id := Underlying_Type (P_Type);
+
+      begin
+         if Known_Esize (P_TypeA) then
+            Fold_Uint (N, Esize (P_TypeA));
+         end if;
+      end Machine_Size;
+
+      --------------
+      -- Mantissa --
+      --------------
+
+      when Attribute_Mantissa =>
+
+         --  Fixed-point mantissa
+
+         if Is_Fixed_Point_Type (P_Type) then
+
+            --  Compile time foldable case
+
+            if Compile_Time_Known_Value (Type_Low_Bound  (P_Type))
+                 and then
+               Compile_Time_Known_Value (Type_High_Bound (P_Type))
+            then
+               --  The calculation of the obsolete Ada 83 attribute Mantissa
+               --  is annoying, because of AI00143, quoted here:
+
+               --  !question 84-01-10
+
+               --  Consider the model numbers for F:
+
+               --         type F is delta 1.0 range -7.0 .. 8.0;
+
+               --  The wording requires that F'MANTISSA be the SMALLEST
+               --  integer number for which each  bound  of the specified
+               --  range is either a model number or lies at most small
+               --  distant from a model number. This means F'MANTISSA
+               --  is required to be 3 since the range  -7.0 .. 7.0 fits
+               --  in 3 signed bits, and 8 is "at most" 1.0 from a model
+               --  number, namely, 7. Is this analysis correct? Note that
+               --  this implies the upper bound of the range is not
+               --  represented as a model number.
+
+               --  !response 84-03-17
+
+               --  The analysis is correct. The upper and lower bounds for
+               --  a fixed  point type can lie outside the range of model
+               --  numbers.
+
+               declare
+                  Siz     : Uint;
+                  LBound  : Ureal;
+                  UBound  : Ureal;
+                  Bound   : Ureal;
+                  Max_Man : Uint;
+
+               begin
+                  LBound  := Expr_Value_R (Type_Low_Bound  (P_Type));
+                  UBound  := Expr_Value_R (Type_High_Bound (P_Type));
+                  Bound   := UR_Max (UR_Abs (LBound), UR_Abs (UBound));
+                  Max_Man := UR_Trunc (Bound / Small_Value (P_Type));
+
+                  --  If the Bound is exactly a model number, i.e. a multiple
+                  --  of Small, then we back it off by one to get the integer
+                  --  value that must be representable.
+
+                  if Small_Value (P_Type) * Max_Man = Bound then
+                     Max_Man := Max_Man - 1;
+                  end if;
+
+                  --  Now find corresponding size = Mantissa value
+
+                  Siz := Uint_0;
+                  while 2 ** Siz < Max_Man loop
+                     Siz := Siz + 1;
+                  end loop;
+
+                  Fold_Uint (N, Siz);
+               end;
+
+            else
+               --  The case of dynamic bounds cannot be evaluated at compile
+               --  time. Instead we use a runtime routine (see Exp_Attr).
+
+               null;
+            end if;
+
+         --  Floating-point Mantissa
+
+         else
+            Fold_Uint (N, Mantissa);
+         end if;
+
+      ---------
+      -- Max --
+      ---------
+
+      when Attribute_Max => Max :
+      begin
+         if Is_Real_Type (P_Type) then
+            Fold_Ureal (N, UR_Max (Expr_Value_R (E1), Expr_Value_R (E2)));
+         else
+            Fold_Uint (N, UI_Max (Expr_Value (E1), Expr_Value (E2)));
+         end if;
+      end Max;
+
+      ----------------------------------
+      -- Max_Size_In_Storage_Elements --
+      ----------------------------------
+
+      --  Max_Size_In_Storage_Elements is simply the Size rounded up to a
+      --  Storage_Unit boundary. We can fold any cases for which the size
+      --  is known by the front end.
+
+      when Attribute_Max_Size_In_Storage_Elements =>
+         if Known_Esize (P_Type) then
+            Fold_Uint (N,
+              (Esize (P_Type) + System_Storage_Unit - 1) /
+                                          System_Storage_Unit);
+         end if;
+
+      --------------------
+      -- Mechanism_Code --
+      --------------------
+
+      when Attribute_Mechanism_Code =>
+         declare
+            Val    : Int;
+            Formal : Entity_Id;
+            Mech   : Mechanism_Type;
+
+         begin
+            if No (E1) then
+               Mech := Mechanism (P_Entity);
+
+            else
+               Val := UI_To_Int (Expr_Value (E1));
+
+               Formal := First_Formal (P_Entity);
+               for J in 1 .. Val - 1 loop
+                  Next_Formal (Formal);
+               end loop;
+               Mech := Mechanism (Formal);
+            end if;
+
+            if Mech < 0 then
+               Fold_Uint (N, UI_From_Int (Int (-Mech)));
+            end if;
+         end;
+
+      ---------
+      -- Min --
+      ---------
+
+      when Attribute_Min => Min :
+      begin
+         if Is_Real_Type (P_Type) then
+            Fold_Ureal (N, UR_Min (Expr_Value_R (E1), Expr_Value_R (E2)));
+         else
+            Fold_Uint (N, UI_Min (Expr_Value (E1), Expr_Value (E2)));
+         end if;
+      end Min;
+
+      -----------
+      -- Model --
+      -----------
+
+      when Attribute_Model =>
+         if Static then
+            Fold_Ureal (N,
+              Eval_Fat.Model (P_Root_Type, Expr_Value_R (E1)));
+         end if;
+
+      ----------------
+      -- Model_Emin --
+      ----------------
+
+      when Attribute_Model_Emin =>
+         Float_Attribute_Universal_Integer (
+           IEEES_Model_Emin,
+           IEEEL_Model_Emin,
+           IEEEX_Model_Emin,
+           VAXFF_Model_Emin,
+           VAXDF_Model_Emin,
+           VAXGF_Model_Emin);
+
+      -------------------
+      -- Model_Epsilon --
+      -------------------
+
+      when Attribute_Model_Epsilon =>
+         Float_Attribute_Universal_Real (
+           IEEES_Model_Epsilon'Universal_Literal_String,
+           IEEEL_Model_Epsilon'Universal_Literal_String,
+           IEEEX_Model_Epsilon'Universal_Literal_String,
+           VAXFF_Model_Epsilon'Universal_Literal_String,
+           VAXDF_Model_Epsilon'Universal_Literal_String,
+           VAXGF_Model_Epsilon'Universal_Literal_String);
+
+      --------------------
+      -- Model_Mantissa --
+      --------------------
+
+      when Attribute_Model_Mantissa =>
+         Float_Attribute_Universal_Integer (
+           IEEES_Model_Mantissa,
+           IEEEL_Model_Mantissa,
+           IEEEX_Model_Mantissa,
+           VAXFF_Model_Mantissa,
+           VAXDF_Model_Mantissa,
+           VAXGF_Model_Mantissa);
+
+      -----------------
+      -- Model_Small --
+      -----------------
+
+      when Attribute_Model_Small =>
+         Float_Attribute_Universal_Real (
+           IEEES_Model_Small'Universal_Literal_String,
+           IEEEL_Model_Small'Universal_Literal_String,
+           IEEEX_Model_Small'Universal_Literal_String,
+           VAXFF_Model_Small'Universal_Literal_String,
+           VAXDF_Model_Small'Universal_Literal_String,
+           VAXGF_Model_Small'Universal_Literal_String);
+
+      -------------
+      -- Modulus --
+      -------------
+
+      when Attribute_Modulus =>
+         Fold_Uint (N, Modulus (P_Type));
+
+      --------------------
+      -- Null_Parameter --
+      --------------------
+
+      --  Cannot fold, we know the value sort of, but the whole point is
+      --  that there is no way to talk about this imaginary value except
+      --  by using the attribute, so we leave it the way it is.
+
+      when Attribute_Null_Parameter =>
+         null;
+
+      -----------------
+      -- Object_Size --
+      -----------------
+
+      --  The Object_Size attribute for a type returns the Esize of the
+      --  type and can be folded if this value is known.
+
+      when Attribute_Object_Size => Object_Size : declare
+         P_TypeA : constant Entity_Id := Underlying_Type (P_Type);
+
+      begin
+         if Known_Esize (P_TypeA) then
+            Fold_Uint (N, Esize (P_TypeA));
+         end if;
+      end Object_Size;
+
+      -------------------------
+      -- Passed_By_Reference --
+      -------------------------
+
+      --  Scalar types are never passed by reference
+
+      when Attribute_Passed_By_Reference =>
+         Fold_Uint (N, False_Value);
+
+      ---------
+      -- Pos --
+      ---------
+
+      when Attribute_Pos =>
+         Fold_Uint (N, Expr_Value (E1));
+
+      ----------
+      -- Pred --
+      ----------
+
+      when Attribute_Pred => Pred :
+      begin
+         if Static then
+
+            --  Floating-point case. For now, do not fold this, since we
+            --  don't know how to do it right (see fixed bug 3512-001 ???)
+
+            if Is_Floating_Point_Type (P_Type) then
+               Fold_Ureal (N,
+                 Eval_Fat.Pred (P_Root_Type, Expr_Value_R (E1)));
+
+            --  Fixed-point case
+
+            elsif Is_Fixed_Point_Type (P_Type) then
+               Fold_Ureal (N,
+                 Expr_Value_R (E1) - Small_Value (P_Type));
+
+            --  Modular integer case (wraps)
+
+            elsif Is_Modular_Integer_Type (P_Type) then
+               Fold_Uint (N, (Expr_Value (E1) - 1) mod Modulus (P_Type));
+
+            --  Other scalar cases
+
+            else
+               pragma Assert (Is_Scalar_Type (P_Type));
+
+               if Is_Enumeration_Type (P_Type)
+                 and then Expr_Value (E1) =
+                            Expr_Value (Type_Low_Bound (P_Base_Type))
+               then
+                  Apply_Compile_Time_Constraint_Error
+                    (N, "Pred of type''First");
+                  Check_Expressions;
+                  return;
+               end if;
+
+               Fold_Uint (N, Expr_Value (E1) - 1);
+            end if;
+         end if;
+      end Pred;
+
+      -----------
+      -- Range --
+      -----------
+
+      --  No processing required, because by this stage, Range has been
+      --  replaced by First .. Last, so this branch can never be taken.
+
+      when Attribute_Range =>
+         raise Program_Error;
+
+      ------------------
+      -- Range_Length --
+      ------------------
+
+      when Attribute_Range_Length =>
+         Set_Bounds;
+
+         if Compile_Time_Known_Value (Hi_Bound)
+           and then Compile_Time_Known_Value (Lo_Bound)
+         then
+            Fold_Uint (N,
+              UI_Max
+                (0, Expr_Value (Hi_Bound) - Expr_Value (Lo_Bound) + 1));
+         end if;
+
+      ---------------
+      -- Remainder --
+      ---------------
+
+      when Attribute_Remainder =>
+         if Static then
+            Fold_Ureal (N,
+              Eval_Fat.Remainder
+                (P_Root_Type, Expr_Value_R (E1), Expr_Value_R (E2)));
+         end if;
+
+      -----------
+      -- Round --
+      -----------
+
+      when Attribute_Round => Round :
+      declare
+         Sr : Ureal;
+         Si : Uint;
+
+      begin
+         if Static then
+            --  First we get the (exact result) in units of small
+
+            Sr := Expr_Value_R (E1) / Small_Value (C_Type);
+
+            --  Now round that exactly to an integer
+
+            Si := UR_To_Uint (Sr);
+
+            --  Finally the result is obtained by converting back to real
+
+            Fold_Ureal (N, Si * Small_Value (C_Type));
+         end if;
+      end Round;
+
+      --------------
+      -- Rounding --
+      --------------
+
+      when Attribute_Rounding =>
+         if Static then
+            Fold_Ureal (N,
+              Eval_Fat.Rounding (P_Root_Type, Expr_Value_R (E1)));
+         end if;
+
+      ---------------
+      -- Safe_Emax --
+      ---------------
+
+      when Attribute_Safe_Emax =>
+         Float_Attribute_Universal_Integer (
+           IEEES_Safe_Emax,
+           IEEEL_Safe_Emax,
+           IEEEX_Safe_Emax,
+           VAXFF_Safe_Emax,
+           VAXDF_Safe_Emax,
+           VAXGF_Safe_Emax);
+
+      ----------------
+      -- Safe_First --
+      ----------------
+
+      when Attribute_Safe_First =>
+         Float_Attribute_Universal_Real (
+           IEEES_Safe_First'Universal_Literal_String,
+           IEEEL_Safe_First'Universal_Literal_String,
+           IEEEX_Safe_First'Universal_Literal_String,
+           VAXFF_Safe_First'Universal_Literal_String,
+           VAXDF_Safe_First'Universal_Literal_String,
+           VAXGF_Safe_First'Universal_Literal_String);
+
+      ----------------
+      -- Safe_Large --
+      ----------------
+
+      when Attribute_Safe_Large =>
+         if Is_Fixed_Point_Type (P_Type) then
+            Fold_Ureal (N, Expr_Value_R (Type_High_Bound (P_Base_Type)));
+         else
+            Float_Attribute_Universal_Real (
+              IEEES_Safe_Large'Universal_Literal_String,
+              IEEEL_Safe_Large'Universal_Literal_String,
+              IEEEX_Safe_Large'Universal_Literal_String,
+              VAXFF_Safe_Large'Universal_Literal_String,
+              VAXDF_Safe_Large'Universal_Literal_String,
+              VAXGF_Safe_Large'Universal_Literal_String);
+         end if;
+
+      ---------------
+      -- Safe_Last --
+      ---------------
+
+      when Attribute_Safe_Last =>
+         Float_Attribute_Universal_Real (
+           IEEES_Safe_Last'Universal_Literal_String,
+           IEEEL_Safe_Last'Universal_Literal_String,
+           IEEEX_Safe_Last'Universal_Literal_String,
+           VAXFF_Safe_Last'Universal_Literal_String,
+           VAXDF_Safe_Last'Universal_Literal_String,
+           VAXGF_Safe_Last'Universal_Literal_String);
+
+      ----------------
+      -- Safe_Small --
+      ----------------
+
+      when Attribute_Safe_Small =>
+
+         --  In Ada 95, the old Ada 83 attribute Safe_Small is redundant
+         --  for fixed-point, since is the same as Small, but we implement
+         --  it for backwards compatibility.
+
+         if Is_Fixed_Point_Type (P_Type) then
+            Fold_Ureal (N, Small_Value (P_Type));
+
+         --  Ada 83 Safe_Small for floating-point cases
+
+         else
+            Float_Attribute_Universal_Real (
+              IEEES_Safe_Small'Universal_Literal_String,
+              IEEEL_Safe_Small'Universal_Literal_String,
+              IEEEX_Safe_Small'Universal_Literal_String,
+              VAXFF_Safe_Small'Universal_Literal_String,
+              VAXDF_Safe_Small'Universal_Literal_String,
+              VAXGF_Safe_Small'Universal_Literal_String);
+         end if;
+
+      -----------
+      -- Scale --
+      -----------
+
+      when Attribute_Scale =>
+         Fold_Uint (N, Scale_Value (P_Type));
+
+      -------------
+      -- Scaling --
+      -------------
+
+      when Attribute_Scaling =>
+         if Static then
+            Fold_Ureal (N,
+              Eval_Fat.Scaling
+                (P_Root_Type, Expr_Value_R (E1), Expr_Value (E2)));
+         end if;
+
+      ------------------
+      -- Signed_Zeros --
+      ------------------
+
+      when Attribute_Signed_Zeros =>
+         Fold_Uint
+           (N, UI_From_Int (Boolean'Pos (Signed_Zeros_On_Target)));
+
+      ----------
+      -- Size --
+      ----------
+
+      --  Size attribute returns the RM size. All scalar types can be folded,
+      --  as well as any types for which the size is known by the front end,
+      --  including any type for which a size attribute is specified.
+
+      when Attribute_Size | Attribute_VADS_Size => Size : declare
+         P_TypeA : constant Entity_Id := Underlying_Type (P_Type);
+
+      begin
+         if RM_Size (P_TypeA) /= Uint_0 then
+
+            --  VADS_Size case
+
+            if (Id = Attribute_VADS_Size or else Use_VADS_Size) then
+
+               declare
+                  S : constant Node_Id := Size_Clause (P_TypeA);
+
+               begin
+                  --  If a size clause applies, then use the size from it.
+                  --  This is one of the rare cases where we can use the
+                  --  Size_Clause field for a subtype when Has_Size_Clause
+                  --  is False. Consider:
+
+                  --    type x is range 1 .. 64;
+                  --    for x'size use 12;
+                  --    subtype y is x range 0 .. 3;
+
+                  --  Here y has a size clause inherited from x, but normally
+                  --  it does not apply, and y'size is 2. However, y'VADS_Size
+                  --  is indeed 12 and not 2.
+
+                  if Present (S)
+                    and then Is_OK_Static_Expression (Expression (S))
+                  then
+                     Fold_Uint (N, Expr_Value (Expression (S)));
+
+                  --  If no size is specified, then we simply use the object
+                  --  size in the VADS_Size case (e.g. Natural'Size is equal
+                  --  to Integer'Size, not one less).
+
+                  else
+                     Fold_Uint (N, Esize (P_TypeA));
+                  end if;
+               end;
+
+            --  Normal case (Size) in which case we want the RM_Size
+
+            else
+               Fold_Uint (N, RM_Size (P_TypeA));
+            end if;
+         end if;
+      end Size;
+
+      -----------
+      -- Small --
+      -----------
+
+      when Attribute_Small =>
+
+         --  The floating-point case is present only for Ada 83 compatability.
+         --  Note that strictly this is an illegal addition, since we are
+         --  extending an Ada 95 defined attribute, but we anticipate an
+         --  ARG ruling that will permit this.
+
+         if Is_Floating_Point_Type (P_Type) then
+
+            --  Ada 83 attribute is defined as (RM83 3.5.8)
+
+            --    T'Small = 2.0**(-T'Emax - 1)
+
+            --  where
+
+            --    T'Emax = 4 * T'Mantissa
+
+            Fold_Ureal (N, Ureal_2 ** ((-(4 * Mantissa)) - 1));
+
+         --  Normal Ada 95 fixed-point case
+
+         else
+            Fold_Ureal (N, Small_Value (P_Type));
+         end if;
+
+      ----------
+      -- Succ --
+      ----------
+
+      when Attribute_Succ => Succ :
+      begin
+         if Static then
+
+            --  Floating-point case. For now, do not fold this, since we
+            --  don't know how to do it right (see fixed bug 3512-001 ???)
+
+            if Is_Floating_Point_Type (P_Type) then
+               Fold_Ureal (N,
+                 Eval_Fat.Succ (P_Root_Type, Expr_Value_R (E1)));
+
+            --  Fixed-point case
+
+            elsif Is_Fixed_Point_Type (P_Type) then
+               Fold_Ureal (N,
+                 Expr_Value_R (E1) + Small_Value (P_Type));
+
+            --  Modular integer case (wraps)
+
+            elsif Is_Modular_Integer_Type (P_Type) then
+               Fold_Uint (N, (Expr_Value (E1) + 1) mod Modulus (P_Type));
+
+            --  Other scalar cases
+
+            else
+               pragma Assert (Is_Scalar_Type (P_Type));
+
+               if Is_Enumeration_Type (P_Type)
+                 and then Expr_Value (E1) =
+                            Expr_Value (Type_High_Bound (P_Base_Type))
+               then
+                  Apply_Compile_Time_Constraint_Error
+                    (N, "Succ of type''Last");
+                  Check_Expressions;
+                  return;
+               else
+                  Fold_Uint (N, Expr_Value (E1) + 1);
+               end if;
+            end if;
+         end if;
+      end Succ;
+
+      ----------------
+      -- Truncation --
+      ----------------
+
+      when Attribute_Truncation =>
+         if Static then
+            Fold_Ureal (N,
+              Eval_Fat.Truncation (P_Root_Type, Expr_Value_R (E1)));
+         end if;
+
+      ----------------
+      -- Type_Class --
+      ----------------
+
+      when Attribute_Type_Class => Type_Class : declare
+         Typ : constant Entity_Id := Underlying_Type (P_Base_Type);
+         Id  : RE_Id;
+
+      begin
+         if Is_RTE (P_Root_Type, RE_Address) then
+            Id := RE_Type_Class_Address;
+
+         elsif Is_Enumeration_Type (Typ) then
+            Id := RE_Type_Class_Enumeration;
+
+         elsif Is_Integer_Type (Typ) then
+            Id := RE_Type_Class_Integer;
+
+         elsif Is_Fixed_Point_Type (Typ) then
+            Id := RE_Type_Class_Fixed_Point;
+
+         elsif Is_Floating_Point_Type (Typ) then
+            Id := RE_Type_Class_Floating_Point;
+
+         elsif Is_Array_Type (Typ) then
+            Id := RE_Type_Class_Array;
+
+         elsif Is_Record_Type (Typ) then
+            Id := RE_Type_Class_Record;
+
+         elsif Is_Access_Type (Typ) then
+            Id := RE_Type_Class_Access;
+
+         elsif Is_Enumeration_Type (Typ) then
+            Id := RE_Type_Class_Enumeration;
+
+         elsif Is_Task_Type (Typ) then
+            Id := RE_Type_Class_Task;
+
+         --  We treat protected types like task types. It would make more
+         --  sense to have another enumeration value, but after all the
+         --  whole point of this feature is to be exactly DEC compatible,
+         --  and changing the type Type_Clas would not meet this requirement.
+
+         elsif Is_Protected_Type (Typ) then
+            Id := RE_Type_Class_Task;
+
+         --  Not clear if there are any other possibilities, but if there
+         --  are, then we will treat them as the address case.
+
+         else
+            Id := RE_Type_Class_Address;
+         end if;
+
+         Rewrite (N, New_Occurrence_Of (RTE (Id), Loc));
+
+      end Type_Class;
+
+      -----------------------
+      -- Unbiased_Rounding --
+      -----------------------
+
+      when Attribute_Unbiased_Rounding =>
+         if Static then
+            Fold_Ureal (N,
+              Eval_Fat.Unbiased_Rounding (P_Root_Type, Expr_Value_R (E1)));
+         end if;
+
+      ---------------
+      -- VADS_Size --
+      ---------------
+
+      --  Processing is shared with Size
+
+      ---------
+      -- Val --
+      ---------
+
+      when Attribute_Val => Val :
+      begin
+         if Static then
+            if  Expr_Value (E1) < Expr_Value (Type_Low_Bound (P_Base_Type))
+              or else
+                Expr_Value (E1) > Expr_Value (Type_High_Bound (P_Base_Type))
+            then
+               Apply_Compile_Time_Constraint_Error
+                 (N, "Val expression out of range");
+               Check_Expressions;
+               return;
+            else
+               Fold_Uint (N, Expr_Value (E1));
+            end if;
+         end if;
+      end Val;
+
+      ----------------
+      -- Value_Size --
+      ----------------
+
+      --  The Value_Size attribute for a type returns the RM size of the
+      --  type. This an always be folded for scalar types, and can also
+      --  be folded for non-scalar types if the size is set.
+
+      when Attribute_Value_Size => Value_Size : declare
+         P_TypeA : constant Entity_Id := Underlying_Type (P_Type);
+
+      begin
+         if RM_Size (P_TypeA) /= Uint_0 then
+            Fold_Uint (N, RM_Size (P_TypeA));
+         end if;
+
+      end Value_Size;
+
+      -------------
+      -- Version --
+      -------------
+
+      --  Version can never be static
+
+      when Attribute_Version =>
+         null;
+
+      ----------------
+      -- Wide_Image --
+      ----------------
+
+      --  Wide_Image is a scalar attribute, but is never static, because it
+      --  is not a static function (having a non-scalar argument (RM 4.9(22))
+
+      when Attribute_Wide_Image =>
+         null;
+
+      ----------------
+      -- Wide_Width --
+      ----------------
+
+      --  Processing for Wide_Width is combined with Width
+
+      -----------
+      -- Width --
+      -----------
+
+      --  This processing also handles the case of Wide_Width
+
+      when Attribute_Width | Attribute_Wide_Width => Width :
+      begin
+         if Static then
+
+            --  Floating-point types
+
+            if Is_Floating_Point_Type (P_Type) then
+
+               --  Width is zero for a null range (RM 3.5 (38))
+
+               if Expr_Value_R (Type_High_Bound (P_Type)) <
+                  Expr_Value_R (Type_Low_Bound (P_Type))
+               then
+                  Fold_Uint (N, Uint_0);
+
+               else
+                  --  For floating-point, we have +N.dddE+nnn where length
+                  --  of ddd is determined by type'Digits - 1, but is one
+                  --  if Digits is one (RM 3.5 (33)).
+
+                  --  nnn is set to 2 for Short_Float and Float (32 bit
+                  --  floats), and 3 for Long_Float and Long_Long_Float.
+                  --  This is not quite right, but is good enough.
+
+                  declare
+                     Len : Int :=
+                             Int'Max (2, UI_To_Int (Digits_Value (P_Type)));
+
+                  begin
+                     if Esize (P_Type) <= 32 then
+                        Len := Len + 6;
+                     else
+                        Len := Len + 7;
+                     end if;
+
+                     Fold_Uint (N, UI_From_Int (Len));
+                  end;
+               end if;
+
+            --  Fixed-point types
+
+            elsif Is_Fixed_Point_Type (P_Type) then
+
+               --  Width is zero for a null range (RM 3.5 (38))
+
+               if Expr_Value (Type_High_Bound (P_Type)) <
+                  Expr_Value (Type_Low_Bound  (P_Type))
+               then
+                  Fold_Uint (N, Uint_0);
+
+               --  The non-null case depends on the specific real type
+
+               else
+                  --  For fixed-point type width is Fore + 1 + Aft (RM 3.5(34))
+
+                  Fold_Uint (N, UI_From_Int (Fore_Value + 1 + Aft_Value));
+               end if;
+
+            --  Discrete types
+
+            else
+               declare
+                  R  : constant Entity_Id := Root_Type (P_Type);
+                  Lo : constant Uint :=
+                         Expr_Value (Type_Low_Bound (P_Type));
+                  Hi : constant Uint :=
+                         Expr_Value (Type_High_Bound (P_Type));
+                  W  : Nat;
+                  Wt : Nat;
+                  T  : Uint;
+                  L  : Node_Id;
+                  C  : Character;
+
+               begin
+                  --  Empty ranges
+
+                  if Lo > Hi then
+                     W := 0;
+
+                  --  Width for types derived from Standard.Character
+                  --  and Standard.Wide_Character.
+
+                  elsif R = Standard_Character
+                    or else R = Standard_Wide_Character
+                  then
+                     W := 0;
+
+                     --  Set W larger if needed
+
+                     for J in UI_To_Int (Lo) .. UI_To_Int (Hi) loop
+
+                        --  Assume all wide-character escape sequences are
+                        --  same length, so we can quit when we reach one.
+
+                        if J > 255 then
+                           if Id = Attribute_Wide_Width then
+                              W := Int'Max (W, 3);
+                              exit;
+                           else
+                              W := Int'Max (W, Length_Wide);
+                              exit;
+                           end if;
+
+                        else
+                           C := Character'Val (J);
+
+                           --  Test for all cases where Character'Image
+                           --  yields an image that is longer than three
+                           --  characters. First the cases of Reserved_xxx
+                           --  names (length = 12).
+
+                           case C is
+                              when Reserved_128 | Reserved_129 |
+                                   Reserved_132 | Reserved_153
+
+                                => Wt := 12;
+
+                              when BS | HT | LF | VT | FF | CR |
+                                   SO | SI | EM | FS | GS | RS |
+                                   US | RI | MW | ST | PM
+
+                                => Wt := 2;
+
+                              when NUL | SOH | STX | ETX | EOT |
+                                   ENQ | ACK | BEL | DLE | DC1 |
+                                   DC2 | DC3 | DC4 | NAK | SYN |
+                                   ETB | CAN | SUB | ESC | DEL |
+                                   BPH | NBH | NEL | SSA | ESA |
+                                   HTS | HTJ | VTS | PLD | PLU |
+                                   SS2 | SS3 | DCS | PU1 | PU2 |
+                                   STS | CCH | SPA | EPA | SOS |
+                                   SCI | CSI | OSC | APC
+
+                                => Wt := 3;
+
+                              when Space .. Tilde |
+                                   No_Break_Space .. LC_Y_Diaeresis
+
+                                => Wt := 3;
+
+                           end case;
+
+                           W := Int'Max (W, Wt);
+                        end if;
+                     end loop;
+
+                  --  Width for types derived from Standard.Boolean
+
+                  elsif R = Standard_Boolean then
+                     if Lo = 0 then
+                        W := 5; -- FALSE
+                     else
+                        W := 4; -- TRUE
+                     end if;
+
+                  --  Width for integer types
+
+                  elsif Is_Integer_Type (P_Type) then
+                     T := UI_Max (abs Lo, abs Hi);
+
+                     W := 2;
+                     while T >= 10 loop
+                        W := W + 1;
+                        T := T / 10;
+                     end loop;
+
+                  --  Only remaining possibility is user declared enum type
+
+                  else
+                     pragma Assert (Is_Enumeration_Type (P_Type));
+
+                     W := 0;
+                     L := First_Literal (P_Type);
+
+                     while Present (L) loop
+
+                        --  Only pay attention to in range characters
+
+                        if Lo <= Enumeration_Pos (L)
+                          and then Enumeration_Pos (L) <= Hi
+                        then
+                           --  For Width case, use decoded name
+
+                           if Id = Attribute_Width then
+                              Get_Decoded_Name_String (Chars (L));
+                              Wt := Nat (Name_Len);
+
+                           --  For Wide_Width, use encoded name, and then
+                           --  adjust for the encoding.
+
+                           else
+                              Get_Name_String (Chars (L));
+
+                              --  Character literals are always of length 3
+
+                              if Name_Buffer (1) = 'Q' then
+                                 Wt := 3;
+
+                              --  Otherwise loop to adjust for upper/wide chars
+
+                              else
+                                 Wt := Nat (Name_Len);
+
+                                 for J in 1 .. Name_Len loop
+                                    if Name_Buffer (J) = 'U' then
+                                       Wt := Wt - 2;
+                                    elsif Name_Buffer (J) = 'W' then
+                                       Wt := Wt - 4;
+                                    end if;
+                                 end loop;
+                              end if;
+                           end if;
+
+                           W := Int'Max (W, Wt);
+                        end if;
+
+                        Next_Literal (L);
+                     end loop;
+                  end if;
+
+                  Fold_Uint (N, UI_From_Int (W));
+               end;
+            end if;
+         end if;
+      end Width;
+
+      --  The following attributes can never be folded, and furthermore we
+      --  should not even have entered the case statement for any of these.
+      --  Note that in some cases, the values have already been folded as
+      --  a result of the processing in Analyze_Attribute.
+
+      when Attribute_Abort_Signal             |
+           Attribute_Access                   |
+           Attribute_Address                  |
+           Attribute_Address_Size             |
+           Attribute_Asm_Input                |
+           Attribute_Asm_Output               |
+           Attribute_Base                     |
+           Attribute_Bit_Order                |
+           Attribute_Bit_Position             |
+           Attribute_Callable                 |
+           Attribute_Caller                   |
+           Attribute_Class                    |
+           Attribute_Code_Address             |
+           Attribute_Count                    |
+           Attribute_Default_Bit_Order        |
+           Attribute_Elaborated               |
+           Attribute_Elab_Body                |
+           Attribute_Elab_Spec                |
+           Attribute_External_Tag             |
+           Attribute_First_Bit                |
+           Attribute_Input                    |
+           Attribute_Last_Bit                 |
+           Attribute_Max_Interrupt_Priority   |
+           Attribute_Max_Priority             |
+           Attribute_Maximum_Alignment        |
+           Attribute_Output                   |
+           Attribute_Partition_ID             |
+           Attribute_Position                 |
+           Attribute_Read                     |
+           Attribute_Storage_Pool             |
+           Attribute_Storage_Size             |
+           Attribute_Storage_Unit             |
+           Attribute_Tag                      |
+           Attribute_Terminated               |
+           Attribute_Tick                     |
+           Attribute_To_Address               |
+           Attribute_UET_Address              |
+           Attribute_Unchecked_Access         |
+           Attribute_Universal_Literal_String |
+           Attribute_Unrestricted_Access      |
+           Attribute_Valid                    |
+           Attribute_Value                    |
+           Attribute_Wchar_T_Size             |
+           Attribute_Wide_Value               |
+           Attribute_Word_Size                |
+           Attribute_Write                    =>
+
+         raise Program_Error;
+
+      end case;
+
+      --  At the end of the case, one more check. If we did a static evaluation
+      --  so that the result is now a literal, then set Is_Static_Expression
+      --  in the constant only if the prefix type is a static subtype. For
+      --  non-static subtypes, the folding is still OK, but not static.
+
+      if Nkind (N) = N_Integer_Literal
+        or else Nkind (N) = N_Real_Literal
+        or else Nkind (N) = N_Character_Literal
+        or else Nkind (N) = N_String_Literal
+        or else (Is_Entity_Name (N)
+                  and then Ekind (Entity (N)) = E_Enumeration_Literal)
+      then
+         Set_Is_Static_Expression (N, Static);
+
+      --  If this is still an attribute reference, then it has not been folded
+      --  and that means that its expressions are in a non-static context.
+
+      elsif Nkind (N) = N_Attribute_Reference then
+         Check_Expressions;
+
+      --  Note: the else case not covered here are odd cases where the
+      --  processing has transformed the attribute into something other
+      --  than a constant. Nothing more to do in such cases.
+
+      else
+         null;
+      end if;
+
+   end Eval_Attribute;
+
+   ------------------------------
+   -- Is_Anonymous_Tagged_Base --
+   ------------------------------
+
+   function Is_Anonymous_Tagged_Base
+     (Anon : Entity_Id;
+      Typ  : Entity_Id)
+      return Boolean
+   is
+   begin
+      return
+        Anon = Current_Scope
+          and then Is_Itype (Anon)
+          and then Associated_Node_For_Itype (Anon) = Parent (Typ);
+   end Is_Anonymous_Tagged_Base;
+
+   -----------------------
+   -- Resolve_Attribute --
+   -----------------------
+
+   procedure Resolve_Attribute (N : Node_Id; Typ : Entity_Id) is
+      Loc      : constant Source_Ptr   := Sloc (N);
+      P        : constant Node_Id      := Prefix (N);
+      Aname    : constant Name_Id      := Attribute_Name (N);
+      Attr_Id  : constant Attribute_Id := Get_Attribute_Id (Aname);
+      Index    : Interp_Index;
+      It       : Interp;
+      Btyp     : Entity_Id := Base_Type (Typ);
+      Nom_Subt : Entity_Id;
+
+   begin
+      --  If error during analysis, no point in continuing, except for
+      --  array types, where we get  better recovery by using unconstrained
+      --  indices than nothing at all (see Check_Array_Type).
+
+      if Error_Posted (N)
+        and then Attr_Id /= Attribute_First
+        and then Attr_Id /= Attribute_Last
+        and then Attr_Id /= Attribute_Length
+        and then Attr_Id /= Attribute_Range
+      then
+         return;
+      end if;
+
+      --  If attribute was universal type, reset to actual type
+
+      if Etype (N) = Universal_Integer
+        or else Etype (N) = Universal_Real
+      then
+         Set_Etype (N, Typ);
+      end if;
+
+      --  Remaining processing depends on attribute
+
+      case Attr_Id is
+
+         ------------
+         -- Access --
+         ------------
+
+         --  For access attributes, if the prefix denotes an entity, it is
+         --  interpreted as a name, never as a call. It may be overloaded,
+         --  in which case resolution uses the profile of the context type.
+         --  Otherwise prefix must be resolved.
+
+         when Attribute_Access
+            | Attribute_Unchecked_Access
+            | Attribute_Unrestricted_Access =>
+
+            if Is_Variable (P) then
+               Note_Possible_Modification (P);
+            end if;
+
+            if Is_Entity_Name (P) then
+
+               if Is_Overloaded (P) then
+                  Get_First_Interp (P, Index, It);
+
+                  while Present (It.Nam) loop
+
+                     if Type_Conformant (Designated_Type (Typ), It.Nam) then
+                        Set_Entity (P, It.Nam);
+
+                        --  The prefix is definitely NOT overloaded anymore
+                        --  at this point, so we reset the Is_Overloaded
+                        --  flag to avoid any confusion when reanalyzing
+                        --  the node.
+
+                        Set_Is_Overloaded (P, False);
+                        Generate_Reference (Entity (P), P);
+                        exit;
+                     end if;
+
+                     Get_Next_Interp (Index, It);
+                  end loop;
+
+               --  If it is a subprogram name or a type, there is nothing
+               --  to resolve.
+
+               elsif not Is_Overloadable (Entity (P))
+                 and then not Is_Type (Entity (P))
+               then
+                  Resolve (P, Etype (P));
+               end if;
+
+               if not Is_Entity_Name (P) then
+                  null;
+
+               elsif Is_Abstract (Entity (P))
+                 and then Is_Overloadable (Entity (P))
+               then
+                  Error_Msg_Name_1 := Aname;
+                  Error_Msg_N ("prefix of % attribute cannot be abstract", P);
+                  Set_Etype (N, Any_Type);
+
+               elsif Convention (Entity (P)) = Convention_Intrinsic then
+                  Error_Msg_Name_1 := Aname;
+
+                  if Ekind (Entity (P)) = E_Enumeration_Literal then
+                     Error_Msg_N
+                       ("prefix of % attribute cannot be enumeration literal",
+                          P);
+                  else
+                     Error_Msg_N
+                       ("prefix of % attribute cannot be intrinsic", P);
+                  end if;
+
+                  Set_Etype (N, Any_Type);
+               end if;
+
+               --  Assignments, return statements, components of aggregates,
+               --  generic instantiations will require convention checks if
+               --  the type is an access to subprogram. Given that there will
+               --  also be accessibility checks on those, this is where the
+               --  checks can eventually be centralized ???
+
+               if Ekind (Btyp) = E_Access_Subprogram_Type then
+                  if Convention (Btyp) /= Convention (Entity (P)) then
+                     Error_Msg_N
+                      ("subprogram has invalid convention for context", P);
+
+                  else
+                     Check_Subtype_Conformant
+                       (New_Id  => Entity (P),
+                        Old_Id  => Designated_Type (Btyp),
+                        Err_Loc => P);
+                  end if;
+
+                  if Attr_Id = Attribute_Unchecked_Access then
+                     Error_Msg_Name_1 := Aname;
+                     Error_Msg_N
+                       ("attribute% cannot be applied to a subprogram", P);
+
+                  elsif Aname = Name_Unrestricted_Access then
+                     null;  --  Nothing to check
+
+                  --  Check the static accessibility rule of 3.10.2(32)
+
+                  elsif Attr_Id = Attribute_Access
+                    and then Subprogram_Access_Level (Entity (P))
+                      > Type_Access_Level (Btyp)
+                  then
+                     if not In_Instance_Body then
+                        Error_Msg_N
+                          ("subprogram must not be deeper than access type",
+                            P);
+                     else
+                        Warn_On_Instance := True;
+                        Error_Msg_N
+                          ("subprogram must not be deeper than access type?",
+                             P);
+                        Error_Msg_N
+                          ("Constraint_Error will be raised ?", P);
+                        Set_Raises_Constraint_Error (N);
+                        Warn_On_Instance := False;
+                     end if;
+
+                  --  Check the restriction of 3.10.2(32) that disallows
+                  --  the type of the access attribute to be declared
+                  --  outside a generic body when the attribute occurs
+                  --  within that generic body.
+
+                  elsif Enclosing_Generic_Body (Entity (P))
+                    /= Enclosing_Generic_Body (Btyp)
+                  then
+                     Error_Msg_N
+                       ("access type must not be outside generic body", P);
+                  end if;
+               end if;
+
+               --  if this is a renaming, an inherited operation, or a
+               --  subprogram instance, use the original entity.
+
+               if Is_Entity_Name (P)
+                 and then Is_Overloadable (Entity (P))
+                 and then Present (Alias (Entity (P)))
+               then
+                  Rewrite (P,
+                    New_Occurrence_Of (Alias (Entity (P)), Sloc (P)));
+               end if;
+
+            elsif Nkind (P) = N_Selected_Component
+              and then Is_Overloadable (Entity (Selector_Name (P)))
+            then
+               --  Protected operation. If operation is overloaded, must
+               --  disambiguate. Prefix that denotes protected object itself
+               --  is resolved with its own type.
+
+               if Attr_Id = Attribute_Unchecked_Access then
+                  Error_Msg_Name_1 := Aname;
+                  Error_Msg_N
+                    ("attribute% cannot be applied to protected operation", P);
+               end if;
+
+               Resolve (Prefix (P), Etype (Prefix (P)));
+
+            elsif Is_Overloaded (P) then
+
+               --  Use the designated type of the context  to disambiguate.
+               declare
+                  Index : Interp_Index;
+                  It    : Interp;
+               begin
+                  Get_First_Interp (P, Index, It);
+
+                  while Present (It.Typ) loop
+                     if Covers (Designated_Type (Typ), It.Typ) then
+                        Resolve (P, It.Typ);
+                        exit;
+                     end if;
+
+                     Get_Next_Interp (Index, It);
+                  end loop;
+               end;
+            else
+               Resolve (P, Etype (P));
+            end if;
+
+            --  X'Access is illegal if X denotes a constant and the access
+            --  type is access-to-variable. Same for 'Unchecked_Access.
+            --  The rule does not apply to 'Unrestricted_Access.
+
+            if not (Ekind (Btyp) = E_Access_Subprogram_Type
+                     or else (Is_Record_Type (Btyp) and then
+                              Present (Corresponding_Remote_Type (Btyp)))
+                     or else Ekind (Btyp) = E_Access_Protected_Subprogram_Type
+                     or else Is_Access_Constant (Btyp)
+                     or else Is_Variable (P)
+                     or else Attr_Id = Attribute_Unrestricted_Access)
+            then
+               if Comes_From_Source (N) then
+                  Error_Msg_N ("access-to-variable designates constant", P);
+               end if;
+            end if;
+
+            if (Attr_Id = Attribute_Access
+                  or else
+                Attr_Id = Attribute_Unchecked_Access)
+              and then (Ekind (Btyp) = E_General_Access_Type
+                         or else Ekind (Btyp) = E_Anonymous_Access_Type)
+            then
+               if Is_Dependent_Component_Of_Mutable_Object (P) then
+                  Error_Msg_N
+                    ("illegal attribute for discriminant-dependent component",
+                     P);
+               end if;
+
+               --  Check the static matching rule of 3.10.2(27). The
+               --  nominal subtype of the prefix must statically
+               --  match the designated type.
+
+               Nom_Subt := Etype (P);
+
+               if Is_Constr_Subt_For_U_Nominal (Nom_Subt) then
+                  Nom_Subt := Etype (Nom_Subt);
+               end if;
+
+               if Is_Tagged_Type (Designated_Type (Typ)) then
+                  --  If the attribute is in the context of an access
+                  --  parameter, then the prefix is allowed to be of
+                  --  the class-wide type (by AI-127).
+
+                  if Ekind (Typ) = E_Anonymous_Access_Type then
+                     if not Covers (Designated_Type (Typ), Nom_Subt)
+                       and then not Covers (Nom_Subt, Designated_Type (Typ))
+                     then
+                        if Is_Anonymous_Tagged_Base
+                             (Nom_Subt, Etype (Designated_Type (Typ)))
+                        then
+                           null;
+
+                        else
+                           Error_Msg_NE
+                             ("type of prefix: & not compatible", P, Nom_Subt);
+                           Error_Msg_NE
+                             ("\with &, the expected designated type",
+                               P, Designated_Type (Typ));
+                        end if;
+                     end if;
+
+                  elsif not Covers (Designated_Type (Typ), Nom_Subt)
+                    or else
+                      (not Is_Class_Wide_Type (Designated_Type (Typ))
+                        and then Is_Class_Wide_Type (Nom_Subt))
+                  then
+                     Error_Msg_NE
+                       ("type of prefix: & is not covered", P, Nom_Subt);
+                     Error_Msg_NE
+                       ("\by &, the expected designated type" &
+                           " ('R'M 3.10.2 (27))", P, Designated_Type (Typ));
+                  end if;
+
+                  if Is_Class_Wide_Type (Designated_Type (Typ))
+                    and then Has_Discriminants (Etype (Designated_Type (Typ)))
+                    and then Is_Constrained (Etype (Designated_Type (Typ)))
+                    and then Designated_Type (Typ) /= Nom_Subt
+                  then
+                     Apply_Discriminant_Check
+                       (N, Etype (Designated_Type (Typ)));
+                  end if;
+
+               elsif not Subtypes_Statically_Match
+                        (Designated_Type (Typ), Nom_Subt)
+                 and then
+                   not (Has_Discriminants (Designated_Type (Typ))
+                        and then not Is_Constrained (Designated_Type (Typ)))
+               then
+                  Error_Msg_N
+                    ("object subtype must statically match "
+                     & "designated subtype", P);
+
+                  if Is_Entity_Name (P)
+                    and then Is_Array_Type (Designated_Type (Typ))
+                  then
+
+                     declare
+                        D : constant Node_Id := Declaration_Node (Entity (P));
+
+                     begin
+                        Error_Msg_N ("aliased object has explicit bounds?",
+                          D);
+                        Error_Msg_N ("\declare without bounds"
+                          & " (and with explicit initialization)?", D);
+                        Error_Msg_N ("\for use with unconstrained access?", D);
+                     end;
+                  end if;
+               end if;
+
+               --  Check the static accessibility rule of 3.10.2(28).
+               --  Note that this check is not performed for the
+               --  case of an anonymous access type, since the access
+               --  attribute is always legal in such a context.
+
+               if Attr_Id /= Attribute_Unchecked_Access
+                 and then Object_Access_Level (P) > Type_Access_Level (Btyp)
+                 and then Ekind (Btyp) = E_General_Access_Type
+               then
+                  --  In an instance, this is a runtime check, but one we
+                  --  know will fail, so generate an appropriate warning.
+
+                  if In_Instance_Body then
+                     Error_Msg_N
+                       ("?non-local pointer cannot point to local object", P);
+                     Error_Msg_N
+                       ("?Program_Error will be raised at run time", P);
+                     Rewrite (N, Make_Raise_Program_Error (Loc));
+                     Set_Etype (N, Typ);
+                     return;
+
+                  else
+                     Error_Msg_N
+                       ("non-local pointer cannot point to local object", P);
+
+                     if Is_Record_Type (Current_Scope)
+                       and then (Nkind (Parent (N)) =
+                                  N_Discriminant_Association
+                                   or else
+                                 Nkind (Parent (N)) =
+                                   N_Index_Or_Discriminant_Constraint)
+                     then
+                        declare
+                           Indic : Node_Id := Parent (Parent (N));
+
+                        begin
+                           while Present (Indic)
+                             and then Nkind (Indic) /= N_Subtype_Indication
+                           loop
+                              Indic := Parent (Indic);
+                           end loop;
+
+                           if Present (Indic) then
+                              Error_Msg_NE
+                                ("\use an access definition for" &
+                                  " the access discriminant of&", N,
+                                  Entity (Subtype_Mark (Indic)));
+                           end if;
+                        end;
+                     end if;
+                  end if;
+               end if;
+            end if;
+
+            if Ekind (Btyp) = E_Access_Protected_Subprogram_Type
+              and then Is_Entity_Name (P)
+              and then not Is_Protected_Type (Scope (Entity (P)))
+            then
+               Error_Msg_N ("context requires a protected subprogram", P);
+
+            elsif Ekind (Btyp) = E_Access_Subprogram_Type
+              and then Ekind (Etype (N)) = E_Access_Protected_Subprogram_Type
+            then
+               Error_Msg_N ("context requires a non-protected subprogram", P);
+            end if;
+
+            --  The context cannot be a pool-specific type, but this is a
+            --  legality rule, not a resolution rule, so it must be checked
+            --  separately, after possibly disambiguation (see AI-245).
+
+            if Ekind (Btyp) = E_Access_Type
+              and then Attr_Id /= Attribute_Unrestricted_Access
+            then
+               Wrong_Type (N, Typ);
+            end if;
+
+            Set_Etype (N, Typ);
+
+            --  Check for incorrect atomic/volatile reference (RM C.6(12))
+
+            if Attr_Id /= Attribute_Unrestricted_Access then
+               if Is_Atomic_Object (P)
+                 and then not Is_Atomic (Designated_Type (Typ))
+               then
+                  Error_Msg_N
+                    ("access to atomic object cannot yield access-to-" &
+                     "non-atomic type", P);
+
+               elsif Is_Volatile_Object (P)
+                 and then not Is_Volatile (Designated_Type (Typ))
+               then
+                  Error_Msg_N
+                    ("access to volatile object cannot yield access-to-" &
+                     "non-volatile type", P);
+               end if;
+            end if;
+
+         -------------
+         -- Address --
+         -------------
+
+         --  Deal with resolving the type for Address attribute, overloading
+         --  is not permitted here, since there is no context to resolve it.
+
+         when Attribute_Address | Attribute_Code_Address =>
+
+            --  To be safe, assume that if the address of a variable is taken,
+            --  it may be modified via this address, so note modification.
+
+            if Is_Variable (P) then
+               Note_Possible_Modification (P);
+            end if;
+
+            if Nkind (P) in  N_Subexpr
+              and then Is_Overloaded (P)
+            then
+               Get_First_Interp (P, Index, It);
+               Get_Next_Interp (Index, It);
+
+               if Present (It.Nam) then
+                  Error_Msg_Name_1 := Aname;
+                  Error_Msg_N
+                    ("prefix of % attribute cannot be overloaded", N);
+                  return;
+               end if;
+            end if;
+
+            --  Do not permit address to be applied to entry
+
+            if (Is_Entity_Name (P) and then Is_Entry (Entity (P)))
+              or else Nkind (P) = N_Entry_Call_Statement
+
+              or else (Nkind (P) = N_Selected_Component
+                and then Is_Entry (Entity (Selector_Name (P))))
+
+              or else (Nkind (P) = N_Indexed_Component
+                and then Nkind (Prefix (P)) = N_Selected_Component
+                and then Is_Entry (Entity (Selector_Name (Prefix (P)))))
+            then
+               Error_Msg_Name_1 := Aname;
+               Error_Msg_N
+                 ("prefix of % attribute cannot be entry", N);
+               return;
+            end if;
+
+            if not Is_Entity_Name (P)
+               or else not Is_Overloadable (Entity (P))
+            then
+               if not Is_Task_Type (Etype (P))
+                 or else Nkind (P) = N_Explicit_Dereference
+               then
+                  Resolve (P, Etype (P));
+               end if;
+            end if;
+
+            --  If this is the name of a derived subprogram, or that of a
+            --  generic actual, the address is that of the original entity.
+
+            if Is_Entity_Name (P)
+              and then Is_Overloadable (Entity (P))
+              and then Present (Alias (Entity (P)))
+            then
+               Rewrite (P,
+                 New_Occurrence_Of (Alias (Entity (P)), Sloc (P)));
+            end if;
+
+         ---------------
+         -- AST_Entry --
+         ---------------
+
+         --  Prefix of the AST_Entry attribute is an entry name which must
+         --  not be resolved, since this is definitely not an entry call.
+
+         when Attribute_AST_Entry =>
+            null;
+
+         ------------------
+         -- Body_Version --
+         ------------------
+
+         --  Prefix of Body_Version attribute can be a subprogram name which
+         --  must not be resolved, since this is not a call.
+
+         when Attribute_Body_Version =>
+            null;
+
+         ------------
+         -- Caller --
+         ------------
+
+         --  Prefix of Caller attribute is an entry name which must not
+         --  be resolved, since this is definitely not an entry call.
+
+         when Attribute_Caller =>
+            null;
+
+         ------------------
+         -- Code_Address --
+         ------------------
+
+         --  Shares processing with Address attribute
+
+         -----------
+         -- Count --
+         -----------
+
+         --  Prefix of the Count attribute is an entry name which must not
+         --  be resolved, since this is definitely not an entry call.
+
+         when Attribute_Count =>
+            null;
+
+         ----------------
+         -- Elaborated --
+         ----------------
+
+         --  Prefix of the Elaborated attribute is a subprogram name which
+         --  must not be resolved, since this is definitely not a call. Note
+         --  that it is a library unit, so it cannot be overloaded here.
+
+         when Attribute_Elaborated =>
+            null;
+
+         --------------------
+         -- Mechanism_Code --
+         --------------------
+
+         --  Prefix of the Mechanism_Code attribute is a function name
+         --  which must not be resolved. Should we check for overloaded ???
+
+         when Attribute_Mechanism_Code =>
+            null;
+
+         ------------------
+         -- Partition_ID --
+         ------------------
+
+         --  Most processing is done in sem_dist, after determining the
+         --  context type. Node is rewritten as a conversion to a runtime call.
+
+         when Attribute_Partition_ID =>
+            Process_Partition_Id (N);
+            return;
+
+         -----------
+         -- Range --
+         -----------
+
+         --  We replace the Range attribute node with a range expression
+         --  whose bounds are the 'First and 'Last attributes applied to the
+         --  same prefix. The reason that we do this transformation here
+         --  instead of in the expander is that it simplifies other parts of
+         --  the semantic analysis which assume that the Range has been
+         --  replaced; thus it must be done even when in semantic-only mode
+         --  (note that the RM specifically mentions this equivalence, we
+         --  take care that the prefix is only evaluated once).
+
+         when Attribute_Range => Range_Attribute :
+            declare
+               LB   : Node_Id;
+               HB   : Node_Id;
+
+               function Check_Discriminated_Prival
+                 (N    : Node_Id)
+                  return Node_Id;
+               --  The range of a private component constrained by a
+               --  discriminant is rewritten to make the discriminant
+               --  explicit. This solves some complex visibility problems
+               --  related to the use of privals.
+
+               function Check_Discriminated_Prival
+                 (N    : Node_Id)
+                  return Node_Id
+               is
+               begin
+                  if Is_Entity_Name (N)
+                    and then Ekind (Entity (N)) = E_In_Parameter
+                    and then not Within_Init_Proc
+                  then
+                     return Make_Identifier (Sloc (N), Chars (Entity (N)));
+                  else
+                     return Duplicate_Subexpr (N);
+                  end if;
+               end Check_Discriminated_Prival;
+
+            --  Start of processing for Range_Attribute
+
+            begin
+               if not Is_Entity_Name (P)
+                 or else not Is_Type (Entity (P))
+               then
+                  Resolve (P, Etype (P));
+               end if;
+
+               --  Check whether prefix is (renaming of) private component
+               --  of protected type.
+
+               if Is_Entity_Name (P)
+                 and then Comes_From_Source (N)
+                 and then Is_Array_Type (Etype (P))
+                 and then Number_Dimensions (Etype (P)) = 1
+                 and then (Ekind (Scope (Entity (P))) = E_Protected_Type
+                            or else
+                           Ekind (Scope (Scope (Entity (P)))) =
+                                                        E_Protected_Type)
+               then
+                  LB := Check_Discriminated_Prival (
+                    Type_Low_Bound (Etype (First_Index (Etype (P)))));
+
+                  HB := Check_Discriminated_Prival (
+                    Type_High_Bound (Etype (First_Index (Etype (P)))));
+
+               else
+                  HB :=
+                    Make_Attribute_Reference (Loc,
+                      Prefix         => Duplicate_Subexpr (P),
+                      Attribute_Name => Name_Last,
+                      Expressions    => Expressions (N));
+
+                  LB :=
+                    Make_Attribute_Reference (Loc,
+                      Prefix         => P,
+                      Attribute_Name => Name_First,
+                      Expressions    => Expressions (N));
+               end if;
+
+               --  If the original was marked as Must_Not_Freeze (see code
+               --  in Sem_Ch3.Make_Index), then make sure the rewriting
+               --  does not freeze either.
+
+               if Must_Not_Freeze (N) then
+                  Set_Must_Not_Freeze (HB);
+                  Set_Must_Not_Freeze (LB);
+                  Set_Must_Not_Freeze (Prefix (HB));
+                  Set_Must_Not_Freeze (Prefix (LB));
+               end if;
+
+               if Raises_Constraint_Error (Prefix (N)) then
+
+                  --  Preserve Sloc of prefix in the new bounds, so that
+                  --  the posted warning can be removed if we are within
+                  --  unreachable code.
+
+                  Set_Sloc (LB, Sloc (Prefix (N)));
+                  Set_Sloc (HB, Sloc (Prefix (N)));
+               end if;
+
+               Rewrite (N, Make_Range (Loc, LB, HB));
+               Analyze_And_Resolve (N, Typ);
+
+               --  Normally after resolving attribute nodes, Eval_Attribute
+               --  is called to do any possible static evaluation of the node.
+               --  However, here since the Range attribute has just been
+               --  transformed into a range expression it is no longer an
+               --  attribute node and therefore the call needs to be avoided
+               --  and is accomplished by simply returning from the procedure.
+
+               return;
+            end Range_Attribute;
+
+         -----------------
+         -- UET_Address --
+         -----------------
+
+         --  Prefix must not be resolved in this case, since it is not a
+         --  real entity reference. No action of any kind is require!
+
+         when Attribute_UET_Address =>
+            return;
+
+         ----------------------
+         -- Unchecked_Access --
+         ----------------------
+
+         --  Processing is shared with Access
+
+         -------------------------
+         -- Unrestricted_Access --
+         -------------------------
+
+         --  Processing is shared with Access
+
+         ---------
+         -- Val --
+         ---------
+
+         --  Apply range check. Note that we did not do this during the
+         --  analysis phase, since we wanted Eval_Attribute to have a
+         --  chance at finding an illegal out of range value.
+
+         when Attribute_Val =>
+
+            --  Note that we do our own Eval_Attribute call here rather than
+            --  use the common one, because we need to do processing after
+            --  the call, as per above comment.
+
+            Eval_Attribute (N);
+
+            --  Eval_Attribute may replace the node with a raise CE, or
+            --  fold it to a constant. Obviously we only apply a scalar
+            --  range check if this did not happen!
+
+            if Nkind (N) = N_Attribute_Reference
+              and then Attribute_Name (N) = Name_Val
+            then
+               Apply_Scalar_Range_Check (First (Expressions (N)), Btyp);
+            end if;
+
+            return;
+
+         -------------
+         -- Version --
+         -------------
+
+         --  Prefix of Version attribute can be a subprogram name which
+         --  must not be resolved, since this is not a call.
+
+         when Attribute_Version =>
+            null;
+
+         ----------------------
+         -- Other Attributes --
+         ----------------------
+
+         --  For other attributes, resolve prefix unless it is a type. If
+         --  the attribute reference itself is a type name ('Base and 'Class)
+         --  then this is only legal within a task or protected record.
+
+         when others =>
+            if not Is_Entity_Name (P)
+              or else not Is_Type (Entity (P))
+            then
+               Resolve (P, Etype (P));
+            end if;
+
+            --  If the attribute reference itself is a type name ('Base,
+            --  'Class) then this is only legal within a task or protected
+            --  record. What is this all about ???
+
+            if Is_Entity_Name (N)
+              and then Is_Type (Entity (N))
+            then
+               if Is_Concurrent_Type (Entity (N))
+                 and then In_Open_Scopes (Entity (P))
+               then
+                  null;
+               else
+                  Error_Msg_N
+                    ("invalid use of subtype name in expression or call", N);
+               end if;
+            end if;
+
+            --  For attributes whose argument may be a string, complete
+            --  resolution of argument now. This avoids premature expansion
+            --  (and the creation of transient scopes) before the attribute
+            --  reference is resolved.
+
+            case Attr_Id is
+               when Attribute_Value =>
+                  Resolve (First (Expressions (N)), Standard_String);
+
+               when Attribute_Wide_Value =>
+                  Resolve (First (Expressions (N)), Standard_Wide_String);
+
+               when others => null;
+            end case;
+      end case;
+
+      --  Normally the Freezing is done by Resolve but sometimes the Prefix
+      --  is not resolved, in which case the freezing must be done now.
+
+      Freeze_Expression (P);
+
+      --  Finally perform static evaluation on the attribute reference
+
+      Eval_Attribute (N);
+
+   end Resolve_Attribute;
+
+end Sem_Attr;
diff --git a/gcc/ada/sem_attr.ads b/gcc/ada/sem_attr.ads
new file mode 100644 (file)
index 0000000..ccbc3f4
--- /dev/null
@@ -0,0 +1,595 @@
+------------------------------------------------------------------------------
+--                                                                          --
+--                         GNAT COMPILER COMPONENTS                         --
+--                                                                          --
+--                             S E M _ A T T R                              --
+--                                                                          --
+--                                 S p e c                                  --
+--                                                                          --
+--                            $Revision: 1.26 $
+--                                                                          --
+--          Copyright (C) 1992-1999, 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- --
+-- ware  Foundation;  either version 2,  or (at your option) any later ver- --
+-- sion.  GNAT is distributed in the hope that it will be useful, but WITH- --
+-- OUT ANY WARRANTY;  without even the  implied warranty of MERCHANTABILITY --
+-- or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License --
+-- for  more details.  You should have  received  a copy of the GNU General --
+-- Public License  distributed with GNAT;  see file COPYING.  If not, write --
+-- to  the Free Software Foundation,  59 Temple Place - Suite 330,  Boston, --
+-- MA 02111-1307, USA.                                                      --
+--                                                                          --
+-- GNAT was originally developed  by the GNAT team at  New York University. --
+-- It is now maintained by Ada Core Technologies Inc (http://www.gnat.com). --
+--                                                                          --
+------------------------------------------------------------------------------
+
+--  Attribute handling is isolated in a separate package to ease the addition
+--  of implementation defined attributes. Logically this processing belongs
+--  in chapter 4. See Sem_Ch4 for a description of the relation of the
+--  Analyze and Resolve routines for expression components.
+
+--  This spec also documents all GNAT implementation defined pragmas
+
+with Snames; use Snames;
+with Types;  use Types;
+
+package Sem_Attr is
+
+   type Attribute_Class_Array is array (Attribute_Id) of Boolean;
+   --  Type used to build attribute classification flag arrays
+
+   -----------------------------------------
+   -- Implementation Dependent Attributes --
+   -----------------------------------------
+
+   --  This section describes the implementation dependent attributes
+   --  provided in GNAT, as well as constructing an array of flags
+   --  indicating which attributes these are.
+
+   Attribute_Impl_Def : Attribute_Class_Array := Attribute_Class_Array'(
+
+      ------------------
+      -- Abort_Signal --
+      ------------------
+
+      Attribute_Abort_Signal => True,
+      --
+      --  Standard'Abort_Signal (Standard is the only allowed prefix)
+      --  provides the entity for the special exception used to signal
+      --  task abort or asynchronous transfer of control. Normally this
+      --  attribute should only be used in the tasking runtime (it is
+      --  highly peculiar, and completely outside the normal semantics
+      --  of Ada, for a user program to intercept the abort exception).
+
+      ------------------
+      -- Address_Size --
+      ------------------
+
+      Attribute_Address_Size => True,
+      --
+      --  Standard'Address_Size (Standard is the only allowed prefix) is
+      --  a static constant giving the number of bits in an Address. It
+      --  is used primarily for constructing the definition of Memory_Size
+      --  in package Standard, but may be freely used in user programs.
+      --  This is a static attribute.
+
+      ---------------
+      -- Asm_Input --
+      ---------------
+
+      Attribute_Asm_Input => True,
+      --
+      --  Used only in conjunction with the Asm and Asm_Volatile subprograms
+      --  in package Machine_Code to construct machine instructions. See
+      --  documentation in package Machine_Code in file s-maccod.ads.
+
+      ----------------
+      -- Asm_Output --
+      ----------------
+
+      Attribute_Asm_Output => True,
+      --
+      --  Used only in conjunction with the Asm and Asm_Volatile subprograms
+      --  in package Machine_Code to construct machine instructions. See
+      --  documentation in package Machine_Code in file s-maccod.ads.
+
+      ---------------
+      -- AST_Entry --
+      ---------------
+
+      Attribute_AST_Entry => True,
+      --
+      --  E'Ast_Entry, where E is a task entry, yields a value of the
+      --  predefined type System.DEC.AST_Handler, that enables the given
+      --  entry to be called when an AST occurs. If the name to which the
+      --  attribute applies has not been specified with the pragma AST_Entry,
+      --  the attribute returns the value No_Ast_Handler, and no AST occurs.
+      --  If the entry is for a task that is not callable (T'Callable False),
+      --  the exception program error is raised. If an AST occurs for an
+      --  entry of a task that is terminated, the program is erroneous.
+      --
+      --  The attribute AST_Entry is supported only in OpenVMS versions
+      --  of GNAT. It will be rejected as illegal in other GNAT versions.
+
+      ---------
+      -- Bit --
+      ---------
+
+      Attribute_Bit => True,
+      --
+      --  Obj'Bit, where Obj is any object, yields the bit offset within
+      --  the storage unit (byte) that contains the first bit of storage
+      --  allocated for the object. The value of this attribute is of the
+      --  type Universal_Integer, and is always a non-negative number not
+      --  exceeding the value of System.Storage_Unit.
+      --
+      --  For an object that is a variable or a constant allocated in a
+      --  register, the value is zero. (The use of this attribute does not
+      --  force the allocation of a variable to memory).
+      --
+      --  For an object that is a formal parameter, this attribute applies
+      --  to either the matching actual parameter or to a copy of the
+      --  matching actual parameter.
+      --
+      --  For an access object the value is zero. Note that Obj.all'Bit is
+      --  subject to an Access_Check for the designated object. Similarly
+      --  for a record component X.C'Bit is subject to a discriminant check
+      --  and X(I).Bit and X(I1..I2)'Bit are subject to index checks.
+      --
+      --  This attribute is designed to be compatible with the DEC Ada
+      --  definition and implementation of the Bit attribute.
+
+      ------------------
+      -- Code_Address --
+      ------------------
+
+      Attribute_Code_Address => True,
+      --
+      --  subp'Code_Address, where subp is a subprogram entity, gives the
+      --  address of the first generated instruction for a subprogram. This
+      --  is often, but not always the same as the 'Address value, which is
+      --  the address to be used in a call. The differences occur in the case
+      --  of a nested procedure (where Address yields the address of the
+      --  trampoline code used to load the static link), and on some systems
+      --  which use procedure descriptors (in which case Address yields the
+      --  address of the descriptor).
+
+      -----------------------
+      -- Default_Bit_Order --
+      -----------------------
+
+      Attribute_Default_Bit_Order => True,
+      --
+      --  Standard'Default_Bit_Order (Standard is the only permissible prefix),
+      --  provides the value System.Default_Bit_Order as a Pos value (0 for
+      --  High_Order_First, 1 for Low_Order_First). This is used to construct
+      --  the definition of Default_Bit_Order in package System. This is a
+      --  static attribute.
+
+      ---------------
+      -- Elab_Body --
+      ---------------
+
+      Attribute_Elab_Body => True,
+      --
+      --  This attribute can only be applied to a program unit name. It
+      --  returns the entity for the corresponding elaboration procedure
+      --  for elaborating the body of the referenced unit. This is used
+      --  in the main generated elaboration procedure by the binder, and
+      --  is not normally used in any other context, but there may be
+      --  specialized situations in which it is useful to be able to
+      --  call this elaboration procedure from Ada code, e.g. if it
+      --  is necessary to do selective reelaboration to fix some error.
+
+      ---------------
+      -- Elab_Spec --
+      ---------------
+
+      Attribute_Elab_Spec => True,
+      --
+      --  This attribute can only be applied to a program unit name. It
+      --  returns the entity for the corresponding elaboration procedure
+      --  for elaborating the spec of the referenced unit. This is used
+      --  in the main generated elaboration procedure by the binder, and
+      --  is not normally used in any other context, but there may be
+      --  specialized situations in which it is useful to be able to
+      --  call this elaboration procedure from Ada code, e.g. if it
+      --  is necessary to do selective reelaboration to fix some error.
+
+      ----------------
+      -- Elaborated --
+      ----------------
+
+      Attribute_Elaborated => True,
+      --
+      --  Lunit'Elaborated, where Lunit is a library unit, yields a boolean
+      --  value indicating whether or not the body of the designated library
+      --  unit has been elaborated yet.
+
+
+      --------------
+      -- Enum_Rep --
+      --------------
+
+      Attribute_Enum_Rep => True,
+      --
+      --  For every enumeration subtype S, S'Enum_Rep denotes a function
+      --  with the following specification:
+      --
+      --    function S'Enum_Rep (Arg : S'Base) return universal_integer;
+      --
+      --  The function returns the representation value for the given
+      --  enumeration value. This will be equal to the 'Pos value in the
+      --  absence of an enumeration representation clause. This is a static
+      --  attribute (i.e. the result is static if the argument is static).
+
+      -----------------
+      -- Fixed_Value --
+      -----------------
+
+      Attribute_Fixed_Value => True,
+      --
+      --  For every fixed-point type S, S'Fixed_Value denotes a function
+      --  with the following specification:
+      --
+      --    function S'Fixed_Value (Arg : universal_integer) return S;
+      --
+      --  The value returned is the fixed-point value V such that
+      --
+      --    V = Arg * S'Small
+      --
+      --  The effect is thus equivalent to first converting the argument
+      --  to the integer type used to represent S, and then doing an
+      --  unchecked conversion to the fixed-point type. This attribute is
+      --  primarily intended for use in implementation of the input-output
+      --  functions for fixed-point values.
+
+      -----------------------
+      -- Has_Discriminants --
+      -----------------------
+
+      Attribute_Has_Discriminants => True,
+      --
+      --  Gtyp'Has_Discriminants, where Gtyp is a generic formal type, yields
+      --  a Boolean value indicating whether or not the actual instantiation
+      --  type has discriminants.
+
+      ---------
+      -- Img --
+      ---------
+
+      Attribute_Img => True,
+      --
+      --  The 'Img function is defined for any prefix, P, that denotes an
+      --  object of scalar type T. P'Img is equivalent to T'Image (P). This
+      --  is convenient for debugging. For example:
+      --
+      --     Put_Line ("X = " & X'Img);
+      --
+      --  has the same meaning as the more verbose:
+      --
+      --     Put_Line ("X = " & Temperature_Type'Image (X));
+      --
+      --  where Temperature_Type is the subtype of the object X.
+
+      -------------------
+      -- Integer_Value --
+      -------------------
+
+      Attribute_Integer_Value => True,
+      --
+      --  For every integer type S, S'Integer_Value denotes a function
+      --  with the following specification:
+      --
+      --    function S'Integer_Value (Arg : universal_fixed) return S;
+      --
+      --  The value returned is the integer value V, such that
+      --
+      --    Arg = V * fixed-type'Small
+      --
+      --  The effect is thus equivalent to first doing an unchecked convert
+      --  from the fixed-point type to its corresponding implementation type,
+      --  and then converting the result to the target integer type. This
+      --  attribute is primarily intended for use in implementation of the
+      --  standard input-output functions for fixed-point values.
+
+      ------------------
+      -- Machine_Size --
+      ------------------
+
+      Attribute_Machine_Size => True,
+      --
+      --  This attribute is identical to the Object_Size attribute. It is
+      --  provided for compatibility with the DEC attribute of this name.
+
+      ----------------------------
+      -- Max_Interrupt_Priority --
+      ----------------------------
+
+      Attribute_Max_Interrupt_Priority => True,
+      --
+      --  Standard'Max_Interrupt_Priority (Standard is the only permissible
+      --  prefix), provides the value System.Max_Interrupt_Priority, and is
+      --  intended primarily for constructing this definition in package
+      --  System (see note above in Default_Bit_Order description}. This
+      --  is a static attribute.
+
+      ------------------
+      -- Max_Priority --
+      ------------------
+
+      Attribute_Max_Priority => True,
+      --
+      --  Standard'Max_Priority (Standard is the only permissible prefix)
+      --  provides the value System.Max_Priority, and is intended primarily
+      --  for constructing this definition in package System (see note above
+      --  in Default_Bit_Order description). This is a static attribute.
+
+      -----------------------
+      -- Maximum_Alignment --
+      -----------------------
+
+      Attribute_Maximum_Alignment => True,
+      --
+      --  Standard'Maximum_Alignment (Standard is the only permissible prefix)
+      --  provides the maximum useful alignment value for the target. This
+      --  is a static value that can be used to specify the alignment for an
+      --  object, guaranteeing that it is properly aligned in all cases. The
+      --  time this is useful is when an external object is imported and its
+      --  alignment requirements are unknown. This is a static attribute.
+
+      --------------------
+      -- Mechanism_Code --
+      --------------------
+
+      Attribute_Mechanism_Code => True,
+      --
+      --  function'Mechanism_Code yeilds an integer code for the mechanism
+      --  used for the result of function, and subprogram'Mechanism_Code (n)
+      --  yields the mechanism used for formal parameter number n (a static
+      --  integer value, 1 = first parameter). The code returned is:
+      --
+      --     1 = by copy (value)
+      --     2 = by reference
+      --     3 = by descriptor (default descriptor type)
+      --     4 = by descriptor (UBS  unaligned bit string)
+      --     5 = by descriptor (UBSB aligned bit string with arbitrary bounds)
+      --     6 = by descriptor (UBA  unaligned bit array)
+      --     7 = by descriptor (S    string, also scalar access type parameter)
+      --     8 = by descriptor (SB   string with arbitrary bounds)
+      --     9 = by descriptor (A    contiguous array)
+      --    10 = by descriptor (NCA  non-contiguous array)
+
+      --------------------
+      -- Null_Parameter --
+      --------------------
+
+      Attribute_Null_Parameter => True,
+      --
+      --  A reference T'Null_Parameter denotes an (imaginary) object of
+      --  type or subtype T allocated at (machine) address zero. The
+      --  attribute is allowed only as the default expression of a formal
+      --  parameter, or as an actual expression of a subporgram call. In
+      --  either case, the subprogram must be imported.
+      --
+      --  The identity of the object is represented by the address zero
+      --  in the argument list, independent of the passing mechanism
+      --  (explicit or default).
+      --
+      --  The reason that this capability is needed is that for a record
+      --  or other composite object passed by reference, there is no other
+      --  way of specifying that a zero address should be passed.
+
+      -----------------
+      -- Object_Size --
+      -----------------
+
+      Attribute_Object_Size => True,
+      --
+      --  Type'Object_Size is the same as Type'Size for all types except
+      --  fixed-point types and discrete types. For fixed-point types and
+      --  discrete types, this attribute gives the size used for default
+      --  allocation of objects and components of the size. See section
+      --  in Einfo ("Handling of type'Size values") for further details.
+
+      -------------------------
+      -- Passed_By_Reference --
+      -------------------------
+
+      Attribute_Passed_By_Reference => True,
+      --
+      --  T'Passed_By_Reference for any subtype T returns a boolean value
+      --  that is true if the type is normally passed by reference and
+      --  false if the type is normally passed by copy in calls. For scalar
+      --  types, the result is always False and is static. For non-scalar
+      --  types, the result is non-static (since it is computed by Gigi).
+
+      ------------------
+      -- Range_Length --
+      ------------------
+
+      Attribute_Range_Length => True,
+      --
+      --  T'Range_Length for any discrete type T yields the number of
+      --  values represented by the subtype (zero for a null range). The
+      --  result is static for static subtypes. Note that Range_Length
+      --  applied to the index subtype of a one dimensional array always
+      --  gives the same result as Range applied to the array itself.
+      --  The result is of type universal integer.
+
+      ------------------
+      -- Storage_Unit --
+      ------------------
+
+      Attribute_Storage_Unit => True,
+      --
+      --  Standard'Storage_Unit (Standard is the only permissible prefix)
+      --  provides the value System.Storage_Unit, and is intended primarily
+      --  for constructing this definition in package System (see note above
+      --  in Default_Bit_Order description). The is a static attribute.
+
+      ----------
+      -- Tick --
+      ----------
+
+      Attribute_Tick => True,
+      --
+      --  Standard'Tick (Standard is the only permissible prefix) provides
+      --  the value System.Tick, and is intended primarily for constructing
+      --  this definition in package System (see note above in description
+      --  of Default_Bit_Order). This is a static attribute.
+
+      ----------------
+      -- To_Address --
+      ----------------
+
+      Attribute_To_Address => True,
+      --
+      --  System'To_Address (Address is the only permissible prefix)
+      --  is a function that takes any integer value, and converts it into
+      --  an address value. The semantics is to first convert the integer
+      --  value to type Integer_Address according to normal conversion
+      --  rules, and then to convert this to an address using the same
+      --  semantics as the System.Storage_Elements.To_Address function.
+      --  The important difference is that this is a static attribute
+      --  so it can be used in initializations in preealborate packages.
+
+      ----------------
+      -- Type_Class --
+      ----------------
+
+      Attribute_Type_Class => True,
+      --
+      --  T'Type_Class for any type or subtype T yields the value of the
+      --  type class for the full type of T. If T is a generic formal type,
+      --  then the value is the value for the corresponding actual subtype.
+      --  The value of this attribute is of type System.Aux_DEC.Type_Class,
+      --  which has the following definition:
+      --
+      --    type Type_Class is
+      --      (Type_Class_Enumeration,
+      --       Type_Class_Integer,
+      --       Type_Class_Fixed_Point,
+      --       Type_Class_Floating_Point,
+      --       Type_Class_Array,
+      --       Type_Class_Record,
+      --       Type_Class_Access,
+      --       Type_Class_Task,
+      --       Type_Class_Address);
+      --
+      --  Protected types yield the value Type_Class_Task, which thus
+      --  applies to all concurrent types. This attribute is designed to
+      --  be compatible with the DEC Ada attribute of the same name.
+      --
+      --  Note: if pragma Extend_System is used to merge the definitions of
+      --  Aux_DEC into System, then the type Type_Class can be referenced
+      --  as an entity within System, as can its enumeration literals.
+
+      -----------------
+      -- UET_Address --
+      -----------------
+
+      Attribute_UET_Address => True,
+      --
+      --  Unit'UET_Address, where Unit is a program unit, yields the address
+      --  of the unit exception table for the specified unit. This is only
+      --  used in the internal implementation of exception handling. See the
+      --  implementation of unit Ada.Exceptions for details on its use.
+
+      ------------------------------
+      -- Universal_Literal_String --
+      ------------------------------
+
+      Attribute_Universal_Literal_String => True,
+      --
+      --  The prefix of 'Universal_Literal_String must be a named number.
+      --  The static result is the string consisting of the characters of
+      --  the number as defined in the original source. This allows the
+      --  user program to access the actual text of named numbers without
+      --  intermediate conversions and without the need to enclose the
+      --  strings in quotes (which would preclude their use as numbers).
+      --  This is used internally for the construction of values of the
+      --  floating-point attributes from the file ttypef.ads, but may
+      --  also be used by user programs.
+
+      -------------------------
+      -- Unrestricted_Access --
+      -------------------------
+
+      Attribute_Unrestricted_Access => True,
+      --
+      --  The Unrestricted_Access attribute is similar to Access except that
+      --  all accessibility and aliased view checks are omitted. This is very
+      --  much a user-beware attribute. Basically its status is very similar
+      --  to Address, for which it is a desirable replacement where the value
+      --  desired is an access type. In other words, its effect is identical
+      --  to first taking 'Address and then doing an unchecked conversion to
+      --  a desired access type. Note that in GNAT, but not necessarily in
+      --  other implementations, the use of static chains for inner level
+      --  subprograms means that Unrestricted_Access applied to a subprogram
+      --  yields a value that can be called as long as the subprogram is in
+      --  scope (normal Ada 95 accessibility rules restrict this usage).
+
+      ---------------
+      -- VADS_Size --
+      ---------------
+
+      Attribute_VADS_Size => True,
+      --
+      --  Typ'VADS_Size yields the Size value typically yielded by some
+      --  Ada 83 compilers. The differences between VADS_Size and Size
+      --  is that for scalar types for which no Size has been specified,
+      --  VADS_Size yields the Object_Size rather than the Value_Size.
+      --  For example, while Natural'Size is typically 31, the value of
+      --  Natural'VADS_Size is 32. For all other types, Size and VADS_Size
+      --  yield the same value.
+
+      ----------------
+      -- Value_Size --
+      ----------------
+
+      Attribute_Value_Size => True,
+      --
+      --  Type'Value_Size is the number of bits required to represent a
+      --  value of the given subtype. It is the same as Type'Size, but,
+      --  unlike Size, may be set for non-first subtypes. See section
+      --  in Einfo ("Handling of type'Size values") for further details.
+
+      ---------------
+      -- Word_Size --
+      ---------------
+
+      Attribute_Word_Size => True,
+      --
+      --  Standard'Word_Size (Standard is the only permissible prefix)
+      --  provides the value System.Word_Size, and is intended primarily
+      --  for constructing this definition in package System (see note above
+      --  in Default_Bit_Order description). This is a static attribute.
+
+      others => False);
+
+   -----------------
+   -- Subprograms --
+   -----------------
+
+   procedure Analyze_Attribute (N : Node_Id);
+   --  Performs bottom up semantic analysis of an attribute. Note that the
+   --  parser has already checked that type returning attributes appear only
+   --  in appropriate contexts (i.e. in subtype marks, or as prefixes for
+   --  other attributes).
+
+   procedure Resolve_Attribute (N : Node_Id; Typ : Entity_Id);
+   --  Performs type resolution of attribute. If the attribute yields
+   --  a universal value, mark its type as that of the context. On
+   --  the other hand, if the context itself is universal (as in
+   --  T'Val (T'Pos (X)), mark the type as being the largest type of
+   --  that class that can be used at run-time. This is correct since
+   --  either the value gets folded (in which case it doesn't matter
+   --  what type of the class we give if, since the folding uses universal
+   --  arithmetic anyway) or it doesn't get folded (in which case it is
+   --  going to be dealt with at runtime, and the largest type is right).
+
+end Sem_Attr;
diff --git a/gcc/ada/sem_case.adb b/gcc/ada/sem_case.adb
new file mode 100644 (file)
index 0000000..a9326c3
--- /dev/null
@@ -0,0 +1,681 @@
+------------------------------------------------------------------------------
+--                                                                          --
+--                         GNAT COMPILER COMPONENTS                         --
+--                                                                          --
+--                             S E M _ C A S E                              --
+--                                                                          --
+--                                 B o d y                                  --
+--                                                                          --
+--                            $Revision: 1.13 $
+--                                                                          --
+--          Copyright (C) 1996-2001 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- --
+-- ware  Foundation;  either version 2,  or (at your option) any later ver- --
+-- sion.  GNAT is distributed in the hope that it will be useful, but WITH- --
+-- OUT ANY WARRANTY;  without even the  implied warranty of MERCHANTABILITY --
+-- or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License --
+-- for  more details.  You should have  received  a copy of the GNU General --
+-- Public License  distributed with GNAT;  see file COPYING.  If not, write --
+-- to  the Free Software Foundation,  59 Temple Place - Suite 330,  Boston, --
+-- MA 02111-1307, USA.                                                      --
+--                                                                          --
+-- GNAT was originally developed  by the GNAT team at  New York University. --
+-- It is now maintained by Ada Core Technologies Inc (http://www.gnat.com). --
+--                                                                          --
+------------------------------------------------------------------------------
+
+with Atree;    use Atree;
+with Einfo;    use Einfo;
+with Errout;   use Errout;
+with Namet;    use Namet;
+with Nlists;   use Nlists;
+with Sem;      use Sem;
+with Sem_Eval; use Sem_Eval;
+with Sem_Res;  use Sem_Res;
+with Sem_Util; use Sem_Util;
+with Sem_Type; use Sem_Type;
+with Snames;   use Snames;
+with Stand;    use Stand;
+with Sinfo;    use Sinfo;
+with Uintp;    use Uintp;
+
+with GNAT.Heap_Sort_A; use GNAT.Heap_Sort_A;
+
+package body Sem_Case is
+
+   -----------------------
+   -- Local Subprograms --
+   -----------------------
+
+   type Sort_Choice_Table_Type is array (Nat range <>) of Choice_Bounds;
+   --  This new array type is used as the actual table type for sorting
+   --  discrete choices. The reason for not using Choice_Table_Type, is that
+   --  in Sort_Choice_Table_Type we reserve entry 0 for the sorting algortim
+   --  (this is not absolutely necessary but it makes the code more
+   --  efficient).
+
+   procedure Check_Choices
+     (Choice_Table   : in out Sort_Choice_Table_Type;
+      Bounds_Type    : Entity_Id;
+      Others_Present : Boolean;
+      Msg_Sloc       : Source_Ptr);
+   --  This is the procedure which verifies that a set of case statement,
+   --  array aggregate or record variant choices has no duplicates, and
+   --  covers the range specified by Bounds_Type. Choice_Table contains the
+   --  discrete choices to check. These must start at position 1.
+   --  Furthermore Choice_Table (0) must exist. This element is used by
+   --  the sorting algorithm as a temporary. Others_Present is a flag
+   --  indicating whether or not an Others choice is present. Finally
+   --  Msg_Sloc gives the source location of the construct containing the
+   --  choices in the Choice_Table.
+
+   function Choice_Image (Value : Uint; Ctype : Entity_Id) return Name_Id;
+   --  Given a Pos value of enumeration type Ctype, returns the name
+   --  ID of an appropriate string to be used in error message output.
+
+   -------------------
+   -- Check_Choices --
+   -------------------
+
+   procedure Check_Choices
+     (Choice_Table   : in out Sort_Choice_Table_Type;
+      Bounds_Type    : Entity_Id;
+      Others_Present : Boolean;
+      Msg_Sloc       : Source_Ptr)
+   is
+
+      function Lt_Choice (C1, C2 : Natural) return Boolean;
+      --  Comparison routine for comparing Choice_Table entries.
+      --  Use the lower bound of each Choice as the key.
+
+      procedure Move_Choice (From : Natural; To : Natural);
+      --  Move routine for sorting the Choice_Table.
+
+      procedure Issue_Msg (Value1 : Node_Id; Value2 : Node_Id);
+      procedure Issue_Msg (Value1 : Node_Id; Value2 : Uint);
+      procedure Issue_Msg (Value1 : Uint;    Value2 : Node_Id);
+      procedure Issue_Msg (Value1 : Uint;    Value2 : Uint);
+      --  Issue an error message indicating that there are missing choices,
+      --  followed by the image of the missing choices themselves which lie
+      --  between Value1 and Value2 inclusive.
+
+      ---------------
+      -- Issue_Msg --
+      ---------------
+
+      procedure Issue_Msg (Value1 : Node_Id; Value2 : Node_Id) is
+      begin
+         Issue_Msg (Expr_Value (Value1), Expr_Value (Value2));
+      end Issue_Msg;
+
+      procedure Issue_Msg (Value1 : Node_Id; Value2 : Uint) is
+      begin
+         Issue_Msg (Expr_Value (Value1), Value2);
+      end Issue_Msg;
+
+      procedure Issue_Msg (Value1 : Uint; Value2 : Node_Id) is
+      begin
+         Issue_Msg (Value1, Expr_Value (Value2));
+      end Issue_Msg;
+
+      procedure Issue_Msg (Value1 : Uint; Value2 : Uint) is
+      begin
+         --  In some situations, we call this with a null range, and
+         --  obviously we don't want to complain in this case!
+
+         if Value1 > Value2 then
+            return;
+         end if;
+
+         --  Case of only one value that is missing
+
+         if Value1 = Value2 then
+            if Is_Integer_Type (Bounds_Type) then
+               Error_Msg_Uint_1 := Value1;
+               Error_Msg ("missing case value: ^!", Msg_Sloc);
+            else
+               Error_Msg_Name_1 := Choice_Image (Value1, Bounds_Type);
+               Error_Msg ("missing case value: %!", Msg_Sloc);
+            end if;
+
+         --  More than one choice value, so print range of values
+
+         else
+            if Is_Integer_Type (Bounds_Type) then
+               Error_Msg_Uint_1 := Value1;
+               Error_Msg_Uint_2 := Value2;
+               Error_Msg ("missing case values: ^ .. ^!", Msg_Sloc);
+            else
+               Error_Msg_Name_1 := Choice_Image (Value1, Bounds_Type);
+               Error_Msg_Name_2 := Choice_Image (Value2, Bounds_Type);
+               Error_Msg ("missing case values: % .. %!", Msg_Sloc);
+            end if;
+         end if;
+      end Issue_Msg;
+
+      ---------------
+      -- Lt_Choice --
+      ---------------
+
+      function Lt_Choice (C1, C2 : Natural) return Boolean is
+      begin
+         return
+           Expr_Value (Choice_Table (Nat (C1)).Lo)
+           <= Expr_Value (Choice_Table (Nat (C2)).Lo);
+      end Lt_Choice;
+
+      -----------------
+      -- Move_Choice --
+      -----------------
+
+      procedure Move_Choice (From : Natural; To : Natural) is
+      begin
+         Choice_Table (Nat (To)) := Choice_Table (Nat (From));
+      end Move_Choice;
+
+      --  Variables local to Check_Choices
+
+      Choice      : Node_Id;
+      Bounds_Lo   : constant Node_Id := Type_Low_Bound (Bounds_Type);
+      Bounds_Hi   : constant Node_Id := Type_High_Bound (Bounds_Type);
+
+      Prev_Choice : Node_Id;
+
+      Hi       : Uint;
+      Lo       : Uint;
+      Prev_Hi  : Uint;
+
+   --  Start processing for Check_Choices
+
+   begin
+
+      --  Choice_Table must start at 0 which is an unused location used
+      --  by the sorting algorithm. However the first valid position for
+      --  a discrete choice is 1.
+
+      pragma Assert (Choice_Table'First = 0);
+
+      if Choice_Table'Last = 0 then
+         if not Others_Present then
+            Issue_Msg (Bounds_Lo, Bounds_Hi);
+         end if;
+         return;
+      end if;
+
+      Sort
+        (Positive (Choice_Table'Last),
+         Move_Choice'Unrestricted_Access,
+         Lt_Choice'Unrestricted_Access);
+
+      Lo      := Expr_Value (Choice_Table (1).Lo);
+      Hi      := Expr_Value (Choice_Table (1).Hi);
+      Prev_Hi := Hi;
+
+      if not Others_Present and then Expr_Value (Bounds_Lo) < Lo then
+         Issue_Msg (Bounds_Lo, Lo - 1);
+      end if;
+
+      for J in 2 .. Choice_Table'Last loop
+         Lo := Expr_Value (Choice_Table (J).Lo);
+         Hi := Expr_Value (Choice_Table (J).Hi);
+
+         if Lo <= Prev_Hi then
+            Prev_Choice := Choice_Table (J - 1).Node;
+            Choice      := Choice_Table (J).Node;
+
+            if Sloc (Prev_Choice) <= Sloc (Choice) then
+               Error_Msg_Sloc := Sloc (Prev_Choice);
+               Error_Msg_N ("duplication of choice value#", Choice);
+            else
+               Error_Msg_Sloc := Sloc (Choice);
+               Error_Msg_N ("duplication of choice value#", Prev_Choice);
+            end if;
+
+         elsif not Others_Present and then Lo /= Prev_Hi + 1 then
+            Issue_Msg (Prev_Hi + 1, Lo - 1);
+         end if;
+
+         Prev_Hi := Hi;
+      end loop;
+
+      if not Others_Present and then Expr_Value (Bounds_Hi) > Hi then
+         Issue_Msg (Hi + 1, Bounds_Hi);
+      end if;
+   end Check_Choices;
+
+   ------------------
+   -- Choice_Image --
+   ------------------
+
+   function Choice_Image (Value : Uint; Ctype : Entity_Id) return Name_Id is
+      Rtp : constant Entity_Id := Root_Type (Ctype);
+      Lit : Entity_Id;
+      C   : Int;
+
+   begin
+      --  For character, or wide character. If we are in 7-bit ASCII graphic
+      --  range, then build and return appropriate character literal name
+
+      if Rtp = Standard_Character
+        or else Rtp = Standard_Wide_Character
+      then
+         C := UI_To_Int (Value);
+
+         if C in 16#20# .. 16#7E# then
+            Name_Buffer (1) := ''';
+            Name_Buffer (2) := Character'Val (C);
+            Name_Buffer (3) := ''';
+            Name_Len := 3;
+            return Name_Find;
+         end if;
+
+      --  For user defined enumeration type, find enum/char literal
+
+      else
+         Lit := First_Literal (Rtp);
+
+         for J in 1 .. UI_To_Int (Value) loop
+            Next_Literal (Lit);
+         end loop;
+
+         --  If enumeration literal, just return its value
+
+         if Nkind (Lit) = N_Defining_Identifier then
+            return Chars (Lit);
+
+         --  For character literal, get the name and use it if it is
+         --  for a 7-bit ASCII graphic character in 16#20#..16#7E#.
+
+         else
+            Get_Decoded_Name_String (Chars (Lit));
+
+            if Name_Len = 3
+              and then Name_Buffer (2) in
+                Character'Val (16#20#) .. Character'Val (16#7E#)
+            then
+               return Chars (Lit);
+            end if;
+         end if;
+      end if;
+
+      --  If we fall through, we have a character literal which is not in
+      --  the 7-bit ASCII graphic set. For such cases, we construct the
+      --  name "type'val(nnn)" where type is the choice type, and nnn is
+      --  the pos value passed as an argument to Choice_Image.
+
+      Get_Name_String (Chars (First_Subtype (Ctype)));
+      Name_Len := Name_Len + 1;
+      Name_Buffer (Name_Len) := ''';
+      Name_Len := Name_Len + 1;
+      Name_Buffer (Name_Len) := 'v';
+      Name_Len := Name_Len + 1;
+      Name_Buffer (Name_Len) := 'a';
+      Name_Len := Name_Len + 1;
+      Name_Buffer (Name_Len) := 'l';
+      Name_Len := Name_Len + 1;
+      Name_Buffer (Name_Len) := '(';
+
+      UI_Image (Value);
+
+      for J in 1 .. UI_Image_Length loop
+         Name_Len := Name_Len + 1;
+         Name_Buffer (Name_Len) := UI_Image_Buffer (J);
+      end loop;
+
+      Name_Len := Name_Len + 1;
+      Name_Buffer (Name_Len) := ')';
+      return Name_Find;
+   end Choice_Image;
+
+   -----------
+   -- No_OP --
+   -----------
+
+   procedure No_OP (C : Node_Id) is
+   begin
+      null;
+   end No_OP;
+
+   --------------------------------
+   -- Generic_Choices_Processing --
+   --------------------------------
+
+   package body Generic_Choices_Processing is
+
+      ---------------------
+      -- Analyze_Choices --
+      ---------------------
+
+      procedure Analyze_Choices
+        (N              : Node_Id;
+         Subtyp         : Entity_Id;
+         Choice_Table   : in out Choice_Table_Type;
+         Last_Choice    : out Nat;
+         Raises_CE      : out Boolean;
+         Others_Present : out Boolean)
+      is
+
+         Nb_Choices        : constant Nat := Choice_Table'Length;
+         Sort_Choice_Table : Sort_Choice_Table_Type (0 .. Nb_Choices);
+
+         Choice_Type : constant Entity_Id := Base_Type (Subtyp);
+         --  The actual type against which the discrete choices are
+         --  resolved.  Note that this type is always the base type not the
+         --  subtype of the ruling expression, index or discriminant.
+
+         Bounds_Type : Entity_Id;
+         --  The type from which are derived the bounds of the values
+         --  covered by th discrete choices (see 3.8.1 (4)). If a discrete
+         --  choice specifies a value outside of these bounds we have an error.
+
+         Bounds_Lo   : Uint;
+         Bounds_Hi   : Uint;
+         --  The actual bounds of the above type.
+
+         Expected_Type : Entity_Id;
+         --  The expected type of each choice. Equal to Choice_Type, except
+         --  if the expression is universal,  in which case the choices can
+         --  be of any integer type.
+
+         procedure Check (Choice : Node_Id; Lo, Hi : Node_Id);
+         --  Checks the validity of the bounds of a choice.  When the bounds
+         --  are static and no error occurred the bounds are entered into
+         --  the choices table so that they can be sorted later on.
+
+         -----------
+         -- Check --
+         -----------
+
+         procedure Check (Choice : Node_Id; Lo, Hi : Node_Id) is
+            Lo_Val : Uint;
+            Hi_Val : Uint;
+
+         begin
+            --  First check if an error was already detected on either bounds
+
+            if Etype (Lo) = Any_Type or else Etype (Hi) = Any_Type then
+               return;
+
+            --  Do not insert non static choices in the table to be sorted
+
+            elsif not Is_Static_Expression (Lo)
+              or else not Is_Static_Expression (Hi)
+            then
+               Process_Non_Static_Choice (Choice);
+               return;
+
+            --  Ignore range which raise constraint error
+
+            elsif Raises_Constraint_Error (Lo)
+              or else Raises_Constraint_Error (Hi)
+            then
+               Raises_CE := True;
+               return;
+
+            --  Otherwise we have an OK static choice
+
+            else
+               Lo_Val := Expr_Value (Lo);
+               Hi_Val := Expr_Value (Hi);
+
+               --  Do not insert null ranges in the choices table
+
+               if Lo_Val > Hi_Val then
+                  Process_Empty_Choice (Choice);
+                  return;
+               end if;
+            end if;
+
+            --  Check for bound out of range.
+
+            if Lo_Val < Bounds_Lo then
+               if Is_Integer_Type (Bounds_Type) then
+                  Error_Msg_Uint_1 := Bounds_Lo;
+                  Error_Msg_N ("minimum allowed choice value is^", Lo);
+               else
+                  Error_Msg_Name_1 := Choice_Image (Bounds_Lo, Bounds_Type);
+                  Error_Msg_N ("minimum allowed choice value is%", Lo);
+               end if;
+
+            elsif Hi_Val > Bounds_Hi then
+               if Is_Integer_Type (Bounds_Type) then
+                  Error_Msg_Uint_1 := Bounds_Hi;
+                  Error_Msg_N ("maximum allowed choice value is^", Hi);
+               else
+                  Error_Msg_Name_1 := Choice_Image (Bounds_Hi, Bounds_Type);
+                  Error_Msg_N ("maximum allowed choice value is%", Hi);
+               end if;
+            end if;
+
+            --  We still store the bounds in the table, even if they are out
+            --  of range, since this may prevent unnecessary cascaded errors
+            --  for values that are covered by such an excessive range.
+
+            Last_Choice := Last_Choice + 1;
+            Sort_Choice_Table (Last_Choice).Lo   := Lo;
+            Sort_Choice_Table (Last_Choice).Hi   := Hi;
+            Sort_Choice_Table (Last_Choice).Node := Choice;
+         end Check;
+
+         --  Variables local to Analyze_Choices
+
+         Alt : Node_Id;
+         --  A case statement alternative, an array aggregate component
+         --  association or a variant in a record type declaration
+
+         Choice : Node_Id;
+         Kind   : Node_Kind;
+         --  The node kind of the current Choice.
+
+         E : Entity_Id;
+
+      --  Start of processing for Analyze_Choices
+
+      begin
+         Last_Choice    := 0;
+         Raises_CE      := False;
+         Others_Present := False;
+
+         --  If Subtyp is not a static subtype Ada 95 requires then we use
+         --  the bounds of its base type to determine the values covered by
+         --  the discrete choices.
+
+         if Is_OK_Static_Subtype (Subtyp) then
+            Bounds_Type := Subtyp;
+         else
+            Bounds_Type := Choice_Type;
+         end if;
+
+         --  Obtain static bounds of type, unless this is a generic formal
+         --  discrete type for which all choices will be non-static.
+
+         if not Is_Generic_Type (Root_Type (Bounds_Type))
+           or else Ekind (Bounds_Type) /= E_Enumeration_Type
+         then
+            Bounds_Lo := Expr_Value (Type_Low_Bound (Bounds_Type));
+            Bounds_Hi := Expr_Value (Type_High_Bound (Bounds_Type));
+         end if;
+
+         if Choice_Type = Universal_Integer then
+            Expected_Type := Any_Integer;
+         else
+            Expected_Type := Choice_Type;
+         end if;
+
+         --  Now loop through the case statement alternatives or array
+         --  aggregate component associations or record variants.
+
+         Alt := First (Get_Alternatives (N));
+         while Present (Alt) loop
+
+            --  If pragma, just analyze it
+
+            if Nkind (Alt) = N_Pragma then
+               Analyze (Alt);
+
+            --  Otherwise check each choice against its base type
+
+            else
+               Choice := First (Get_Choices (Alt));
+
+               while Present (Choice) loop
+                  Analyze (Choice);
+                  Kind := Nkind (Choice);
+
+                  --  Choice is a Range
+
+                  if Kind = N_Range
+                    or else (Kind = N_Attribute_Reference
+                             and then Attribute_Name (Choice) = Name_Range)
+                  then
+                     Resolve (Choice, Expected_Type);
+                     Check (Choice, Low_Bound (Choice), High_Bound (Choice));
+
+                  --  Choice is a subtype name
+
+                  elsif Is_Entity_Name (Choice)
+                    and then Is_Type (Entity (Choice))
+                  then
+                     if not Covers (Expected_Type, Etype (Choice)) then
+                        Wrong_Type (Choice, Choice_Type);
+
+                     else
+                        E := Entity (Choice);
+
+                        if not Is_Static_Subtype (E) then
+                           Process_Non_Static_Choice (Choice);
+                        else
+                           Check
+                             (Choice, Type_Low_Bound (E), Type_High_Bound (E));
+                        end if;
+                     end if;
+
+                  --  Choice is a subtype indication
+
+                  elsif Kind = N_Subtype_Indication then
+                     Resolve_Discrete_Subtype_Indication
+                       (Choice, Expected_Type);
+
+                     if Etype (Choice) /= Any_Type then
+                        declare
+                           C : constant Node_Id := Constraint (Choice);
+                           R : constant Node_Id := Range_Expression (C);
+                           L : constant Node_Id := Low_Bound (R);
+                           H : constant Node_Id := High_Bound (R);
+
+                        begin
+                           E := Entity (Subtype_Mark (Choice));
+
+                           if not Is_Static_Subtype (E) then
+                              Process_Non_Static_Choice (Choice);
+
+                           else
+                              if Is_OK_Static_Expression (L)
+                                and then Is_OK_Static_Expression (H)
+                              then
+                                 if Expr_Value (L) > Expr_Value (H) then
+                                    Process_Empty_Choice (Choice);
+                                 else
+                                    if Is_Out_Of_Range (L, E) then
+                                       Apply_Compile_Time_Constraint_Error
+                                         (L, "static value out of range");
+                                    end if;
+
+                                    if Is_Out_Of_Range (H, E) then
+                                       Apply_Compile_Time_Constraint_Error
+                                         (H, "static value out of range");
+                                    end if;
+                                 end if;
+                              end if;
+
+                              Check (Choice, L, H);
+                           end if;
+                        end;
+                     end if;
+
+                  --  The others choice is only allowed for the last
+                  --  alternative and as its only choice.
+
+                  elsif Kind = N_Others_Choice then
+                     if not (Choice = First (Get_Choices (Alt))
+                             and then Choice = Last (Get_Choices (Alt))
+                             and then Alt = Last (Get_Alternatives (N)))
+                     then
+                        Error_Msg_N
+                          ("the choice OTHERS must appear alone and last",
+                           Choice);
+                        return;
+                     end if;
+
+                     Others_Present := True;
+
+                  --  Only other possibility is an expression
+
+                  else
+                     Resolve (Choice, Expected_Type);
+                     Check (Choice, Choice, Choice);
+                  end if;
+
+                  Next (Choice);
+               end loop;
+
+               Process_Associated_Node (Alt);
+            end if;
+
+            Next (Alt);
+         end loop;
+
+         Check_Choices
+           (Sort_Choice_Table (0 .. Last_Choice),
+            Bounds_Type,
+            Others_Present or else (Choice_Type = Universal_Integer),
+            Sloc (N));
+
+         --  Now copy the sorted discrete choices
+
+         for J in 1 .. Last_Choice loop
+            Choice_Table (Choice_Table'First - 1 + J) := Sort_Choice_Table (J);
+         end loop;
+
+      end Analyze_Choices;
+
+      -----------------------
+      -- Number_Of_Choices --
+      -----------------------
+
+      function Number_Of_Choices (N : Node_Id) return Nat is
+         Alt : Node_Id;
+         --  A case statement alternative, an array aggregate component
+         --  association or a record variant.
+
+         Choice : Node_Id;
+         Count  : Nat := 0;
+
+      begin
+         if not Present (Get_Alternatives (N)) then
+            return 0;
+         end if;
+
+         Alt := First_Non_Pragma (Get_Alternatives (N));
+         while Present (Alt) loop
+
+            Choice := First (Get_Choices (Alt));
+            while Present (Choice) loop
+               if Nkind (Choice) /= N_Others_Choice then
+                  Count := Count + 1;
+               end if;
+
+               Next (Choice);
+            end loop;
+
+            Next_Non_Pragma (Alt);
+         end loop;
+
+         return Count;
+      end Number_Of_Choices;
+
+   end Generic_Choices_Processing;
+
+end Sem_Case;
diff --git a/gcc/ada/sem_case.ads b/gcc/ada/sem_case.ads
new file mode 100644 (file)
index 0000000..192b6b1
--- /dev/null
@@ -0,0 +1,122 @@
+------------------------------------------------------------------------------
+--                                                                          --
+--                         GNAT COMPILER COMPONENTS                         --
+--                                                                          --
+--                             S E M _ C A S E                              --
+--                                                                          --
+--                                 S p e c                                  --
+--                                                                          --
+--                            $Revision: 1.5 $                              --
+--                                                                          --
+--            Copyright (C) 1996 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- --
+-- ware  Foundation;  either version 2,  or (at your option) any later ver- --
+-- sion.  GNAT is distributed in the hope that it will be useful, but WITH- --
+-- OUT ANY WARRANTY;  without even the  implied warranty of MERCHANTABILITY --
+-- or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License --
+-- for  more details.  You should have  received  a copy of the GNU General --
+-- Public License  distributed with GNAT;  see file COPYING.  If not, write --
+-- to  the Free Software Foundation,  59 Temple Place - Suite 330,  Boston, --
+-- MA 02111-1307, USA.                                                      --
+--                                                                          --
+-- GNAT was originally developed  by the GNAT team at  New York University. --
+-- It is now maintained by Ada Core Technologies Inc (http://www.gnat.com). --
+--                                                                          --
+------------------------------------------------------------------------------
+
+with Types; use Types;
+
+--  Package containing all the routines to proces a list of discrete choices.
+--  Such lists can occur in 3 different constructs: case statements, array
+--  aggregates and record variants. We have factorized what used to be 3 very
+--  similar sets of routines here. If you didn't figure it out already Choi
+--  in the package name stands for Choices.
+
+package Sem_Case is
+
+   type Choice_Bounds is record
+     Lo   : Node_Id;
+     Hi   : Node_Id;
+     Node : Node_Id;
+   end record;
+
+   type Choice_Table_Type is array (Pos range <>) of Choice_Bounds;
+   --  Table type used to sort the choices present in a case statement,
+   --  array aggregate or record variant.
+
+   procedure No_OP (C : Node_Id);
+   --  The no-operation routine. Does absolutely nothing. Can be used
+   --  in the following generic for the parameter Proces_Empty_Choice.
+
+   generic
+      with function Get_Alternatives (N : Node_Id) return List_Id;
+      --  Function needed to get to the actual list of case statement
+      --  alternatives, or array aggregate component associations or
+      --  record variants from which we can then access the actual lists
+      --  of discrete choices. N is the node for the original construct
+      --  ie a case statement, an array aggregate or a record variant.
+
+      with function Get_Choices (A : Node_Id) return List_Id;
+      --  Given a case statement alternative, array aggregate component
+      --  association or record variant A we need different access functions
+      --  to get to the actual list of discrete choices.
+
+      with procedure Process_Empty_Choice (Choice : Node_Id);
+      --  Processing to carry out for an empty Choice.
+
+      with procedure Process_Non_Static_Choice (Choice : Node_Id);
+      --  Processing to carry out for a non static Choice.
+
+      with procedure Process_Associated_Node (A : Node_Id);
+      --  Associated to each case alternative, aggregate component
+      --  association or record variant A there is a node or list of nodes
+      --  that need semantic processing. This routine implements that
+      --  processing.
+
+   package Generic_Choices_Processing is
+
+      function Number_Of_Choices (N : Node_Id) return Nat;
+      --  Iterates through the choices of N, (N can be a case statement,
+      --  array aggregate or record variant), counting all the Choice nodes
+      --  except for the Others choice.
+
+      procedure Analyze_Choices
+        (N              : Node_Id;
+         Subtyp         : Entity_Id;
+         Choice_Table   : in out Choice_Table_Type;
+         Last_Choice    : out Nat;
+         Raises_CE      : out Boolean;
+         Others_Present : out Boolean);
+      --  From a case statement, array aggregate or record variant N, this
+      --  routine analyzes the corresponding list of discrete choices.
+      --  Subtyp is the subtype of the discrete choices. The type against
+      --  which the discrete choices must be resolved is its base type.
+      --
+      --  On entry Choice_Table must be big enough to contain all the
+      --  discrete choices encountered.
+      --
+      --  On exit Choice_Table contains all the static and non empty
+      --  discrete choices in sorted order. Last_Choice gives the position
+      --  of the last valid choice in Choice_Table, Choice_Table'First
+      --  contains the first. We can have Last_Choice < Choice_Table'Last
+      --  for one (or several) of the following reasons:
+      --
+      --    (a) The list of choices contained a non static choice
+      --
+      --    (b) The list of choices contained an empty choice
+      --        (something like "1 .. 0 => ")
+      --
+      --    (c) One of the bounds of a discrete choice contains an
+      --        error or raises constraint error.
+      --
+      --  In one of the bounds of a discrete choice raises a constraint
+      --  error the flag Raise_CE is set.
+      --
+      --  Finally Others_Present is set to True if an Others choice is
+      --  present in the list of choices.
+
+   end Generic_Choices_Processing;
+
+end Sem_Case;
diff --git a/gcc/ada/sem_cat.adb b/gcc/ada/sem_cat.adb
new file mode 100644 (file)
index 0000000..29c48a5
--- /dev/null
@@ -0,0 +1,1804 @@
+------------------------------------------------------------------------------
+--                                                                          --
+--                         GNAT COMPILER COMPONENTS                         --
+--                                                                          --
+--                              S E M _ C A T                               --
+--                                                                          --
+--                                 B o d y                                  --
+--                                                                          --
+--                            $Revision: 1.57 $
+--                                                                          --
+--          Copyright (C) 1992-2001, 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- --
+-- ware  Foundation;  either version 2,  or (at your option) any later ver- --
+-- sion.  GNAT is distributed in the hope that it will be useful, but WITH- --
+-- OUT ANY WARRANTY;  without even the  implied warranty of MERCHANTABILITY --
+-- or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License --
+-- for  more details.  You should have  received  a copy of the GNU General --
+-- Public License  distributed with GNAT;  see file COPYING.  If not, write --
+-- to  the Free Software Foundation,  59 Temple Place - Suite 330,  Boston, --
+-- MA 02111-1307, USA.                                                      --
+--                                                                          --
+-- GNAT was originally developed  by the GNAT team at  New York University. --
+-- It is now maintained by Ada Core Technologies Inc (http://www.gnat.com). --
+--                                                                          --
+------------------------------------------------------------------------------
+
+with Atree;    use Atree;
+with Debug;    use Debug;
+with Einfo;    use Einfo;
+with Elists;   use Elists;
+with Errout;   use Errout;
+with Exp_Tss;  use Exp_Tss;
+with Fname;    use Fname;
+with Lib;      use Lib;
+with Nlists;   use Nlists;
+with Sem;      use Sem;
+with Sem_Util; use Sem_Util;
+with Sinfo;    use Sinfo;
+with Snames;   use Snames;
+with Stand;    use Stand;
+
+package body Sem_Cat is
+
+   -----------------------
+   -- Local Subprograms --
+   -----------------------
+
+   procedure Check_Categorization_Dependencies
+     (Unit_Entity     : Entity_Id;
+      Depended_Entity : Entity_Id;
+      Info_Node       : Node_Id;
+      Is_Subunit      : Boolean);
+   --  This procedure checks that the categorization of a lib unit and that
+   --  of the depended unit satisfy dependency restrictions.
+   --  The depended_entity can be the entity in a with_clause item, in which
+   --  case Info_Node denotes that item. The depended_entity can also be the
+   --  parent unit of a child unit, in which case Info_Node is the declaration
+   --  of the child unit.  The error message is posted on Info_Node, and is
+   --  specialized if Is_Subunit is true.
+
+   procedure Check_Non_Static_Default_Expr
+     (Type_Def : Node_Id;
+      Obj_Decl : Node_Id);
+   --  Iterate through the component list of a record definition, check
+   --  that no component is declared with a nonstatic default value.
+   --  If a nonstatic default exists, report an error on Obj_Decl.
+
+   --  Iterate through the component list of a record definition, check
+   --  that no component is declared with a non-static default value.
+
+   function Missing_Read_Write_Attributes (E : Entity_Id) return Boolean;
+   --  Return True if the entity or one of its subcomponent is an access
+   --  type which does not have user-defined Read and Write attribute.
+
+   function In_RCI_Declaration (N : Node_Id) return Boolean;
+   --  Determines if a declaration is  within the visible part of  a Remote
+   --  Call Interface compilation unit, for semantic checking purposes only,
+   --  (returns false within an instance and within the package body).
+
+   function In_RT_Declaration return Boolean;
+   --  Determines if current scope is within a Remote Types compilation unit,
+   --  for semantic checking purposes.
+
+   function Is_Non_Remote_Access_Type (E : Entity_Id) return Boolean;
+   --  Returns true if the entity is a non-remote access type
+
+   function In_Shared_Passive_Unit return Boolean;
+   --  Determines if current scope is within a Shared Passive compilation unit
+
+   function Static_Discriminant_Expr (L : List_Id) return Boolean;
+   --  Iterate through the list of discriminants to check if any of them
+   --  contains non-static default expression, which is a violation in
+   --  a preelaborated library unit.
+
+   procedure Validate_Remote_Access_Object_Type_Declaration (T : Entity_Id);
+   --  Check validity of declaration if RCI unit. It should not contain
+   --  the declaration of an access-to-object type unless it is a
+   --  general access type that designates a class-wide limited
+   --  private type. There are also constraints about the primitive
+   --  subprograms of the class-wide type. RM E.2 (9, 13, 14)
+
+   function Is_Recursively_Limited_Private (E : Entity_Id) return Boolean;
+   --  Return True if E is a limited private type, or if E is a private
+   --  extension of a type whose parent verifies this property (hence the
+   --  recursive keyword).
+
+   ---------------------------------------
+   -- Check_Categorization_Dependencies --
+   ---------------------------------------
+
+   procedure Check_Categorization_Dependencies
+     (Unit_Entity     : Entity_Id;
+      Depended_Entity : Entity_Id;
+      Info_Node       : Node_Id;
+      Is_Subunit      : Boolean)
+   is
+      N                  : Node_Id := Info_Node;
+
+      type Categorization is
+         (Pure, Shared_Passive, Remote_Types,
+           Remote_Call_Interface, Pre_Elaborated, Normal);
+
+      Unit_Category : Categorization;
+      With_Category : Categorization;
+
+      function Get_Categorization (E : Entity_Id) return Categorization;
+      --  Check categorization flags from entity, and return in the form
+      --  of a corresponding enumeration value.
+
+      function Get_Categorization (E : Entity_Id) return Categorization is
+      begin
+         if Is_Preelaborated (E) then
+            return Pre_Elaborated;
+         elsif Is_Pure (E) then
+            return Pure;
+         elsif Is_Shared_Passive (E) then
+            return Shared_Passive;
+         elsif Is_Remote_Types (E) then
+            return Remote_Types;
+         elsif Is_Remote_Call_Interface (E) then
+            return Remote_Call_Interface;
+         else
+            return Normal;
+         end if;
+      end Get_Categorization;
+
+   --  Start of processing for Check_Categorization_Dependencies
+
+   begin
+      --  Intrinsic subprograms are preelaborated, so do not impose any
+      --  categorization dependencies.
+
+      if Is_Intrinsic_Subprogram (Depended_Entity) then
+         return;
+      end if;
+
+      Unit_Category := Get_Categorization (Unit_Entity);
+      With_Category := Get_Categorization (Depended_Entity);
+
+      if With_Category > Unit_Category then
+
+         if (Unit_Category = Remote_Types
+                 or else Unit_Category = Remote_Call_Interface)
+           and then In_Package_Body (Unit_Entity)
+         then
+            null;
+
+         elsif Is_Subunit then
+            Error_Msg_NE ("subunit cannot depend on&"
+              & " (parent has wrong categorization)", N, Depended_Entity);
+         else
+            Error_Msg_NE ("current unit cannot depend on&"
+              & " (wrong categorization)", N, Depended_Entity);
+         end if;
+      end if;
+
+   end Check_Categorization_Dependencies;
+
+   -----------------------------------
+   -- Check_Non_Static_Default_Expr --
+   -----------------------------------
+
+   procedure Check_Non_Static_Default_Expr
+     (Type_Def : Node_Id;
+      Obj_Decl : Node_Id)
+   is
+      Recdef         : Node_Id;
+      Component_Decl : Node_Id;
+
+   begin
+      if Nkind (Type_Def) = N_Derived_Type_Definition then
+         Recdef := Record_Extension_Part (Type_Def);
+
+         if No (Recdef) then
+            return;
+         end if;
+
+      else
+         Recdef := Type_Def;
+      end if;
+
+      --  Check that component declarations do not involve:
+
+      --    a. a non-static default expression, where the object is
+      --       declared to be default initialized.
+
+      --    b. a dynamic Itype (discriminants and constraints)
+
+      if Null_Present (Recdef) then
+         return;
+      else
+         Component_Decl := First (Component_Items (Component_List (Recdef)));
+      end if;
+
+      while Present (Component_Decl)
+        and then Nkind (Component_Decl) = N_Component_Declaration
+      loop
+         if Present (Expression (Component_Decl))
+           and then Nkind (Expression (Component_Decl)) /= N_Null
+           and then not Is_Static_Expression (Expression (Component_Decl))
+         then
+            Error_Msg_Sloc := Sloc (Component_Decl);
+            Error_Msg_N
+              ("object in preelaborated unit has nonstatic default#",
+               Obj_Decl);
+
+         --  Fix this later ???
+
+         --  elsif Has_Dynamic_Itype (Component_Decl) then
+         --     Error_Msg_N
+         --       ("dynamic type discriminant," &
+         --        " constraint in preelaborated unit",
+         --        Component_Decl);
+         end if;
+
+         Next (Component_Decl);
+      end loop;
+   end Check_Non_Static_Default_Expr;
+
+   ---------------------------
+   -- In_Preelaborated_Unit --
+   ---------------------------
+
+   function In_Preelaborated_Unit return Boolean is
+      Unit_Entity : constant Entity_Id := Current_Scope;
+      Unit_Kind   : constant Node_Kind :=
+                      Nkind (Unit (Cunit (Current_Sem_Unit)));
+
+   begin
+      --  There are no constraints on body of remote_call_interface or
+      --  remote_types packages..
+
+      return (Unit_Entity /= Standard_Standard)
+        and then (Is_Preelaborated (Unit_Entity)
+                    or else Is_Pure (Unit_Entity)
+                    or else Is_Shared_Passive (Unit_Entity)
+                    or else
+                      ((Is_Remote_Types (Unit_Entity)
+                               or else Is_Remote_Call_Interface (Unit_Entity))
+                         and then Ekind (Unit_Entity) = E_Package
+                         and then Unit_Kind /= N_Package_Body
+                         and then not In_Package_Body (Unit_Entity)
+                         and then not In_Instance));
+   end In_Preelaborated_Unit;
+
+   ------------------
+   -- In_Pure_Unit --
+   ------------------
+
+   function In_Pure_Unit return Boolean is
+   begin
+      return Is_Pure (Current_Scope);
+   end In_Pure_Unit;
+
+   ------------------------
+   -- In_RCI_Declaration --
+   ------------------------
+
+   function In_RCI_Declaration (N : Node_Id) return Boolean is
+      Unit_Entity : constant Entity_Id := Current_Scope;
+      Unit_Kind   : constant Node_Kind :=
+                      Nkind (Unit (Cunit (Current_Sem_Unit)));
+
+   begin
+      --  There are no restrictions on the private part or body
+      --  of an RCI unit.
+
+      return Is_Remote_Call_Interface (Unit_Entity)
+        and then (Ekind (Unit_Entity) = E_Package
+                  or else Ekind (Unit_Entity) = E_Generic_Package)
+        and then Unit_Kind /= N_Package_Body
+        and then List_Containing (N) =
+                  Visible_Declarations
+                    (Specification (Unit_Declaration_Node (Unit_Entity)))
+        and then not In_Package_Body (Unit_Entity)
+        and then not In_Instance;
+   end In_RCI_Declaration;
+
+   -----------------------
+   -- In_RT_Declaration --
+   -----------------------
+
+   function In_RT_Declaration return Boolean is
+      Unit_Entity : constant Entity_Id := Current_Scope;
+      Unit_Kind   : constant Node_Kind :=
+                      Nkind (Unit (Cunit (Current_Sem_Unit)));
+
+   begin
+      --  There are no restrictions on the body of a Remote Types unit.
+
+      return Is_Remote_Types (Unit_Entity)
+        and then (Ekind (Unit_Entity) = E_Package
+                   or else Ekind (Unit_Entity) = E_Generic_Package)
+        and then Unit_Kind /= N_Package_Body
+        and then not In_Package_Body (Unit_Entity)
+        and then not In_Instance;
+   end In_RT_Declaration;
+
+   ----------------------------
+   -- In_Shared_Passive_Unit --
+   ----------------------------
+
+   function In_Shared_Passive_Unit return Boolean is
+      Unit_Entity : constant Entity_Id := Current_Scope;
+
+   begin
+      return Is_Shared_Passive (Unit_Entity);
+   end In_Shared_Passive_Unit;
+
+   ---------------------------------------
+   -- In_Subprogram_Task_Protected_Unit --
+   ---------------------------------------
+
+   function In_Subprogram_Task_Protected_Unit return Boolean is
+      E : Entity_Id;
+      K : Entity_Kind;
+
+   begin
+      --  The following is to verify that a declaration is inside
+      --  subprogram, generic subprogram, task unit, protected unit.
+      --  Used to validate if a lib. unit is Pure. RM 10.2.1(16).
+
+      --  Use scope chain to check successively outer scopes
+
+      E := Current_Scope;
+      loop
+         K := Ekind (E);
+
+         if        K = E_Procedure
+           or else K = E_Function
+           or else K = E_Generic_Procedure
+           or else K = E_Generic_Function
+           or else K = E_Task_Type
+           or else K = E_Task_Subtype
+           or else K = E_Protected_Type
+           or else K = E_Protected_Subtype
+         then
+            return True;
+
+         elsif E = Standard_Standard then
+            return False;
+         end if;
+
+         E := Scope (E);
+      end loop;
+
+   end In_Subprogram_Task_Protected_Unit;
+
+   -------------------------------
+   -- Is_Non_Remote_Access_Type --
+   -------------------------------
+
+   function Is_Non_Remote_Access_Type (E : Entity_Id) return Boolean is
+   begin
+      return Is_Access_Type (E)
+        and then not Is_Remote_Access_To_Class_Wide_Type (E)
+        and then not Is_Remote_Access_To_Subprogram_Type (E);
+   end Is_Non_Remote_Access_Type;
+
+   ------------------------------------
+   -- Is_Recursively_Limited_Private --
+   ------------------------------------
+
+   function Is_Recursively_Limited_Private (E : Entity_Id) return Boolean is
+      P : constant Node_Id := Parent (E);
+
+   begin
+      if Nkind (P) = N_Private_Type_Declaration
+        and then Is_Limited_Record (E)
+      then
+         return True;
+      elsif Nkind (P) = N_Private_Extension_Declaration then
+         return Is_Recursively_Limited_Private (Etype (E));
+      elsif Nkind (P) = N_Formal_Type_Declaration
+        and then Ekind (E) = E_Record_Type_With_Private
+        and then Is_Generic_Type (E)
+        and then Is_Limited_Record (E)
+      then
+         return True;
+      else
+         return False;
+      end if;
+   end Is_Recursively_Limited_Private;
+
+   ----------------------------------
+   -- Missing_Read_Write_Attribute --
+   ----------------------------------
+
+   function Missing_Read_Write_Attributes (E : Entity_Id) return Boolean is
+      Component      : Entity_Id;
+      Component_Type : Entity_Id;
+
+      function Has_Read_Write_Attributes (E : Entity_Id) return Boolean;
+      --  Return True if entity has Read and Write attributes
+
+      -------------------------------
+      -- Has_Read_Write_Attributes --
+      -------------------------------
+
+      function Has_Read_Write_Attributes (E : Entity_Id) return Boolean is
+         Rep_Item        : Node_Id := First_Rep_Item (E);
+         Read_Attribute  : Boolean := False;
+         Write_Attribute : Boolean := False;
+
+      begin
+         --  We start from the declaration node and then loop until the end
+         --  of the list until we find those two attribute definition clauses.
+
+         while Present (Rep_Item) loop
+            if Chars (Rep_Item) = Name_Read then
+               Read_Attribute := True;
+            elsif Chars (Rep_Item) = Name_Write then
+               Write_Attribute := True;
+            end if;
+
+            if Read_Attribute and Write_Attribute then
+               return True;
+            end if;
+
+            Next_Rep_Item (Rep_Item);
+         end loop;
+
+         return False;
+      end Has_Read_Write_Attributes;
+
+   --  Start of processing for Missing_Read_Write_Attributes
+
+   begin
+      if Has_Read_Write_Attributes (E) then
+         return False;
+      elsif Is_Non_Remote_Access_Type (E) then
+         return True;
+      end if;
+
+      if Is_Record_Type (E) then
+         Component := First_Entity (E);
+         while Present (Component) loop
+            Component_Type := Etype (Component);
+
+            if (Is_Non_Remote_Access_Type (Component_Type)
+                or else Is_Record_Type (Component_Type))
+              and then Missing_Read_Write_Attributes (Component_Type)
+            then
+               return True;
+            end if;
+
+            Next_Entity (Component);
+         end loop;
+      end if;
+
+      return False;
+   end Missing_Read_Write_Attributes;
+
+   -------------------------------------
+   -- Set_Categorization_From_Pragmas --
+   -------------------------------------
+
+   procedure Set_Categorization_From_Pragmas (N : Node_Id) is
+      P   : constant Node_Id := Parent (N);
+      S   : constant Entity_Id := Current_Scope;
+
+      procedure Set_Parents (Visibility : Boolean);
+         --  If this is a child instance, the parents are not immediately
+         --  visible during analysis. Make them momentarily visible so that
+         --  the argument of the pragma can be resolved properly, and reset
+         --  afterwards.
+
+      procedure Set_Parents (Visibility : Boolean) is
+         Par : Entity_Id := Scope (S);
+
+      begin
+         while Present (Par) and then Par /= Standard_Standard loop
+            Set_Is_Immediately_Visible (Par, Visibility);
+            Par := Scope (Par);
+         end loop;
+      end Set_Parents;
+
+   begin
+      --  Deal with categorization pragmas in Pragmas of Compilation_Unit.
+      --  The purpose is to set categorization flags before analyzing the
+      --  unit itself, so as to diagnose violations of categorization as
+      --  we process each declaration, even though the pragma appears after
+      --  the unit.
+
+      if Nkind (P) /= N_Compilation_Unit then
+         return;
+      end if;
+
+      declare
+         PN : Node_Id := First (Pragmas_After (Aux_Decls_Node (P)));
+
+      begin
+
+         if Is_Child_Unit (S)
+           and then Is_Generic_Instance (S)
+         then
+            Set_Parents (True);
+         end if;
+
+         while Present (PN) loop
+
+            --  Skip implicit types that may have been introduced by
+            --  previous analysis.
+
+            if Nkind (PN) = N_Pragma then
+
+               case Get_Pragma_Id (Chars (PN)) is
+                  when Pragma_All_Calls_Remote   |
+                    Pragma_Preelaborate          |
+                    Pragma_Pure                  |
+                    Pragma_Remote_Call_Interface |
+                    Pragma_Remote_Types          |
+                    Pragma_Shared_Passive        => Analyze (PN);
+                  when others                    => null;
+               end case;
+            end if;
+
+            Next (PN);
+         end loop;
+         if Is_Child_Unit (S)
+           and then Is_Generic_Instance (S)
+         then
+            Set_Parents (False);
+         end if;
+
+      end;
+   end Set_Categorization_From_Pragmas;
+
+   ------------------------------
+   -- Static_Discriminant_Expr --
+   ------------------------------
+
+   function Static_Discriminant_Expr (L : List_Id) return Boolean is
+      Discriminant_Spec : Node_Id;
+
+   begin
+      Discriminant_Spec := First (L);
+      while Present (Discriminant_Spec) loop
+         if Present (Expression (Discriminant_Spec))
+           and then not Is_Static_Expression (Expression (Discriminant_Spec))
+         then
+            return False;
+         end if;
+
+         Next (Discriminant_Spec);
+      end loop;
+
+      return True;
+   end Static_Discriminant_Expr;
+
+   --------------------------------------
+   -- Validate_Access_Type_Declaration --
+   --------------------------------------
+
+   procedure Validate_Access_Type_Declaration (T : Entity_Id; N : Node_Id) is
+      Def : constant Node_Id := Type_Definition (N);
+
+   begin
+      case Nkind (Def) is
+         when N_Access_To_Subprogram_Definition =>
+
+            --  A pure library_item must not contain the declaration of a
+            --  named access type, except within a subprogram, generic
+            --  subprogram, task unit, or protected unit (RM 10.2.1(16)).
+
+            if Comes_From_Source (T)
+               and then In_Pure_Unit
+               and then not In_Subprogram_Task_Protected_Unit
+            then
+               Error_Msg_N ("named access type not allowed in pure unit", T);
+            end if;
+
+         when N_Access_To_Object_Definition =>
+
+            if Comes_From_Source (T)
+              and then In_Pure_Unit
+              and then not In_Subprogram_Task_Protected_Unit
+            then
+               Error_Msg_N
+                 ("named access type not allowed in pure unit", T);
+            end if;
+
+            --  Check for RCI unit type declaration. It should not contain
+            --  the declaration of an access-to-object type unless it is a
+            --  general access type that designates a class-wide limited
+            --  private type. There are also constraints about the primitive
+            --  subprograms of the class-wide type.
+
+            Validate_Remote_Access_Object_Type_Declaration (T);
+
+            --  Check for shared passive unit type declaration. It should
+            --  not contain the declaration of access to class wide type,
+            --  access to task type and access to protected type with entry.
+
+            Validate_SP_Access_Object_Type_Decl (T);
+
+         when others => null;
+      end case;
+
+      --  Set Categorization flag of package on entity as well, to allow
+      --  easy checks later on for required validations of RCI units. This
+      --  is only done for entities that are in the original source.
+
+      if Comes_From_Source (T) then
+         if Is_Remote_Call_Interface (Scope (T))
+           and then not In_Package_Body (Scope (T))
+         then
+            Set_Is_Remote_Call_Interface (T);
+         end if;
+
+         if Is_Remote_Types (Scope (T))
+           and then not In_Package_Body (Scope (T))
+         then
+            Set_Is_Remote_Types (T);
+         end if;
+      end if;
+   end Validate_Access_Type_Declaration;
+
+   ----------------------------
+   -- Validate_Ancestor_Part --
+   ----------------------------
+
+   procedure Validate_Ancestor_Part (N : Node_Id) is
+      A : constant Node_Id := Ancestor_Part (N);
+      T : Entity_Id        := Entity (A);
+
+   begin
+      if In_Preelaborated_Unit
+        and then not In_Subprogram_Or_Concurrent_Unit
+        and then (not Inside_A_Generic
+                   or else Present (Enclosing_Generic_Body (N)))
+      then
+         --  We relax the restriction of 10.2.1(9) within GNAT
+         --  units to allow packages such as Ada.Strings.Unbounded
+         --  to be implemented (i.p., Null_Unbounded_String).
+         --  (There are ACVC tests that check that the restriction
+         --  is enforced, but note that AI-161, once approved,
+         --  will relax the restriction prohibiting default-
+         --  initialized objects of private and controlled
+         --  types.)
+
+         if Is_Private_Type (T)
+           and then not Is_Internal_File_Name
+                          (Unit_File_Name (Get_Source_Unit (N)))
+         then
+            Error_Msg_N
+              ("private ancestor type not allowed in preelaborated unit", A);
+
+         elsif Is_Record_Type (T) then
+            if Nkind (Parent (T)) = N_Full_Type_Declaration then
+               Check_Non_Static_Default_Expr
+                 (Type_Definition (Parent (T)), A);
+            end if;
+         end if;
+      end if;
+   end Validate_Ancestor_Part;
+
+   ----------------------------------------
+   -- Validate_Categorization_Dependency --
+   ----------------------------------------
+
+   procedure Validate_Categorization_Dependency
+     (N : Node_Id;
+      E : Entity_Id)
+   is
+      K          : constant Node_Kind := Nkind (N);
+      P          : Node_Id            := Parent (N);
+      U          : Entity_Id := E;
+      Is_Subunit : constant Boolean := Nkind (P) = N_Subunit;
+
+   begin
+      --  Only validate library units and subunits. For subunits, checks
+      --  concerning withed units apply to the parent compilation unit.
+
+      if Is_Subunit then
+         P := Parent (P);
+         U := Scope (E);
+
+         while Present (U)
+           and then not Is_Compilation_Unit (U)
+           and then not Is_Child_Unit (U)
+         loop
+            U := Scope (U);
+         end loop;
+
+      end if;
+
+      if Nkind (P) /= N_Compilation_Unit then
+         return;
+      end if;
+
+      --  Body of RCI unit does not need validation.
+
+      if Is_Remote_Call_Interface (E)
+        and then (Nkind (N) = N_Package_Body
+                   or else Nkind (N) = N_Subprogram_Body)
+      then
+         return;
+      end if;
+
+      --  Process with clauses
+
+      declare
+         Item             : Node_Id;
+         Entity_Of_Withed : Entity_Id;
+
+      begin
+         Item := First (Context_Items (P));
+
+         while Present (Item) loop
+            if Nkind (Item) = N_With_Clause
+              and then not Implicit_With (Item)
+            then
+               Entity_Of_Withed := Entity (Name (Item));
+               Check_Categorization_Dependencies
+                (U, Entity_Of_Withed, Item, Is_Subunit);
+            end if;
+
+            Next (Item);
+         end loop;
+      end;
+
+      --  Child depends on parent; therefore parent should also
+      --  be categorized and satify the dependency hierarchy.
+
+      --  Check if N is a child spec.
+
+      if (K in N_Generic_Declaration              or else
+          K in N_Generic_Instantiation            or else
+          K in N_Generic_Renaming_Declaration     or else
+          K =  N_Package_Declaration              or else
+          K =  N_Package_Renaming_Declaration     or else
+          K =  N_Subprogram_Declaration           or else
+          K =  N_Subprogram_Renaming_Declaration)
+        and then Present (Parent_Spec (N))
+      then
+         declare
+            Parent_Lib_U  : constant Node_Id   := Parent_Spec (N);
+            Parent_Kind   : constant Node_Kind :=
+                              Nkind (Unit (Parent_Lib_U));
+            Parent_Entity : Entity_Id;
+
+         begin
+            if        Parent_Kind =  N_Package_Instantiation
+              or else Parent_Kind =  N_Procedure_Instantiation
+              or else Parent_Kind =  N_Function_Instantiation
+              or else Parent_Kind =  N_Package_Renaming_Declaration
+              or else Parent_Kind in N_Generic_Renaming_Declaration
+            then
+               Parent_Entity := Defining_Entity (Unit (Parent_Lib_U));
+
+            else
+               Parent_Entity :=
+                 Defining_Entity (Specification (Unit (Parent_Lib_U)));
+            end if;
+
+            Check_Categorization_Dependencies (E, Parent_Entity, N, False);
+
+            --  Verify that public child of an RCI library unit
+            --  must also be an RCI library unit (RM E.2.3(15)).
+
+            if Is_Remote_Call_Interface (Parent_Entity)
+              and then not Private_Present (P)
+              and then not Is_Remote_Call_Interface (E)
+            then
+               Error_Msg_N
+                 ("public child of rci unit must also be rci unit", N);
+               return;
+            end if;
+         end;
+      end if;
+
+   end Validate_Categorization_Dependency;
+
+   --------------------------------
+   -- Validate_Controlled_Object --
+   --------------------------------
+
+   procedure Validate_Controlled_Object (E : Entity_Id) is
+   begin
+      --  For now, never apply this check for internal GNAT units, since we
+      --  have a number of cases in the library where we are stuck with objects
+      --  of this type, and the RM requires Preelaborate.
+
+      --  For similar reasons, we only do this check for source entities, since
+      --  we generate entities of this type in some situations.
+
+      --  Note that the 10.2.1(9) restrictions are not relevant to us anyway.
+      --  We have to enforce them for RM compatibility, but we have no trouble
+      --  accepting these objects and doing the right thing. Note that there is
+      --  no requirement that Preelaborate not actually generate any code!
+
+      if In_Preelaborated_Unit
+        and then not Debug_Flag_PP
+        and then Comes_From_Source (E)
+        and then not
+          Is_Internal_File_Name (Unit_File_Name (Get_Source_Unit (E)))
+        and then (not Inside_A_Generic
+                   or else Present (Enclosing_Generic_Body (E)))
+        and then not Is_Protected_Type (Etype (E))
+      then
+         Error_Msg_N
+           ("library level controlled object not allowed in " &
+            "preelaborated unit", E);
+      end if;
+   end Validate_Controlled_Object;
+
+   --------------------------------------
+   -- Validate_Null_Statement_Sequence --
+   --------------------------------------
+
+   procedure Validate_Null_Statement_Sequence (N : Node_Id) is
+      Item : Node_Id;
+
+   begin
+      if In_Preelaborated_Unit then
+         Item := First (Statements (Handled_Statement_Sequence (N)));
+
+         while Present (Item) loop
+            if Nkind (Item) /= N_Label
+              and then Nkind (Item) /= N_Null_Statement
+            then
+               Error_Msg_N
+                 ("statements not allowed in preelaborated unit", Item);
+               exit;
+            end if;
+
+            Next (Item);
+         end loop;
+      end if;
+   end Validate_Null_Statement_Sequence;
+
+   ---------------------------------
+   -- Validate_Object_Declaration --
+   ---------------------------------
+
+   procedure Validate_Object_Declaration (N : Node_Id) is
+      Id  : constant Entity_Id  := Defining_Identifier (N);
+      E   : constant Node_Id    := Expression (N);
+      Odf : constant Node_Id    := Object_Definition (N);
+      T   : constant Entity_Id  := Etype (Id);
+
+   begin
+      --  Verify that any access to subprogram object does not have in its
+      --  subprogram profile access type parameters or limited parameters
+      --  without Read and Write attributes (E.2.3(13)).
+
+      Validate_RCI_Subprogram_Declaration (N);
+
+      --  Check that if we are in preelaborated elaboration code, then we
+      --  do not have an instance of a default initialized private, task or
+      --  protected object declaration which would violate (RM 10.2.1(9)).
+      --  Note that constants are never default initialized (and the test
+      --  below also filters out deferred constants). A variable is default
+      --  initialized if it does *not* have an initialization expression.
+
+      --  Filter out cases that are not declaration of a variable from source
+
+      if Nkind (N) /= N_Object_Declaration
+        or else Constant_Present (N)
+        or else not Comes_From_Source (Id)
+      then
+         return;
+      end if;
+
+      --  Exclude generic specs from the checks (this will get rechecked
+      --  on instantiations).
+
+      if Inside_A_Generic
+        and then not Present (Enclosing_Generic_Body (Id))
+      then
+         return;
+      end if;
+
+      --  Required checks for declaration that is in a preelaborated
+      --  package and is not within some subprogram.
+
+      if In_Preelaborated_Unit
+        and then not In_Subprogram_Or_Concurrent_Unit
+      then
+         --  Check for default initialized variable case. Note that in
+         --  accordance with (RM B.1(24)) imported objects are not
+         --  subject to default initialization.
+
+         if No (E) and then not Is_Imported (Id) then
+            declare
+               Ent : Entity_Id := T;
+
+            begin
+               --  An array whose component type is a record with nonstatic
+               --  default expressions is a violation, so we get the array's
+               --  component type.
+
+               if Is_Array_Type (Ent) then
+                  declare
+                     Comp_Type : Entity_Id := Component_Type (Ent);
+
+                  begin
+                     while Is_Array_Type (Comp_Type) loop
+                        Comp_Type := Component_Type (Comp_Type);
+                     end loop;
+
+                     Ent := Comp_Type;
+                  end;
+               end if;
+
+               --  Object decl. that is of record type and has no default expr.
+               --  should check if there is any non-static default expression
+               --  in component decl. of the record type decl.
+
+               if Is_Record_Type (Ent) then
+                  if Nkind (Parent (Ent)) = N_Full_Type_Declaration then
+                     Check_Non_Static_Default_Expr
+                       (Type_Definition (Parent (Ent)), N);
+
+                  elsif Nkind (Odf) = N_Subtype_Indication
+                    and then not Is_Array_Type (T)
+                    and then not Is_Private_Type (T)
+                  then
+                     Check_Non_Static_Default_Expr (Type_Definition
+                       (Parent (Entity (Subtype_Mark (Odf)))), N);
+                  end if;
+               end if;
+
+               --  We relax the restriction of 10.2.1(9) within GNAT
+               --  units. (There are ACVC tests that check that the
+               --  restriction is enforced, but note that AI-161,
+               --  once approved, will relax the restriction prohibiting
+               --  default-initialized objects of private types, and
+               --  will recommend a pragma for marking private types.)
+
+               if (Is_Private_Type (Ent)
+                    or else Depends_On_Private (Ent))
+                 and then not Is_Internal_File_Name
+                                (Unit_File_Name (Get_Source_Unit (N)))
+               then
+                  Error_Msg_N
+                    ("private object not allowed in preelaborated unit", N);
+                  return;
+
+               --  Access to Task or Protected type
+
+               elsif Is_Entity_Name (Odf)
+                 and then Present (Etype (Odf))
+                 and then Is_Access_Type (Etype (Odf))
+               then
+                  Ent := Designated_Type (Etype (Odf));
+
+               elsif Is_Entity_Name (Odf) then
+                  Ent := Entity (Odf);
+
+               elsif Nkind (Odf) = N_Subtype_Indication then
+                  Ent := Etype (Subtype_Mark (Odf));
+
+               elsif
+                  Nkind (Odf) = N_Constrained_Array_Definition
+               then
+                  Ent := Component_Type (T);
+
+               --  else
+               --     return;
+               end if;
+
+               if Is_Task_Type (Ent)
+                 or else (Is_Protected_Type (Ent) and then Has_Entries (Ent))
+               then
+                  Error_Msg_N
+                    ("concurrent object not allowed in preelaborated unit",
+                     N);
+                  return;
+               end if;
+            end;
+         end if;
+
+         --  Non-static discriminant not allowed in preelaborayted unit
+
+         if Is_Record_Type (Etype (Id)) then
+            declare
+               ET  : constant Entity_Id := Etype (Id);
+               EE  : constant Entity_Id := Etype (Etype (Id));
+               PEE : Node_Id;
+
+            begin
+               if Has_Discriminants (ET)
+                 and then Present (EE)
+               then
+                  PEE := Parent (EE);
+
+                  if Nkind (PEE) = N_Full_Type_Declaration
+                    and then not Static_Discriminant_Expr
+                                  (Discriminant_Specifications (PEE))
+                  then
+                     Error_Msg_N
+                       ("non-static discriminant in preelaborated unit",
+                        PEE);
+                  end if;
+               end if;
+            end;
+         end if;
+      end if;
+
+      --  A pure library_item must not contain the declaration of any
+      --  variable except within  a subprogram, generic subprogram, task
+      --  unit or protected unit (RM 10.2.1(16)).
+
+      if In_Pure_Unit
+        and then not In_Subprogram_Task_Protected_Unit
+      then
+         Error_Msg_N ("declaration of variable not allowed in pure unit", N);
+
+      --  The visible part of an RCI library unit must not contain the
+      --  declaration of a variable (RM E.1.3(9))
+
+      elsif In_RCI_Declaration (N) then
+         Error_Msg_N ("declaration of variable not allowed in rci unit", N);
+
+      --  The visible part of a Shared Passive library unit must not contain
+      --  the declaration of a variable (RM E.2.2(7))
+
+      elsif In_RT_Declaration then
+         Error_Msg_N
+           ("variable declaration not allowed in remote types unit", N);
+      end if;
+
+   end Validate_Object_Declaration;
+
+   --------------------------------
+   --  Validate_RCI_Declarations --
+   --------------------------------
+
+   procedure Validate_RCI_Declarations (P : Entity_Id) is
+      E : Entity_Id;
+
+   begin
+      E := First_Entity (P);
+
+      while Present (E) loop
+         if Comes_From_Source (E) then
+
+            if Is_Limited_Type (E) then
+               Error_Msg_N
+                 ("Limited type not allowed in rci unit", Parent (E));
+
+            elsif Ekind (E) = E_Generic_Function
+              or else Ekind (E) = E_Generic_Package
+              or else Ekind (E) = E_Generic_Procedure
+            then
+               Error_Msg_N ("generic declaration not allowed in rci unit",
+                 Parent (E));
+
+            elsif (Ekind (E) = E_Function
+                    or else Ekind (E) = E_Procedure)
+              and then Has_Pragma_Inline (E)
+            then
+               Error_Msg_N
+                 ("inlined subprogram not allowed in rci unit", Parent (E));
+
+            --  Inner packages that are renamings need not be checked.
+            --  Generic RCI packages are subject to the checks, but
+            --  entities that come from formal packages are not part of the
+            --  visible declarations of the package and are not checked.
+
+            elsif Ekind (E) = E_Package then
+               if Present (Renamed_Entity (E)) then
+                  null;
+
+               elsif Ekind (P) /= E_Generic_Package
+                 or else List_Containing (Unit_Declaration_Node (E)) /=
+                           Generic_Formal_Declarations
+                             (Unit_Declaration_Node (P))
+               then
+                  Validate_RCI_Declarations (E);
+               end if;
+            end if;
+         end if;
+
+         Next_Entity (E);
+      end loop;
+   end Validate_RCI_Declarations;
+
+   -----------------------------------------
+   -- Validate_RCI_Subprogram_Declaration --
+   -----------------------------------------
+
+   procedure Validate_RCI_Subprogram_Declaration (N : Node_Id) is
+      K               : Node_Kind := Nkind (N);
+      Profile         : List_Id;
+      Id              : Node_Id;
+      Param_Spec      : Node_Id;
+      Param_Type      : Entity_Id;
+      Base_Param_Type : Entity_Id;
+      Type_Decl       : Node_Id;
+      Error_Node      : Node_Id := N;
+
+   begin
+      --  There are two possible cases in which this procedure is called:
+
+      --    1. called from Analyze_Subprogram_Declaration.
+      --    2. called from Validate_Object_Declaration (access to subprogram).
+
+      if not In_RCI_Declaration (N) then
+         return;
+      end if;
+
+      if K = N_Subprogram_Declaration then
+         Profile := Parameter_Specifications (Specification (N));
+
+      else pragma Assert (K = N_Object_Declaration);
+         Id := Defining_Identifier (N);
+
+         if Nkind (Id) = N_Defining_Identifier
+           and then Nkind (Parent (Etype (Id))) = N_Full_Type_Declaration
+           and then Ekind (Etype (Id)) = E_Access_Subprogram_Type
+         then
+            Profile :=
+              Parameter_Specifications (Type_Definition (Parent (Etype (Id))));
+         else
+            return;
+         end if;
+      end if;
+
+      --  Iterate through the parameter specification list, checking that
+      --  no access parameter and no limited type parameter in the list.
+      --  RM E.2.3 (14)
+
+      if Present (Profile) then
+         Param_Spec := First (Profile);
+
+         while Present (Param_Spec) loop
+            Param_Type := Etype (Defining_Identifier (Param_Spec));
+            Type_Decl  := Parent (Param_Type);
+
+            if Ekind (Param_Type) = E_Anonymous_Access_Type then
+
+               if K = N_Subprogram_Declaration then
+                  Error_Node := Param_Spec;
+               end if;
+
+               --  Report error only if declaration is in source program.
+
+               if Comes_From_Source
+                 (Defining_Entity (Specification (N)))
+               then
+                  Error_Msg_N
+                    ("subprogram in rci unit cannot have access parameter",
+                      Error_Node);
+               end if;
+
+            --  For limited private type parameter, we check only the
+            --  private declaration and ignore full type declaration,
+            --  unless this is the only declaration for the type, eg.
+            --  as a limited record.
+
+            elsif Is_Limited_Type (Param_Type)
+              and then (Nkind (Type_Decl) = N_Private_Type_Declaration
+                         or else
+                        (Nkind (Type_Decl) = N_Full_Type_Declaration
+                          and then not (Has_Private_Declaration (Param_Type))
+                          and then Comes_From_Source (N)))
+            then
+
+               --  A limited parameter is legal only if user-specified
+               --  Read and Write attributes exist for it.
+               --  second part of RM E.2.3 (14)
+
+               if No (Full_View (Param_Type))
+                 and then Ekind (Param_Type) /= E_Record_Type
+               then
+                  --  type does not have completion yet, so if declared in
+                  --  in the current RCI scope it is illegal, and will be
+                  --  flagged subsequently.
+                  return;
+               end if;
+
+               Base_Param_Type := Base_Type (Underlying_Type (Param_Type));
+
+               if No (TSS (Base_Param_Type, Name_uRead))
+                 or else No (TSS (Base_Param_Type, Name_uWrite))
+               then
+
+                  if K = N_Subprogram_Declaration then
+                     Error_Node := Param_Spec;
+                  end if;
+
+                  Error_Msg_N
+                    ("limited parameter in rci unit "
+                       & "must have read/write attributes ", Error_Node);
+               end if;
+            end if;
+
+            Next (Param_Spec);
+         end loop;
+      end if;
+   end Validate_RCI_Subprogram_Declaration;
+
+   ----------------------------------------------------
+   -- Validate_Remote_Access_Object_Type_Declaration --
+   ----------------------------------------------------
+
+   procedure Validate_Remote_Access_Object_Type_Declaration (T : Entity_Id) is
+      Direct_Designated_Type : Entity_Id;
+      Desig_Type             : Entity_Id;
+      Primitive_Subprograms  : Elist_Id;
+      Subprogram             : Elmt_Id;
+      Subprogram_Node        : Node_Id;
+      Profile                : List_Id;
+      Param_Spec             : Node_Id;
+      Param_Type             : Entity_Id;
+      Limited_Type_Decl      : Node_Id;
+
+   begin
+      --  We are called from Analyze_Type_Declaration, and the Nkind
+      --  of the given node is N_Access_To_Object_Definition.
+
+      if not Comes_From_Source (T)
+        or else (not In_RCI_Declaration (Parent (T))
+                   and then not In_RT_Declaration)
+      then
+         return;
+      end if;
+
+      --  An access definition in the private part of a Remote Types package
+      --  may be legal if it has user-defined Read and Write attributes. This
+      --  will be checked at the end of the package spec processing.
+
+      if In_RT_Declaration and then In_Private_Part (Scope (T)) then
+         return;
+      end if;
+
+      --  Check RCI unit type declaration. It should not contain the
+      --  declaration of an access-to-object type unless it is a
+      --  general access type that designates a class-wide limited
+      --  private type. There are also constraints about the primitive
+      --  subprograms of the class-wide type (RM E.2.3(14)).
+
+      if Ekind (T) /= E_General_Access_Type
+        or else Ekind (Designated_Type (T)) /= E_Class_Wide_Type
+      then
+         if In_RCI_Declaration (Parent (T)) then
+            Error_Msg_N
+              ("access type in Remote_Call_Interface unit must be " &
+               "general access", T);
+         else
+            Error_Msg_N ("access type in Remote_Types unit must be " &
+              "general access", T);
+         end if;
+         Error_Msg_N ("\to class-wide type", T);
+         return;
+      end if;
+
+      Direct_Designated_Type := Designated_Type (T);
+
+      Desig_Type := Etype (Direct_Designated_Type);
+
+      if not Is_Recursively_Limited_Private (Desig_Type) then
+         Error_Msg_N
+           ("error in designated type of remote access to class-wide type", T);
+         Error_Msg_N
+           ("\must be tagged limited private or private extension of type", T);
+         return;
+      end if;
+
+      Primitive_Subprograms := Primitive_Operations (Desig_Type);
+      Subprogram            := First_Elmt (Primitive_Subprograms);
+
+      while Subprogram /= No_Elmt loop
+         Subprogram_Node := Node (Subprogram);
+
+         if not Comes_From_Source (Subprogram_Node) then
+            goto Next_Subprogram;
+         end if;
+
+         Profile := Parameter_Specifications (Parent (Subprogram_Node));
+
+         --  Profile must exist, otherwise not primitive operation
+
+         Param_Spec := First (Profile);
+
+         while Present (Param_Spec) loop
+
+            --  Now find out if this parameter is a controlling parameter
+
+            Param_Type := Parameter_Type (Param_Spec);
+
+            if (Nkind (Param_Type) = N_Access_Definition
+                  and then Etype (Subtype_Mark (Param_Type)) = Desig_Type)
+              or else (Nkind (Param_Type) /= N_Access_Definition
+                        and then Etype (Param_Type) = Desig_Type)
+            then
+               --  It is a controlling parameter, so specific checks below
+               --  do not apply.
+
+               null;
+
+            elsif
+              Nkind (Param_Type) = N_Access_Definition
+            then
+               --  From RM E.2.2(14), no access parameter other than
+               --  controlling ones may be used.
+
+               Error_Msg_N
+                 ("non-controlling access parameter", Param_Spec);
+
+            elsif
+              Is_Limited_Type (Etype (Defining_Identifier (Param_Spec)))
+            then
+               --  Not a controlling parameter, so type must have Read
+               --  and Write attributes.
+               --  ??? I suspect this to be dead code because any violation
+               --  should be caught before in sem_attr.adb (with the message
+               --  "limited type ... used in ... has no stream attr.").  ST
+
+               if Nkind (Param_Type) in N_Has_Etype
+                 and then Nkind (Parent (Etype (Param_Type))) =
+                          N_Private_Type_Declaration
+               then
+                  Param_Type := Etype (Param_Type);
+                  Limited_Type_Decl := Parent (Param_Type);
+
+                  if No (TSS (Param_Type, Name_uRead))
+                    or else No (TSS (Param_Type, Name_uWrite))
+                  then
+                     Error_Msg_N
+                       ("limited formal must have Read and Write attributes",
+                         Param_Spec);
+                  end if;
+               end if;
+            end if;
+
+            --  Check next parameter in this subprogram
+
+            Next (Param_Spec);
+         end loop;
+
+         <<Next_Subprogram>>
+            Next_Elmt (Subprogram);
+      end loop;
+
+      --  Now this is an RCI unit access-to-class-wide-limited-private type
+      --  declaration. Set the type entity to be Is_Remote_Call_Interface to
+      --  optimize later checks by avoiding tree traversal to find out if this
+      --  entity is inside an RCI unit.
+
+      Set_Is_Remote_Call_Interface (T);
+
+   end Validate_Remote_Access_Object_Type_Declaration;
+
+   -----------------------------------------------
+   -- Validate_Remote_Access_To_Class_Wide_Type --
+   -----------------------------------------------
+
+   procedure Validate_Remote_Access_To_Class_Wide_Type (N : Node_Id) is
+      K  : constant Node_Kind := Nkind (N);
+      PK : constant Node_Kind := Nkind (Parent (N));
+      E  : Entity_Id;
+
+   begin
+      --  This subprogram enforces the checks in (RM E.2.2(8)) for
+      --  certain uses of class-wide limited private types.
+
+      --    Storage_Pool and Storage_Size are not defined for such types
+      --
+      --    The expected type of allocator must not not be such a type.
+
+      --    The actual parameter of generic instantiation must not
+      --    be such a type if the formal parameter is of an access type.
+
+      --  On entry, there are five cases
+
+      --    1. called from sem_attr Analyze_Attribute where attribute
+      --       name is either Storage_Pool or Storage_Size.
+
+      --    2. called from exp_ch4 Expand_N_Allocator
+
+      --    3. called from sem_ch12 Analyze_Associations
+
+      --    4. called from sem_ch4 Analyze_Explicit_Dereference
+
+      --    5. called from sem_res Resolve_Actuals
+
+      if K = N_Attribute_Reference then
+         E := Etype (Prefix (N));
+
+         if Is_Remote_Access_To_Class_Wide_Type (E) then
+            Error_Msg_N ("incorrect attribute of remote operand", N);
+            return;
+         end if;
+
+      elsif K = N_Allocator then
+         E := Etype (N);
+
+         if Is_Remote_Access_To_Class_Wide_Type (E) then
+            Error_Msg_N ("incorrect expected remote type of allocator", N);
+            return;
+         end if;
+
+      elsif K in N_Has_Entity then
+         E := Entity (N);
+
+         if Is_Remote_Access_To_Class_Wide_Type (E) then
+            Error_Msg_N ("incorrect remote type generic actual", N);
+            return;
+         end if;
+
+      --  This subprogram also enforces the checks in E.2.2(13).
+      --  A value of such type must not be dereferenced unless as a
+      --  controlling operand of a dispatching call.
+
+      elsif K = N_Explicit_Dereference
+        and then (Comes_From_Source (N)
+                    or else (Nkind (Original_Node (N)) = N_Selected_Component
+                               and then Comes_From_Source (Original_Node (N))))
+      then
+         E := Etype (Prefix (N));
+
+         --  If the class-wide type is not a remote one, the restrictions
+         --  do not apply.
+
+         if not Is_Remote_Access_To_Class_Wide_Type (E) then
+            return;
+         end if;
+
+         --  If we have a true dereference that comes from source and that
+         --  is a controlling argument for a dispatching call, accept it.
+
+         if K = N_Explicit_Dereference
+           and then Is_Actual_Parameter (N)
+           and then Is_Controlling_Actual (N)
+         then
+            return;
+         end if;
+
+         --  If we are just within a procedure or function call and the
+         --  dereference has not been analyzed, return because this
+         --  procedure will be called again from sem_res Resolve_Actuals.
+
+         if Is_Actual_Parameter (N)
+           and then not Analyzed (N)
+         then
+            return;
+         end if;
+
+         --  The following is to let the compiler generated tags check
+         --  pass through without error message. This is a bit kludgy
+         --  isn't there some better way of making this exclusion ???
+
+         if (PK = N_Selected_Component
+              and then Present (Parent (Parent (N)))
+              and then Nkind (Parent (Parent (N))) = N_Op_Ne)
+           or else (PK = N_Unchecked_Type_Conversion
+                    and then Present (Parent (Parent (N)))
+                    and then
+                      Nkind (Parent (Parent (N))) = N_Selected_Component)
+         then
+            return;
+         end if;
+
+         --  The following code is needed for expansion of RACW Write
+         --  attribute, since such expressions can appear in the expanded
+         --  code.
+
+         if not Comes_From_Source (N)
+           and then
+           (PK = N_In
+            or else PK = N_Attribute_Reference
+            or else
+              (PK = N_Type_Conversion
+               and then Present (Parent (N))
+               and then Present (Parent (Parent (N)))
+               and then
+                 Nkind (Parent (Parent (N))) = N_Selected_Component))
+         then
+            return;
+         end if;
+
+         Error_Msg_N ("incorrect remote type dereference", N);
+      end if;
+   end Validate_Remote_Access_To_Class_Wide_Type;
+
+   -----------------------------------------------
+   -- Validate_Remote_Access_To_Subprogram_Type --
+   -----------------------------------------------
+
+   procedure Validate_Remote_Access_To_Subprogram_Type (N : Node_Id) is
+      Type_Def          : constant Node_Id := Type_Definition (N);
+      Current_Parameter : Node_Id;
+
+   begin
+      if Present (Parameter_Specifications (Type_Def)) then
+         Current_Parameter := First (Parameter_Specifications (Type_Def));
+         while Present (Current_Parameter) loop
+            if Nkind (Parameter_Type (Current_Parameter)) =
+                                                         N_Access_Definition
+            then
+               Error_Msg_N
+                 ("remote access to subprogram type declaration contains",
+                  Current_Parameter);
+               Error_Msg_N
+                 ("\parameter of an anonymous access type", Current_Parameter);
+            end if;
+
+            Current_Parameter := Next (Current_Parameter);
+         end loop;
+      end if;
+   end Validate_Remote_Access_To_Subprogram_Type;
+
+   ------------------------------------------
+   -- Validate_Remote_Type_Type_Conversion --
+   ------------------------------------------
+
+   procedure Validate_Remote_Type_Type_Conversion (N : Node_Id) is
+      S : constant Entity_Id := Etype (N);
+      E : constant Entity_Id := Etype (Expression (N));
+
+   begin
+      --  This test is required in the case where a conversion appears
+      --  inside a normal package, it does not necessarily have to be
+      --  inside an RCI, Remote_Types unit (RM E.2.2(9,12)).
+
+      if Is_Remote_Access_To_Subprogram_Type (E)
+        and then not Is_Remote_Access_To_Subprogram_Type (S)
+      then
+         Error_Msg_N ("incorrect conversion of remote operand", N);
+         return;
+
+      elsif Is_Remote_Access_To_Class_Wide_Type (E)
+        and then not Is_Remote_Access_To_Class_Wide_Type (S)
+      then
+         Error_Msg_N ("incorrect conversion of remote operand", N);
+         return;
+      end if;
+
+      --  If a local access type is converted into a RACW type, then the
+      --  current unit has a pointer that may now be exported to another
+      --  partition.
+
+      if Is_Remote_Access_To_Class_Wide_Type (S)
+        and then not Is_Remote_Access_To_Class_Wide_Type (E)
+      then
+         Set_Has_RACW (Current_Sem_Unit);
+      end if;
+   end Validate_Remote_Type_Type_Conversion;
+
+   -------------------------------
+   -- Validate_RT_RAT_Component --
+   -------------------------------
+
+   procedure Validate_RT_RAT_Component (N : Node_Id) is
+      Spec            : constant Node_Id   := Specification (N);
+      Name_U          : constant Entity_Id := Defining_Entity (Spec);
+      Typ             : Entity_Id;
+      First_Priv_Ent  : constant Entity_Id := First_Private_Entity (Name_U);
+      In_Visible_Part : Boolean            := True;
+
+   begin
+      if not Is_Remote_Types (Name_U) then
+         return;
+      end if;
+
+      Typ := First_Entity (Name_U);
+      while Present (Typ) loop
+         if In_Visible_Part and then Typ = First_Priv_Ent then
+            In_Visible_Part := False;
+         end if;
+
+         if Comes_From_Source (Typ)
+           and then Is_Type (Typ)
+           and then (In_Visible_Part or else Has_Private_Declaration (Typ))
+         then
+            if Missing_Read_Write_Attributes (Typ) then
+               if Is_Non_Remote_Access_Type (Typ) then
+                  Error_Msg_N
+                    ("non-remote access type without user-defined Read " &
+                     "and Write attributes", Typ);
+               else
+                  Error_Msg_N
+                    ("record type containing a component of a " &
+                     "non-remote access", Typ);
+                  Error_Msg_N
+                    ("\type without Read and Write attributes " &
+                     "('R'M E.2.2(8))", Typ);
+               end if;
+            end if;
+         end if;
+
+         Next_Entity (Typ);
+      end loop;
+   end Validate_RT_RAT_Component;
+
+   -----------------------------------------
+   -- Validate_SP_Access_Object_Type_Decl --
+   -----------------------------------------
+
+   procedure Validate_SP_Access_Object_Type_Decl (T : Entity_Id) is
+      Direct_Designated_Type : Entity_Id;
+
+      function Has_Entry_Declarations (E : Entity_Id) return Boolean;
+      --  Return true if the protected type designated by T has
+      --  entry declarations.
+
+      function Has_Entry_Declarations (E : Entity_Id) return Boolean is
+         Ety : Entity_Id;
+
+      begin
+         if Nkind (Parent (E)) = N_Protected_Type_Declaration then
+            Ety := First_Entity (E);
+            while Present (Ety) loop
+               if Ekind (Ety) = E_Entry then
+                  return True;
+               end if;
+
+               Next_Entity (Ety);
+            end loop;
+         end if;
+
+         return False;
+      end Has_Entry_Declarations;
+
+   --  Start of processing for Validate_SP_Access_Object_Type_Decl
+
+   begin
+      --  We are called from Sem_Ch3.Analyze_Type_Declaration, and the
+      --  Nkind of the given entity is N_Access_To_Object_Definition.
+
+      if not Comes_From_Source (T)
+        or else not In_Shared_Passive_Unit
+        or else In_Subprogram_Task_Protected_Unit
+      then
+         return;
+      end if;
+
+      --  Check Shared Passive unit. It should not contain the declaration
+      --  of an access-to-object type whose designated type is a class-wide
+      --  type, task type or protected type with entry (RM E.2.1(7)).
+
+      Direct_Designated_Type := Designated_Type (T);
+
+      if Ekind (Direct_Designated_Type) = E_Class_Wide_Type then
+         Error_Msg_N
+           ("invalid access-to-class-wide type in shared passive unit", T);
+         return;
+
+      elsif Ekind (Direct_Designated_Type) in Task_Kind then
+         Error_Msg_N
+           ("invalid access-to-task type in shared passive unit", T);
+         return;
+
+      elsif Ekind (Direct_Designated_Type) in Protected_Kind
+        and then Has_Entry_Declarations (Direct_Designated_Type)
+      then
+         Error_Msg_N
+           ("invalid access-to-protected type in shared passive unit", T);
+         return;
+      end if;
+   end Validate_SP_Access_Object_Type_Decl;
+
+   ---------------------------------
+   -- Validate_Static_Object_Name --
+   ---------------------------------
+
+   procedure Validate_Static_Object_Name (N : Node_Id) is
+      E : Entity_Id;
+
+      function Is_Primary (N : Node_Id) return Boolean;
+      --  Determine whether node is syntactically a primary in an expression.
+
+      function Is_Primary (N : Node_Id) return Boolean is
+         K : constant Node_Kind := Nkind (Parent (N));
+
+      begin
+         case K is
+
+            when N_Op | N_In | N_Not_In =>
+               return True;
+
+            when N_Aggregate
+               | N_Component_Association
+               | N_Index_Or_Discriminant_Constraint =>
+               return True;
+
+            when N_Attribute_Reference =>
+               return Attribute_Name (Parent (N)) /= Name_Address
+                 and then Attribute_Name (Parent (N)) /= Name_Access
+                 and then Attribute_Name (Parent (N)) /= Name_Unchecked_Access
+                 and then
+                   Attribute_Name (Parent (N)) /= Name_Unrestricted_Access;
+
+            when N_Indexed_Component =>
+               return (N /= Prefix (Parent (N))
+                 or else Is_Primary (Parent (N)));
+
+            when N_Qualified_Expression | N_Type_Conversion =>
+               return Is_Primary (Parent (N));
+
+            when N_Assignment_Statement | N_Object_Declaration =>
+               return (N = Expression (Parent (N)));
+
+            when N_Selected_Component =>
+               return Is_Primary (Parent (N));
+
+            when others =>
+               return False;
+         end case;
+      end Is_Primary;
+
+   --  Start of processing for Validate_Static_Object_Name
+
+   begin
+      if not In_Preelaborated_Unit
+        or else not Comes_From_Source (N)
+        or else In_Subprogram_Or_Concurrent_Unit
+        or else Ekind (Current_Scope) = E_Block
+      then
+         return;
+
+      --  Filter out cases where primary is default in a component
+      --  declaration, discriminant specification, or actual in a record
+      --  type initialization call.
+
+      --  Initialization call of internal types.
+
+      elsif Nkind (Parent (N)) = N_Procedure_Call_Statement then
+
+         if Present (Parent (Parent (N)))
+           and then Nkind (Parent (Parent (N))) = N_Freeze_Entity
+         then
+            return;
+         end if;
+
+         if Nkind (Name (Parent (N))) = N_Identifier
+           and then not Comes_From_Source (Entity (Name (Parent (N))))
+         then
+            return;
+         end if;
+      end if;
+
+      --  Error if the name is a primary in an expression. The parent must not
+      --  be an operator, or a selected component or an indexed component that
+      --  is itself a primary. Entities that are actuals do not need to be
+      --  checked, because the call itself will be diagnosed.
+
+      if Is_Primary (N)
+        and then (not Inside_A_Generic
+                   or else Present (Enclosing_Generic_Body (N)))
+      then
+         if Ekind (Entity (N)) = E_Variable then
+            Error_Msg_N ("non-static object name in preelaborated unit", N);
+
+         --  We take the view that a constant defined in another preelaborated
+         --  unit is preelaborable, even though it may have a private type and
+         --  thus appear non-static in a client. This must be the intent of
+         --  the language, but currently is an RM gap.
+
+         elsif Ekind (Entity (N)) = E_Constant
+           and then not Is_Static_Expression (N)
+         then
+            E := Entity (N);
+
+            if Is_Internal_File_Name (Unit_File_Name (Get_Source_Unit (N)))
+              and then
+                Enclosing_Lib_Unit_Node (N) /= Enclosing_Lib_Unit_Node (E)
+              and then (Is_Preelaborated (Scope (E))
+                          or else Is_Pure (Scope (E))
+                          or else (Present (Renamed_Object (E))
+                                     and then
+                                       Is_Entity_Name (Renamed_Object (E))
+                                     and then
+                                       (Is_Preelaborated
+                                         (Scope (Renamed_Object (E)))
+                                            or else
+                                              Is_Pure (Scope
+                                                (Renamed_Object (E))))))
+            then
+               null;
+            else
+               Error_Msg_N ("non-static constant in preelaborated unit", N);
+            end if;
+         end if;
+      end if;
+   end Validate_Static_Object_Name;
+
+end Sem_Cat;
diff --git a/gcc/ada/sem_cat.ads b/gcc/ada/sem_cat.ads
new file mode 100644 (file)
index 0000000..3591e74
--- /dev/null
@@ -0,0 +1,144 @@
+------------------------------------------------------------------------------
+--                                                                          --
+--                         GNAT COMPILER COMPONENTS                         --
+--                                                                          --
+--                              S E M _ C A T                               --
+--                                                                          --
+--                                 S p e c                                  --
+--                                                                          --
+--                            $Revision: 1.14 $
+--                                                                          --
+--          Copyright (C) 1992-2000 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- --
+-- ware  Foundation;  either version 2,  or (at your option) any later ver- --
+-- sion.  GNAT is distributed in the hope that it will be useful, but WITH- --
+-- OUT ANY WARRANTY;  without even the  implied warranty of MERCHANTABILITY --
+-- or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License --
+-- for  more details.  You should have  received  a copy of the GNU General --
+-- Public License  distributed with GNAT;  see file COPYING.  If not, write --
+-- to  the Free Software Foundation,  59 Temple Place - Suite 330,  Boston, --
+-- MA 02111-1307, USA.                                                      --
+--                                                                          --
+-- GNAT was originally developed  by the GNAT team at  New York University. --
+-- It is now maintained by Ada Core Technologies Inc (http://www.gnat.com). --
+--                                                                          --
+------------------------------------------------------------------------------
+
+--  This unit contains the routines used for checking for conformance with
+--  the semantic restrictions required for the categorization pragmas:
+--
+--    Preelaborate
+--    Pure,
+--    Remote_Call_Interface
+--    Remote_Types
+--    Shared_Passive
+--
+--  Note that we treat Preelaborate as a categorization pragma, even though
+--  strictly, according to RM E.2(2,3), the term does not apply in this case.
+
+with Types; use Types;
+
+package Sem_Cat is
+
+   function In_Preelaborated_Unit return Boolean;
+   --  Determines if the current scope is within a preelaborated compilation
+   --  unit, that is one to which one of the pragmas Preelaborate, Pure,
+   --  Shared_Passive, Remote_Types, or inside a unit other than a package
+   --  body with pragma Remote_Call_Interface.
+
+   function In_Pure_Unit return Boolean;
+   pragma Inline (In_Pure_Unit);
+   --  Determines if the current scope is within pure compilation unit,
+   --  that is, one to which the pragmas Pure is applied.
+
+   function In_Subprogram_Task_Protected_Unit return Boolean;
+   --  Determines if the current scope is within a subprogram, task
+   --  or protected unit. Used to validate if the library unit is Pure
+   --  (RM 10.2.1(16)).
+
+   procedure Set_Categorization_From_Pragmas (N : Node_Id);
+   --  Since validation of categorization dependency is done during analyze
+   --  so categorization flags from following pragmas should be set before
+   --  validation begin. N is the N_Compilation_Unit node.
+
+   procedure Validate_Access_Type_Declaration (T : Entity_Id; N : Node_Id);
+   --  Validate all constraints against declaration of access types in
+   --  categorized library units. Usually this is a violation in Pure unit,
+   --  Shared_Passive unit. N is the declaration node.
+
+   procedure Validate_Ancestor_Part (N : Node_Id);
+   --  Checks that a type given as the ancestor in an extension aggregate
+   --  satisfies the restriction of 10.2.1(9).
+
+   procedure Validate_Categorization_Dependency (N : Node_Id; E : Entity_Id);
+   --  There are restrictions on lib unit that semantically depends on other
+   --  units (RM E.2(5), 10.2.1(11). This procedure checks the restrictions
+   --  on categorizations. N is the current unit node, and E is the current
+   --  library unit entity.
+
+   procedure Validate_Controlled_Object (E : Entity_Id);
+   --  Given an entity for a library level controlled object, check that it is
+   --  not in a preelaborated unit (prohibited by RM 10.2.1(9)).
+
+   procedure Validate_Null_Statement_Sequence (N : Node_Id);
+   --  Given N, a package body node, check that a handled statement sequence
+   --  in a preelaborable body contains no statements other than labels or
+   --  null statements, as required by RM 10.2.1(6).
+
+   procedure Validate_Object_Declaration (N : Node_Id);
+   --  Given N, an object declaration node, validates all the constraints in
+   --  a preelaborable library unit, including creation of task objects etc.
+   --  Note that this is called when the corresponding object is frozen since
+   --  the checks cannot be made before knowing if the object is imported.
+
+   procedure Validate_RCI_Declarations (P : Entity_Id);
+   --  Apply semantic checks given in  E2.3(10-14).
+
+   procedure Validate_RCI_Subprogram_Declaration (N : Node_Id);
+   --  Check for RCI unit subprogram declarations with respect to
+   --  in-lined subprogram and subprogram with access parameter or
+   --  limited type parameter without Read and Write.
+
+   procedure Validate_Remote_Access_To_Class_Wide_Type (N : Node_Id);
+   --  Checks that Storage_Pool and Storage_Size attribute references are
+   --  not applied to remote access-to-class-wide types. And the expected
+   --  type for an allocator shall not be a remote access-to-class-wide
+   --  type. And a remote access-to-class-wide type shall not be an actual
+   --  parameter for a generic formal access type. RM E.2.3(22).
+
+   procedure Validate_Remote_Access_To_Subprogram_Type (N : Node_Id);
+   --  Checks that a remote access to subprogram type does not have a
+   --  parameter of an access type. This is not strictly forbidden at this
+   --  time, but this is useless, as such a RAS type will not be usable
+   --  per E.2.2(12) and E.2.3(14).
+
+   procedure Validate_RT_RAT_Component (N : Node_Id);
+   --  Given N, the package library unit declaration node, we should check
+   --  against RM:9.95 E.2.2(8): the full view of a type declared in the
+   --  visible part of a Remote Types unit has a part that is of a non-remote
+   --  access type which has no read/write.
+
+   procedure Validate_Remote_Type_Type_Conversion (N : Node_Id);
+   --  Check for remote-type type conversion constraints. First, a value of
+   --  a remote access-to-subprogram type can be converted only to another
+   --  type conformant remote access-to-subprogram type. Secondly, a value
+   --  of a remote access-to-class-wide type can be converted only to another
+   --  remote access-to-class-wide type (RM E.2.3(17,20)).
+
+   procedure Validate_SP_Access_Object_Type_Decl (T : Entity_Id);
+   --  Check validity of declaration if shared passive unit. It should not
+   --  contain the declaration of an access-to-object type whose designated
+   --  type is a class-wide type ,task type or protected type. E.2.1(7).
+   --  T is the entity of the declared type.
+
+   procedure Validate_Static_Object_Name (N : Node_Id);
+   --  In the elaboration code of a preelaborated library unit, check
+   --  that we do not have the evaluation of a primary that is a name of
+   --  an object, unless the name is a static expression (RM 10.2.1(8)).
+   --  Non-static constant and variable are the targets, generic parameters
+   --  are not included because the generic declaration and body are
+   --  preelaborable.
+
+end Sem_Cat;
diff --git a/gcc/ada/sem_ch10.adb b/gcc/ada/sem_ch10.adb
new file mode 100644 (file)
index 0000000..2bbe0a5
--- /dev/null
@@ -0,0 +1,3072 @@
+------------------------------------------------------------------------------
+--                                                                          --
+--                         GNAT COMPILER COMPONENTS                         --
+--                                                                          --
+--                             S E M _ C H 1 0                              --
+--                                                                          --
+--                                 B o d y                                  --
+--                                                                          --
+--                            $Revision: 1.402 $
+--                                                                          --
+--          Copyright (C) 1992-2001 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- --
+-- ware  Foundation;  either version 2,  or (at your option) any later ver- --
+-- sion.  GNAT is distributed in the hope that it will be useful, but WITH- --
+-- OUT ANY WARRANTY;  without even the  implied warranty of MERCHANTABILITY --
+-- or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License --
+-- for  more details.  You should have  received  a copy of the GNU General --
+-- Public License  distributed with GNAT;  see file COPYING.  If not, write --
+-- to  the Free Software Foundation,  59 Temple Place - Suite 330,  Boston, --
+-- MA 02111-1307, USA.                                                      --
+--                                                                          --
+-- GNAT was originally developed  by the GNAT team at  New York University. --
+-- It is now maintained by Ada Core Technologies Inc (http://www.gnat.com). --
+--                                                                          --
+------------------------------------------------------------------------------
+
+with Atree;    use Atree;
+with Debug;    use Debug;
+with Einfo;    use Einfo;
+with Errout;   use Errout;
+with Exp_Util; use Exp_Util;
+with Fname;    use Fname;
+with Fname.UF; use Fname.UF;
+with Freeze;   use Freeze;
+with Impunit;  use Impunit;
+with Inline;   use Inline;
+with Lib;      use Lib;
+with Lib.Load; use Lib.Load;
+with Lib.Xref; use Lib.Xref;
+with Namet;    use Namet;
+with Nlists;   use Nlists;
+with Nmake;    use Nmake;
+with Opt;      use Opt;
+with Output;   use Output;
+with Restrict; use Restrict;
+with Sem;      use Sem;
+with Sem_Ch6;  use Sem_Ch6;
+with Sem_Ch7;  use Sem_Ch7;
+with Sem_Ch8;  use Sem_Ch8;
+with Sem_Dist; use Sem_Dist;
+with Sem_Prag; use Sem_Prag;
+with Sem_Util; use Sem_Util;
+with Sem_Warn; use Sem_Warn;
+with Stand;    use Stand;
+with Sinfo;    use Sinfo;
+with Sinfo.CN; use Sinfo.CN;
+with Sinput;   use Sinput;
+with Snames;   use Snames;
+with Style;    use Style;
+with Tbuild;   use Tbuild;
+with Ttypes;   use Ttypes;
+with Uname;    use Uname;
+
+package body Sem_Ch10 is
+
+   -----------------------
+   -- Local Subprograms --
+   -----------------------
+
+   procedure Analyze_Context (N : Node_Id);
+   --  Analyzes items in the context clause of compilation unit
+
+   procedure Check_With_Type_Clauses (N : Node_Id);
+   --  If N is a body, verify that any with_type clauses on the spec, or
+   --  on the spec of any parent, have a matching with_clause.
+
+   procedure Check_Private_Child_Unit (N : Node_Id);
+   --  If a with_clause mentions a private child unit, the compilation
+   --  unit must be a member of the same family, as described in 10.1.2 (8).
+
+   procedure Check_Stub_Level (N : Node_Id);
+   --  Verify that a stub is declared immediately within a compilation unit,
+   --  and not in an inner frame.
+
+   procedure Expand_With_Clause (Nam : Node_Id; N : Node_Id);
+   --  When a child unit appears in a context clause, the implicit withs on
+   --  parents are made explicit, and with clauses are inserted in the context
+   --  clause before the one for the child. If a parent in the with_clause
+   --  is a renaming, the implicit with_clause is on the renaming whose name
+   --  is mentioned in the with_clause, and not on the package it renames.
+   --  N is the compilation unit whose list of context items receives the
+   --  implicit with_clauses.
+
+   procedure Implicit_With_On_Parent (Child_Unit : Node_Id; N : Node_Id);
+   --  If the main unit is a child unit, implicit withs are also added for
+   --  all its ancestors.
+
+   procedure Install_Context_Clauses (N : Node_Id);
+   --  Subsidiary to previous one. Process only with_ and use_clauses for
+   --  current unit and its library unit if any.
+
+   procedure Install_Withed_Unit (With_Clause : Node_Id);
+   --  If the unit is not a child unit, make unit immediately visible.
+   --  The caller ensures that the unit is not already currently installed.
+
+   procedure Install_Parents (Lib_Unit : Node_Id; Is_Private : Boolean);
+   --  This procedure establishes the context for the compilation of a child
+   --  unit. If Lib_Unit is a child library spec then the context of the parent
+   --  is installed, and the parent itself made immediately visible, so that
+   --  the child unit is processed in the declarative region of the parent.
+   --  Install_Parents makes a recursive call to itself to ensure that all
+   --  parents are loaded in the nested case. If Lib_Unit is a library body,
+   --  the only effect of Install_Parents is to install the private decls of
+   --  the parents, because the visible parent declarations will have been
+   --  installed as part of the context of the corresponding spec.
+
+   procedure Install_Siblings (U_Name : Entity_Id; N : Node_Id);
+   --  In the compilation of a child unit, a child of any of the  ancestor
+   --  units is directly visible if it is visible, because the parent is in
+   --  an enclosing scope. Iterate over context to find child units of U_Name
+   --  or of some ancestor of it.
+
+   function Is_Child_Spec (Lib_Unit : Node_Id) return Boolean;
+   --  Lib_Unit is a library unit which may be a spec or a body. Is_Child_Spec
+   --  returns True if Lib_Unit is a library spec which is a child spec, i.e.
+   --  a library spec that has a parent. If the call to Is_Child_Spec returns
+   --  True, then Parent_Spec (Lib_Unit) is non-Empty and points to the
+   --  compilation unit for the parent spec.
+   --
+   --  Lib_Unit can also be a subprogram body that acts as its own spec. If
+   --  the Parent_Spec is  non-empty, this is also a child unit.
+
+   procedure Remove_With_Type_Clause (Name : Node_Id);
+   --  Remove imported type and its enclosing package from visibility, and
+   --  remove attributes of imported type so they don't interfere with its
+   --  analysis (should it appear otherwise in the context).
+
+   procedure Remove_Context_Clauses (N : Node_Id);
+   --  Subsidiary of previous one. Remove use_ and with_clauses.
+
+   procedure Remove_Parents (Lib_Unit : Node_Id);
+   --  Remove_Parents checks if Lib_Unit is a child spec. If so then the parent
+   --  contexts established by the corresponding call to Install_Parents are
+   --  removed. Remove_Parents contains a recursive call to itself to ensure
+   --  that all parents are removed in the nested case.
+
+   procedure Remove_Unit_From_Visibility (Unit_Name : Entity_Id);
+   --  Reset all visibility flags on unit after compiling it, either as a
+   --  main unit or as a unit in the context.
+
+   procedure Analyze_Proper_Body (N : Node_Id; Nam : Entity_Id);
+   --  Common processing for all stubs (subprograms, tasks, packages, and
+   --  protected cases). N is the stub to be analyzed. Once the subunit
+   --  name is established, load and analyze. Nam is the non-overloadable
+   --  entity for which the proper body provides a completion. Subprogram
+   --  stubs are handled differently because they can be declarations.
+
+   ------------------------------
+   -- Analyze_Compilation_Unit --
+   ------------------------------
+
+   procedure Analyze_Compilation_Unit (N : Node_Id) is
+      Unit_Node     : constant Node_Id := Unit (N);
+      Lib_Unit      : Node_Id          := Library_Unit (N);
+      Spec_Id       : Node_Id;
+      Main_Cunit    : constant Node_Id := Cunit (Main_Unit);
+      Par_Spec_Name : Unit_Name_Type;
+      Unum          : Unit_Number_Type;
+
+      procedure Generate_Parent_References (N : Node_Id; P_Id : Entity_Id);
+      --  Generate cross-reference information for the parents of child units.
+      --  N is a defining_program_unit_name, and P_Id is the immediate parent.
+
+      --------------------------------
+      -- Generate_Parent_References --
+      --------------------------------
+
+      procedure Generate_Parent_References (N : Node_Id; P_Id : Entity_Id) is
+         Pref   : Node_Id;
+         P_Name : Entity_Id := P_Id;
+
+      begin
+         Pref   := Name (Parent (Defining_Entity (N)));
+
+         if Nkind (Pref) = N_Expanded_Name then
+
+            --  Done already, if the unit has been compiled indirectly as
+            --  part of the closure of its context because of inlining.
+
+            return;
+         end if;
+
+         while Nkind (Pref) = N_Selected_Component loop
+            Change_Selected_Component_To_Expanded_Name (Pref);
+            Set_Entity (Pref, P_Name);
+            Set_Etype (Pref, Etype (P_Name));
+            Generate_Reference (P_Name, Pref, 'r');
+            Pref   := Prefix (Pref);
+            P_Name := Scope (P_Name);
+         end loop;
+
+         --  The guard here on P_Name is to handle the error condition where
+         --  the parent unit is missing because the file was not found.
+
+         if Present (P_Name) then
+            Set_Entity (Pref, P_Name);
+            Set_Etype (Pref, Etype (P_Name));
+            Generate_Reference (P_Name, Pref, 'r');
+            Style.Check_Identifier (Pref, P_Name);
+         end if;
+      end Generate_Parent_References;
+
+   --  Start of processing for Analyze_Compilation_Unit
+
+   begin
+      Process_Compilation_Unit_Pragmas (N);
+
+      --  If the unit is a subunit whose parent has not been analyzed (which
+      --  indicates that the main unit is a subunit, either the current one or
+      --  one of its descendents) then the subunit is compiled as part of the
+      --  analysis of the parent, which we proceed to do. Basically this gets
+      --  handled from the top down and we don't want to do anything at this
+      --  level (i.e. this subunit will be handled on the way down from the
+      --  parent), so at this level we immediately return. If the subunit
+      --  ends up not analyzed, it means that the parent did not contain a
+      --  stub for it, or that there errors were dectected in some ancestor.
+
+      if Nkind (Unit_Node) = N_Subunit
+        and then not Analyzed (Lib_Unit)
+      then
+         Semantics (Lib_Unit);
+
+         if not Analyzed (Proper_Body (Unit_Node)) then
+            if Errors_Detected > 0 then
+               Error_Msg_N ("subunit not analyzed (errors in parent unit)", N);
+            else
+               Error_Msg_N ("missing stub for subunit", N);
+            end if;
+         end if;
+
+         return;
+      end if;
+
+      --  Analyze context (this will call Sem recursively for with'ed units)
+
+      Analyze_Context (N);
+
+      --  If the unit is a package body, the spec is already loaded and must
+      --  be analyzed first, before we analyze the body.
+
+      if Nkind (Unit_Node) = N_Package_Body then
+
+         --  If no Lib_Unit, then there was a serious previous error, so
+         --  just ignore the entire analysis effort
+
+         if No (Lib_Unit) then
+            return;
+
+         else
+            Semantics (Lib_Unit);
+            Check_Unused_Withs (Get_Cunit_Unit_Number (Lib_Unit));
+
+            --  Verify that the library unit is a package declaration.
+
+            if Nkind (Unit (Lib_Unit)) /= N_Package_Declaration
+                 and then
+               Nkind (Unit (Lib_Unit)) /= N_Generic_Package_Declaration
+            then
+               Error_Msg_N
+                 ("no legal package declaration for package body", N);
+               return;
+
+            --  Otherwise, the entity in the declaration is visible. Update
+            --  the version to reflect dependence of this body on the spec.
+
+            else
+               Spec_Id := Defining_Entity (Unit (Lib_Unit));
+               Set_Is_Immediately_Visible (Spec_Id, True);
+               Version_Update (N, Lib_Unit);
+
+               if Nkind (Defining_Unit_Name (Unit_Node))
+                 = N_Defining_Program_Unit_Name
+               then
+                  Generate_Parent_References (Unit_Node, Scope (Spec_Id));
+               end if;
+            end if;
+         end if;
+
+      --  If the unit is a subprogram body, then we similarly need to analyze
+      --  its spec. However, things are a little simpler in this case, because
+      --  here, this analysis is done only for error checking and consistency
+      --  purposes, so there's nothing else to be done.
+
+      elsif Nkind (Unit_Node) = N_Subprogram_Body then
+         if Acts_As_Spec (N) then
+
+            --  If the subprogram body is a child unit, we must create a
+            --  declaration for it, in order to properly load the parent(s).
+            --  After this, the original unit does not acts as a spec, because
+            --  there is an explicit one. If this  unit appears in a context
+            --  clause, then an implicit with on the parent will be added when
+            --  installing the context. If this is the main unit, there is no
+            --  Unit_Table entry for the declaration, (It has the unit number
+            --  of the main unit) and code generation is unaffected.
+
+            Unum := Get_Cunit_Unit_Number (N);
+            Par_Spec_Name := Get_Parent_Spec_Name (Unit_Name (Unum));
+
+            if Par_Spec_Name /= No_Name then
+               Unum :=
+                 Load_Unit
+                   (Load_Name  => Par_Spec_Name,
+                    Required   => True,
+                    Subunit    => False,
+                    Error_Node => N);
+
+               if Unum /= No_Unit then
+
+                  --  Build subprogram declaration and attach parent unit to it
+                  --  This subprogram declaration does not come from source!
+
+                  declare
+                     Loc : constant Source_Ptr := Sloc (N);
+                     SCS : constant Boolean :=
+                             Get_Comes_From_Source_Default;
+
+                  begin
+                     Set_Comes_From_Source_Default (False);
+                     Lib_Unit :=
+                       Make_Compilation_Unit (Loc,
+                         Context_Items => New_Copy_List (Context_Items (N)),
+                         Unit =>
+                           Make_Subprogram_Declaration (Sloc (N),
+                             Specification =>
+                               Copy_Separate_Tree
+                                 (Specification (Unit_Node))),
+                         Aux_Decls_Node =>
+                           Make_Compilation_Unit_Aux (Loc));
+
+                     Set_Library_Unit (N, Lib_Unit);
+                     Set_Parent_Spec (Unit (Lib_Unit), Cunit (Unum));
+                     Semantics (Lib_Unit);
+                     Set_Acts_As_Spec (N, False);
+                     Set_Comes_From_Source_Default (SCS);
+                  end;
+               end if;
+            end if;
+
+         --  Here for subprogram with separate declaration
+
+         else
+            Semantics (Lib_Unit);
+            Check_Unused_Withs (Get_Cunit_Unit_Number (Lib_Unit));
+            Version_Update (N, Lib_Unit);
+         end if;
+
+         if Nkind (Defining_Unit_Name (Specification (Unit_Node))) =
+                                             N_Defining_Program_Unit_Name
+         then
+            Generate_Parent_References (
+              Specification (Unit_Node),
+                Scope (Defining_Entity (Unit (Lib_Unit))));
+         end if;
+      end if;
+
+      --  If it is a child unit, the parent must be elaborated first
+      --  and we update version, since we are dependent on our parent.
+
+      if Is_Child_Spec (Unit_Node) then
+
+         --  The analysis of the parent is done with style checks off
+
+         declare
+            Save_Style_Check : constant Boolean := Opt.Style_Check;
+            Save_C_Restrict  : constant Save_Compilation_Unit_Restrictions :=
+                                 Compilation_Unit_Restrictions_Save;
+
+         begin
+            if not GNAT_Mode then
+               Style_Check := False;
+            end if;
+
+            Semantics (Parent_Spec (Unit_Node));
+            Version_Update (N, Parent_Spec (Unit_Node));
+            Style_Check := Save_Style_Check;
+            Compilation_Unit_Restrictions_Restore (Save_C_Restrict);
+         end;
+      end if;
+
+      --  With the analysis done, install the context. Note that we can't
+      --  install the context from the with clauses as we analyze them,
+      --  because each with clause must be analyzed in a clean visibility
+      --  context, so we have to wait and install them all at once.
+
+      Install_Context (N);
+
+      if Is_Child_Spec (Unit_Node) then
+
+         --  Set the entities of all parents in the program_unit_name.
+
+         Generate_Parent_References (
+           Unit_Node, Defining_Entity (Unit (Parent_Spec (Unit_Node))));
+      end if;
+
+      --  All components of the context: with-clauses, library unit, ancestors
+      --  if any, (and their context)  are analyzed and installed. Now analyze
+      --  the unit itself, which is either a package, subprogram spec or body.
+
+      Analyze (Unit_Node);
+
+      --  The above call might have made Unit_Node an N_Subprogram_Body
+      --  from something else, so propagate any Acts_As_Spec flag.
+
+      if Nkind (Unit_Node) = N_Subprogram_Body
+        and then Acts_As_Spec (Unit_Node)
+      then
+         Set_Acts_As_Spec (N);
+      end if;
+
+      --  Treat compilation unit pragmas that appear after the library unit
+
+      if Present (Pragmas_After (Aux_Decls_Node (N))) then
+         declare
+            Prag_Node : Node_Id := First (Pragmas_After (Aux_Decls_Node (N)));
+
+         begin
+            while Present (Prag_Node) loop
+               Analyze (Prag_Node);
+               Next (Prag_Node);
+            end loop;
+         end;
+      end if;
+
+      --  Generate distribution stub files if requested and no error
+
+      if N = Main_Cunit
+        and then (Distribution_Stub_Mode = Generate_Receiver_Stub_Body
+                    or else
+                  Distribution_Stub_Mode = Generate_Caller_Stub_Body)
+        and then not Fatal_Error (Main_Unit)
+      then
+         if Is_RCI_Pkg_Spec_Or_Body (N) then
+
+            --  Regular RCI package
+
+            Add_Stub_Constructs (N);
+
+         elsif (Nkind (Unit_Node) = N_Package_Declaration
+                 and then Is_Shared_Passive (Defining_Entity
+                                              (Specification (Unit_Node))))
+           or else (Nkind (Unit_Node) = N_Package_Body
+                     and then
+                       Is_Shared_Passive (Corresponding_Spec (Unit_Node)))
+         then
+            --  Shared passive package
+
+            Add_Stub_Constructs (N);
+
+         elsif Nkind (Unit_Node) = N_Package_Instantiation
+           and then
+             Is_Remote_Call_Interface
+               (Defining_Entity (Specification (Instance_Spec (Unit_Node))))
+         then
+            --  Instantiation of a RCI generic package
+
+            Add_Stub_Constructs (N);
+         end if;
+
+         --  Reanalyze the unit with the new constructs
+
+         Analyze (Unit_Node);
+      end if;
+
+      if Nkind (Unit_Node) = N_Package_Declaration
+        or else Nkind (Unit_Node) in N_Generic_Declaration
+        or else Nkind (Unit_Node) = N_Package_Renaming_Declaration
+        or else Nkind (Unit_Node) = N_Subprogram_Declaration
+      then
+         Remove_Unit_From_Visibility (Defining_Entity (Unit_Node));
+
+      elsif Nkind (Unit_Node) = N_Package_Body
+        or else (Nkind (Unit_Node) = N_Subprogram_Body
+                  and then not Acts_As_Spec (Unit_Node))
+      then
+         --  Bodies that are not the main unit are compiled if they
+         --  are generic or contain generic or inlined units. Their
+         --  analysis brings in the context of the corresponding spec
+         --  (unit declaration) which must be removed as well, to
+         --  return the compilation environment to its proper state.
+
+         Remove_Context (Lib_Unit);
+         Set_Is_Immediately_Visible (Defining_Entity (Unit (Lib_Unit)), False);
+      end if;
+
+      --  Last step is to deinstall the context we just installed
+      --  as well as the unit just compiled.
+
+      Remove_Context (N);
+
+      --  If this is the main unit and we are generating code, we must
+      --  check that all generic units in the context have a body if they
+      --  need it, even if they have not been instantiated. In the absence
+      --  of .ali files for generic units, we must force the load of the body,
+      --  just to produce the proper error if the body is absent. We skip this
+      --  verification if the main unit itself is generic.
+
+      if Get_Cunit_Unit_Number (N) = Main_Unit
+        and then Operating_Mode = Generate_Code
+        and then Expander_Active
+      then
+         --  Indicate that the main unit is now analyzed, to catch possible
+         --  circularities between it and generic bodies. Remove main unit
+         --  from visibility. This might seem superfluous, but the main unit
+         --  must not be visible in the generic body expansions that follow.
+
+         Set_Analyzed (N, True);
+         Set_Is_Immediately_Visible (Cunit_Entity (Main_Unit), False);
+
+         declare
+            Item  : Node_Id;
+            Nam   : Entity_Id;
+            Un    : Unit_Number_Type;
+
+            Save_Style_Check : constant Boolean := Opt.Style_Check;
+            Save_C_Restrict  : constant Save_Compilation_Unit_Restrictions :=
+                                 Compilation_Unit_Restrictions_Save;
+
+         begin
+            Item := First (Context_Items (N));
+
+            while Present (Item) loop
+
+               if Nkind (Item) = N_With_Clause
+                  and then not Implicit_With (Item)
+               then
+                  Nam := Entity (Name (Item));
+
+                  if (Ekind (Nam) = E_Generic_Procedure
+                       and then not Is_Intrinsic_Subprogram (Nam))
+                    or else (Ekind (Nam) = E_Generic_Function
+                              and then not Is_Intrinsic_Subprogram (Nam))
+                    or else (Ekind (Nam) = E_Generic_Package
+                              and then Unit_Requires_Body (Nam))
+                  then
+                     Opt.Style_Check := False;
+
+                     if Present (Renamed_Object (Nam)) then
+                        Un :=
+                           Load_Unit
+                             (Load_Name  => Get_Body_Name
+                                              (Get_Unit_Name
+                                                (Unit_Declaration_Node
+                                                  (Renamed_Object (Nam)))),
+                              Required   => False,
+                              Subunit    => False,
+                              Error_Node => N,
+                              Renamings  => True);
+                     else
+                        Un :=
+                          Load_Unit
+                            (Load_Name  => Get_Body_Name
+                                             (Get_Unit_Name (Item)),
+                             Required   => False,
+                             Subunit    => False,
+                             Error_Node => N,
+                             Renamings  => True);
+                     end if;
+
+                     if Un = No_Unit then
+                        Error_Msg_NE
+                          ("body of generic unit& not found", Item, Nam);
+                        exit;
+
+                     elsif not Analyzed (Cunit (Un))
+                       and then Un /= Main_Unit
+                     then
+                        Opt.Style_Check := False;
+                        Semantics (Cunit (Un));
+                     end if;
+                  end if;
+               end if;
+
+               Next (Item);
+            end loop;
+
+            Style_Check := Save_Style_Check;
+            Compilation_Unit_Restrictions_Restore (Save_C_Restrict);
+         end;
+      end if;
+
+      --  Deal with creating elaboration Boolean if needed. We create an
+      --  elaboration boolean only for units that come from source since
+      --  units manufactured by the compiler never need elab checks.
+
+      if Comes_From_Source (N)
+        and then
+          (Nkind (Unit (N)) =  N_Package_Declaration         or else
+           Nkind (Unit (N)) =  N_Generic_Package_Declaration or else
+           Nkind (Unit (N)) =  N_Subprogram_Declaration      or else
+           Nkind (Unit (N)) =  N_Generic_Subprogram_Declaration)
+      then
+         declare
+            Loc  : constant Source_Ptr := Sloc (N);
+            Unum : constant Unit_Number_Type := Get_Source_Unit (Loc);
+
+         begin
+            Spec_Id := Defining_Entity (Unit (N));
+            Generate_Definition (Spec_Id);
+
+            --  See if an elaboration entity is required for possible
+            --  access before elaboration checking. Note that we must
+            --  allow for this even if -gnatE is not set, since a client
+            --  may be compiled in -gnatE mode and reference the entity.
+
+            --  Case of units which do not require elaboration checks
+
+            if
+               --  Pure units do not need checks
+
+                 Is_Pure (Spec_Id)
+
+               --  Preelaborated units do not need checks
+
+                 or else Is_Preelaborated (Spec_Id)
+
+               --  No checks needed if pagma Elaborate_Body present
+
+                 or else Has_Pragma_Elaborate_Body (Spec_Id)
+
+               --  No checks needed if unit does not require a body
+
+                 or else not Unit_Requires_Body (Spec_Id)
+
+               --  No checks needed for predefined files
+
+                 or else Is_Predefined_File_Name (Unit_File_Name (Unum))
+
+               --  No checks required if no separate spec
+
+                 or else Acts_As_Spec (N)
+            then
+               --  This is a case where we only need the entity for
+               --  checking to prevent multiple elaboration checks.
+
+               Set_Elaboration_Entity_Required (Spec_Id, False);
+
+            --  Case of elaboration entity is required for access before
+            --  elaboration checking (so certainly we must build it!)
+
+            else
+               Set_Elaboration_Entity_Required (Spec_Id, True);
+            end if;
+
+            Build_Elaboration_Entity (N, Spec_Id);
+         end;
+      end if;
+
+      --  Finally, freeze the compilation unit entity. This for sure is needed
+      --  because of some warnings that can be output (see Freeze_Subprogram),
+      --  but may in general be required. If freezing actions result, place
+      --  them in the compilation unit actions list, and analyze them.
+
+      declare
+         Loc : constant Source_Ptr := Sloc (N);
+         L   : constant List_Id :=
+                 Freeze_Entity (Cunit_Entity (Current_Sem_Unit), Loc);
+
+      begin
+         while Is_Non_Empty_List (L) loop
+            Insert_Library_Level_Action (Remove_Head (L));
+         end loop;
+      end;
+
+      Set_Analyzed (N);
+
+      if Nkind (Unit_Node) = N_Package_Declaration
+        and then Get_Cunit_Unit_Number (N) /= Main_Unit
+        and then Front_End_Inlining
+        and then Expander_Active
+      then
+         Check_Body_For_Inlining (N, Defining_Entity (Unit_Node));
+      end if;
+   end Analyze_Compilation_Unit;
+
+   ---------------------
+   -- Analyze_Context --
+   ---------------------
+
+   procedure Analyze_Context (N : Node_Id) is
+      Item  : Node_Id;
+
+   begin
+      --  Loop through context items
+
+      Item := First (Context_Items (N));
+      while Present (Item) loop
+
+         --  For with clause, analyze the with clause, and then update
+         --  the version, since we are dependent on a unit that we with.
+
+         if Nkind (Item) = N_With_Clause then
+
+            --  Skip analyzing with clause if no unit, nothing to do (this
+            --  happens for a with that references a non-existant unit)
+
+            if Present (Library_Unit (Item)) then
+               Analyze (Item);
+            end if;
+
+            if not Implicit_With (Item) then
+               Version_Update (N, Library_Unit (Item));
+            end if;
+
+         --  But skip use clauses at this stage, since we don't want to do
+         --  any installing of potentially use visible entities until we
+         --  we actually install the complete context (in Install_Context).
+         --  Otherwise things can get installed in the wrong context.
+         --  Similarly, pragmas are analyzed in Install_Context, after all
+         --  the implicit with's on parent units are generated.
+
+         else
+            null;
+         end if;
+
+         Next (Item);
+      end loop;
+   end Analyze_Context;
+
+   -------------------------------
+   -- Analyze_Package_Body_Stub --
+   -------------------------------
+
+   procedure Analyze_Package_Body_Stub (N : Node_Id) is
+      Id   : constant Entity_Id := Defining_Identifier (N);
+      Nam  : Entity_Id;
+
+   begin
+      --  The package declaration must be in the current declarative part.
+
+      Check_Stub_Level (N);
+      Nam := Current_Entity_In_Scope (Id);
+
+      if No (Nam) or else not Is_Package (Nam) then
+         Error_Msg_N ("missing specification for package stub", N);
+
+      elsif Has_Completion (Nam)
+        and then Present (Corresponding_Body (Unit_Declaration_Node (Nam)))
+      then
+         Error_Msg_N ("duplicate or redundant stub for package", N);
+
+      else
+         --  Indicate that the body of the package exists. If we are doing
+         --  only semantic analysis, the stub stands for the body. If we are
+         --  generating code, the existence of the body will be confirmed
+         --  when we load the proper body.
+
+         Set_Has_Completion (Nam);
+         Set_Scope (Defining_Entity (N), Current_Scope);
+         Analyze_Proper_Body (N, Nam);
+      end if;
+   end Analyze_Package_Body_Stub;
+
+   -------------------------
+   -- Analyze_Proper_Body --
+   -------------------------
+
+   procedure Analyze_Proper_Body (N : Node_Id; Nam : Entity_Id) is
+      Subunit_Name      : constant Unit_Name_Type := Get_Unit_Name (N);
+      Unum              : Unit_Number_Type;
+      Subunit_Not_Found : Boolean := False;
+
+      procedure Optional_Subunit;
+      --  This procedure is called when the main unit is a stub, or when we
+      --  are not generating code. In such a case, we analyze the subunit if
+      --  present, which is user-friendly and in fact required for ASIS, but
+      --  we don't complain if the subunit is missing.
+
+      ----------------------
+      -- Optional_Subunit --
+      ----------------------
+
+      procedure Optional_Subunit is
+         Comp_Unit : Node_Id;
+
+      begin
+         --  Try to load subunit, but ignore any errors that occur during
+         --  the loading of the subunit, by using the special feature in
+         --  Errout to ignore all errors. Note that Fatal_Error will still
+         --  be set, so we will be able to check for this case below.
+
+         Ignore_Errors_Enable := Ignore_Errors_Enable + 1;
+         Unum :=
+           Load_Unit
+             (Load_Name  => Subunit_Name,
+              Required   => False,
+              Subunit    => True,
+              Error_Node => N);
+         Ignore_Errors_Enable := Ignore_Errors_Enable - 1;
+
+         --  All done if we successfully loaded the subunit
+
+         if Unum /= No_Unit and then not Fatal_Error (Unum) then
+            Comp_Unit := Cunit (Unum);
+
+            Set_Corresponding_Stub (Unit (Comp_Unit), N);
+            Analyze_Subunit (Comp_Unit);
+            Set_Library_Unit (N, Comp_Unit);
+
+         elsif Unum = No_Unit
+           and then Present (Nam)
+         then
+            if Is_Protected_Type (Nam) then
+               Set_Corresponding_Body (Parent (Nam), Defining_Identifier (N));
+            else
+               Set_Corresponding_Body (
+                 Unit_Declaration_Node (Nam), Defining_Identifier (N));
+            end if;
+         end if;
+      end Optional_Subunit;
+
+   --  Start of processing for Analyze_Proper_Body
+
+   begin
+      --  If the subunit is already loaded, it means that the main unit
+      --  is a subunit, and that the current unit is one of its parents
+      --  which was being analyzed to provide the needed context for the
+      --  analysis of the subunit. In this case we analyze the subunit and
+      --  continue with the parent, without looking a subsequent subunits.
+
+      if Is_Loaded (Subunit_Name) then
+
+         --  If the proper body is already linked to the stub node,
+         --  the stub is in a generic unit and just needs analyzing.
+
+         if Present (Library_Unit (N)) then
+            Set_Corresponding_Stub (Unit (Library_Unit (N)), N);
+            Analyze_Subunit (Library_Unit (N));
+
+         --  Otherwise we must load the subunit and link to it
+
+         else
+            --  Load the subunit, this must work, since we originally
+            --  loaded the subunit earlier on. So this will not really
+            --  load it, just give access to it.
+
+            Unum :=
+              Load_Unit
+                (Load_Name  => Subunit_Name,
+                 Required   => True,
+                 Subunit    => False,
+                 Error_Node => N);
+
+            --  And analyze the subunit in the parent context (note that we
+            --  do not call Semantics, since that would remove the parent
+            --  context). Because of this, we have to manually reset the
+            --  compiler state to Analyzing since it got destroyed by Load.
+
+            if Unum /= No_Unit then
+               Compiler_State := Analyzing;
+               Set_Corresponding_Stub (Unit (Cunit (Unum)), N);
+               Analyze_Subunit (Cunit (Unum));
+               Set_Library_Unit (N, Cunit (Unum));
+            end if;
+         end if;
+
+      --  If the main unit is a subunit, then we are just performing semantic
+      --  analysis on that subunit, and any other subunits of any parent unit
+      --  should be ignored, except that if we are building trees for ASIS
+      --  usage we want to annotate the stub properly.
+
+      elsif Nkind (Unit (Cunit (Main_Unit))) = N_Subunit
+        and then Subunit_Name /= Unit_Name (Main_Unit)
+      then
+         if Tree_Output then
+            Optional_Subunit;
+         end if;
+
+         --  But before we return, set the flag for unloaded subunits. This
+         --  will suppress junk warnings of variables in the same declarative
+         --  part (or a higher level one) that are in danger of looking unused
+         --  when in fact there might be a declaration in the subunit that we
+         --  do not intend to load.
+
+         Unloaded_Subunits := True;
+         return;
+
+      --  If the subunit is not already loaded, and we are generating code,
+      --  then this is the case where compilation started from the parent,
+      --  and we are generating code for an entire subunit tree. In that
+      --  case we definitely need to load the subunit.
+
+      --  In order to continue the analysis with the rest of the parent,
+      --  and other subunits, we load the unit without requiring its
+      --  presence, and emit a warning if not found, rather than terminating
+      --  the compilation abruptly, as for other missing file problems.
+
+      elsif Operating_Mode = Generate_Code then
+
+         --  If the proper body is already linked to the stub node,
+         --  the stub is in a generic unit and just needs analyzing.
+
+         --  We update the version. Although we are not technically
+         --  semantically dependent on the subunit, given our approach
+         --  of macro substitution of subunits, it makes sense to
+         --  include it in the version identification.
+
+         if Present (Library_Unit (N)) then
+            Set_Corresponding_Stub (Unit (Library_Unit (N)), N);
+            Analyze_Subunit (Library_Unit (N));
+            Version_Update (Cunit (Main_Unit), Library_Unit (N));
+
+         --  Otherwise we must load the subunit and link to it
+
+         else
+            Unum :=
+              Load_Unit
+                (Load_Name  => Subunit_Name,
+                 Required   => False,
+                 Subunit    => True,
+                 Error_Node => N);
+
+            if Operating_Mode = Generate_Code
+              and then Unum = No_Unit
+            then
+               Error_Msg_Name_1 := Subunit_Name;
+               Error_Msg_Name_2 :=
+                 Get_File_Name (Subunit_Name, Subunit => True);
+               Error_Msg_N
+                 ("subunit% in file{ not found!?", N);
+               Subunits_Missing := True;
+               Subunit_Not_Found := True;
+            end if;
+
+            --  Load_Unit may reset Compiler_State, since it may have been
+            --  necessary to parse an additional units, so we make sure
+            --  that we reset it to the Analyzing state.
+
+            Compiler_State := Analyzing;
+
+            if Unum /= No_Unit and then not Fatal_Error (Unum) then
+
+               if Debug_Flag_L then
+                  Write_Str ("*** Loaded subunit from stub. Analyze");
+                  Write_Eol;
+               end if;
+
+               declare
+                  Comp_Unit : constant Node_Id := Cunit (Unum);
+
+               begin
+                  --  Check for child unit instead of subunit
+
+                  if Nkind (Unit (Comp_Unit)) /= N_Subunit then
+                     Error_Msg_N
+                       ("expected SEPARATE subunit, found child unit",
+                        Cunit_Entity (Unum));
+
+                  --  OK, we have a subunit, so go ahead and analyze it,
+                  --  and set Scope of entity in stub, for ASIS use.
+
+                  else
+                     Set_Corresponding_Stub (Unit (Comp_Unit), N);
+                     Analyze_Subunit (Comp_Unit);
+                     Set_Library_Unit (N, Comp_Unit);
+
+                     --  We update the version. Although we are not technically
+                     --  semantically dependent on the subunit, given our
+                     --  approach of macro substitution of subunits, it makes
+                     --  sense to include it in the version identification.
+
+                     Version_Update (Cunit (Main_Unit), Comp_Unit);
+                  end if;
+               end;
+            end if;
+         end if;
+
+         --  The remaining case is when the subunit is not already loaded and
+         --  we are not generating code. In this case we are just performing
+         --  semantic analysis on the parent, and we are not interested in
+         --  the subunit. For subprograms, analyze the stub as a body. For
+         --  other entities the stub has already been marked as completed.
+
+      else
+         Optional_Subunit;
+      end if;
+
+   end Analyze_Proper_Body;
+
+   ----------------------------------
+   -- Analyze_Protected_Body_Stub --
+   ----------------------------------
+
+   procedure Analyze_Protected_Body_Stub (N : Node_Id) is
+      Nam : Entity_Id := Current_Entity_In_Scope (Defining_Identifier (N));
+
+   begin
+      Check_Stub_Level (N);
+
+      --  First occurence of name may have been as an incomplete type.
+
+      if Present (Nam) and then Ekind (Nam) = E_Incomplete_Type then
+         Nam := Full_View (Nam);
+      end if;
+
+      if No (Nam)
+        or else not Is_Protected_Type (Etype (Nam))
+      then
+         Error_Msg_N ("missing specification for Protected body", N);
+      else
+         Set_Scope (Defining_Entity (N), Current_Scope);
+         Set_Has_Completion (Etype (Nam));
+         Analyze_Proper_Body (N, Etype (Nam));
+      end if;
+   end Analyze_Protected_Body_Stub;
+
+   ----------------------------------
+   -- Analyze_Subprogram_Body_Stub --
+   ----------------------------------
+
+   --  A subprogram body stub can appear with or without a previous
+   --  specification. If there is one, the analysis of the body will
+   --  find it and verify conformance.  The formals appearing in the
+   --  specification of the stub play no role, except for requiring an
+   --  additional conformance check. If there is no previous subprogram
+   --  declaration, the stub acts as a spec, and provides the defining
+   --  entity for the subprogram.
+
+   procedure Analyze_Subprogram_Body_Stub (N : Node_Id) is
+      Decl : Node_Id;
+
+   begin
+      Check_Stub_Level (N);
+
+      --  Verify that the identifier for the stub is unique within this
+      --  declarative part.
+
+      if Nkind (Parent (N)) = N_Block_Statement
+        or else Nkind (Parent (N)) = N_Package_Body
+        or else Nkind (Parent (N)) = N_Subprogram_Body
+      then
+         Decl := First (Declarations (Parent (N)));
+
+         while Present (Decl)
+           and then Decl /= N
+         loop
+            if Nkind (Decl) = N_Subprogram_Body_Stub
+              and then (Chars (Defining_Unit_Name (Specification (Decl)))
+                      = Chars (Defining_Unit_Name (Specification (N))))
+            then
+               Error_Msg_N ("identifier for stub is not unique", N);
+            end if;
+
+            Next (Decl);
+         end loop;
+      end if;
+
+      --  Treat stub as a body, which checks conformance if there is a previous
+      --  declaration, or else introduces entity and its signature.
+
+      Analyze_Subprogram_Body (N);
+
+      if Errors_Detected = 0 then
+         Analyze_Proper_Body (N, Empty);
+      end if;
+
+   end Analyze_Subprogram_Body_Stub;
+
+   ---------------------
+   -- Analyze_Subunit --
+   ---------------------
+
+   --  A subunit is compiled either by itself (for semantic checking)
+   --  or as part of compiling the parent (for code generation). In
+   --  either case, by the time we actually process the subunit, the
+   --  parent has already been installed and analyzed. The node N is
+   --  a compilation unit, whose context needs to be treated here,
+   --  because we come directly here from the parent without calling
+   --  Analyze_Compilation_Unit.
+
+   --  The compilation context includes the explicit context of the
+   --  subunit, and the context of the parent, together with the parent
+   --  itself. In order to compile the current context, we remove the
+   --  one inherited from the parent, in order to have a clean visibility
+   --  table. We restore the parent context before analyzing the proper
+   --  body itself. On exit, we remove only the explicit context of the
+   --  subunit.
+
+   procedure Analyze_Subunit (N : Node_Id) is
+      Lib_Unit : constant Node_Id   := Library_Unit (N);
+      Par_Unit : constant Entity_Id := Current_Scope;
+
+      Lib_Spec        : Node_Id := Library_Unit (Lib_Unit);
+      Num_Scopes      : Int := 0;
+      Use_Clauses     : array (1 .. Scope_Stack.Last) of Node_Id;
+      Enclosing_Child : Entity_Id := Empty;
+
+      procedure Analyze_Subunit_Context;
+      --  Capture names in use clauses of the subunit. This must be done
+      --  before re-installing parent declarations, because items in the
+      --  context must not be hidden by declarations local to the parent.
+
+      procedure Re_Install_Parents (L : Node_Id; Scop : Entity_Id);
+      --  Recursive procedure to restore scope of all ancestors of subunit,
+      --  from outermost in. If parent is not a subunit, the call to install
+      --  context installs context of spec and (if parent is a child unit)
+      --  the context of its parents as well. It is confusing that parents
+      --  should be treated differently in both cases, but the semantics are
+      --  just not identical.
+
+      procedure Re_Install_Use_Clauses;
+      --  As part of the removal of the parent scope, the use clauses are
+      --  removed, to be reinstalled when the context of the subunit has
+      --  been analyzed. Use clauses may also have been affected by the
+      --  analysis of the context of the subunit, so they have to be applied
+      --  again, to insure that the compilation environment of the rest of
+      --  the parent unit is identical.
+
+      procedure Remove_Scope;
+      --  Remove current scope from scope stack, and preserve the list
+      --  of use clauses in it, to be reinstalled after context is analyzed.
+
+      ------------------------------
+      --  Analyze_Subunit_Context --
+      ------------------------------
+
+      procedure Analyze_Subunit_Context is
+         Item      :  Node_Id;
+         Nam       :  Node_Id;
+         Unit_Name : Entity_Id;
+
+      begin
+         Analyze_Context (N);
+         Item := First (Context_Items (N));
+
+         --  make withed units immediately visible. If child unit, make the
+         --  ultimate parent immediately visible.
+
+         while Present (Item) loop
+
+            if Nkind (Item) = N_With_Clause then
+               Unit_Name := Entity (Name (Item));
+
+               while Is_Child_Unit (Unit_Name) loop
+                  Set_Is_Visible_Child_Unit (Unit_Name);
+                  Unit_Name := Scope (Unit_Name);
+               end loop;
+
+               if not Is_Immediately_Visible (Unit_Name) then
+                  Set_Is_Immediately_Visible (Unit_Name);
+                  Set_Context_Installed (Item);
+               end if;
+
+            elsif Nkind (Item) = N_Use_Package_Clause then
+               Nam := First (Names (Item));
+
+               while Present (Nam) loop
+                  Analyze (Nam);
+                  Next (Nam);
+               end loop;
+
+            elsif Nkind (Item) = N_Use_Type_Clause then
+               Nam := First (Subtype_Marks (Item));
+
+               while Present (Nam) loop
+                  Analyze (Nam);
+                  Next (Nam);
+               end loop;
+            end if;
+
+            Next (Item);
+         end loop;
+
+         Item := First (Context_Items (N));
+
+         --  reset visibility of withed units. They will be made visible
+         --  again when we install the subunit context.
+
+         while Present (Item) loop
+
+            if Nkind (Item) = N_With_Clause then
+               Unit_Name := Entity (Name (Item));
+
+               while Is_Child_Unit (Unit_Name) loop
+                  Set_Is_Visible_Child_Unit (Unit_Name, False);
+                  Unit_Name := Scope (Unit_Name);
+               end loop;
+
+               if Context_Installed (Item) then
+                  Set_Is_Immediately_Visible (Unit_Name, False);
+                  Set_Context_Installed (Item, False);
+               end if;
+            end if;
+
+            Next (Item);
+         end loop;
+
+      end Analyze_Subunit_Context;
+
+      ------------------------
+      -- Re_Install_Parents --
+      ------------------------
+
+      procedure Re_Install_Parents (L : Node_Id; Scop : Entity_Id) is
+         E : Entity_Id;
+
+      begin
+         if Nkind (Unit (L)) = N_Subunit then
+            Re_Install_Parents (Library_Unit (L), Scope (Scop));
+         end if;
+
+         Install_Context (L);
+
+         --  If the subunit occurs within a child unit, we must restore the
+         --  immediate visibility of any siblings that may occur in context.
+
+         if Present (Enclosing_Child) then
+            Install_Siblings (Enclosing_Child, L);
+         end if;
+
+         New_Scope (Scop);
+
+         if Scop /= Par_Unit then
+            Set_Is_Immediately_Visible (Scop);
+         end if;
+
+         E := First_Entity (Current_Scope);
+
+         while Present (E) loop
+            Set_Is_Immediately_Visible (E);
+            Next_Entity (E);
+         end loop;
+
+         --  A subunit appears within a body, and for a nested subunits
+         --  all the parents are bodies. Restore full visibility of their
+         --  private entities.
+
+         if Ekind (Scop) = E_Package then
+            Set_In_Package_Body (Scop);
+            Install_Private_Declarations (Scop);
+         end if;
+      end Re_Install_Parents;
+
+      ----------------------------
+      -- Re_Install_Use_Clauses --
+      ----------------------------
+
+      procedure Re_Install_Use_Clauses is
+         U  : Node_Id;
+
+      begin
+         for J in reverse 1 .. Num_Scopes loop
+            U := Use_Clauses (J);
+            Scope_Stack.Table (Scope_Stack.Last - J + 1).First_Use_Clause := U;
+            Install_Use_Clauses (U);
+         end loop;
+      end Re_Install_Use_Clauses;
+
+      ------------------
+      -- Remove_Scope --
+      ------------------
+
+      procedure Remove_Scope is
+         E : Entity_Id;
+
+      begin
+         Num_Scopes := Num_Scopes + 1;
+         Use_Clauses (Num_Scopes) :=
+               Scope_Stack.Table (Scope_Stack.Last).First_Use_Clause;
+         E := First_Entity (Current_Scope);
+
+         while Present (E) loop
+            Set_Is_Immediately_Visible (E, False);
+            Next_Entity (E);
+         end loop;
+
+         if Is_Child_Unit (Current_Scope) then
+            Enclosing_Child := Current_Scope;
+         end if;
+
+         Pop_Scope;
+      end Remove_Scope;
+
+   --  Start of processing for Analyze_Subunit
+
+   begin
+      if not Is_Empty_List (Context_Items (N)) then
+
+         --  Save current use clauses.
+
+         Remove_Scope;
+         Remove_Context (Lib_Unit);
+
+         --  Now remove parents and their context, including enclosing
+         --  subunits and the outer parent body which is not a subunit.
+
+         if Present (Lib_Spec) then
+            Remove_Context (Lib_Spec);
+
+            while Nkind (Unit (Lib_Spec)) = N_Subunit loop
+               Lib_Spec := Library_Unit (Lib_Spec);
+               Remove_Scope;
+               Remove_Context (Lib_Spec);
+            end loop;
+
+            if Nkind (Unit (Lib_Unit)) = N_Subunit then
+               Remove_Scope;
+            end if;
+
+            if Nkind (Unit (Lib_Spec)) = N_Package_Body then
+               Remove_Context (Library_Unit (Lib_Spec));
+            end if;
+         end if;
+
+         Analyze_Subunit_Context;
+         Re_Install_Parents (Lib_Unit, Par_Unit);
+
+         --  If the context includes a child unit of the parent of the
+         --  subunit, the parent will have been removed from visibility,
+         --  after compiling that cousin in the context. The visibility
+         --  of the parent must be restored now. This also applies if the
+         --  context includes another subunit of the same parent which in
+         --  turn includes a child unit in its context.
+
+         if Ekind (Par_Unit) = E_Package then
+            if not Is_Immediately_Visible (Par_Unit)
+              or else (Present (First_Entity (Par_Unit))
+                        and then not Is_Immediately_Visible
+                                      (First_Entity (Par_Unit)))
+            then
+               Set_Is_Immediately_Visible   (Par_Unit);
+               Install_Visible_Declarations (Par_Unit);
+               Install_Private_Declarations (Par_Unit);
+            end if;
+         end if;
+
+         Re_Install_Use_Clauses;
+         Install_Context (N);
+
+         --  If the subunit is within a child unit, then siblings of any
+         --  parent unit that appear in the context clause of the subunit
+         --  must also be made immediately visible.
+
+         if Present (Enclosing_Child) then
+            Install_Siblings (Enclosing_Child, N);
+         end if;
+
+      end if;
+
+      Analyze (Proper_Body (Unit (N)));
+      Remove_Context (N);
+
+   end Analyze_Subunit;
+
+   ----------------------------
+   -- Analyze_Task_Body_Stub --
+   ----------------------------
+
+   procedure Analyze_Task_Body_Stub (N : Node_Id) is
+      Nam : Entity_Id := Current_Entity_In_Scope (Defining_Identifier (N));
+      Loc : constant Source_Ptr := Sloc (N);
+
+   begin
+      Check_Stub_Level (N);
+
+      --  First occurence of name may have been as an incomplete type.
+
+      if Present (Nam) and then Ekind (Nam) = E_Incomplete_Type then
+         Nam := Full_View (Nam);
+      end if;
+
+      if No (Nam)
+        or else not Is_Task_Type (Etype (Nam))
+      then
+         Error_Msg_N ("missing specification for task body", N);
+      else
+         Set_Scope (Defining_Entity (N), Current_Scope);
+         Set_Has_Completion (Etype (Nam));
+         Analyze_Proper_Body (N, Etype (Nam));
+
+         --  Set elaboration flag to indicate that entity is callable.
+         --  This cannot be done in the expansion of the body  itself,
+         --  because the proper body is not in a declarative part. This
+         --  is only done if expansion is active, because the context
+         --  may be generic and the flag not defined yet.
+
+         if Expander_Active then
+            Insert_After (N,
+              Make_Assignment_Statement (Loc,
+                Name =>
+                  Make_Identifier (Loc,
+                    New_External_Name (Chars (Etype (Nam)), 'E')),
+                 Expression => New_Reference_To (Standard_True, Loc)));
+         end if;
+
+      end if;
+   end Analyze_Task_Body_Stub;
+
+   -------------------------
+   -- Analyze_With_Clause --
+   -------------------------
+
+   --  Analyze the declaration of a unit in a with clause. At end,
+   --  label the with clause with the defining entity for the unit.
+
+   procedure Analyze_With_Clause (N : Node_Id) is
+      Unit_Kind : constant Node_Kind := Nkind (Unit (Library_Unit (N)));
+      E_Name    : Entity_Id;
+      Par_Name  : Entity_Id;
+      Pref      : Node_Id;
+      U         : Node_Id;
+
+      Intunit : Boolean;
+      --  Set True if the unit currently being compiled is an internal unit
+
+      Save_Style_Check : constant Boolean := Opt.Style_Check;
+      Save_C_Restrict  : constant Save_Compilation_Unit_Restrictions :=
+                           Compilation_Unit_Restrictions_Save;
+
+   begin
+      --  We reset ordinary style checking during the analysis of a with'ed
+      --  unit, but we do NOT reset GNAT special analysis mode (the latter
+      --  definitely *does* apply to with'ed units).
+
+      if not GNAT_Mode then
+         Style_Check := False;
+      end if;
+
+      --  If the library unit is a predefined unit, and we are in no
+      --  run time mode, then temporarily reset No_Run_Time mode for the
+      --  analysis of the with'ed unit. The No_Run_Time pragma does not
+      --  prevent explicit with'ing of run-time units.
+
+      if No_Run_Time
+        and then
+          Is_Predefined_File_Name
+            (Unit_File_Name (Get_Source_Unit (Unit (Library_Unit (N)))))
+      then
+         No_Run_Time := False;
+         Semantics (Library_Unit (N));
+         No_Run_Time := True;
+
+      else
+         Semantics (Library_Unit (N));
+      end if;
+
+      U := Unit (Library_Unit (N));
+      Intunit := Is_Internal_File_Name (Unit_File_Name (Current_Sem_Unit));
+
+      --  Following checks are skipped for dummy packages (those supplied
+      --  for with's where no matching file could be found). Such packages
+      --  are identified by the Sloc value being set to No_Location
+
+      if Sloc (U) /= No_Location then
+
+         --  Check restrictions, except that we skip the check if this
+         --  is an internal unit unless we are compiling the internal
+         --  unit as the main unit. We also skip this for dummy packages.
+
+         if not Intunit or else Current_Sem_Unit = Main_Unit then
+            Check_Restricted_Unit (Unit_Name (Get_Source_Unit (U)), N);
+         end if;
+
+         --  Check for inappropriate with of internal implementation unit
+         --  if we are currently compiling the main unit and the main unit
+         --  is itself not an internal unit.
+
+         if Implementation_Unit_Warnings
+           and then Current_Sem_Unit = Main_Unit
+           and then Implementation_Unit (Get_Source_Unit (U))
+           and then not Intunit
+         then
+            Error_Msg_N ("& is an internal 'G'N'A'T unit?", Name (N));
+            Error_Msg_N
+              ("\use of this unit is non-portable and version-dependent?",
+               Name (N));
+         end if;
+      end if;
+
+      --  Semantic analysis of a generic unit is performed on a copy of
+      --  the original tree. Retrieve the entity on  which semantic info
+      --  actually appears.
+
+      if Unit_Kind in N_Generic_Declaration then
+         E_Name := Defining_Entity (U);
+
+      --  Note: in the following test, Unit_Kind is the original Nkind, but
+      --  in the case of an instantiation, the call to Semantics above will
+      --  have replaced the unit by its instantiated version.
+
+      elsif Unit_Kind = N_Package_Instantiation
+        and then Nkind (U) = N_Package_Body
+      then
+         --  Instantiation node is replaced with body of instance.
+         --  Unit name is defining unit name in corresponding spec.
+
+         E_Name := Corresponding_Spec (U);
+
+      elsif Unit_Kind = N_Package_Instantiation
+        and then Nkind (U) = N_Package_Instantiation
+      then
+         --  If the instance has not been rewritten as a package declaration,
+         --  then it appeared already in a previous with clause. Retrieve
+         --  the entity from the previous instance.
+
+         E_Name := Defining_Entity (Specification (Instance_Spec (U)));
+
+      elsif Unit_Kind = N_Procedure_Instantiation
+        or else Unit_Kind = N_Function_Instantiation
+      then
+         --  Instantiation node is replaced with a package that contains
+         --  renaming declarations and instance itself. The subprogram
+         --  Instance is declared in the visible part of the wrapper package.
+
+         E_Name := First_Entity (Defining_Entity (U));
+
+         while Present (E_Name) loop
+            exit when Is_Subprogram (E_Name)
+              and then Is_Generic_Instance (E_Name);
+            E_Name := Next_Entity (E_Name);
+         end loop;
+
+      elsif Unit_Kind = N_Package_Renaming_Declaration
+        or else Unit_Kind in N_Generic_Renaming_Declaration
+      then
+         E_Name := Defining_Entity (U);
+
+      elsif Unit_Kind = N_Subprogram_Body
+        and then Nkind (Name (N)) = N_Selected_Component
+        and then not Acts_As_Spec (Library_Unit (N))
+      then
+         --  For a child unit that has no spec, one has been created and
+         --  analyzed. The entity required is that of the spec.
+
+         E_Name := Corresponding_Spec (U);
+
+      else
+         E_Name := Defining_Entity (U);
+      end if;
+
+      if Nkind (Name (N)) = N_Selected_Component then
+
+         --  Child unit in a with clause
+
+         Change_Selected_Component_To_Expanded_Name (Name (N));
+      end if;
+
+      --  Restore style checks and restrictions
+
+      Style_Check := Save_Style_Check;
+      Compilation_Unit_Restrictions_Restore (Save_C_Restrict);
+
+      --  Record the reference, but do NOT set the unit as referenced, we
+      --  want to consider the unit as unreferenced if this is the only
+      --  reference that occurs.
+
+      Set_Entity_With_Style_Check (Name (N), E_Name);
+      Generate_Reference (E_Name, Name (N), Set_Ref => False);
+
+      if Is_Child_Unit (E_Name) then
+         Pref     := Prefix (Name (N));
+         Par_Name := Scope (E_Name);
+
+         while Nkind (Pref) = N_Selected_Component loop
+            Change_Selected_Component_To_Expanded_Name (Pref);
+            Set_Entity_With_Style_Check (Pref, Par_Name);
+
+            Generate_Reference (Par_Name, Pref);
+            Pref := Prefix (Pref);
+            Par_Name := Scope (Par_Name);
+         end loop;
+
+         if Present (Entity (Pref))
+           and then not Analyzed (Parent (Parent (Entity (Pref))))
+         then
+            --  If the entity is set without its unit being compiled,
+            --  the original parent is a renaming, and Par_Name is the
+            --  renamed entity. For visibility purposes, we need the
+            --  original entity, which must be analyzed now, because
+            --  Load_Unit retrieves directly the renamed unit, and the
+            --  renaming declaration itself has not been analyzed.
+
+            Analyze (Parent (Parent (Entity (Pref))));
+            pragma Assert (Renamed_Object (Entity (Pref)) = Par_Name);
+            Par_Name := Entity (Pref);
+         end if;
+
+         Set_Entity_With_Style_Check (Pref, Par_Name);
+         Generate_Reference (Par_Name, Pref);
+      end if;
+
+      --  If the withed unit is System, and a system extension pragma is
+      --  present, compile the extension now, rather than waiting for
+      --  a visibility check on a specific entity.
+
+      if Chars (E_Name) = Name_System
+        and then Scope (E_Name) = Standard_Standard
+        and then Present (System_Extend_Pragma_Arg)
+        and then Present_System_Aux (N)
+      then
+         --  If the extension is not present, an error will have been emitted.
+
+         null;
+      end if;
+   end Analyze_With_Clause;
+
+   ------------------------------
+   -- Analyze_With_Type_Clause --
+   ------------------------------
+
+   procedure Analyze_With_Type_Clause (N : Node_Id) is
+      Loc  : constant Source_Ptr := Sloc (N);
+      Nam  : Node_Id := Name (N);
+      Pack : Node_Id;
+      Decl : Node_Id;
+      P    : Entity_Id;
+      Unum : Unit_Number_Type;
+      Sel  : Node_Id;
+
+      procedure Decorate_Tagged_Type (T : Entity_Id; Kind : Entity_Kind);
+      --  Set basic attributes of type, including its class_wide type.
+
+      function In_Chain (E : Entity_Id) return Boolean;
+      --  Check that the imported type is not already in the homonym chain,
+      --  for example through a with_type clause in a parent unit.
+
+      --------------------------
+      -- Decorate_Tagged_Type --
+      --------------------------
+
+      procedure Decorate_Tagged_Type (T : Entity_Id; Kind : Entity_Kind) is
+         CW : Entity_Id;
+
+      begin
+         Set_Ekind (T, E_Record_Type);
+         Set_Is_Tagged_Type (T);
+         Set_Etype (T, T);
+         Set_From_With_Type (T);
+         Set_Scope (T, P);
+
+         if not In_Chain (T) then
+            Set_Homonym (T, Current_Entity (T));
+            Set_Current_Entity (T);
+         end if;
+
+         --  Build bogus class_wide type, if not previously done.
+
+         if No (Class_Wide_Type (T)) then
+            CW := Make_Defining_Identifier (Loc,  New_Internal_Name ('S'));
+
+            Set_Ekind            (CW, E_Class_Wide_Type);
+            Set_Etype            (CW, T);
+            Set_Scope            (CW, P);
+            Set_Is_Tagged_Type   (CW);
+            Set_Is_First_Subtype (CW, True);
+            Init_Size_Align      (CW);
+            Set_Has_Unknown_Discriminants
+                                 (CW, True);
+            Set_Class_Wide_Type  (CW, CW);
+            Set_Equivalent_Type  (CW, Empty);
+            Set_From_With_Type   (CW);
+
+            Set_Class_Wide_Type (T, CW);
+         end if;
+      end Decorate_Tagged_Type;
+
+      --------------
+      -- In_Chain --
+      --------------
+
+      function In_Chain (E : Entity_Id) return Boolean is
+         H : Entity_Id := Current_Entity (E);
+
+      begin
+         while Present (H) loop
+
+            if H = E then
+               return True;
+            else
+               H := Homonym (H);
+            end if;
+         end loop;
+
+         return False;
+      end In_Chain;
+
+   --  Start of processing for Analyze_With_Type_Clause
+
+   begin
+      if Nkind (Nam) = N_Selected_Component then
+         Pack := New_Copy_Tree (Prefix (Nam));
+         Sel  := Selector_Name (Nam);
+
+      else
+         Error_Msg_N ("illegal name for imported type", Nam);
+         return;
+      end if;
+
+      Decl :=
+        Make_Package_Declaration (Loc,
+          Specification =>
+             (Make_Package_Specification (Loc,
+               Defining_Unit_Name   => Pack,
+               Visible_Declarations => New_List,
+               End_Label            => Empty)));
+
+      Unum :=
+        Load_Unit
+          (Load_Name  => Get_Unit_Name (Decl),
+           Required   => True,
+           Subunit    => False,
+           Error_Node => Nam);
+
+      if Unum = No_Unit
+         or else Nkind (Unit (Cunit (Unum))) /= N_Package_Declaration
+      then
+         Error_Msg_N ("imported type must be declared in package", Nam);
+         return;
+
+      elsif Unum = Current_Sem_Unit then
+
+         --  If type is defined in unit being analyzed, then the clause
+         --  is redundant.
+
+         return;
+
+      else
+         P := Cunit_Entity (Unum);
+      end if;
+
+      --  Find declaration for imported type, and set its basic attributes
+      --  if it has not been analyzed (which will be the case if there is
+      --  circular dependence).
+
+      declare
+         Decl : Node_Id;
+         Typ  : Entity_Id;
+
+      begin
+         if not Analyzed (Cunit (Unum))
+           and then not From_With_Type (P)
+         then
+            Set_Ekind (P, E_Package);
+            Set_Etype (P, Standard_Void_Type);
+            Set_From_With_Type (P);
+            Set_Scope (P, Standard_Standard);
+            Set_Homonym (P, Current_Entity (P));
+            Set_Current_Entity (P);
+
+         elsif Analyzed (Cunit (Unum))
+           and then Is_Child_Unit (P)
+         then
+            --  If the child unit is already in scope, indicate that it is
+            --  visible, and remains so after intervening calls to rtsfind.
+
+            Set_Is_Visible_Child_Unit (P);
+         end if;
+
+         if Nkind (Parent (P)) = N_Defining_Program_Unit_Name then
+
+            --  Make parent packages visible.
+
+            declare
+               Parent_Comp : Node_Id;
+               Parent_Id   : Entity_Id;
+               Child       : Entity_Id;
+
+            begin
+               Child   := P;
+               Parent_Comp := Parent_Spec (Unit (Cunit (Unum)));
+
+               loop
+                  Parent_Id := Defining_Entity (Unit (Parent_Comp));
+                  Set_Scope (Child, Parent_Id);
+
+                  --  The type may be imported from a child unit, in which
+                  --  case the current compilation appears in the name. Do
+                  --  not change its visibility here because it will conflict
+                  --  with the subsequent normal processing.
+
+                  if not Analyzed (Unit_Declaration_Node (Parent_Id))
+                    and then Parent_Id /= Cunit_Entity (Current_Sem_Unit)
+                  then
+                     Set_Ekind (Parent_Id, E_Package);
+                     Set_Etype (Parent_Id, Standard_Void_Type);
+
+                     --  The same package may appear is several with_type
+                     --  clauses.
+
+                     if not From_With_Type (Parent_Id) then
+                        Set_Homonym (Parent_Id, Current_Entity (Parent_Id));
+                        Set_Current_Entity (Parent_Id);
+                        Set_From_With_Type (Parent_Id);
+                     end if;
+                  end if;
+
+                  Set_Is_Immediately_Visible (Parent_Id);
+
+                  Child := Parent_Id;
+                  Parent_Comp := Parent_Spec (Unit (Parent_Comp));
+                  exit when No (Parent_Comp);
+               end loop;
+
+               Set_Scope (Parent_Id, Standard_Standard);
+            end;
+         end if;
+
+         --  Even if analyzed, the package may not be currently visible. It
+         --  must be while the with_type clause is active.
+
+         Set_Is_Immediately_Visible (P);
+
+         Decl :=
+           First (Visible_Declarations (Specification (Unit (Cunit (Unum)))));
+
+         while Present (Decl) loop
+
+            if Nkind (Decl) = N_Full_Type_Declaration
+              and then Chars (Defining_Identifier (Decl)) = Chars (Sel)
+            then
+               Typ := Defining_Identifier (Decl);
+
+               if Tagged_Present (N) then
+
+                  --  The declaration must indicate that this is a tagged
+                  --  type or a type extension.
+
+                  if (Nkind (Type_Definition (Decl)) = N_Record_Definition
+                       and then Tagged_Present (Type_Definition (Decl)))
+                    or else
+                      (Nkind (Type_Definition (Decl))
+                          = N_Derived_Type_Definition
+                         and then Present
+                           (Record_Extension_Part (Type_Definition (Decl))))
+                  then
+                     null;
+                  else
+                     Error_Msg_N ("imported type is not a tagged type", Nam);
+                     return;
+                  end if;
+
+                  if not Analyzed (Decl) then
+
+                     --  Unit is not currently visible. Add basic attributes
+                     --  to type and build its class-wide type.
+
+                     Init_Size_Align (Typ);
+                     Decorate_Tagged_Type (Typ, E_Record_Type);
+                  end if;
+
+               else
+                  if Nkind (Type_Definition (Decl))
+                     /= N_Access_To_Object_Definition
+                  then
+                     Error_Msg_N
+                      ("imported type is not an access type", Nam);
+
+                  elsif not Analyzed (Decl) then
+                     Set_Ekind                    (Typ, E_Access_Type);
+                     Set_Etype                    (Typ, Typ);
+                     Set_Scope                    (Typ, P);
+                     Init_Size                    (Typ, System_Address_Size);
+                     Init_Alignment               (Typ);
+                     Set_Directly_Designated_Type (Typ, Standard_Integer);
+                     Set_From_With_Type           (Typ);
+
+                     if not In_Chain (Typ) then
+                        Set_Homonym               (Typ, Current_Entity (Typ));
+                        Set_Current_Entity        (Typ);
+                     end if;
+                  end if;
+               end if;
+
+               Set_Entity (Sel, Typ);
+               return;
+
+            elsif ((Nkind (Decl) = N_Private_Type_Declaration
+                      and then Tagged_Present (Decl))
+                or else (Nkind (Decl) = N_Private_Extension_Declaration))
+              and then Chars (Defining_Identifier (Decl)) = Chars (Sel)
+            then
+               Typ := Defining_Identifier (Decl);
+
+               if not Tagged_Present (N) then
+                  Error_Msg_N ("type must be declared tagged", N);
+
+               elsif not Analyzed (Decl) then
+                  Decorate_Tagged_Type (Typ, E_Private_Type);
+               end if;
+
+               Set_Entity (Sel, Typ);
+               Set_From_With_Type (Typ);
+               return;
+            end if;
+
+            Decl := Next (Decl);
+         end loop;
+
+         Error_Msg_NE ("not a visible access or tagged type in&", Nam, P);
+      end;
+   end Analyze_With_Type_Clause;
+
+   -----------------------------
+   -- Check_With_Type_Clauses --
+   -----------------------------
+
+   procedure Check_With_Type_Clauses (N : Node_Id) is
+      Lib_Unit : constant Node_Id := Unit (N);
+
+      procedure Check_Parent_Context (U : Node_Id);
+      --  Examine context items of parent unit to locate with_type clauses.
+
+      --------------------------
+      -- Check_Parent_Context --
+      --------------------------
+
+      procedure Check_Parent_Context (U : Node_Id) is
+         Item : Node_Id;
+
+      begin
+         Item := First (Context_Items (U));
+         while Present (Item) loop
+            if Nkind (Item) = N_With_Type_Clause
+              and then not Error_Posted (Item)
+              and then
+                From_With_Type (Scope (Entity (Selector_Name (Name (Item)))))
+            then
+               Error_Msg_Sloc := Sloc (Item);
+               Error_Msg_N ("Missing With_Clause for With_Type_Clause#", N);
+            end if;
+
+            Next (Item);
+         end loop;
+      end Check_Parent_Context;
+
+   --  Start of processing for Check_With_Type_Clauses
+
+   begin
+      if Extensions_Allowed
+        and then (Nkind (Lib_Unit) = N_Package_Body
+                   or else Nkind (Lib_Unit) = N_Subprogram_Body)
+      then
+         Check_Parent_Context (Library_Unit (N));
+         if Is_Child_Spec (Unit (Library_Unit (N))) then
+            Check_Parent_Context (Parent_Spec (Unit (Library_Unit (N))));
+         end if;
+      end if;
+   end Check_With_Type_Clauses;
+
+   ------------------------------
+   -- Check_Private_Child_Unit --
+   ------------------------------
+
+   procedure Check_Private_Child_Unit (N : Node_Id) is
+      Lib_Unit   : constant Node_Id := Unit (N);
+      Item       : Node_Id;
+      Curr_Unit  : Entity_Id;
+      Sub_Parent : Node_Id;
+      Priv_Child : Entity_Id;
+      Par_Lib    : Entity_Id;
+      Par_Spec   : Node_Id;
+
+      function Is_Private_Library_Unit (Unit : Entity_Id) return Boolean;
+      --  Returns true if and only if the library unit is declared with
+      --  an explicit designation of private.
+
+      function Is_Private_Library_Unit (Unit : Entity_Id) return Boolean is
+      begin
+         return Private_Present (Parent (Unit_Declaration_Node (Unit)));
+      end Is_Private_Library_Unit;
+
+   --  Start of processing for Check_Private_Child_Unit
+
+   begin
+      if Nkind (Lib_Unit) = N_Package_Body
+        or else Nkind (Lib_Unit) = N_Subprogram_Body
+      then
+         Curr_Unit := Defining_Entity (Unit (Library_Unit (N)));
+         Par_Lib   := Curr_Unit;
+
+      elsif Nkind (Lib_Unit) = N_Subunit then
+
+         --  The parent is itself a body. The parent entity is to be found
+         --  in the corresponding spec.
+
+         Sub_Parent := Library_Unit (N);
+         Curr_Unit  := Defining_Entity (Unit (Library_Unit (Sub_Parent)));
+
+         --  If the parent itself is a subunit, Curr_Unit is the entity
+         --  of the enclosing body, retrieve the spec entity which is
+         --  the proper ancestor we need for the following tests.
+
+         if Ekind (Curr_Unit) = E_Package_Body then
+            Curr_Unit := Spec_Entity (Curr_Unit);
+         end if;
+
+         Par_Lib    := Curr_Unit;
+
+      else
+         Curr_Unit := Defining_Entity (Lib_Unit);
+
+         Par_Lib := Curr_Unit;
+         Par_Spec  := Parent_Spec (Lib_Unit);
+
+         if No (Par_Spec) then
+            Par_Lib := Empty;
+         else
+            Par_Lib := Defining_Entity (Unit (Par_Spec));
+         end if;
+      end if;
+
+      --  Loop through context items
+
+      Item := First (Context_Items (N));
+      while Present (Item) loop
+
+         if Nkind (Item) = N_With_Clause
+            and then not Implicit_With (Item)
+            and then Is_Private_Descendant (Entity (Name (Item)))
+         then
+            Priv_Child := Entity (Name (Item));
+
+            declare
+               Curr_Parent  : Entity_Id := Par_Lib;
+               Child_Parent : Entity_Id := Scope (Priv_Child);
+               Prv_Ancestor : Entity_Id := Child_Parent;
+               Curr_Private : Boolean   := Is_Private_Library_Unit (Curr_Unit);
+
+            begin
+               --  If the child unit is a public child then locate
+               --  the nearest private ancestor; Child_Parent will
+               --  then be set to the parent of that ancestor.
+
+               if not Is_Private_Library_Unit (Priv_Child) then
+                  while Present (Prv_Ancestor)
+                    and then not Is_Private_Library_Unit (Prv_Ancestor)
+                  loop
+                     Prv_Ancestor := Scope (Prv_Ancestor);
+                  end loop;
+
+                  if Present (Prv_Ancestor) then
+                     Child_Parent := Scope (Prv_Ancestor);
+                  end if;
+               end if;
+
+               while Present (Curr_Parent)
+                 and then Curr_Parent /= Standard_Standard
+                 and then Curr_Parent /= Child_Parent
+               loop
+                  Curr_Private :=
+                    Curr_Private or else Is_Private_Library_Unit (Curr_Parent);
+                  Curr_Parent := Scope (Curr_Parent);
+               end loop;
+
+               if not Present (Curr_Parent) then
+                  Curr_Parent := Standard_Standard;
+               end if;
+
+               if Curr_Parent /= Child_Parent then
+
+                  if Ekind (Priv_Child) = E_Generic_Package
+                    and then Chars (Priv_Child) in Text_IO_Package_Name
+                    and then Chars (Scope (Scope (Priv_Child))) = Name_Ada
+                  then
+                     Error_Msg_NE
+                       ("& is a nested package, not a compilation unit",
+                       Name (Item), Priv_Child);
+
+                  else
+                     Error_Msg_N
+                       ("unit in with clause is private child unit!", Item);
+                     Error_Msg_NE
+                       ("current unit must also have parent&!",
+                        Item, Child_Parent);
+                  end if;
+
+               elsif not Curr_Private
+                 and then Nkind (Lib_Unit) /= N_Package_Body
+                 and then Nkind (Lib_Unit) /= N_Subprogram_Body
+                 and then Nkind (Lib_Unit) /= N_Subunit
+               then
+                  Error_Msg_NE
+                    ("current unit must also be private descendant of&",
+                     Item, Child_Parent);
+               end if;
+            end;
+         end if;
+
+         Next (Item);
+      end loop;
+
+   end Check_Private_Child_Unit;
+
+   ----------------------
+   -- Check_Stub_Level --
+   ----------------------
+
+   procedure Check_Stub_Level (N : Node_Id) is
+      Par  : constant Node_Id   := Parent (N);
+      Kind : constant Node_Kind := Nkind (Par);
+
+   begin
+      if (Kind = N_Package_Body
+           or else Kind = N_Subprogram_Body
+           or else Kind = N_Task_Body
+           or else Kind = N_Protected_Body)
+
+        and then (Nkind (Parent (Par)) = N_Compilation_Unit
+                   or else Nkind (Parent (Par)) = N_Subunit)
+      then
+         null;
+
+      --  In an instance, a missing stub appears at any level. A warning
+      --  message will have been emitted already for the missing file.
+
+      elsif not In_Instance then
+         Error_Msg_N ("stub cannot appear in an inner scope", N);
+
+      elsif Expander_Active then
+         Error_Msg_N ("missing proper body", N);
+      end if;
+   end Check_Stub_Level;
+
+   ------------------------
+   -- Expand_With_Clause --
+   ------------------------
+
+   procedure Expand_With_Clause (Nam : Node_Id; N : Node_Id) is
+      Loc   : constant Source_Ptr := Sloc (Nam);
+      Ent   : constant Entity_Id := Entity (Nam);
+      Withn : Node_Id;
+      P     : Node_Id;
+
+      function Build_Unit_Name (Nam : Node_Id) return Node_Id;
+
+      function Build_Unit_Name (Nam : Node_Id) return Node_Id is
+         Result : Node_Id;
+
+      begin
+         if Nkind (Nam) = N_Identifier then
+            return New_Occurrence_Of (Entity (Nam), Loc);
+
+         else
+            Result :=
+              Make_Expanded_Name (Loc,
+                Chars  => Chars (Entity (Nam)),
+                Prefix => Build_Unit_Name (Prefix (Nam)),
+                Selector_Name => New_Occurrence_Of (Entity (Nam), Loc));
+            Set_Entity (Result, Entity (Nam));
+            return Result;
+         end if;
+      end Build_Unit_Name;
+
+   begin
+      New_Nodes_OK := New_Nodes_OK + 1;
+      Withn :=
+        Make_With_Clause (Loc, Name => Build_Unit_Name (Nam));
+
+      P := Parent (Unit_Declaration_Node (Ent));
+      Set_Library_Unit          (Withn, P);
+      Set_Corresponding_Spec    (Withn, Ent);
+      Set_First_Name            (Withn, True);
+      Set_Implicit_With         (Withn, True);
+
+      Prepend (Withn, Context_Items (N));
+      Mark_Rewrite_Insertion (Withn);
+      Install_Withed_Unit (Withn);
+
+      if Nkind (Nam) = N_Expanded_Name then
+         Expand_With_Clause (Prefix (Nam), N);
+      end if;
+
+      New_Nodes_OK := New_Nodes_OK - 1;
+   end Expand_With_Clause;
+
+   -----------------------------
+   -- Implicit_With_On_Parent --
+   -----------------------------
+
+   procedure Implicit_With_On_Parent
+     (Child_Unit : Node_Id;
+      N          : Node_Id)
+   is
+      Loc    : constant Source_Ptr := Sloc (N);
+      P      : constant Node_Id    := Parent_Spec (Child_Unit);
+      P_Unit : constant Node_Id    := Unit (P);
+
+      P_Name : Entity_Id := Defining_Entity (P_Unit);
+      Withn  : Node_Id;
+
+      function Build_Ancestor_Name (P : Node_Id)  return Node_Id;
+      --  Build prefix of child unit name. Recurse if needed.
+
+      function Build_Unit_Name return Node_Id;
+      --  If the unit is a child unit, build qualified name with all
+      --  ancestors.
+
+      -------------------------
+      -- Build_Ancestor_Name --
+      -------------------------
+
+      function Build_Ancestor_Name (P : Node_Id) return Node_Id is
+         P_Ref : Node_Id := New_Reference_To (Defining_Entity (P), Loc);
+
+      begin
+         if No (Parent_Spec (P)) then
+            return P_Ref;
+         else
+            return
+              Make_Selected_Component (Loc,
+                Prefix => Build_Ancestor_Name (Unit (Parent_Spec (P))),
+                Selector_Name => P_Ref);
+         end if;
+      end Build_Ancestor_Name;
+
+      ---------------------
+      -- Build_Unit_Name --
+      ---------------------
+
+      function Build_Unit_Name return Node_Id is
+         Result : Node_Id;
+
+      begin
+         if No (Parent_Spec (P_Unit)) then
+            return New_Reference_To (P_Name, Loc);
+         else
+            Result :=
+              Make_Expanded_Name (Loc,
+                Chars  => Chars (P_Name),
+                Prefix => Build_Ancestor_Name (Unit (Parent_Spec (P_Unit))),
+                Selector_Name => New_Reference_To (P_Name, Loc));
+            Set_Entity (Result, P_Name);
+            return Result;
+         end if;
+      end Build_Unit_Name;
+
+   --  Start of processing for Implicit_With_On_Parent
+
+   begin
+      New_Nodes_OK := New_Nodes_OK + 1;
+      Withn := Make_With_Clause (Loc, Name => Build_Unit_Name);
+
+      Set_Library_Unit          (Withn, P);
+      Set_Corresponding_Spec    (Withn, P_Name);
+      Set_First_Name            (Withn, True);
+      Set_Implicit_With         (Withn, True);
+
+      --  Node is placed at the beginning of the context items, so that
+      --  subsequent use clauses on the parent can be validated.
+
+      Prepend (Withn, Context_Items (N));
+      Mark_Rewrite_Insertion (Withn);
+      Install_Withed_Unit (Withn);
+
+      if Is_Child_Spec (P_Unit) then
+         Implicit_With_On_Parent (P_Unit, N);
+      end if;
+      New_Nodes_OK := New_Nodes_OK - 1;
+   end Implicit_With_On_Parent;
+
+   ---------------------
+   -- Install_Context --
+   ---------------------
+
+   procedure Install_Context (N : Node_Id) is
+      Lib_Unit : Node_Id := Unit (N);
+
+   begin
+      Install_Context_Clauses (N);
+
+      if Is_Child_Spec (Lib_Unit) then
+         Install_Parents (Lib_Unit, Private_Present (Parent (Lib_Unit)));
+      end if;
+
+      Check_With_Type_Clauses (N);
+   end Install_Context;
+
+   -----------------------------
+   -- Install_Context_Clauses --
+   -----------------------------
+
+   procedure Install_Context_Clauses (N : Node_Id) is
+      Lib_Unit      : Node_Id := Unit (N);
+      Item          : Node_Id;
+      Uname_Node    : Entity_Id;
+      Check_Private : Boolean := False;
+      Decl_Node     : Node_Id;
+      Lib_Parent    : Entity_Id;
+
+   begin
+      --  Loop through context clauses to find the with/use clauses
+
+      Item := First (Context_Items (N));
+      while Present (Item) loop
+
+         --  Case of explicit WITH clause
+
+         if Nkind (Item) = N_With_Clause
+           and then not Implicit_With (Item)
+         then
+            --  If Name (Item) is not an entity name, something is wrong, and
+            --  this will be detected in due course, for now ignore the item
+
+            if not Is_Entity_Name (Name (Item)) then
+               goto Continue;
+            end if;
+
+            Uname_Node := Entity (Name (Item));
+
+            if Is_Private_Descendant (Uname_Node) then
+               Check_Private := True;
+            end if;
+
+            Install_Withed_Unit (Item);
+
+            Decl_Node := Unit_Declaration_Node (Uname_Node);
+
+            --  If the unit is a subprogram instance, it appears nested
+            --  within a package that carries the parent information.
+
+            if Is_Generic_Instance (Uname_Node)
+              and then Ekind (Uname_Node) /= E_Package
+            then
+               Decl_Node := Parent (Parent (Decl_Node));
+            end if;
+
+            if Is_Child_Spec (Decl_Node) then
+               if Nkind (Name (Item)) = N_Expanded_Name then
+                  Expand_With_Clause (Prefix (Name (Item)), N);
+               else
+                  --  if not an expanded name, the child unit must be a
+                  --  renaming, nothing to do.
+
+                  null;
+               end if;
+
+            elsif Nkind (Decl_Node) = N_Subprogram_Body
+              and then not Acts_As_Spec (Parent (Decl_Node))
+              and then Is_Child_Spec (Unit (Library_Unit (Parent (Decl_Node))))
+            then
+               Implicit_With_On_Parent
+                 (Unit (Library_Unit (Parent (Decl_Node))), N);
+            end if;
+
+            --  Check license conditions unless this is a dummy unit
+
+            if Sloc (Library_Unit (Item)) /= No_Location then
+               License_Check : declare
+                  Withl : constant License_Type :=
+                            License (Source_Index
+                                       (Get_Source_Unit
+                                         (Library_Unit (Item))));
+
+                  Unitl : constant License_Type :=
+                           License (Source_Index (Current_Sem_Unit));
+
+                  procedure License_Error;
+                  --  Signal error of bad license
+
+                  -------------------
+                  -- License_Error --
+                  -------------------
+
+                  procedure License_Error is
+                  begin
+                     Error_Msg_N
+                       ("?license of with'ed unit & is incompatible",
+                        Name (Item));
+                  end License_Error;
+
+               --  Start of processing for License_Check
+
+               begin
+                  case Unitl is
+                     when Unknown =>
+                        null;
+
+                     when Restricted =>
+                        if Withl = GPL then
+                           License_Error;
+                        end if;
+
+                     when GPL =>
+                        if Withl = Restricted then
+                           License_Error;
+                        end if;
+
+                     when Modified_GPL =>
+                        if Withl = Restricted or else Withl = GPL then
+                           License_Error;
+                        end if;
+
+                     when Unrestricted =>
+                        null;
+                  end case;
+               end License_Check;
+            end if;
+
+         --  Case of USE PACKAGE clause
+
+         elsif Nkind (Item) = N_Use_Package_Clause then
+            Analyze_Use_Package (Item);
+
+         --  Case of USE TYPE clause
+
+         elsif Nkind (Item) = N_Use_Type_Clause then
+            Analyze_Use_Type (Item);
+
+         --  Case of WITH TYPE clause
+
+         --  A With_Type_Clause is processed when installing the context,
+         --  because it is a visibility mechanism and does not create a
+         --  semantic dependence on other units, as a With_Clause does.
+
+         elsif Nkind (Item) = N_With_Type_Clause then
+            Analyze_With_Type_Clause (Item);
+
+         --  case of PRAGMA
+
+         elsif Nkind (Item) = N_Pragma then
+            Analyze (Item);
+         end if;
+
+      <<Continue>>
+         Next (Item);
+      end loop;
+
+      if Is_Child_Spec (Lib_Unit) then
+
+         --  The unit also has implicit withs on its own parents.
+
+         if No (Context_Items (N)) then
+            Set_Context_Items (N, New_List);
+         end if;
+
+         Implicit_With_On_Parent (Lib_Unit, N);
+      end if;
+
+      --  If the unit is a body, the context of the specification must also
+      --  be installed.
+
+      if Nkind (Lib_Unit) = N_Package_Body
+        or else (Nkind (Lib_Unit) = N_Subprogram_Body
+                  and then not Acts_As_Spec (N))
+      then
+         Install_Context (Library_Unit (N));
+
+         if Is_Child_Spec (Unit (Library_Unit (N))) then
+
+            --  If the unit is the body of a public child unit, the private
+            --  declarations of the parent must be made visible. If the child
+            --  unit is private, the private declarations have been installed
+            --  already in the call to Install_Parents for the spec. Installing
+            --  private declarations must be done for all ancestors of public
+            --  child units. In addition, sibling units mentioned in the
+            --  context clause of the body are directly visible.
+
+            declare
+               Lib_Spec : Node_Id := Unit (Library_Unit (N));
+               P        : Node_Id;
+               P_Name   : Entity_Id;
+
+            begin
+               while Is_Child_Spec (Lib_Spec) loop
+                  P := Unit (Parent_Spec (Lib_Spec));
+
+                  if not (Private_Present (Parent (Lib_Spec))) then
+                     P_Name := Defining_Entity (P);
+                     Install_Private_Declarations (P_Name);
+                     Set_Use (Private_Declarations (Specification (P)));
+                  end if;
+
+                  Lib_Spec := P;
+               end loop;
+            end;
+         end if;
+
+         --  For a package body, children in context are immediately visible
+
+         Install_Siblings (Defining_Entity (Unit (Library_Unit (N))), N);
+      end if;
+
+      if Nkind (Lib_Unit) = N_Generic_Package_Declaration
+        or else Nkind (Lib_Unit) = N_Generic_Subprogram_Declaration
+        or else Nkind (Lib_Unit) = N_Package_Declaration
+        or else Nkind (Lib_Unit) = N_Subprogram_Declaration
+      then
+         if Is_Child_Spec (Lib_Unit) then
+            Lib_Parent := Defining_Entity (Unit (Parent_Spec (Lib_Unit)));
+            Set_Is_Private_Descendant
+              (Defining_Entity (Lib_Unit),
+               Is_Private_Descendant (Lib_Parent)
+                 or else Private_Present (Parent (Lib_Unit)));
+
+         else
+            Set_Is_Private_Descendant
+              (Defining_Entity (Lib_Unit),
+               Private_Present (Parent (Lib_Unit)));
+         end if;
+      end if;
+
+      if Check_Private then
+         Check_Private_Child_Unit (N);
+      end if;
+   end Install_Context_Clauses;
+
+   ---------------------
+   -- Install_Parents --
+   ---------------------
+
+   procedure Install_Parents (Lib_Unit : Node_Id; Is_Private : Boolean) is
+      P      : Node_Id;
+      E_Name : Entity_Id;
+      P_Name : Entity_Id;
+      P_Spec : Node_Id;
+
+   begin
+      P := Unit (Parent_Spec (Lib_Unit));
+      P_Name := Defining_Entity (P);
+
+      if Etype (P_Name) = Any_Type then
+         return;
+      end if;
+
+      if Ekind (P_Name) = E_Generic_Package
+        and then Nkind (Lib_Unit) /= N_Generic_Subprogram_Declaration
+        and then Nkind (Lib_Unit) /= N_Generic_Package_Declaration
+        and then Nkind (Lib_Unit) not in N_Generic_Renaming_Declaration
+      then
+         Error_Msg_N
+           ("child of a generic package must be a generic unit", Lib_Unit);
+
+      elsif not Is_Package (P_Name) then
+         Error_Msg_N
+           ("parent unit must be package or generic package", Lib_Unit);
+         raise Unrecoverable_Error;
+
+      elsif Present (Renamed_Object (P_Name)) then
+         Error_Msg_N ("parent unit cannot be a renaming", Lib_Unit);
+         raise Unrecoverable_Error;
+
+      --  Verify that a child of an instance is itself an instance, or
+      --  the renaming of one. Given that an instance that is a unit is
+      --  replaced with a package declaration, check against the original
+      --  node.
+
+      elsif Nkind (Original_Node (P)) = N_Package_Instantiation
+        and then Nkind (Lib_Unit)
+                   not in N_Renaming_Declaration
+        and then Nkind (Original_Node (Lib_Unit))
+                   not in N_Generic_Instantiation
+      then
+         Error_Msg_N
+           ("child of an instance must be an instance or renaming", Lib_Unit);
+      end if;
+
+      --  This is the recursive call that ensures all parents are loaded
+
+      if Is_Child_Spec (P) then
+         Install_Parents (P,
+           Is_Private or else Private_Present (Parent (Lib_Unit)));
+      end if;
+
+      --  Now we can install the context for this parent
+
+      Install_Context_Clauses (Parent_Spec (Lib_Unit));
+      Install_Siblings (P_Name, Parent (Lib_Unit));
+
+      --  The child unit is in the declarative region of the parent. The
+      --  parent must therefore appear in the scope stack and be visible,
+      --  as when compiling the corresponding body. If the child unit is
+      --  private or it is a package body, private declarations must be
+      --  accessible as well. Use declarations in the parent must also
+      --  be installed. Finally, other child units of the same parent that
+      --  are in the context are immediately visible.
+
+      --  Find entity for compilation unit, and set its private descendant
+      --  status as needed.
+
+      E_Name := Defining_Entity (Lib_Unit);
+
+      Set_Is_Child_Unit (E_Name);
+
+      Set_Is_Private_Descendant (E_Name,
+         Is_Private_Descendant (P_Name)
+           or else Private_Present (Parent (Lib_Unit)));
+
+      P_Spec := Specification (Unit_Declaration_Node (P_Name));
+      New_Scope (P_Name);
+
+      --  Save current visibility of unit
+
+      Scope_Stack.Table (Scope_Stack.Last).Previous_Visibility :=
+        Is_Immediately_Visible (P_Name);
+      Set_Is_Immediately_Visible (P_Name);
+      Install_Visible_Declarations (P_Name);
+      Set_Use (Visible_Declarations (P_Spec));
+
+      if Is_Private
+        or else Private_Present (Parent (Lib_Unit))
+      then
+         Install_Private_Declarations (P_Name);
+         Set_Use (Private_Declarations (P_Spec));
+      end if;
+   end Install_Parents;
+
+   ----------------------
+   -- Install_Siblings --
+   ----------------------
+
+   procedure Install_Siblings (U_Name : Entity_Id; N : Node_Id) is
+      Item : Node_Id;
+      Id   : Entity_Id;
+      Prev : Entity_Id;
+
+      function Is_Ancestor (E : Entity_Id) return Boolean;
+      --  Determine whether the scope of a child unit is an ancestor of
+      --  the current unit.
+      --  Shouldn't this be somewhere more general ???
+
+      function Is_Ancestor (E : Entity_Id) return Boolean is
+         Par : Entity_Id;
+
+      begin
+         Par := U_Name;
+
+         while Present (Par)
+           and then Par /= Standard_Standard
+         loop
+
+            if Par = E then
+               return True;
+            end if;
+
+            Par := Scope (Par);
+         end loop;
+
+         return False;
+      end Is_Ancestor;
+
+   --  Start of processing for Install_Siblings
+
+   begin
+      --  Iterate over explicit with clauses, and check whether the
+      --  scope of each entity is an ancestor of the current unit.
+
+      Item := First (Context_Items (N));
+
+      while Present (Item) loop
+
+         if Nkind (Item) = N_With_Clause
+           and then not Implicit_With (Item)
+         then
+            Id := Entity (Name (Item));
+
+            if Is_Child_Unit (Id)
+              and then Is_Ancestor (Scope (Id))
+            then
+               Set_Is_Immediately_Visible (Id);
+               Prev := Current_Entity (Id);
+
+               --  Check for the presence of another unit in the context,
+               --  that may be inadvertently hidden by the child.
+
+               if Present (Prev)
+                 and then Is_Immediately_Visible (Prev)
+                 and then not Is_Child_Unit (Prev)
+               then
+                  declare
+                     Clause : Node_Id;
+
+                  begin
+                     Clause := First (Context_Items (N));
+
+                     while Present (Clause) loop
+                        if Nkind (Clause) = N_With_Clause
+                          and then Entity (Name (Clause)) = Prev
+                        then
+                           Error_Msg_NE
+                              ("child unit& hides compilation unit " &
+                               "with the same name?",
+                                 Name (Item), Id);
+                           exit;
+                        end if;
+
+                        Next (Clause);
+                     end loop;
+                  end;
+               end if;
+
+            --  the With_Clause may be on a grand-child, which makes
+            --  the child immediately visible.
+
+            elsif Is_Child_Unit (Scope (Id))
+              and then Is_Ancestor (Scope (Scope (Id)))
+            then
+               Set_Is_Immediately_Visible (Scope (Id));
+            end if;
+         end if;
+
+         Next (Item);
+      end loop;
+   end Install_Siblings;
+
+   -------------------------
+   -- Install_Withed_Unit --
+   -------------------------
+
+   procedure Install_Withed_Unit (With_Clause : Node_Id) is
+      Uname : constant Entity_Id := Entity (Name (With_Clause));
+      P     : constant Entity_Id := Scope (Uname);
+
+   begin
+      --  We do not apply the restrictions to an internal unit unless
+      --  we are compiling the internal unit as a main unit. This check
+      --  is also skipped for dummy units (for missing packages).
+
+      if Sloc (Uname) /= No_Location
+        and then (not Is_Internal_File_Name (Unit_File_Name (Current_Sem_Unit))
+                    or else Current_Sem_Unit = Main_Unit)
+      then
+         Check_Restricted_Unit
+           (Unit_Name (Get_Source_Unit (Uname)), With_Clause);
+      end if;
+
+      if P /= Standard_Standard then
+
+         --  If the unit is not analyzed after analysis of the with clause,
+         --  and it is an instantiation, then it awaits a body and is the main
+         --  unit. Its appearance in the context of some other unit indicates
+         --  a circular dependency (DEC suite perversity).
+
+         if not Analyzed (Uname)
+           and then Nkind (Parent (Uname)) = N_Package_Instantiation
+         then
+            Error_Msg_N
+              ("instantiation depends on itself", Name (With_Clause));
+
+         elsif not Is_Visible_Child_Unit (Uname) then
+            Set_Is_Visible_Child_Unit (Uname);
+
+            if Is_Generic_Instance (Uname)
+              and then Ekind (Uname) in Subprogram_Kind
+            then
+               --  Set flag as well on the visible entity that denotes the
+               --  instance, which renames the current one.
+
+               Set_Is_Visible_Child_Unit
+                 (Related_Instance
+                   (Defining_Entity (Unit (Library_Unit (With_Clause)))));
+               null;
+            end if;
+
+            --  The parent unit may have been installed already, and
+            --  may have appeared in a use clause.
+
+            if In_Use (Scope (Uname)) then
+               Set_Is_Potentially_Use_Visible (Uname);
+            end if;
+
+            Set_Context_Installed (With_Clause);
+         end if;
+
+      elsif not Is_Immediately_Visible (Uname) then
+         Set_Is_Immediately_Visible (Uname);
+         Set_Context_Installed (With_Clause);
+      end if;
+
+      --   A with-clause overrides a with-type clause: there are no restric-
+      --   tions on the use of package entities.
+
+      if Ekind (Uname) = E_Package then
+         Set_From_With_Type (Uname, False);
+      end if;
+   end Install_Withed_Unit;
+
+   -------------------
+   -- Is_Child_Spec --
+   -------------------
+
+   function Is_Child_Spec (Lib_Unit : Node_Id) return Boolean is
+      K : constant Node_Kind := Nkind (Lib_Unit);
+
+   begin
+      return (K in N_Generic_Declaration              or else
+              K in N_Generic_Instantiation            or else
+              K in N_Generic_Renaming_Declaration     or else
+              K =  N_Package_Declaration              or else
+              K =  N_Package_Renaming_Declaration     or else
+              K =  N_Subprogram_Declaration           or else
+              K =  N_Subprogram_Renaming_Declaration)
+        and then Present (Parent_Spec (Lib_Unit));
+   end Is_Child_Spec;
+
+   -----------------------
+   -- Load_Needed_Body --
+   -----------------------
+
+   --  N is a generic unit named in a with clause, or else it is
+   --  a unit that contains a generic unit or an inlined function.
+   --  In order to perform an instantiation, the body of the unit
+   --  must be present. If the unit itself is generic, we assume
+   --  that an instantiation follows, and  load and analyze the body
+   --  unconditionally. This forces analysis of the spec as well.
+
+   --  If the unit is not generic, but contains a generic unit, it
+   --  is loaded on demand, at the point of instantiation (see ch12).
+
+   procedure Load_Needed_Body (N : Node_Id; OK : out Boolean) is
+      Body_Name : Unit_Name_Type;
+      Unum      : Unit_Number_Type;
+
+      Save_Style_Check : constant Boolean := Opt.Style_Check;
+      --  The loading and analysis is done with style checks off
+
+   begin
+      if not GNAT_Mode then
+         Style_Check := False;
+      end if;
+
+      Body_Name := Get_Body_Name (Get_Unit_Name (Unit (N)));
+      Unum :=
+        Load_Unit
+          (Load_Name  => Body_Name,
+           Required   => False,
+           Subunit    => False,
+           Error_Node => N,
+           Renamings  => True);
+
+      if Unum = No_Unit then
+         OK := False;
+
+      else
+         Compiler_State := Analyzing; -- reset after load
+
+         if not Fatal_Error (Unum) then
+            if Debug_Flag_L then
+               Write_Str ("*** Loaded generic body");
+               Write_Eol;
+            end if;
+
+            Semantics (Cunit (Unum));
+         end if;
+
+         OK := True;
+      end if;
+
+      Style_Check := Save_Style_Check;
+   end Load_Needed_Body;
+
+   --------------------
+   -- Remove_Context --
+   --------------------
+
+   procedure Remove_Context (N : Node_Id) is
+      Lib_Unit : constant Node_Id := Unit (N);
+
+   begin
+      --  If this is a child unit, first remove the parent units.
+
+      if Is_Child_Spec (Lib_Unit) then
+         Remove_Parents (Lib_Unit);
+      end if;
+
+      Remove_Context_Clauses (N);
+   end Remove_Context;
+
+   ----------------------------
+   -- Remove_Context_Clauses --
+   ----------------------------
+
+   procedure Remove_Context_Clauses (N : Node_Id) is
+      Item      : Node_Id;
+      Unit_Name : Entity_Id;
+
+   begin
+
+      --  Loop through context items and undo with_clauses and use_clauses.
+
+      Item := First (Context_Items (N));
+
+      while Present (Item) loop
+
+         --  We are interested only in with clauses which got installed
+         --  on entry, as indicated by their Context_Installed flag set
+
+         if Nkind (Item) = N_With_Clause
+            and then Context_Installed (Item)
+         then
+            --  Remove items from one with'ed unit
+
+            Unit_Name := Entity (Name (Item));
+            Remove_Unit_From_Visibility (Unit_Name);
+            Set_Context_Installed (Item, False);
+
+         elsif Nkind (Item) = N_Use_Package_Clause then
+            End_Use_Package (Item);
+
+         elsif Nkind (Item) = N_Use_Type_Clause then
+            End_Use_Type (Item);
+
+         elsif Nkind (Item) = N_With_Type_Clause then
+            Remove_With_Type_Clause (Name (Item));
+         end if;
+
+         Next (Item);
+      end loop;
+
+   end Remove_Context_Clauses;
+
+   --------------------
+   -- Remove_Parents --
+   --------------------
+
+   procedure Remove_Parents (Lib_Unit : Node_Id) is
+      P      : Node_Id;
+      P_Name : Entity_Id;
+      E      : Entity_Id;
+      Vis    : constant Boolean :=
+                 Scope_Stack.Table (Scope_Stack.Last).Previous_Visibility;
+
+   begin
+      if Is_Child_Spec (Lib_Unit) then
+         P := Unit (Parent_Spec (Lib_Unit));
+         P_Name := Defining_Entity (P);
+
+         Remove_Context_Clauses (Parent_Spec (Lib_Unit));
+         End_Package_Scope (P_Name);
+         Set_Is_Immediately_Visible (P_Name, Vis);
+
+         --  Remove from visibility the siblings as well, which are directly
+         --  visible while the parent is in scope.
+
+         E := First_Entity (P_Name);
+
+         while Present (E) loop
+
+            if Is_Child_Unit (E) then
+               Set_Is_Immediately_Visible (E, False);
+            end if;
+
+            Next_Entity (E);
+         end loop;
+
+         Set_In_Package_Body (P_Name, False);
+
+         --  This is the recursive call to remove the context of any
+         --  higher level parent. This recursion ensures that all parents
+         --  are removed in the reverse order of their installation.
+
+         Remove_Parents (P);
+      end if;
+   end Remove_Parents;
+
+   -----------------------------
+   -- Remove_With_Type_Clause --
+   -----------------------------
+
+   procedure Remove_With_Type_Clause (Name : Node_Id) is
+      Typ : Entity_Id;
+      P   : Entity_Id;
+
+      procedure Unchain (E : Entity_Id);
+      --  Remove entity from visibility list.
+
+      procedure Unchain (E : Entity_Id) is
+         Prev : Entity_Id;
+
+      begin
+         Prev := Current_Entity (E);
+
+         --  Package entity may appear is several with_type_clauses, and
+         --  may have been removed already.
+
+         if No (Prev) then
+            return;
+
+         elsif Prev = E then
+            Set_Name_Entity_Id (Chars (E), Homonym (E));
+
+         else
+            while Present (Prev)
+              and then Homonym (Prev) /= E
+            loop
+               Prev := Homonym (Prev);
+            end loop;
+
+            if (Present (Prev)) then
+               Set_Homonym (Prev, Homonym (E));
+            end if;
+         end if;
+      end Unchain;
+
+   begin
+      if Nkind (Name) = N_Selected_Component then
+         Typ := Entity (Selector_Name (Name));
+
+         if No (Typ) then    --  error in declaration.
+            return;
+         end if;
+      else
+         return;
+      end if;
+
+      P := Scope (Typ);
+
+      --  If the exporting package has been analyzed, it has appeared in the
+      --  context already and should be left alone. Otherwise, remove from
+      --  visibility.
+
+      if not Analyzed (Unit_Declaration_Node (P)) then
+         Unchain (P);
+         Unchain (Typ);
+         Set_Is_Frozen (Typ, False);
+      end if;
+
+      if Ekind (Typ) = E_Record_Type then
+         Set_From_With_Type (Class_Wide_Type (Typ), False);
+         Set_From_With_Type (Typ, False);
+      end if;
+
+      Set_From_With_Type (P, False);
+
+      --  If P is a child unit, remove parents as well.
+
+      P := Scope (P);
+
+      while Present (P)
+        and then P /= Standard_Standard
+      loop
+         Set_From_With_Type (P, False);
+
+         if not Analyzed (Unit_Declaration_Node (P)) then
+            Unchain (P);
+         end if;
+
+         P := Scope (P);
+      end loop;
+
+      --  The back-end needs to know that an access type is imported, so it
+      --  does not need elaboration and can appear in a mutually recursive
+      --  record definition, so the imported flag on an access  type is
+      --  preserved.
+
+   end Remove_With_Type_Clause;
+
+   ---------------------------------
+   -- Remove_Unit_From_Visibility --
+   ---------------------------------
+
+   procedure Remove_Unit_From_Visibility (Unit_Name : Entity_Id) is
+      P : Entity_Id := Scope (Unit_Name);
+
+   begin
+
+      if Debug_Flag_I then
+         Write_Str ("remove withed unit ");
+         Write_Name (Chars (Unit_Name));
+         Write_Eol;
+      end if;
+
+      if P /= Standard_Standard then
+         Set_Is_Visible_Child_Unit (Unit_Name, False);
+      end if;
+
+      Set_Is_Potentially_Use_Visible (Unit_Name, False);
+      Set_Is_Immediately_Visible     (Unit_Name, False);
+
+   end Remove_Unit_From_Visibility;
+
+end Sem_Ch10;
diff --git a/gcc/ada/sem_ch10.ads b/gcc/ada/sem_ch10.ads
new file mode 100644 (file)
index 0000000..4ea1acc
--- /dev/null
@@ -0,0 +1,60 @@
+------------------------------------------------------------------------------
+--                                                                          --
+--                         GNAT COMPILER COMPONENTS                         --
+--                                                                          --
+--                             S E M _ C H 1 0                              --
+--                                                                          --
+--                                 S p e c                                  --
+--                                                                          --
+--                            $Revision: 1.7 $                              --
+--                                                                          --
+--          Copyright (C) 1992-2001 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- --
+-- ware  Foundation;  either version 2,  or (at your option) any later ver- --
+-- sion.  GNAT is distributed in the hope that it will be useful, but WITH- --
+-- OUT ANY WARRANTY;  without even the  implied warranty of MERCHANTABILITY --
+-- or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License --
+-- for  more details.  You should have  received  a copy of the GNU General --
+-- Public License  distributed with GNAT;  see file COPYING.  If not, write --
+-- to  the Free Software Foundation,  59 Temple Place - Suite 330,  Boston, --
+-- MA 02111-1307, USA.                                                      --
+--                                                                          --
+-- GNAT was originally developed  by the GNAT team at  New York University. --
+-- It is now maintained by Ada Core Technologies Inc (http://www.gnat.com). --
+--                                                                          --
+------------------------------------------------------------------------------
+
+with Types; use Types;
+package Sem_Ch10 is
+   procedure Analyze_Compilation_Unit                   (N : Node_Id);
+   procedure Analyze_With_Clause                        (N : Node_Id);
+   procedure Analyze_With_Type_Clause                   (N : Node_Id);
+   procedure Analyze_Subprogram_Body_Stub               (N : Node_Id);
+   procedure Analyze_Package_Body_Stub                  (N : Node_Id);
+   procedure Analyze_Task_Body_Stub                     (N : Node_Id);
+   procedure Analyze_Protected_Body_Stub                (N : Node_Id);
+   procedure Analyze_Subunit                            (N : Node_Id);
+
+   procedure Install_Context (N : Node_Id);
+   --  Installs the entities from the context clause of the given compilation
+   --  unit into the visibility chains. This is done before analyzing a unit.
+   --  For a child unit, install context of parents as well.
+
+   procedure Remove_Context (N : Node_Id);
+   --  Removes the entities from the context clause of the given compilation
+   --  unit from the visibility chains. This is done on exit from a unit as
+   --  part of cleaning up the visibility chains for the caller. A special
+   --  case is that the call from the Main_Unit can be ignored, since at the
+   --  end of the main unit the visibility table won't be needed in any case.
+   --  For a child unit, remove parents and their context as well.
+
+   procedure Load_Needed_Body (N : Node_Id; OK : out Boolean);
+   --  Load and analyze the body of a context unit that is generic, or
+   --  that contains generic units or inlined units. The body becomes
+   --  part of the semantic dependency set of the unit that needs it.
+   --  The returned result in OK is True if the load is successful,
+   --  and False if the requested file cannot be found.
+
+end Sem_Ch10;
diff --git a/gcc/ada/sem_ch11.adb b/gcc/ada/sem_ch11.adb
new file mode 100644 (file)
index 0000000..2a3536b
--- /dev/null
@@ -0,0 +1,387 @@
+------------------------------------------------------------------------------
+--                                                                          --
+--                         GNAT COMPILER COMPONENTS                         --
+--                                                                          --
+--                             S E M _ C H 1 1                              --
+--                                                                          --
+--                                 B o d y                                  --
+--                                                                          --
+--                            $Revision: 1.96 $
+--                                                                          --
+--          Copyright (C) 1992-2001 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- --
+-- ware  Foundation;  either version 2,  or (at your option) any later ver- --
+-- sion.  GNAT is distributed in the hope that it will be useful, but WITH- --
+-- OUT ANY WARRANTY;  without even the  implied warranty of MERCHANTABILITY --
+-- or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License --
+-- for  more details.  You should have  received  a copy of the GNU General --
+-- Public License  distributed with GNAT;  see file COPYING.  If not, write --
+-- to  the Free Software Foundation,  59 Temple Place - Suite 330,  Boston, --
+-- MA 02111-1307, USA.                                                      --
+--                                                                          --
+-- GNAT was originally developed  by the GNAT team at  New York University. --
+-- It is now maintained by Ada Core Technologies Inc (http://www.gnat.com). --
+--                                                                          --
+------------------------------------------------------------------------------
+
+with Atree;    use Atree;
+with Einfo;    use Einfo;
+with Errout;   use Errout;
+with Lib;      use Lib;
+with Lib.Xref; use Lib.Xref;
+with Nlists;   use Nlists;
+with Nmake;    use Nmake;
+with Opt;      use Opt;
+with Restrict; use Restrict;
+with Rtsfind;  use Rtsfind;
+with Sem;      use Sem;
+with Sem_Ch5;  use Sem_Ch5;
+with Sem_Ch8;  use Sem_Ch8;
+with Sem_Res;  use Sem_Res;
+with Sem_Util; use Sem_Util;
+with Sinfo;    use Sinfo;
+with Stand;    use Stand;
+with Uintp;    use Uintp;
+
+package body Sem_Ch11 is
+
+   -----------------------------------
+   -- Analyze_Exception_Declaration --
+   -----------------------------------
+
+   procedure Analyze_Exception_Declaration (N : Node_Id) is
+      Id : constant Entity_Id := Defining_Identifier (N);
+      PF : constant Boolean   := Is_Pure (Current_Scope);
+
+   begin
+      Generate_Definition (Id);
+      Enter_Name          (Id);
+      Set_Ekind           (Id, E_Exception);
+      Set_Exception_Code  (Id, Uint_0);
+      Set_Etype           (Id, Standard_Exception_Type);
+
+      Set_Is_Statically_Allocated (Id);
+      Set_Is_Pure (Id, PF);
+
+   end Analyze_Exception_Declaration;
+
+   --------------------------------
+   -- Analyze_Exception_Handlers --
+   --------------------------------
+
+   procedure Analyze_Exception_Handlers (L : List_Id) is
+      Handler : Node_Id;
+      Choice  : Entity_Id;
+      Id      : Node_Id;
+      H_Scope : Entity_Id := Empty;
+
+      procedure Check_Duplication (Id : Node_Id);
+      --  Iterate through the identifiers in each handler to find duplicates
+
+      -----------------------
+      -- Check_Duplication --
+      -----------------------
+
+      procedure Check_Duplication (Id : Node_Id) is
+         Handler : Node_Id;
+         Id1     : Node_Id;
+
+      begin
+         Handler := First_Non_Pragma (L);
+         while Present (Handler) loop
+            Id1 := First (Exception_Choices (Handler));
+
+            while Present (Id1) loop
+
+               --  Only check against the exception choices which precede
+               --  Id in the handler, since the ones that follow Id have not
+               --  been analyzed yet and will be checked in a subsequent call.
+
+               if Id = Id1 then
+                  return;
+
+               elsif Nkind (Id1) /= N_Others_Choice
+                 and then Entity (Id) = Entity (Id1)
+               then
+                  if Handler /= Parent (Id) then
+                     Error_Msg_Sloc := Sloc (Id1);
+                     Error_Msg_NE
+                       ("exception choice duplicates &#", Id, Id1);
+
+                  else
+                     if Ada_83 and then Comes_From_Source (Id) then
+                        Error_Msg_N
+                          ("(Ada 83): duplicate exception choice&", Id);
+                     end if;
+                  end if;
+               end if;
+
+               Next_Non_Pragma (Id1);
+            end loop;
+
+            Next (Handler);
+         end loop;
+      end Check_Duplication;
+
+   --  Start processing for Analyze_Exception_Handlers
+
+   begin
+      Handler := First (L);
+      Check_Restriction (No_Exceptions, Handler);
+      Check_Restriction (No_Exception_Handlers, Handler);
+
+      --  Loop through handlers (which can include pragmas)
+
+      while Present (Handler) loop
+
+         --  If pragma just analyze it
+
+         if Nkind (Handler) = N_Pragma then
+            Analyze (Handler);
+
+         --  Otherwise we have a real exception handler
+
+         else
+            --  Deal with choice parameter. The exception handler is
+            --  a declarative part for it, so it constitutes a scope
+            --  for visibility purposes. We create an entity to denote
+            --  the whole exception part, and use it as the scope of all
+            --  the choices, which may even have the same name without
+            --  conflict. This scope plays no other role in expansion or
+            --  or code generation.
+
+            Choice := Choice_Parameter (Handler);
+
+            if Present (Choice) then
+
+               if No (H_Scope) then
+                  H_Scope := New_Internal_Entity
+                    (E_Block, Current_Scope, Sloc (Choice), 'E');
+               end if;
+
+               New_Scope (H_Scope);
+               Set_Etype (H_Scope, Standard_Void_Type);
+
+               --  Set the Finalization Chain entity to Error means that it
+               --  should not be used at that level but the parent one
+               --  should be used instead.
+
+               --  ??? this usage needs documenting in Einfo/Exp_Ch7 ???
+               --  ??? using Error for this non-error condition is nasty ???
+
+               Set_Finalization_Chain_Entity (H_Scope, Error);
+
+               Enter_Name (Choice);
+               Set_Ekind (Choice, E_Variable);
+               Set_Etype (Choice, RTE (RE_Exception_Occurrence));
+               Generate_Definition (Choice);
+            end if;
+
+            Id := First (Exception_Choices (Handler));
+            while Present (Id) loop
+               if Nkind (Id) = N_Others_Choice then
+                  if Present (Next (Id))
+                    or else Present (Next (Handler))
+                    or else Present (Prev (Id))
+                  then
+                     Error_Msg_N ("OTHERS must appear alone and last", Id);
+                  end if;
+
+               else
+                  Analyze (Id);
+
+                  if not Is_Entity_Name (Id)
+                    or else Ekind (Entity (Id)) /= E_Exception
+                  then
+                     Error_Msg_N ("exception name expected", Id);
+
+                  else
+                     if Present (Renamed_Entity (Entity (Id))) then
+                        Set_Entity (Id, Renamed_Entity (Entity (Id)));
+                     end if;
+
+                     Check_Duplication (Id);
+
+                     --  Check for exception declared within generic formal
+                     --  package (which is illegal, see RM 11.2(8))
+
+                     declare
+                        Ent  : Entity_Id := Entity (Id);
+                        Scop : Entity_Id := Scope (Ent);
+
+                     begin
+                        while Scop /= Standard_Standard
+                          and then Ekind (Scop) = E_Package
+                        loop
+                           --  If the exception is declared in an inner
+                           --  instance, nothing else to check.
+
+                           if Is_Generic_Instance (Scop) then
+                              exit;
+
+                           elsif Nkind (Declaration_Node (Scop)) =
+                                           N_Package_Specification
+                             and then
+                               Nkind (Original_Node (Parent
+                                 (Declaration_Node (Scop)))) =
+                                           N_Formal_Package_Declaration
+                           then
+                              Error_Msg_NE
+                                ("exception& is declared in "  &
+                                 "generic formal package", Id, Ent);
+                              Error_Msg_N
+                                ("\and therefore cannot appear in " &
+                                 "handler ('R'M 11.2(8))", Id);
+                              exit;
+                           end if;
+
+                           Scop := Scope (Scop);
+                        end loop;
+                     end;
+                  end if;
+               end if;
+
+               Next (Id);
+            end loop;
+
+            Analyze_Statements (Statements (Handler));
+
+            if Present (Choice) then
+               End_Scope;
+            end if;
+
+         end if;
+
+         Next (Handler);
+      end loop;
+   end Analyze_Exception_Handlers;
+
+   --------------------------------
+   -- Analyze_Handled_Statements --
+   --------------------------------
+
+   procedure Analyze_Handled_Statements (N : Node_Id) is
+      Handlers : constant List_Id := Exception_Handlers (N);
+
+   begin
+      Analyze_Statements (Statements (N));
+
+      if Present (Handlers) then
+         Analyze_Exception_Handlers (Handlers);
+
+      elsif Present (At_End_Proc (N)) then
+         Analyze (At_End_Proc (N));
+      end if;
+   end Analyze_Handled_Statements;
+
+   -----------------------------
+   -- Analyze_Raise_Statement --
+   -----------------------------
+
+   procedure Analyze_Raise_Statement (N : Node_Id) is
+      Exception_Id   : constant Node_Id := Name (N);
+      Exception_Name : Entity_Id := Empty;
+      P              : Node_Id;
+      Nkind_P        : Node_Kind;
+
+   begin
+      Check_Unreachable_Code (N);
+
+      --  Check exception restrictions on the original source
+
+      if Comes_From_Source (N) then
+         Check_Restriction (No_Exceptions, N);
+      end if;
+
+      --  Reraise statement
+
+      if No (Exception_Id) then
+
+         P := Parent (N);
+         Nkind_P := Nkind (P);
+
+         while Nkind_P /= N_Exception_Handler
+           and then Nkind_P /= N_Subprogram_Body
+           and then Nkind_P /= N_Package_Body
+           and then Nkind_P /= N_Task_Body
+           and then Nkind_P /= N_Entry_Body
+         loop
+            P := Parent (P);
+            Nkind_P := Nkind (P);
+         end loop;
+
+         if Nkind (P) /= N_Exception_Handler then
+            Error_Msg_N
+              ("reraise statement must appear directly in a handler", N);
+         end if;
+
+      --  Normal case with exception id present
+
+      else
+         Analyze (Exception_Id);
+
+         if Is_Entity_Name (Exception_Id) then
+            Exception_Name := Entity (Exception_Id);
+
+            if Present (Renamed_Object (Exception_Name)) then
+               Set_Entity (Exception_Id, Renamed_Object (Exception_Name));
+            end if;
+         end if;
+
+         if No (Exception_Name)
+           or else Ekind (Exception_Name) /= E_Exception
+         then
+            Error_Msg_N
+              ("exception name expected in raise statement", Exception_Id);
+         end if;
+      end if;
+   end Analyze_Raise_Statement;
+
+   -----------------------------
+   -- Analyze_Raise_xxx_Error --
+   -----------------------------
+
+   --  Normally, the Etype is already set (when this node is used within
+   --  an expression, since it is copied from the node which it rewrites).
+   --  If this node is used in a statement context, then we set the type
+   --  Standard_Void_Type. This is used both by Gigi and by the front end
+   --  to distinguish the statement use and the subexpression use.
+
+   --  The only other required processing is to take care of the Condition
+   --  field if one is present.
+
+   procedure Analyze_Raise_xxx_Error (N : Node_Id) is
+   begin
+      if No (Etype (N)) then
+         Set_Etype (N, Standard_Void_Type);
+      end if;
+
+      if Present (Condition (N)) then
+         Analyze_And_Resolve (Condition (N), Standard_Boolean);
+      end if;
+
+      --  Deal with static cases in obvious manner
+
+      if Nkind (Condition (N)) = N_Identifier then
+         if Entity (Condition (N)) = Standard_True then
+            Set_Condition (N, Empty);
+
+         elsif Entity (Condition (N)) = Standard_False then
+            Rewrite (N, Make_Null_Statement (Sloc (N)));
+         end if;
+      end if;
+
+   end Analyze_Raise_xxx_Error;
+
+   -----------------------------
+   -- Analyze_Subprogram_Info --
+   -----------------------------
+
+   procedure Analyze_Subprogram_Info (N : Node_Id) is
+   begin
+      Set_Etype (N, RTE (RE_Code_Loc));
+   end Analyze_Subprogram_Info;
+
+end Sem_Ch11;
diff --git a/gcc/ada/sem_ch11.ads b/gcc/ada/sem_ch11.ads
new file mode 100644 (file)
index 0000000..a56ddee
--- /dev/null
@@ -0,0 +1,40 @@
+------------------------------------------------------------------------------
+--                                                                          --
+--                         GNAT COMPILER COMPONENTS                         --
+--                                                                          --
+--                             S E M _ C H 1 1                              --
+--                                                                          --
+--                                 S p e c                                  --
+--                                                                          --
+--                            $Revision: 1.9 $                              --
+--                                                                          --
+--          Copyright (C) 1992-1998 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- --
+-- ware  Foundation;  either version 2,  or (at your option) any later ver- --
+-- sion.  GNAT is distributed in the hope that it will be useful, but WITH- --
+-- OUT ANY WARRANTY;  without even the  implied warranty of MERCHANTABILITY --
+-- or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License --
+-- for  more details.  You should have  received  a copy of the GNU General --
+-- Public License  distributed with GNAT;  see file COPYING.  If not, write --
+-- to  the Free Software Foundation,  59 Temple Place - Suite 330,  Boston, --
+-- MA 02111-1307, USA.                                                      --
+--                                                                          --
+-- GNAT was originally developed  by the GNAT team at  New York University. --
+-- It is now maintained by Ada Core Technologies Inc (http://www.gnat.com). --
+--                                                                          --
+------------------------------------------------------------------------------
+
+with Types; use Types;
+package Sem_Ch11 is
+   procedure Analyze_Exception_Declaration              (N : Node_Id);
+   procedure Analyze_Handled_Statements                 (N : Node_Id);
+   procedure Analyze_Raise_Statement                    (N : Node_Id);
+   procedure Analyze_Raise_xxx_Error                    (N : Node_Id);
+   procedure Analyze_Subprogram_Info                    (N : Node_Id);
+
+   procedure Analyze_Exception_Handlers (L : List_Id);
+   --  Analyze list of exception handlers of a handled statement sequence
+
+end Sem_Ch11;
diff --git a/gcc/ada/sem_ch12.adb b/gcc/ada/sem_ch12.adb
new file mode 100644 (file)
index 0000000..3f47a62
--- /dev/null
@@ -0,0 +1,8932 @@
+------------------------------------------------------------------------------
+--                                                                          --
+--                         GNAT COMPILER COMPONENTS                         --
+--                                                                          --
+--                             S E M _ C H 1 2                              --
+--                                                                          --
+--                                 B o d y                                  --
+--                                                                          --
+--                            $Revision: 1.776 $
+--                                                                          --
+--          Copyright (C) 1992-2001, 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- --
+-- ware  Foundation;  either version 2,  or (at your option) any later ver- --
+-- sion.  GNAT is distributed in the hope that it will be useful, but WITH- --
+-- OUT ANY WARRANTY;  without even the  implied warranty of MERCHANTABILITY --
+-- or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License --
+-- for  more details.  You should have  received  a copy of the GNU General --
+-- Public License  distributed with GNAT;  see file COPYING.  If not, write --
+-- to  the Free Software Foundation,  59 Temple Place - Suite 330,  Boston, --
+-- MA 02111-1307, USA.                                                      --
+--                                                                          --
+-- GNAT was originally developed  by the GNAT team at  New York University. --
+-- It is now maintained by Ada Core Technologies Inc (http://www.gnat.com). --
+--                                                                          --
+------------------------------------------------------------------------------
+
+with Atree;    use Atree;
+with Einfo;    use Einfo;
+with Elists;   use Elists;
+with Errout;   use Errout;
+with Expander; use Expander;
+with Fname;    use Fname;
+with Fname.UF; use Fname.UF;
+with Freeze;   use Freeze;
+with Hostparm;
+with Inline;   use Inline;
+with Lib;      use Lib;
+with Lib.Load; use Lib.Load;
+with Lib.Xref; use Lib.Xref;
+with Nlists;   use Nlists;
+with Nmake;    use Nmake;
+with Opt;      use Opt;
+with Restrict; use Restrict;
+with Rtsfind;  use Rtsfind;
+with Sem;      use Sem;
+with Sem_Cat;  use Sem_Cat;
+with Sem_Ch3;  use Sem_Ch3;
+with Sem_Ch6;  use Sem_Ch6;
+with Sem_Ch7;  use Sem_Ch7;
+with Sem_Ch8;  use Sem_Ch8;
+with Sem_Ch10; use Sem_Ch10;
+with Sem_Ch13; use Sem_Ch13;
+with Sem_Elab; use Sem_Elab;
+with Sem_Elim; use Sem_Elim;
+with Sem_Eval; use Sem_Eval;
+with Sem_Res;  use Sem_Res;
+with Sem_Type; use Sem_Type;
+with Sem_Util; use Sem_Util;
+with Stand;    use Stand;
+with Sinfo;    use Sinfo;
+with Sinfo.CN; use Sinfo.CN;
+with Sinput;   use Sinput;
+with Sinput.L; use Sinput.L;
+with Snames;   use Snames;
+with Stringt;  use Stringt;
+with Uname;    use Uname;
+with Table;
+with Tbuild;   use Tbuild;
+with Uintp;    use Uintp;
+with Urealp;   use Urealp;
+
+with GNAT.HTable;
+
+package body Sem_Ch12 is
+
+   use Atree.Unchecked_Access;
+   --  This package performs untyped traversals of the tree, therefore it
+   --  needs direct access to the fields of a node.
+
+   ----------------------------------------------------------
+   -- Implementation of Generic Analysis and Instantiation --
+   -----------------------------------------------------------
+
+   --  GNAT implements generics by macro expansion. No attempt is made to
+   --  share generic instantiations (for now). Analysis of a generic definition
+   --  does not perform any expansion action, but the expander must be called
+   --  on the tree for each instantiation, because the expansion may of course
+   --  depend on the generic actuals. All of this is best achieved as follows:
+   --
+   --  a) Semantic analysis of a generic unit is performed on a copy of the
+   --  tree for the generic unit. All tree modifications that follow analysis
+   --  do not affect the original tree. Links are kept between the original
+   --  tree and the copy, in order to recognize non-local references within
+   --  the generic, and propagate them to each instance (recall that name
+   --  resolution is done on the generic declaration: generics are not really
+   --  macros!). This is summarized in the following diagram:
+   --
+   --              .-----------.               .----------.
+   --              |  semantic |<--------------|  generic |
+   --              |    copy   |               |    unit  |
+   --              |           |==============>|          |
+   --              |___________|    global     |__________|
+   --                             references     |   |  |
+   --                                            |   |  |
+   --                                          .-----|--|.
+   --                                          |  .-----|---.
+   --                                          |  |  .----------.
+   --                                          |  |  |  generic |
+   --                                          |__|  |          |
+   --                                             |__| instance |
+   --                                                |__________|
+   --
+   --  b) Each instantiation copies the original tree, and inserts into it a
+   --  series of declarations that describe the mapping between generic formals
+   --  and actuals. For example, a generic In OUT parameter is an object
+   --  renaming of the corresponing actual, etc. Generic IN parameters are
+   --  constant declarations.
+   --
+   --  c) In order to give the right visibility for these renamings, we use
+   --  a different scheme for package and subprogram instantiations. For
+   --  packages, the list of renamings is inserted into the package
+   --  specification, before the visible declarations of the package. The
+   --  renamings are analyzed before any of the text of the instance, and are
+   --  thus visible at the right place. Furthermore, outside of the instance,
+   --  the generic parameters are visible and denote their corresponding
+   --  actuals.
+
+   --  For subprograms, we create a container package to hold the renamings
+   --  and the subprogram instance itself. Analysis of the package makes the
+   --  renaming declarations visible to the subprogram. After analyzing the
+   --  package, the defining entity for the subprogram is touched-up so that
+   --  it appears declared in the current scope, and not inside the container
+   --  package.
+
+   --  If the instantiation is a compilation unit, the container package is
+   --  given the same name as the subprogram instance. This ensures that
+   --  the elaboration procedure called by the binder, using the compilation
+   --  unit name, calls in fact the elaboration procedure for the package.
+
+   --  Not surprisingly, private types complicate this approach. By saving in
+   --  the original generic object the non-local references, we guarantee that
+   --  the proper entities are referenced at the point of instantiation.
+   --  However, for private types, this by itself does not insure that the
+   --  proper VIEW of the entity is used (the full type may be visible at the
+   --  point of generic definition, but not at instantiation, or vice-versa).
+   --  In  order to reference the proper view, we special-case any reference
+   --  to private types in the generic object, by saving both views, one in
+   --  the generic and one in the semantic copy. At time of instantiation, we
+   --  check whether the two views are consistent, and exchange declarations if
+   --  necessary, in order to restore the correct visibility. Similarly, if
+   --  the instance view is private when the generic view was not, we perform
+   --  the exchange. After completing the instantiation, we restore the
+   --  current visibility. The flag Has_Private_View marks identifiers in the
+   --  the generic unit that require checking.
+
+   --  Visibility within nested generic units requires special handling.
+   --  Consider the following scheme:
+   --
+   --  type Global is ...         --  outside of generic unit.
+   --  generic ...
+   --  package Outer is
+   --     ...
+   --     type Semi_Global is ... --  global to inner.
+   --
+   --     generic ...                                         -- 1
+   --     procedure inner (X1 : Global;  X2 : Semi_Global);
+   --
+   --     procedure in2 is new inner (...);                   -- 4
+   --  end Outer;
+
+   --  package New_Outer is new Outer (...);                  -- 2
+   --  procedure New_Inner is new New_Outer.Inner (...);      -- 3
+
+   --  The semantic analysis of Outer captures all occurrences of Global.
+   --  The semantic analysis of Inner (at 1) captures both occurrences of
+   --  Global and Semi_Global.
+
+   --  At point 2 (instantiation of Outer), we also produce a generic copy
+   --  of Inner, even though Inner is, at that point, not being instantiated.
+   --  (This is just part of the semantic analysis of New_Outer).
+
+   --  Critically, references to Global within Inner must be preserved, while
+   --  references to Semi_Global should not preserved, because they must now
+   --  resolve to an entity within New_Outer. To distinguish between these, we
+   --  use a global variable, Current_Instantiated_Parent, which is set when
+   --  performing a generic copy during instantiation (at 2). This variable is
+   --  used when performing a generic copy that is not an instantiation, but
+   --  that is nested within one, as the occurrence of 1 within 2. The analysis
+   --  of a nested generic only preserves references that are global to the
+   --  enclosing Current_Instantiated_Parent. We use the Scope_Depth value to
+   --  determine whether a reference is external to the given parent.
+
+   --  The instantiation at point 3 requires no special treatment. The method
+   --  works as well for further nestings of generic units, but of course the
+   --  variable Current_Instantiated_Parent must be stacked because nested
+   --  instantiations can occur, e.g. the occurrence of 4 within 2.
+
+   --  The instantiation of package and subprogram bodies is handled in a
+   --  similar manner, except that it is delayed until after semantic
+   --  analysis is complete. In this fashion complex cross-dependencies
+   --  between several package declarations and bodies containing generics
+   --  can be compiled which otherwise would diagnose spurious circularities.
+
+   --  For example, it is possible to compile two packages A and B that
+   --  have the following structure:
+
+   --    package A is                         package B is
+   --       generic ...                          generic ...
+   --       package G_A is                       package G_B is
+
+   --    with B;                              with A;
+   --    package body A is                    package body B is
+   --       package N_B is new G_B (..)          package N_A is new G_A (..)
+
+   --  The table Pending_Instantiations in package Inline is used to keep
+   --  track of body instantiations that are delayed in this manner. Inline
+   --  handles the actual calls to do the body instantiations. This activity
+   --  is part of Inline, since the processing occurs at the same point, and
+   --  for essentially the same reason, as the handling of inlined routines.
+
+   ----------------------------------------------
+   -- Detection of Instantiation Circularities --
+   ----------------------------------------------
+
+   --  If we have a chain of instantiations that is circular, this is a
+   --  static error which must be detected at compile time. The detection
+   --  of these circularities is carried out at the point that we insert
+   --  a generic instance spec or body. If there is a circularity, then
+   --  the analysis of the offending spec or body will eventually result
+   --  in trying to load the same unit again, and we detect this problem
+   --  as we analyze the package instantiation for the second time.
+
+   --  At least in some cases after we have detected the circularity, we
+   --  get into trouble if we try to keep going. The following flag is
+   --  set if a circularity is detected, and used to abandon compilation
+   --  after the messages have been posted.
+
+   Circularity_Detected : Boolean := False;
+   --  This should really be reset on encountering a new main unit, but in
+   --  practice we are not using multiple main units so it is not critical.
+
+   -----------------------
+   -- Local subprograms --
+   -----------------------
+
+   procedure Abandon_Instantiation (N : Node_Id);
+   pragma No_Return (Abandon_Instantiation);
+   --  Posts an error message "instantiation abandoned" at the indicated
+   --  node and then raises the exception Instantiation_Error to do it.
+
+   procedure Analyze_Formal_Array_Type
+     (T   : in out Entity_Id;
+      Def : Node_Id);
+   --  A formal array type is treated like an array type declaration, and
+   --  invokes Array_Type_Declaration (sem_ch3) whose first parameter is
+   --  in-out, because in the case of an anonymous type the entity is
+   --  actually created in the procedure.
+
+   --  The following procedures treat other kinds of formal parameters.
+
+   procedure Analyze_Formal_Derived_Type
+     (N   : Node_Id;
+      T   : Entity_Id;
+      Def : Node_Id);
+
+   --  All the following need comments???
+
+   procedure Analyze_Formal_Decimal_Fixed_Point_Type
+                                                (T : Entity_Id; Def : Node_Id);
+   procedure Analyze_Formal_Discrete_Type       (T : Entity_Id; Def : Node_Id);
+   procedure Analyze_Formal_Floating_Type       (T : Entity_Id; Def : Node_Id);
+   procedure Analyze_Formal_Signed_Integer_Type (T : Entity_Id; Def : Node_Id);
+   procedure Analyze_Formal_Modular_Type        (T : Entity_Id; Def : Node_Id);
+   procedure Analyze_Formal_Ordinary_Fixed_Point_Type
+                                                (T : Entity_Id; Def : Node_Id);
+
+   procedure Analyze_Formal_Private_Type
+     (N   : Node_Id;
+      T   : Entity_Id;
+      Def : Node_Id);
+   --  This needs comments???
+
+   procedure Analyze_Generic_Formal_Part (N : Node_Id);
+
+   procedure Analyze_Generic_Access_Type (T : Entity_Id; Def : Node_Id);
+   --  This needs comments ???
+
+   function Analyze_Associations
+     (I_Node  : Node_Id;
+      Formals : List_Id;
+      F_Copy  : List_Id)
+      return    List_Id;
+   --  At instantiation time, build the list of associations between formals
+   --  and actuals. Each association becomes a renaming declaration for the
+   --  formal entity. F_Copy is the analyzed list of formals in the generic
+   --  copy. It is used to apply legality checks to the actuals. I_Node is the
+   --  instantiation node itself.
+
+   procedure Analyze_Subprogram_Instantiation
+     (N : Node_Id;
+      K : Entity_Kind);
+
+   procedure Build_Instance_Compilation_Unit_Nodes
+     (N        : Node_Id;
+      Act_Body : Node_Id;
+      Act_Decl : Node_Id);
+   --  This procedure is used in the case where the generic instance of a
+   --  subprogram body or package body is a library unit. In this case, the
+   --  original library unit node for the generic instantiation must be
+   --  replaced by the resulting generic body, and a link made to a new
+   --  compilation unit node for the generic declaration. The argument N is
+   --  the original generic instantiation. Act_Body and Act_Decl are the body
+   --  and declaration of the instance (either package body and declaration
+   --  nodes or subprogram body and declaration nodes depending on the case).
+   --  On return, the node N has been rewritten with the actual body.
+
+   procedure Check_Formal_Packages (P_Id : Entity_Id);
+   --  Apply the following to all formal packages in generic associations.
+
+   procedure Check_Formal_Package_Instance
+     (Formal_Pack : Entity_Id;
+      Actual_Pack : Entity_Id);
+   --  Verify that the actuals of the actual instance match the actuals of
+   --  the template for a formal package that is not declared with a box.
+
+   procedure Check_Forward_Instantiation (N : Node_Id; Decl : Node_Id);
+   --  If the generic is a local entity and the corresponding body has not
+   --  been seen yet, flag enclosing packages to indicate that it will be
+   --  elaborated after the generic body. Subprograms declared in the same
+   --  package cannot be inlined by the front-end because front-end inlining
+   --  requires a strict linear order of elaboration.
+
+   procedure Check_Hidden_Child_Unit
+     (N           : Node_Id;
+      Gen_Unit    : Entity_Id;
+      Act_Decl_Id : Entity_Id);
+   --  If the generic unit is an implicit child instance within a parent
+   --  instance, we need to make an explicit test that it is not hidden by
+   --  a child instance of the same name and parent.
+
+   procedure Check_Private_View (N : Node_Id);
+   --  Check whether the type of a generic entity has a different view between
+   --  the point of generic analysis and the point of instantiation. If the
+   --  view has changed, then at the point of instantiation we restore the
+   --  correct view to perform semantic analysis of the instance, and reset
+   --  the current view after instantiation. The processing is driven by the
+   --  current private status of the type of the node, and Has_Private_View,
+   --  a flag that is set at the point of generic compilation. If view and
+   --  flag are inconsistent then the type is updated appropriately.
+
+   procedure Check_Generic_Actuals
+     (Instance      : Entity_Id;
+      Is_Formal_Box : Boolean);
+   --  Similar to previous one. Check the actuals in the instantiation,
+   --  whose views can change between the point of instantiation and the point
+   --  of instantiation of the body. In addition, mark the generic renamings
+   --  as generic actuals, so that they are not compatible with other actuals.
+   --  Recurse on an actual that is a formal package whose declaration has
+   --  a box.
+
+   function Contains_Instance_Of
+     (Inner : Entity_Id;
+      Outer : Entity_Id;
+      N     : Node_Id)
+      return  Boolean;
+   --  Inner is instantiated within the generic Outer. Check whether Inner
+   --  directly or indirectly contains an instance of Outer or of one of its
+   --  parents, in the case of a subunit. Each generic unit holds a list of
+   --  the entities instantiated within (at any depth). This procedure
+   --  determines whether the set of such lists contains a cycle, i.e. an
+   --  illegal circular instantiation.
+
+   function Denotes_Formal_Package (Pack : Entity_Id) return Boolean;
+   --  Returns True if E is a formal package of an enclosing generic, or
+   --  the actual for such a formal in an enclosing instantiation. Used in
+   --  Restore_Private_Views, to keep the formals of such a package visible
+   --  on exit from an inner instantiation.
+
+   function Find_Actual_Type
+     (Typ       : Entity_Id;
+      Gen_Scope : Entity_Id)
+      return      Entity_Id;
+   --  When validating the actual types of a child instance, check whether
+   --  the formal is a formal type of the parent unit, and retrieve the current
+   --  actual for it. Typ is the entity in the analyzed formal type declaration
+   --  (component or index type of an array type) and Gen_Scope is the scope of
+   --  the analyzed formal array type.
+
+   function Get_Package_Instantiation_Node (A : Entity_Id) return Node_Id;
+   --  Given the entity of a unit that is an instantiation, retrieve the
+   --  original instance node. This is used when loading the instantiations
+   --  of the ancestors of a child generic that is being instantiated.
+
+   function In_Same_Declarative_Part
+     (F_Node : Node_Id;
+      Inst   : Node_Id)
+      return   Boolean;
+   --  True if the instantiation Inst and the given freeze_node F_Node appear
+   --  within the same declarative part, ignoring subunits, but with no inter-
+   --  vening suprograms or concurrent units. If true, the freeze node
+   --  of the instance can be placed after the freeze node of the parent,
+   --  which it itself an instance.
+
+   procedure Set_Instance_Of (A : Entity_Id; B : Entity_Id);
+   --  Associate analyzed generic parameter with corresponding
+   --  instance. Used for semantic checks at instantiation time.
+
+   function Has_Been_Exchanged (E : Entity_Id) return Boolean;
+   --  Traverse the Exchanged_Views list to see if a type was private
+   --  and has already been flipped during this phase of instantiation.
+
+   procedure Hide_Current_Scope;
+   --  When compiling a generic child unit, the parent context must be
+   --  present, but the instance and all entities that may be generated
+   --  must be inserted in the current scope. We leave the current scope
+   --  on the stack, but make its entities invisible to avoid visibility
+   --  problems. This is reversed at the end of instantiations. This is
+   --  not done for the instantiation of the bodies, which only require the
+   --  instances of the generic parents to be in scope.
+
+   procedure Install_Body
+     (Act_Body : Node_Id;
+      N        : Node_Id;
+      Gen_Body : Node_Id;
+      Gen_Decl : Node_Id);
+   --  If the instantiation happens textually before the body of the generic,
+   --  the instantiation of the body must be analyzed after the generic body,
+   --  and not at the point of instantiation. Such early instantiations can
+   --  happen if the generic and the instance appear in  a package declaration
+   --  because the generic body can only appear in the corresponding package
+   --  body. Early instantiations can also appear if generic, instance and
+   --  body are all in the declarative part of a subprogram or entry. Entities
+   --  of packages that are early instantiations are delayed, and their freeze
+   --  node appears after the generic body.
+
+   procedure Insert_After_Last_Decl (N : Node_Id; F_Node : Node_Id);
+   --  Insert freeze node at the end of the declarative part that includes the
+   --  instance node N. If N is in the visible part of an enclosing package
+   --  declaration, the freeze node has to be inserted at the end of the
+   --  private declarations, if any.
+
+   procedure Freeze_Subprogram_Body
+     (Inst_Node : Node_Id;
+      Gen_Body  : Node_Id;
+      Pack_Id   : Entity_Id);
+   --  The generic body may appear textually after the instance, including
+   --  in the proper body of a stub, or within a different package instance.
+   --  Given that the instance can only be elaborated after the generic, we
+   --  place freeze_nodes for the instance and/or for packages that may enclose
+   --  the instance and the generic, so that the back-end can establish the
+   --  proper order of elaboration.
+
+   procedure Install_Parent (P : Entity_Id; In_Body : Boolean := False);
+   --  When compiling an instance of a child unit the parent (which is
+   --  itself an instance) is an enclosing scope that must be made
+   --  immediately visible. This procedure is also used to install the non-
+   --  generic parent of a generic child unit when compiling its body, so that
+   --  full views of types in the parent are made visible.
+
+   procedure Remove_Parent (In_Body : Boolean := False);
+   --  Reverse effect after instantiation of child is complete.
+
+   procedure Inline_Instance_Body
+     (N        : Node_Id;
+      Gen_Unit : Entity_Id;
+      Act_Decl : Node_Id);
+   --  If front-end inlining is requested, instantiate the package body,
+   --  and preserve the visibility of its compilation unit, to insure
+   --  that successive instantiations succeed.
+
+   --  The functions Instantiate_XXX perform various legality checks and build
+   --  the declarations for instantiated generic parameters.
+   --  Need to describe what the parameters are ???
+
+   function Instantiate_Object
+     (Formal          : Node_Id;
+      Actual          : Node_Id;
+      Analyzed_Formal : Node_Id)
+      return            List_Id;
+
+   function Instantiate_Type
+     (Formal          : Node_Id;
+      Actual          : Node_Id;
+      Analyzed_Formal : Node_Id)
+      return            Node_Id;
+
+   function Instantiate_Formal_Subprogram
+     (Formal          : Node_Id;
+      Actual          : Node_Id;
+      Analyzed_Formal : Node_Id)
+      return            Node_Id;
+
+   function Instantiate_Formal_Package
+     (Formal          : Node_Id;
+      Actual          : Node_Id;
+      Analyzed_Formal : Node_Id)
+      return            List_Id;
+   --  If the formal package is declared with a box, special visibility rules
+   --  apply to its formals: they are in the visible part of the package. This
+   --  is true in the declarative region of the formal package, that is to say
+   --  in the enclosing generic or instantiation. For an instantiation, the
+   --  parameters of the formal package are made visible in an explicit step.
+   --  Furthermore, if the actual is a visible use_clause, these formals must
+   --  be made potentially use_visible as well. On exit from the enclosing
+   --  instantiation, the reverse must be done.
+
+   --  For a formal package declared without a box, there are conformance rules
+   --  that apply to the actuals in the generic declaration and the actuals of
+   --  the actual package in the enclosing instantiation. The simplest way to
+   --  apply these rules is to repeat the instantiation of the formal package
+   --  in the context of the enclosing instance, and compare the generic
+   --  associations of this instantiation with those of the actual package.
+
+   function Is_In_Main_Unit (N : Node_Id) return Boolean;
+   --  Test if given node is in the main unit
+
+   procedure Load_Parent_Of_Generic (N : Node_Id; Spec : Node_Id);
+   --  If the generic appears in a separate non-generic library unit,
+   --  load the corresponding body to retrieve the body of the generic.
+   --  N is the node for the generic instantiation, Spec is the generic
+   --  package declaration.
+
+   procedure Inherit_Context (Gen_Decl : Node_Id; Inst : Node_Id);
+   --  Add the context clause of the unit containing a generic unit to
+   --  an instantiation that is a compilation unit.
+
+   function Associated_Node (N : Node_Id) return Node_Id;
+   --  In order to propagate semantic information back from the analyzed
+   --  copy to the original generic, we maintain links between selected nodes
+   --  in the generic and their corresponding copies. At the end of generic
+   --  analysis, the routine Save_Global_References traverses the generic
+   --  tree, examines the semantic information, and preserves the links to
+   --  those nodes that contain global information. At instantiation, the
+   --  information from the associated node is placed on the new copy, so that
+   --  name resolution is not repeated.
+   --  Two kinds of nodes have associated nodes:
+
+   --  a) those that contain entities, that is to say identifiers, expanded_
+   --    names, and operators.
+
+   --  b) aggregates.
+
+   --  For the first class, the associated node preserves the entity if it is
+   --  global. If the generic contains nested instantiations, the associated_
+   --  node itself has been recopied, and a chain of them must be followed.
+
+   --  For aggregates, the associated node allows retrieval of the type, which
+   --  may otherwise not appear in the generic. The view of this type may be
+   --  different between generic and instantiation, and the full view can be
+   --  installed before the instantiation is analyzed. For aggregates of
+   --  type extensions, the same view exchange may have to be performed for
+   --  some of the ancestor types, if their view is private at the point of
+   --  instantiation.
+
+   --  The associated node is stored in Node4, using this field as a free
+   --  union in a fashion that should clearly be under control of sinfo ???
+
+   procedure Move_Freeze_Nodes
+     (Out_Of : Entity_Id;
+      After  : Node_Id;
+      L      : List_Id);
+   --  Freeze nodes can be generated in the analysis of a generic unit, but
+   --  will not be seen by the back-end. It is necessary to move those nodes
+   --  to the enclosing scope if they freeze an outer entity. We place them
+   --  at the end of the enclosing generic package, which is semantically
+   --  neutral.
+
+   procedure Pre_Analyze_Actuals (N : Node_Id);
+   --  Analyze actuals to perform name resolution. Full resolution is done
+   --  later, when the expected types are known, but names have to be captured
+   --  before installing parents of generics, that are not visible for the
+   --  actuals themselves.
+
+   procedure Set_Associated_Node
+     (Gen_Node  : Node_Id;
+      Copy_Node : Node_Id);
+   --  Establish the link between an identifier in the generic unit, and the
+   --  corresponding node in the semantic copy.
+
+   procedure Valid_Default_Attribute (Nam : Entity_Id; Def : Node_Id);
+   --  Verify that an attribute that appears as the default for a formal
+   --  subprogram is a function or procedure with the correct profile.
+
+   -------------------------------------------
+   -- Data Structures for Generic Renamings --
+   -------------------------------------------
+
+   --  The map Generic_Renamings associates generic entities with their
+   --  corresponding actuals. Currently used to validate type instances.
+   --  It will eventually be used for all generic parameters to eliminate
+   --  the need for overload resolution in the instance.
+
+   type Assoc_Ptr is new Int;
+
+   Assoc_Null : constant Assoc_Ptr := -1;
+
+   type Assoc is record
+      Gen_Id         : Entity_Id;
+      Act_Id         : Entity_Id;
+      Next_In_HTable : Assoc_Ptr;
+   end record;
+
+   package Generic_Renamings is new Table.Table
+     (Table_Component_Type => Assoc,
+      Table_Index_Type     => Assoc_Ptr,
+      Table_Low_Bound      => 0,
+      Table_Initial        => 10,
+      Table_Increment      => 100,
+      Table_Name           => "Generic_Renamings");
+
+   --  Variable to hold enclosing instantiation. When the environment is
+   --  saved for a subprogram inlining, the corresponding Act_Id is empty.
+
+   Current_Instantiated_Parent : Assoc := (Empty, Empty, Assoc_Null);
+
+   --  Hash table for associations
+
+   HTable_Size : constant := 37;
+   type HTable_Range is range 0 .. HTable_Size - 1;
+
+   procedure Set_Next_Assoc (E : Assoc_Ptr; Next : Assoc_Ptr);
+   function  Next_Assoc     (E : Assoc_Ptr) return Assoc_Ptr;
+   function Get_Gen_Id      (E : Assoc_Ptr) return Entity_Id;
+   function Hash            (F : Entity_Id)   return HTable_Range;
+
+   package Generic_Renamings_HTable is new GNAT.HTable.Static_HTable (
+      Header_Num => HTable_Range,
+      Element    => Assoc,
+      Elmt_Ptr   => Assoc_Ptr,
+      Null_Ptr   => Assoc_Null,
+      Set_Next   => Set_Next_Assoc,
+      Next       => Next_Assoc,
+      Key        => Entity_Id,
+      Get_Key    => Get_Gen_Id,
+      Hash       => Hash,
+      Equal      => "=");
+
+   Exchanged_Views : Elist_Id;
+   --  This list holds the private views that have been exchanged during
+   --  instantiation to restore the visibility of the generic declaration.
+   --  (see comments above). After instantiation, the current visibility is
+   --  reestablished by means of a traversal of this list.
+
+   Hidden_Entities : Elist_Id;
+   --  This list holds the entities of the current scope that are removed
+   --  from immediate visibility when instantiating a child unit. Their
+   --  visibility is restored in Remove_Parent.
+
+   --  Because instantiations can be recursive, the following must be saved
+   --  on entry and restored on exit from an instantiation (spec or body).
+   --  This is done by the two procedures Save_Env and Restore_Env.
+
+   type Instance_Env is record
+      Ada_83              : Boolean;
+      Instantiated_Parent : Assoc;
+      Exchanged_Views     : Elist_Id;
+      Hidden_Entities     : Elist_Id;
+      Current_Sem_Unit    : Unit_Number_Type;
+   end record;
+
+   package Instance_Envs is new Table.Table (
+     Table_Component_Type => Instance_Env,
+     Table_Index_Type     => Int,
+     Table_Low_Bound      => 0,
+     Table_Initial        => 32,
+     Table_Increment      => 100,
+     Table_Name           => "Instance_Envs");
+
+   procedure Restore_Private_Views
+     (Pack_Id    : Entity_Id;
+      Is_Package : Boolean := True);
+   --  Restore the private views of external types, and unmark the generic
+   --  renamings of actuals, so that they become comptible subtypes again.
+   --  For subprograms, Pack_Id is the package constructed to hold the
+   --  renamings.
+
+   procedure Switch_View (T : Entity_Id);
+   --  Switch the partial and full views of a type and its private
+   --  dependents (i.e. its subtypes and derived types).
+
+   ------------------------------------
+   -- Structures for Error Reporting --
+   ------------------------------------
+
+   Instantiation_Node : Node_Id;
+   --  Used by subprograms that validate instantiation of formal parameters
+   --  where there might be no actual on which to place the error message.
+   --  Also used to locate the instantiation node for generic subunits.
+
+   Instantiation_Error : exception;
+   --  When there is a semantic error in the generic parameter matching,
+   --  there is no point in continuing the instantiation, because the
+   --  number of cascaded errors is unpredictable. This exception aborts
+   --  the instantiation process altogether.
+
+   S_Adjustment : Sloc_Adjustment;
+   --  Offset created for each node in an instantiation, in order to keep
+   --  track of the source position of the instantiation in each of its nodes.
+   --  A subsequent semantic error or warning on a construct of the instance
+   --  points to both places: the original generic node, and the point of
+   --  instantiation. See Sinput and Sinput.L for additional details.
+
+   ------------------------------------------------------------
+   -- Data structure for keeping track when inside a Generic --
+   ------------------------------------------------------------
+
+   --  The following table is used to save values of the Inside_A_Generic
+   --  flag (see spec of Sem) when they are saved by Start_Generic.
+
+   package Generic_Flags is new Table.Table (
+     Table_Component_Type => Boolean,
+     Table_Index_Type     => Int,
+     Table_Low_Bound      => 0,
+     Table_Initial        => 32,
+     Table_Increment      => 200,
+     Table_Name           => "Generic_Flags");
+
+   ---------------------------
+   -- Abandon_Instantiation --
+   ---------------------------
+
+   procedure Abandon_Instantiation (N : Node_Id) is
+   begin
+      Error_Msg_N ("instantiation abandoned!", N);
+      raise Instantiation_Error;
+   end Abandon_Instantiation;
+
+   --------------------------
+   -- Analyze_Associations --
+   --------------------------
+
+   function Analyze_Associations
+     (I_Node  : Node_Id;
+      Formals : List_Id;
+      F_Copy  : List_Id)
+      return    List_Id
+   is
+      Actuals         : List_Id := Generic_Associations (I_Node);
+      Actual          : Node_Id;
+      Actual_Types    : Elist_Id := New_Elmt_List;
+      Assoc           : List_Id  := New_List;
+      Formal          : Node_Id;
+      Next_Formal     : Node_Id;
+      Temp_Formal     : Node_Id;
+      Analyzed_Formal : Node_Id;
+      Defaults        : Elist_Id := New_Elmt_List;
+      Match           : Node_Id;
+      Named           : Node_Id;
+      First_Named     : Node_Id := Empty;
+      Found_Assoc     : Node_Id;
+      Is_Named_Assoc  : Boolean;
+      Num_Matched     : Int := 0;
+      Num_Actuals     : Int := 0;
+
+      function Matching_Actual
+        (F    : Entity_Id;
+         A_F  : Entity_Id)
+         return Node_Id;
+      --  Find actual that corresponds to a given a formal parameter. If the
+      --  actuals are positional, return the next one, if any. If the actuals
+      --  are named, scan the parameter associations to find the right one.
+      --  A_F is the corresponding entity in the analyzed generic,which is
+      --  placed on the selector name for ASIS use.
+
+      procedure Set_Analyzed_Formal;
+      --  Find the node in the generic copy that corresponds to a given formal.
+      --  The semantic information on this node is used to perform legality
+      --  checks on the actuals. Because semantic analysis can introduce some
+      --  anonymous entities or modify the declaration node itself, the
+      --  correspondence between the two lists is not one-one. In addition to
+      --  anonymous types, the presence a formal equality will introduce an
+      --  implicit declaration for the corresponding inequality.
+
+      ---------------------
+      -- Matching_Actual --
+      ---------------------
+
+      function Matching_Actual
+        (F    : Entity_Id;
+         A_F  : Entity_Id)
+         return Node_Id
+      is
+         Found : Node_Id;
+         Prev  : Node_Id;
+
+      begin
+         Is_Named_Assoc := False;
+
+         --  End of list of purely positional parameters
+
+         if No (Actual) then
+            Found := Empty;
+
+         --  Case of positional parameter corresponding to current formal
+
+         elsif No (Selector_Name (Actual)) then
+            Found := Explicit_Generic_Actual_Parameter (Actual);
+            Found_Assoc := Actual;
+            Num_Matched := Num_Matched + 1;
+            Next (Actual);
+
+         --  Otherwise scan list of named actuals to find the one with the
+         --  desired name. All remaining actuals have explicit names.
+
+         else
+            Is_Named_Assoc := True;
+            Found := Empty;
+            Prev  := Empty;
+
+            while Present (Actual) loop
+               if Chars (Selector_Name (Actual)) = Chars (F) then
+                  Found := Explicit_Generic_Actual_Parameter (Actual);
+                  Set_Entity (Selector_Name (Actual), A_F);
+                  Set_Etype  (Selector_Name (Actual), Etype (A_F));
+                  Found_Assoc := Actual;
+                  Num_Matched := Num_Matched + 1;
+                  exit;
+               end if;
+
+               Prev := Actual;
+               Next (Actual);
+            end loop;
+
+            --  Reset for subsequent searches. In most cases the named
+            --  associations are in order. If they are not, we reorder them
+            --  to avoid scanning twice the same actual. This is not just a
+            --  question of efficiency: there may be multiple defaults with
+            --  boxes that have the same name. In a nested instantiation we
+            --  insert actuals for those defaults, and cannot rely on their
+            --  names to disambiguate them.
+
+            if Actual = First_Named  then
+               Next (First_Named);
+
+            elsif Present (Actual) then
+               Insert_Before (First_Named, Remove_Next (Prev));
+            end if;
+
+            Actual := First_Named;
+         end if;
+
+         return Found;
+      end Matching_Actual;
+
+      -------------------------
+      -- Set_Analyzed_Formal --
+      -------------------------
+
+      procedure Set_Analyzed_Formal is
+         Kind : Node_Kind;
+      begin
+         while Present (Analyzed_Formal) loop
+            Kind := Nkind (Analyzed_Formal);
+
+            case Nkind (Formal) is
+
+               when N_Formal_Subprogram_Declaration =>
+                  exit when Kind = N_Formal_Subprogram_Declaration
+                    and then
+                      Chars
+                        (Defining_Unit_Name (Specification (Formal))) =
+                      Chars
+                        (Defining_Unit_Name (Specification (Analyzed_Formal)));
+
+               when N_Formal_Package_Declaration =>
+                  exit when
+                    Kind = N_Formal_Package_Declaration
+                      or else
+                    Kind = N_Generic_Package_Declaration;
+
+               when N_Use_Package_Clause | N_Use_Type_Clause => exit;
+
+               when others =>
+
+                  --  Skip freeze nodes, and nodes inserted to replace
+                  --  unrecognized pragmas.
+
+                  exit when
+                    Kind /= N_Formal_Subprogram_Declaration
+                      and then Kind /= N_Subprogram_Declaration
+                      and then Kind /= N_Freeze_Entity
+                      and then Kind /= N_Null_Statement
+                      and then Kind /= N_Itype_Reference
+                      and then Chars (Defining_Identifier (Formal)) =
+                               Chars (Defining_Identifier (Analyzed_Formal));
+            end case;
+
+            Next (Analyzed_Formal);
+         end loop;
+
+      end Set_Analyzed_Formal;
+
+   --  Start of processing for Analyze_Associations
+
+   begin
+      --  If named associations are present, save the first named association
+      --  (it may of course be Empty) to facilitate subsequent name search.
+
+      if Present (Actuals) then
+         First_Named := First (Actuals);
+
+         while Present (First_Named)
+           and then No (Selector_Name (First_Named))
+         loop
+            Num_Actuals := Num_Actuals + 1;
+            Next (First_Named);
+         end loop;
+      end if;
+
+      Named := First_Named;
+      while Present (Named) loop
+         if No (Selector_Name (Named)) then
+            Error_Msg_N ("invalid positional actual after named one", Named);
+            Abandon_Instantiation (Named);
+         end if;
+
+         Num_Actuals := Num_Actuals + 1;
+         Next (Named);
+      end loop;
+
+      if Present (Formals) then
+         Formal := First_Non_Pragma (Formals);
+         Analyzed_Formal := First_Non_Pragma (F_Copy);
+
+         if Present (Actuals) then
+            Actual := First (Actuals);
+
+         --  All formals should have default values
+
+         else
+            Actual := Empty;
+         end if;
+
+         while Present (Formal) loop
+            Set_Analyzed_Formal;
+            Next_Formal := Next_Non_Pragma (Formal);
+
+            case Nkind (Formal) is
+               when N_Formal_Object_Declaration =>
+                  Match :=
+                    Matching_Actual (
+                      Defining_Identifier (Formal),
+                      Defining_Identifier (Analyzed_Formal));
+
+                  Append_List
+                    (Instantiate_Object (Formal, Match, Analyzed_Formal),
+                     Assoc);
+
+               when N_Formal_Type_Declaration =>
+                  Match :=
+                    Matching_Actual (
+                      Defining_Identifier (Formal),
+                      Defining_Identifier (Analyzed_Formal));
+
+                  if No (Match) then
+                     Error_Msg_NE ("missing actual for instantiation of &",
+                        Instantiation_Node, Defining_Identifier (Formal));
+                     Abandon_Instantiation (Instantiation_Node);
+
+                  else
+                     Analyze (Match);
+                     Append_To (Assoc,
+                       Instantiate_Type (Formal, Match, Analyzed_Formal));
+
+                     --  an instantiation is a freeze point for the actuals,
+                     --  unless this is a rewritten formal package.
+
+                     if Nkind (I_Node) /= N_Formal_Package_Declaration then
+                        Append_Elmt (Entity (Match), Actual_Types);
+                     end if;
+                  end if;
+
+                  --  A remote access-to-class-wide type must not be an
+                  --  actual parameter for a generic formal of an access
+                  --  type (E.2.2 (17)).
+
+                  if Nkind (Analyzed_Formal) = N_Formal_Type_Declaration
+                    and then
+                      Nkind (Formal_Type_Definition (Analyzed_Formal)) =
+                                            N_Access_To_Object_Definition
+                  then
+                     Validate_Remote_Access_To_Class_Wide_Type (Match);
+                  end if;
+
+               when N_Formal_Subprogram_Declaration =>
+                  Match :=
+                    Matching_Actual (
+                      Defining_Unit_Name (Specification (Formal)),
+                      Defining_Unit_Name (Specification (Analyzed_Formal)));
+
+                  --  If the formal subprogram has the same name as
+                  --  another formal subprogram of the generic, then
+                  --  a named association is illegal (12.3(9)). Exclude
+                  --  named associations that are generated for a nested
+                  --  instance.
+
+                  if Present (Match)
+                    and then Is_Named_Assoc
+                    and then Comes_From_Source (Found_Assoc)
+                  then
+                     Temp_Formal := First (Formals);
+                     while Present (Temp_Formal) loop
+                        if Nkind (Temp_Formal) =
+                             N_Formal_Subprogram_Declaration
+                          and then Temp_Formal /= Formal
+                          and then
+                            Chars (Selector_Name (Found_Assoc)) =
+                              Chars (Defining_Unit_Name
+                                       (Specification (Temp_Formal)))
+                        then
+                           Error_Msg_N
+                             ("name not allowed for overloaded formal",
+                              Found_Assoc);
+                           Abandon_Instantiation (Instantiation_Node);
+                        end if;
+
+                        Next (Temp_Formal);
+                     end loop;
+                  end if;
+
+                  Append_To (Assoc,
+                    Instantiate_Formal_Subprogram
+                      (Formal, Match, Analyzed_Formal));
+
+                  if No (Match)
+                    and then Box_Present (Formal)
+                  then
+                     Append_Elmt
+                       (Defining_Unit_Name (Specification (Last (Assoc))),
+                         Defaults);
+                  end if;
+
+               when N_Formal_Package_Declaration =>
+                  Match :=
+                    Matching_Actual (
+                      Defining_Identifier (Formal),
+                      Defining_Identifier (Original_Node (Analyzed_Formal)));
+
+                  if No (Match) then
+                     Error_Msg_NE
+                       ("missing actual for instantiation of&",
+                        Instantiation_Node,
+                        Defining_Identifier (Formal));
+
+                     Abandon_Instantiation (Instantiation_Node);
+
+                  else
+                     Analyze (Match);
+                     Append_List
+                       (Instantiate_Formal_Package
+                         (Formal, Match, Analyzed_Formal),
+                        Assoc);
+                  end if;
+
+               --  For use type and use package appearing in the context
+               --  clause, we have already copied them, so we can just
+               --  move them where they belong (we mustn't recopy them
+               --  since this would mess up the Sloc values).
+
+               when N_Use_Package_Clause |
+                    N_Use_Type_Clause    =>
+                  Remove (Formal);
+                  Append (Formal, Assoc);
+
+               when others =>
+                  raise Program_Error;
+
+            end case;
+
+            Formal := Next_Formal;
+            Next_Non_Pragma (Analyzed_Formal);
+         end loop;
+
+         if Num_Actuals > Num_Matched then
+            Error_Msg_N
+              ("unmatched actuals in instantiation", Instantiation_Node);
+         end if;
+
+      elsif Present (Actuals) then
+         Error_Msg_N
+           ("too many actuals in generic instantiation", Instantiation_Node);
+      end if;
+
+      declare
+         Elmt : Elmt_Id := First_Elmt (Actual_Types);
+
+      begin
+         while Present (Elmt) loop
+            Freeze_Before (I_Node, Node (Elmt));
+            Next_Elmt (Elmt);
+         end loop;
+      end;
+
+      --  If there are default subprograms, normalize the tree by adding
+      --  explicit associations for them. This is required if the instance
+      --  appears within a generic.
+
+      declare
+         Elmt  : Elmt_Id;
+         Subp  : Entity_Id;
+         New_D : Node_Id;
+
+      begin
+         Elmt := First_Elmt (Defaults);
+         while Present (Elmt) loop
+            if No (Actuals) then
+               Actuals := New_List;
+               Set_Generic_Associations (I_Node, Actuals);
+            end if;
+
+            Subp := Node (Elmt);
+            New_D :=
+              Make_Generic_Association (Sloc (Subp),
+                Selector_Name => New_Occurrence_Of (Subp, Sloc (Subp)),
+                  Explicit_Generic_Actual_Parameter =>
+                    New_Occurrence_Of (Subp, Sloc (Subp)));
+            Mark_Rewrite_Insertion (New_D);
+            Append_To (Actuals, New_D);
+            Next_Elmt (Elmt);
+         end loop;
+      end;
+
+      return Assoc;
+   end Analyze_Associations;
+
+   -------------------------------
+   -- Analyze_Formal_Array_Type --
+   -------------------------------
+
+   procedure Analyze_Formal_Array_Type
+     (T   : in out Entity_Id;
+      Def : Node_Id)
+   is
+      DSS : Node_Id;
+
+   begin
+      --  Treated like a non-generic array declaration, with
+      --  additional semantic checks.
+
+      Enter_Name (T);
+
+      if Nkind (Def) = N_Constrained_Array_Definition then
+         DSS := First (Discrete_Subtype_Definitions (Def));
+         while Present (DSS) loop
+            if Nkind (DSS) = N_Subtype_Indication
+              or else Nkind (DSS) = N_Range
+              or else Nkind (DSS) = N_Attribute_Reference
+            then
+               Error_Msg_N ("only a subtype mark is allowed in a formal", DSS);
+            end if;
+
+            Next (DSS);
+         end loop;
+      end if;
+
+      Array_Type_Declaration (T, Def);
+      Set_Is_Generic_Type (Base_Type (T));
+
+      if Ekind (Component_Type (T)) = E_Incomplete_Type
+        and then No (Full_View (Component_Type (T)))
+      then
+         Error_Msg_N ("premature usage of incomplete type", Def);
+
+      elsif Is_Internal (Component_Type (T))
+        and then Nkind (Original_Node (Subtype_Indication (Def)))
+          /= N_Attribute_Reference
+      then
+         Error_Msg_N
+           ("only a subtype mark is allowed in a formal",
+              Subtype_Indication (Def));
+      end if;
+
+   end Analyze_Formal_Array_Type;
+
+   ---------------------------------------------
+   -- Analyze_Formal_Decimal_Fixed_Point_Type --
+   ---------------------------------------------
+
+   --  As for other generic types, we create a valid type representation
+   --  with legal but arbitrary attributes, whose values are never considered
+   --  static. For all scalar types we introduce an anonymous base type, with
+   --  the same attributes. We choose the corresponding integer type to be
+   --  Standard_Integer.
+
+   procedure Analyze_Formal_Decimal_Fixed_Point_Type
+     (T   : Entity_Id;
+      Def : Node_Id)
+   is
+      Loc       : constant Source_Ptr := Sloc (Def);
+      Base      : constant Entity_Id :=
+                    New_Internal_Entity
+                      (E_Decimal_Fixed_Point_Type,
+                       Current_Scope, Sloc (Def), 'G');
+      Int_Base  : constant Entity_Id := Standard_Integer;
+      Delta_Val : constant Ureal := Ureal_1;
+      Digs_Val  : constant Uint  := Uint_6;
+
+   begin
+      Enter_Name (T);
+
+      Set_Etype          (Base, Base);
+      Set_Size_Info      (Base, Int_Base);
+      Set_RM_Size        (Base, RM_Size (Int_Base));
+      Set_First_Rep_Item (Base, First_Rep_Item (Int_Base));
+      Set_Digits_Value   (Base, Digs_Val);
+      Set_Delta_Value    (Base, Delta_Val);
+      Set_Small_Value    (Base, Delta_Val);
+      Set_Scalar_Range   (Base,
+        Make_Range (Loc,
+          Low_Bound  => Make_Real_Literal (Loc, Ureal_1),
+          High_Bound => Make_Real_Literal (Loc, Ureal_1)));
+
+      Set_Is_Generic_Type (Base);
+      Set_Parent          (Base, Parent (Def));
+
+      Set_Ekind          (T, E_Decimal_Fixed_Point_Subtype);
+      Set_Etype          (T, Base);
+      Set_Size_Info      (T, Int_Base);
+      Set_RM_Size        (T, RM_Size (Int_Base));
+      Set_First_Rep_Item (T, First_Rep_Item (Int_Base));
+      Set_Digits_Value   (T, Digs_Val);
+      Set_Delta_Value    (T, Delta_Val);
+      Set_Small_Value    (T, Delta_Val);
+      Set_Scalar_Range   (T, Scalar_Range (Base));
+
+   end Analyze_Formal_Decimal_Fixed_Point_Type;
+
+   ---------------------------------
+   -- Analyze_Formal_Derived_Type --
+   ---------------------------------
+
+   procedure Analyze_Formal_Derived_Type
+     (N   : Node_Id;
+      T   : Entity_Id;
+      Def : Node_Id)
+   is
+      Loc      : constant Source_Ptr := Sloc (Def);
+      New_N    : Node_Id;
+      Unk_Disc : Boolean := Unknown_Discriminants_Present (N);
+
+   begin
+      Set_Is_Generic_Type (T);
+
+      if Private_Present (Def) then
+         New_N :=
+           Make_Private_Extension_Declaration (Loc,
+             Defining_Identifier           => T,
+             Discriminant_Specifications   => Discriminant_Specifications (N),
+             Unknown_Discriminants_Present => Unk_Disc,
+             Subtype_Indication            => Subtype_Mark (Def));
+
+         Set_Abstract_Present (New_N, Abstract_Present (Def));
+
+      else
+         New_N :=
+           Make_Full_Type_Declaration (Loc,
+             Defining_Identifier => T,
+             Discriminant_Specifications =>
+               Discriminant_Specifications (Parent (T)),
+              Type_Definition =>
+                Make_Derived_Type_Definition (Loc,
+                  Subtype_Indication => Subtype_Mark (Def)));
+
+         Set_Abstract_Present
+           (Type_Definition (New_N), Abstract_Present (Def));
+      end if;
+
+      Rewrite (N, New_N);
+      Analyze (N);
+
+      if Unk_Disc then
+         if not Is_Composite_Type (T) then
+            Error_Msg_N
+              ("unknown discriminants not allowed for elementary types", N);
+         else
+            Set_Has_Unknown_Discriminants (T);
+            Set_Is_Constrained (T, False);
+         end if;
+      end if;
+
+      --  If the parent type has a known size, so does the formal, which
+      --  makes legal representation clauses that involve the formal.
+
+      Set_Size_Known_At_Compile_Time
+        (T, Size_Known_At_Compile_Time (Entity (Subtype_Mark (Def))));
+
+   end Analyze_Formal_Derived_Type;
+
+   ----------------------------------
+   -- Analyze_Formal_Discrete_Type --
+   ----------------------------------
+
+   --  The operations defined for a discrete types are those of an
+   --  enumeration type. The size is set to an arbitrary value, for use
+   --  in analyzing the generic unit.
+
+   procedure Analyze_Formal_Discrete_Type (T : Entity_Id; Def : Node_Id) is
+      Loc : constant Source_Ptr := Sloc (Def);
+      Lo  : Node_Id;
+      Hi  : Node_Id;
+
+   begin
+      Enter_Name     (T);
+      Set_Ekind      (T, E_Enumeration_Type);
+      Set_Etype      (T, T);
+      Init_Size      (T, 8);
+      Init_Alignment (T);
+
+      --  For semantic analysis, the bounds of the type must be set to some
+      --  non-static value. The simplest is to create attribute nodes for
+      --  those bounds, that refer to the type itself. These bounds are never
+      --  analyzed but serve as place-holders.
+
+      Lo :=
+        Make_Attribute_Reference (Loc,
+          Attribute_Name => Name_First,
+          Prefix => New_Reference_To (T, Loc));
+      Set_Etype (Lo, T);
+
+      Hi :=
+        Make_Attribute_Reference (Loc,
+          Attribute_Name => Name_Last,
+          Prefix => New_Reference_To (T, Loc));
+      Set_Etype (Hi, T);
+
+      Set_Scalar_Range (T,
+        Make_Range (Loc,
+          Low_Bound => Lo,
+          High_Bound => Hi));
+
+   end Analyze_Formal_Discrete_Type;
+
+   ----------------------------------
+   -- Analyze_Formal_Floating_Type --
+   ---------------------------------
+
+   procedure Analyze_Formal_Floating_Type (T : Entity_Id; Def : Node_Id) is
+      Base : constant Entity_Id :=
+               New_Internal_Entity
+                 (E_Floating_Point_Type, Current_Scope, Sloc (Def), 'G');
+
+   begin
+      --  The various semantic attributes are taken from the predefined type
+      --  Float, just so that all of them are initialized. Their values are
+      --  never used because no constant folding or expansion takes place in
+      --  the generic itself.
+
+      Enter_Name (T);
+      Set_Ekind        (T, E_Floating_Point_Subtype);
+      Set_Etype        (T, Base);
+      Set_Size_Info    (T,              (Standard_Float));
+      Set_RM_Size      (T, RM_Size      (Standard_Float));
+      Set_Digits_Value (T, Digits_Value (Standard_Float));
+      Set_Scalar_Range (T, Scalar_Range (Standard_Float));
+
+      Set_Is_Generic_Type (Base);
+      Set_Etype           (Base, Base);
+      Set_Size_Info       (Base,              (Standard_Float));
+      Set_RM_Size         (Base, RM_Size      (Standard_Float));
+      Set_Digits_Value    (Base, Digits_Value (Standard_Float));
+      Set_Scalar_Range    (Base, Scalar_Range (Standard_Float));
+      Set_Parent          (Base, Parent (Def));
+   end Analyze_Formal_Floating_Type;
+
+   ---------------------------------
+   -- Analyze_Formal_Modular_Type --
+   ---------------------------------
+
+   procedure Analyze_Formal_Modular_Type (T : Entity_Id; Def : Node_Id) is
+   begin
+      --  Apart from their entity kind, generic modular types are treated
+      --  like signed integer types, and have the same attributes.
+
+      Analyze_Formal_Signed_Integer_Type (T, Def);
+      Set_Ekind (T, E_Modular_Integer_Subtype);
+      Set_Ekind (Etype (T), E_Modular_Integer_Type);
+
+   end Analyze_Formal_Modular_Type;
+
+   ---------------------------------------
+   -- Analyze_Formal_Object_Declaration --
+   ---------------------------------------
+
+   procedure Analyze_Formal_Object_Declaration (N : Node_Id) is
+      E  : constant Node_Id := Expression (N);
+      Id : Node_Id := Defining_Identifier (N);
+      K  : Entity_Kind;
+      T  : Node_Id;
+
+   begin
+      Enter_Name (Id);
+
+      --  Determine the mode of the formal object
+
+      if Out_Present (N) then
+         K := E_Generic_In_Out_Parameter;
+
+         if not In_Present (N) then
+            Error_Msg_N ("formal generic objects cannot have mode OUT", N);
+         end if;
+
+      else
+         K := E_Generic_In_Parameter;
+      end if;
+
+      Find_Type (Subtype_Mark (N));
+      T  := Entity (Subtype_Mark (N));
+
+      if Ekind (T) = E_Incomplete_Type then
+         Error_Msg_N ("premature usage of incomplete type", Subtype_Mark (N));
+      end if;
+
+      if K = E_Generic_In_Parameter then
+         if Is_Limited_Type (T) then
+            Error_Msg_N
+              ("generic formal of mode IN must not be of limited type", N);
+         end if;
+
+         if Is_Abstract (T) then
+            Error_Msg_N
+              ("generic formal of mode IN must not be of abstract type", N);
+         end if;
+
+         if Present (E) then
+            Analyze_Default_Expression (E, T);
+         end if;
+
+         Set_Ekind (Id, K);
+         Set_Etype (Id, T);
+
+      --  Case of generic IN OUT parameter.
+
+      else
+         --  If the formal has an unconstrained type, construct its
+         --  actual subtype, as is done for subprogram formals. In this
+         --  fashion, all its uses can refer to specific bounds.
+
+         Set_Ekind (Id, K);
+         Set_Etype (Id, T);
+
+         if (Is_Array_Type (T)
+              and then not Is_Constrained (T))
+           or else
+            (Ekind (T) = E_Record_Type
+              and then Has_Discriminants (T))
+         then
+            declare
+               Non_Freezing_Ref : constant Node_Id :=
+                                    New_Reference_To (Id, Sloc (Id));
+               Decl : Node_Id;
+
+            begin
+               --  Make sure that the actual subtype doesn't generate
+               --  bogus freezing.
+
+               Set_Must_Not_Freeze (Non_Freezing_Ref);
+               Decl := Build_Actual_Subtype (T, Non_Freezing_Ref);
+               Insert_Before_And_Analyze (N, Decl);
+               Set_Actual_Subtype (Id, Defining_Identifier (Decl));
+            end;
+         else
+            Set_Actual_Subtype (Id, T);
+         end if;
+
+         if Present (E) then
+            Error_Msg_N
+              ("initialization not allowed for `IN OUT` formals", N);
+         end if;
+      end if;
+
+   end Analyze_Formal_Object_Declaration;
+
+   ----------------------------------------------
+   -- Analyze_Formal_Ordinary_Fixed_Point_Type --
+   ----------------------------------------------
+
+   procedure Analyze_Formal_Ordinary_Fixed_Point_Type
+     (T   : Entity_Id;
+      Def : Node_Id)
+   is
+      Loc  : constant Source_Ptr := Sloc (Def);
+      Base : constant Entity_Id :=
+               New_Internal_Entity
+                 (E_Ordinary_Fixed_Point_Type, Current_Scope, Sloc (Def), 'G');
+   begin
+      --  The semantic attributes are set for completeness only, their
+      --  values will never be used, because all properties of the type
+      --  are non-static.
+
+      Enter_Name (T);
+      Set_Ekind            (T, E_Ordinary_Fixed_Point_Subtype);
+      Set_Etype            (T, Base);
+      Set_Size_Info        (T, Standard_Integer);
+      Set_RM_Size          (T, RM_Size (Standard_Integer));
+      Set_Small_Value      (T, Ureal_1);
+      Set_Delta_Value      (T, Ureal_1);
+      Set_Scalar_Range     (T,
+        Make_Range (Loc,
+          Low_Bound  => Make_Real_Literal (Loc, Ureal_1),
+          High_Bound => Make_Real_Literal (Loc, Ureal_1)));
+
+      Set_Is_Generic_Type (Base);
+      Set_Etype           (Base, Base);
+      Set_Size_Info       (Base, Standard_Integer);
+      Set_RM_Size         (Base, RM_Size (Standard_Integer));
+      Set_Small_Value     (Base, Ureal_1);
+      Set_Delta_Value     (Base, Ureal_1);
+      Set_Scalar_Range    (Base, Scalar_Range (T));
+      Set_Parent          (Base, Parent (Def));
+   end Analyze_Formal_Ordinary_Fixed_Point_Type;
+
+   ----------------------------
+   -- Analyze_Formal_Package --
+   ----------------------------
+
+   procedure Analyze_Formal_Package (N : Node_Id) is
+      Loc              : constant Source_Ptr := Sloc (N);
+      Formal           : Entity_Id := Defining_Identifier (N);
+      Gen_Id           : constant Node_Id   := Name (N);
+      Gen_Decl         : Node_Id;
+      Gen_Unit         : Entity_Id;
+      New_N            : Node_Id;
+      Parent_Installed : Boolean := False;
+      Renaming         : Node_Id;
+      Parent_Instance  : Entity_Id;
+      Renaming_In_Par  : Entity_Id;
+
+   begin
+      Text_IO_Kludge (Gen_Id);
+
+      Check_Generic_Child_Unit (Gen_Id, Parent_Installed);
+      Gen_Unit := Entity (Gen_Id);
+
+      if Ekind (Gen_Unit) /= E_Generic_Package then
+         Error_Msg_N ("expect generic package name", Gen_Id);
+         return;
+
+      elsif  Gen_Unit = Current_Scope then
+         Error_Msg_N
+           ("generic package cannot be used as a formal package of itself",
+             Gen_Id);
+         return;
+      end if;
+
+      --  Check for a formal package that is a package renaming.
+
+      if Present (Renamed_Object (Gen_Unit)) then
+         Gen_Unit := Renamed_Object (Gen_Unit);
+      end if;
+
+      --  The formal package is treated like a regular instance, but only
+      --  the specification needs to be instantiated, to make entities visible.
+
+      if not Box_Present (N) then
+         Hidden_Entities := New_Elmt_List;
+         Analyze_Package_Instantiation (N);
+
+         if Parent_Installed then
+            Remove_Parent;
+         end if;
+
+      else
+         --  If there are no generic associations, the generic parameters
+         --  appear as local entities and are instantiated like them. We copy
+         --  the generic package declaration as if it were an instantiation,
+         --  and analyze it like a regular package, except that we treat the
+         --  formals as additional visible components.
+
+         Save_Env (Gen_Unit, Formal);
+
+         Gen_Decl := Unit_Declaration_Node (Gen_Unit);
+
+         if In_Extended_Main_Source_Unit (N) then
+            Set_Is_Instantiated (Gen_Unit);
+            Generate_Reference  (Gen_Unit, N);
+         end if;
+
+         New_N :=
+           Copy_Generic_Node
+             (Original_Node (Gen_Decl), Empty, Instantiating => True);
+         Set_Defining_Unit_Name (Specification (New_N), Formal);
+         Rewrite (N, New_N);
+
+         Enter_Name (Formal);
+         Set_Ekind  (Formal, E_Generic_Package);
+         Set_Etype  (Formal, Standard_Void_Type);
+         Set_Inner_Instances (Formal, New_Elmt_List);
+         New_Scope  (Formal);
+
+         --  Within the formal, the name of the generic package is a renaming
+         --  of the formal (as for a regular instantiation).
+
+         Renaming := Make_Package_Renaming_Declaration (Loc,
+             Defining_Unit_Name =>
+               Make_Defining_Identifier (Loc, Chars (Gen_Unit)),
+             Name => New_Reference_To (Formal, Loc));
+
+         if Present (Visible_Declarations (Specification (N))) then
+            Prepend (Renaming, To => Visible_Declarations (Specification (N)));
+         elsif Present (Private_Declarations (Specification (N))) then
+            Prepend (Renaming, To => Private_Declarations (Specification (N)));
+         end if;
+
+         if Is_Child_Unit (Gen_Unit)
+           and then Parent_Installed
+         then
+            --  Similarly, we have to make the name of the formal visible in
+            --  the parent instance, to resolve properly fully qualified names
+            --  that may appear in the generic unit. The parent instance has
+            --  been placed on the scope stack ahead of the current scope.
+
+            Parent_Instance := Scope_Stack.Table (Scope_Stack.Last - 1).Entity;
+
+            Renaming_In_Par :=
+              Make_Defining_Identifier (Loc, Chars (Gen_Unit));
+            Set_Ekind (Renaming_In_Par, E_Package);
+            Set_Etype (Renaming_In_Par, Standard_Void_Type);
+            Set_Scope (Renaming_In_Par, Parent_Instance);
+            Set_Parent (Renaming_In_Par, Parent (Formal));
+            Set_Renamed_Object (Renaming_In_Par, Formal);
+            Append_Entity (Renaming_In_Par, Parent_Instance);
+         end if;
+
+         Analyze_Generic_Formal_Part (N);
+         Analyze (Specification (N));
+         End_Package_Scope (Formal);
+
+         if Parent_Installed then
+            Remove_Parent;
+         end if;
+
+         Restore_Env;
+
+         --  Inside the generic unit, the formal package is a regular
+         --  package, but no body is needed for it. Note that after
+         --  instantiation, the defining_unit_name we need is in the
+         --  new tree and not in the original. (see Package_Instantiation).
+         --  A generic formal package is an instance, and can be used as
+         --  an actual for an inner instance. Mark its generic parent.
+
+         Set_Ekind (Formal, E_Package);
+         Set_Generic_Parent (Specification (N), Gen_Unit);
+         Set_Has_Completion (Formal, True);
+      end if;
+   end Analyze_Formal_Package;
+
+   ---------------------------------
+   -- Analyze_Formal_Private_Type --
+   ---------------------------------
+
+   procedure Analyze_Formal_Private_Type
+     (N   : Node_Id;
+      T   : Entity_Id;
+      Def : Node_Id)
+   is
+   begin
+      New_Private_Type (N, T, Def);
+
+      --  Set the size to an arbitrary but legal value.
+
+      Set_Size_Info (T, Standard_Integer);
+      Set_RM_Size   (T, RM_Size (Standard_Integer));
+   end Analyze_Formal_Private_Type;
+
+   ----------------------------------------
+   -- Analyze_Formal_Signed_Integer_Type --
+   ----------------------------------------
+
+   procedure Analyze_Formal_Signed_Integer_Type
+     (T   : Entity_Id;
+      Def : Node_Id)
+   is
+      Base : constant Entity_Id :=
+               New_Internal_Entity
+                 (E_Signed_Integer_Type, Current_Scope, Sloc (Def), 'G');
+
+   begin
+      Enter_Name (T);
+
+      Set_Ekind        (T, E_Signed_Integer_Subtype);
+      Set_Etype        (T, Base);
+      Set_Size_Info    (T, Standard_Integer);
+      Set_RM_Size      (T, RM_Size (Standard_Integer));
+      Set_Scalar_Range (T, Scalar_Range (Standard_Integer));
+
+      Set_Is_Generic_Type (Base);
+      Set_Size_Info       (Base, Standard_Integer);
+      Set_RM_Size         (Base, RM_Size (Standard_Integer));
+      Set_Etype           (Base, Base);
+      Set_Scalar_Range    (Base, Scalar_Range (Standard_Integer));
+      Set_Parent          (Base, Parent (Def));
+   end Analyze_Formal_Signed_Integer_Type;
+
+   -------------------------------
+   -- Analyze_Formal_Subprogram --
+   -------------------------------
+
+   procedure Analyze_Formal_Subprogram (N : Node_Id) is
+      Spec : constant Node_Id   := Specification (N);
+      Def  : constant Node_Id   := Default_Name (N);
+      Nam  : constant Entity_Id := Defining_Unit_Name (Spec);
+      Subp : Entity_Id;
+
+   begin
+      if Nkind (Nam) = N_Defining_Program_Unit_Name then
+         Error_Msg_N ("name of formal subprogram must be a direct name", Nam);
+         return;
+      end if;
+
+      Analyze_Subprogram_Declaration (N);
+      Set_Is_Formal_Subprogram (Nam);
+      Set_Has_Completion (Nam);
+
+      --  Default name is resolved at the point of instantiation
+
+      if Box_Present (N) then
+         null;
+
+      --  Else default is bound at the point of generic declaration
+
+      elsif Present (Def) then
+         if Nkind (Def) = N_Operator_Symbol then
+            Find_Direct_Name (Def);
+
+         elsif Nkind (Def) /= N_Attribute_Reference then
+            Analyze (Def);
+
+         else
+            --  For an attribute reference, analyze the prefix and verify
+            --  that it has the proper profile for the subprogram.
+
+            Analyze (Prefix (Def));
+            Valid_Default_Attribute (Nam, Def);
+            return;
+         end if;
+
+         --  Default name may be overloaded, in which case the interpretation
+         --  with the correct profile must be  selected, as for a renaming.
+
+         if Etype (Def) = Any_Type then
+            return;
+
+         elsif Nkind (Def) = N_Selected_Component then
+            Subp := Entity (Selector_Name (Def));
+
+            if Ekind (Subp) /= E_Entry then
+               Error_Msg_N ("expect valid subprogram name as default", Def);
+               return;
+            end if;
+
+         elsif Nkind (Def) = N_Indexed_Component then
+
+            if  Nkind (Prefix (Def)) /= N_Selected_Component then
+               Error_Msg_N ("expect valid subprogram name as default", Def);
+               return;
+
+            else
+               Subp := Entity (Selector_Name (Prefix (Def)));
+
+               if Ekind (Subp) /= E_Entry_Family then
+                  Error_Msg_N ("expect valid subprogram name as default", Def);
+                  return;
+               end if;
+            end if;
+
+         elsif Nkind (Def) = N_Character_Literal then
+
+            --  Needs some type checks: subprogram should be parameterless???
+
+            Resolve (Def, (Etype (Nam)));
+
+         elsif (not Is_Entity_Name (Def)
+           or else not Is_Overloadable (Entity (Def)))
+         then
+            Error_Msg_N ("expect valid subprogram name as default", Def);
+            return;
+
+         elsif not Is_Overloaded (Def) then
+            Subp := Entity (Def);
+
+            if Subp = Nam then
+               Error_Msg_N ("premature usage of formal subprogram", Def);
+
+            elsif not Entity_Matches_Spec (Subp, Nam) then
+               Error_Msg_N ("no visible entity matches specification", Def);
+            end if;
+
+         else
+            declare
+               I   : Interp_Index;
+               I1  : Interp_Index := 0;
+               It  : Interp;
+               It1 : Interp;
+
+            begin
+               Subp := Any_Id;
+               Get_First_Interp (Def, I, It);
+               while Present (It.Nam) loop
+
+                  if Entity_Matches_Spec (It.Nam, Nam) then
+                     if Subp /= Any_Id then
+                        It1 := Disambiguate (Def, I1, I, Etype (Subp));
+
+                        if It1 = No_Interp then
+                           Error_Msg_N ("ambiguous default subprogram", Def);
+                        else
+                           Subp := It1.Nam;
+                        end if;
+
+                        exit;
+
+                     else
+                        I1  := I;
+                        Subp := It.Nam;
+                     end if;
+                  end if;
+
+                  Get_Next_Interp (I, It);
+               end loop;
+            end;
+
+            if Subp /= Any_Id then
+               Set_Entity (Def, Subp);
+
+               if Subp = Nam then
+                  Error_Msg_N ("premature usage of formal subprogram", Def);
+
+               elsif Ekind (Subp) /= E_Operator then
+                  Check_Mode_Conformant (Subp, Nam);
+               end if;
+
+            else
+               Error_Msg_N ("no visible subprogram matches specification", N);
+            end if;
+         end if;
+      end if;
+   end Analyze_Formal_Subprogram;
+
+   -------------------------------------
+   -- Analyze_Formal_Type_Declaration --
+   -------------------------------------
+
+   procedure Analyze_Formal_Type_Declaration (N : Node_Id) is
+      Def : constant Node_Id := Formal_Type_Definition (N);
+      T   : Entity_Id;
+
+   begin
+      T := Defining_Identifier (N);
+
+      if Present (Discriminant_Specifications (N))
+        and then Nkind (Def) /= N_Formal_Private_Type_Definition
+      then
+         Error_Msg_N
+           ("discriminants not allowed for this formal type",
+            Defining_Identifier (First (Discriminant_Specifications (N))));
+      end if;
+
+      --  Enter the new name, and branch to specific routine.
+
+      case Nkind (Def) is
+         when N_Formal_Private_Type_Definition
+                        => Analyze_Formal_Private_Type (N, T, Def);
+
+         when N_Formal_Derived_Type_Definition
+                        => Analyze_Formal_Derived_Type (N, T, Def);
+
+         when N_Formal_Discrete_Type_Definition
+                        => Analyze_Formal_Discrete_Type (T, Def);
+
+         when N_Formal_Signed_Integer_Type_Definition
+                        => Analyze_Formal_Signed_Integer_Type (T, Def);
+
+         when N_Formal_Modular_Type_Definition
+                        => Analyze_Formal_Modular_Type (T, Def);
+
+         when N_Formal_Floating_Point_Definition
+                        => Analyze_Formal_Floating_Type (T, Def);
+
+         when N_Formal_Ordinary_Fixed_Point_Definition
+                        => Analyze_Formal_Ordinary_Fixed_Point_Type (T, Def);
+
+         when N_Formal_Decimal_Fixed_Point_Definition
+                        => Analyze_Formal_Decimal_Fixed_Point_Type (T, Def);
+
+         when N_Array_Type_Definition
+                        => Analyze_Formal_Array_Type (T, Def);
+
+         when N_Access_To_Object_Definition |
+              N_Access_Function_Definition  |
+              N_Access_Procedure_Definition
+                        => Analyze_Generic_Access_Type (T, Def);
+
+         when others =>
+            raise Program_Error;
+
+      end case;
+
+      Set_Is_Generic_Type (T);
+
+   end Analyze_Formal_Type_Declaration;
+
+   ------------------------------------
+   -- Analyze_Function_Instantiation --
+   ------------------------------------
+
+   procedure Analyze_Function_Instantiation (N : Node_Id) is
+   begin
+      Analyze_Subprogram_Instantiation (N, E_Function);
+   end Analyze_Function_Instantiation;
+
+   ---------------------------------
+   -- Analyze_Generic_Access_Type --
+   ---------------------------------
+
+   procedure Analyze_Generic_Access_Type (T : Entity_Id; Def : Node_Id) is
+   begin
+      Enter_Name (T);
+
+      if Nkind (Def) = N_Access_To_Object_Definition then
+         Access_Type_Declaration (T, Def);
+
+         if Is_Incomplete_Or_Private_Type (Designated_Type (T))
+           and then No (Full_View (Designated_Type (T)))
+           and then not Is_Generic_Type (Designated_Type (T))
+         then
+            Error_Msg_N ("premature usage of incomplete type", Def);
+
+         elsif Is_Internal (Designated_Type (T)) then
+            Error_Msg_N
+              ("only a subtype mark is allowed in a formal", Def);
+         end if;
+
+      else
+         Access_Subprogram_Declaration (T, Def);
+      end if;
+   end Analyze_Generic_Access_Type;
+
+   ---------------------------------
+   -- Analyze_Generic_Formal_Part --
+   ---------------------------------
+
+   procedure Analyze_Generic_Formal_Part (N : Node_Id) is
+      Gen_Parm_Decl : Node_Id;
+
+   begin
+      --  The generic formals are processed in the scope of the generic
+      --  unit, where they are immediately visible. The scope is installed
+      --  by the caller.
+
+      Gen_Parm_Decl := First (Generic_Formal_Declarations (N));
+
+      while Present (Gen_Parm_Decl) loop
+         Analyze (Gen_Parm_Decl);
+         Next (Gen_Parm_Decl);
+      end loop;
+   end Analyze_Generic_Formal_Part;
+
+   ------------------------------------------
+   -- Analyze_Generic_Package_Declaration  --
+   ------------------------------------------
+
+   procedure Analyze_Generic_Package_Declaration (N : Node_Id) is
+      Id          : Entity_Id;
+      New_N       : Node_Id;
+      Save_Parent : Node_Id;
+
+   begin
+      --  Create copy of generic unit, and save for instantiation.
+      --  If the unit is a child unit, do not copy the specifications
+      --  for the parent, which are not part of the generic tree.
+
+      Save_Parent := Parent_Spec (N);
+      Set_Parent_Spec (N, Empty);
+
+      New_N := Copy_Generic_Node (N, Empty, Instantiating => False);
+      Set_Parent_Spec (New_N, Save_Parent);
+      Rewrite (N, New_N);
+      Id := Defining_Entity (N);
+      Generate_Definition (Id);
+
+      --  Expansion is not applied to generic units.
+
+      Start_Generic;
+
+      Enter_Name (Id);
+      Set_Ekind (Id, E_Generic_Package);
+      Set_Etype (Id, Standard_Void_Type);
+      New_Scope (Id);
+      Enter_Generic_Scope (Id);
+      Set_Inner_Instances (Id, New_Elmt_List);
+
+      Set_Categorization_From_Pragmas (N);
+      Set_Is_Pure (Id, Is_Pure (Current_Scope));
+
+      --  For a library unit, we have reconstructed the entity for the
+      --  unit, and must reset it in the library tables.
+
+      if Nkind (Parent (N)) = N_Compilation_Unit then
+         Set_Cunit_Entity (Current_Sem_Unit, Id);
+      end if;
+
+      Analyze_Generic_Formal_Part (N);
+
+      --  After processing the generic formals, analysis proceeds
+      --  as for a non-generic package.
+
+      Analyze (Specification (N));
+
+      Validate_Categorization_Dependency (N, Id);
+
+      End_Generic;
+
+      End_Package_Scope (Id);
+      Exit_Generic_Scope (Id);
+
+      if Nkind (Parent (N)) /= N_Compilation_Unit then
+         Move_Freeze_Nodes (Id, N, Visible_Declarations (Specification (N)));
+         Move_Freeze_Nodes (Id, N, Private_Declarations (Specification (N)));
+         Move_Freeze_Nodes (Id, N, Generic_Formal_Declarations (N));
+
+      else
+         Set_Body_Required (Parent (N), Unit_Requires_Body (Id));
+         Validate_RT_RAT_Component (N);
+      end if;
+
+   end Analyze_Generic_Package_Declaration;
+
+   --------------------------------------------
+   -- Analyze_Generic_Subprogram_Declaration --
+   --------------------------------------------
+
+   procedure Analyze_Generic_Subprogram_Declaration (N : Node_Id) is
+      Spec        : Node_Id;
+      Id          : Entity_Id;
+      Formals     : List_Id;
+      New_N       : Node_Id;
+      Save_Parent : Node_Id;
+
+   begin
+      --  Create copy of generic unit,and save for instantiation.
+      --  If the unit is a child unit, do not copy the specifications
+      --  for the parent, which are not part of the generic tree.
+
+      Save_Parent := Parent_Spec (N);
+      Set_Parent_Spec (N, Empty);
+
+      New_N := Copy_Generic_Node (N, Empty, Instantiating => False);
+      Set_Parent_Spec (New_N, Save_Parent);
+      Rewrite (N, New_N);
+
+      Spec := Specification (N);
+      Id := Defining_Entity (Spec);
+      Generate_Definition (Id);
+
+      if Nkind (Id) = N_Defining_Operator_Symbol then
+         Error_Msg_N
+           ("operator symbol not allowed for generic subprogram", Id);
+      end if;
+
+      Start_Generic;
+
+      Enter_Name (Id);
+
+      New_Scope (Id);
+      Set_Inner_Instances (Id, New_Elmt_List);
+      Set_Is_Pure (Id, Is_Pure (Current_Scope));
+
+      Analyze_Generic_Formal_Part (N);
+
+      Formals := Parameter_Specifications (Spec);
+
+      if Present (Formals) then
+         Process_Formals (Id, Formals, Spec);
+      end if;
+
+      if Nkind (Spec) = N_Function_Specification then
+         Set_Ekind (Id, E_Generic_Function);
+         Find_Type (Subtype_Mark (Spec));
+         Set_Etype (Id, Entity (Subtype_Mark (Spec)));
+      else
+         Set_Ekind (Id, E_Generic_Procedure);
+         Set_Etype (Id, Standard_Void_Type);
+      end if;
+
+      --  For a library unit, we have reconstructed the entity for the
+      --  unit, and must reset it in the library tables. We also need
+      --  to make sure that Body_Required is set properly in the original
+      --  compilation unit node.
+
+      if Nkind (Parent (N)) = N_Compilation_Unit then
+         Set_Cunit_Entity (Current_Sem_Unit, Id);
+         Set_Body_Required (Parent (N), Unit_Requires_Body (Id));
+      end if;
+
+      Set_Categorization_From_Pragmas (N);
+      Validate_Categorization_Dependency (N, Id);
+
+      Save_Global_References (Original_Node (N));
+
+      End_Generic;
+      End_Scope;
+
+   end Analyze_Generic_Subprogram_Declaration;
+
+   -----------------------------------
+   -- Analyze_Package_Instantiation --
+   -----------------------------------
+
+   --  Note: this procedure is also used for formal package declarations,
+   --  in which case the argument N is an N_Formal_Package_Declaration
+   --  node. This should really be noted in the spec! ???
+
+   procedure Analyze_Package_Instantiation (N : Node_Id) is
+      Loc     : constant Source_Ptr := Sloc (N);
+      Gen_Id  : constant Node_Id    := Name (N);
+
+      Act_Decl      : Node_Id;
+      Act_Decl_Name : Node_Id;
+      Act_Decl_Id   : Entity_Id;
+      Act_Spec      : Node_Id;
+      Act_Tree      : Node_Id;
+
+      Gen_Decl : Node_Id;
+      Gen_Unit : Entity_Id;
+
+      Is_Actual_Pack   : Boolean := Is_Internal (Defining_Entity (N));
+      Parent_Installed : Boolean := False;
+      Renaming_List    : List_Id;
+      Unit_Renaming    : Node_Id;
+      Needs_Body       : Boolean;
+      Inline_Now       : Boolean := False;
+
+      procedure Delay_Descriptors (E : Entity_Id);
+      --  Delay generation of subprogram descriptors for given entity
+
+      function Might_Inline_Subp return Boolean;
+      --  If inlining is active and the generic contains inlined subprograms,
+      --  we instantiate the body. This may cause superfluous instantiations,
+      --  but it is simpler than detecting the need for the body at the point
+      --  of inlining, when the context of the instance is not available.
+
+      -----------------------
+      -- Delay_Descriptors --
+      -----------------------
+
+      procedure Delay_Descriptors (E : Entity_Id) is
+      begin
+         if not Delay_Subprogram_Descriptors (E) then
+            Set_Delay_Subprogram_Descriptors (E);
+            Pending_Descriptor.Increment_Last;
+            Pending_Descriptor.Table (Pending_Descriptor.Last) := E;
+         end if;
+      end Delay_Descriptors;
+
+      -----------------------
+      -- Might_Inline_Subp --
+      -----------------------
+
+      function Might_Inline_Subp return Boolean is
+         E : Entity_Id;
+
+      begin
+         if not Inline_Processing_Required then
+            return False;
+
+         else
+            E := First_Entity (Gen_Unit);
+
+            while Present (E) loop
+
+               if Is_Subprogram (E)
+                 and then Is_Inlined (E)
+               then
+                  return True;
+               end if;
+
+               Next_Entity (E);
+            end loop;
+         end if;
+
+         return False;
+      end Might_Inline_Subp;
+
+   --  Start of processing for Analyze_Package_Instantiation
+
+   begin
+      --  Very first thing: apply the special kludge for Text_IO processing
+      --  in case we are instantiating one of the children of [Wide_]Text_IO.
+
+      Text_IO_Kludge (Name (N));
+
+      --  Make node global for error reporting.
+
+      Instantiation_Node := N;
+
+      --  Case of instantiation of a generic package
+
+      if Nkind (N) = N_Package_Instantiation then
+         Act_Decl_Id := New_Copy (Defining_Entity (N));
+         Set_Comes_From_Source (Act_Decl_Id, True);
+
+         if Nkind (Defining_Unit_Name (N)) = N_Defining_Program_Unit_Name then
+            Act_Decl_Name :=
+              Make_Defining_Program_Unit_Name (Loc,
+                Name => New_Copy_Tree (Name (Defining_Unit_Name (N))),
+                Defining_Identifier => Act_Decl_Id);
+         else
+            Act_Decl_Name :=  Act_Decl_Id;
+         end if;
+
+      --  Case of instantiation of a formal package
+
+      else
+         Act_Decl_Id   := Defining_Identifier (N);
+         Act_Decl_Name := Act_Decl_Id;
+      end if;
+
+      Generate_Definition (Act_Decl_Id);
+      Pre_Analyze_Actuals (N);
+
+      Check_Generic_Child_Unit (Gen_Id, Parent_Installed);
+      Gen_Unit := Entity (Gen_Id);
+
+      --  Verify that it is the name of a generic package
+
+      if Etype (Gen_Unit) = Any_Type then
+         return;
+
+      elsif Ekind (Gen_Unit) /= E_Generic_Package then
+         Error_Msg_N
+           ("expect name of generic package in instantiation", Gen_Id);
+         return;
+      end if;
+
+      if In_Extended_Main_Source_Unit (N) then
+         Set_Is_Instantiated (Gen_Unit);
+         Generate_Reference  (Gen_Unit, N);
+
+         if Present (Renamed_Object (Gen_Unit)) then
+            Set_Is_Instantiated (Renamed_Object (Gen_Unit));
+            Generate_Reference  (Renamed_Object (Gen_Unit), N);
+         end if;
+      end if;
+
+      if Nkind (Gen_Id) = N_Identifier
+        and then Chars (Gen_Unit) = Chars (Defining_Entity (N))
+      then
+         Error_Msg_NE
+           ("& is hidden within declaration of instance", Gen_Id, Gen_Unit);
+
+      elsif Nkind (Gen_Id) = N_Expanded_Name
+        and then Is_Child_Unit (Gen_Unit)
+        and then Nkind (Prefix (Gen_Id)) = N_Identifier
+        and then Chars (Act_Decl_Id) = Chars (Prefix (Gen_Id))
+      then
+         Error_Msg_N
+           ("& is hidden within declaration of instance ", Prefix (Gen_Id));
+      end if;
+
+      --  If renaming, indicate this is an instantiation of renamed unit.
+
+      if Present (Renamed_Object (Gen_Unit))
+        and then Ekind (Renamed_Object (Gen_Unit)) = E_Generic_Package
+      then
+         Gen_Unit := Renamed_Object (Gen_Unit);
+         Set_Entity (Gen_Id, Gen_Unit);
+      end if;
+
+      --  Verify that there are no circular instantiations.
+
+      if In_Open_Scopes (Gen_Unit) then
+         Error_Msg_NE ("instantiation of & within itself", N, Gen_Unit);
+         return;
+
+      elsif Contains_Instance_Of (Gen_Unit, Current_Scope, Gen_Id) then
+         Error_Msg_Node_2 := Current_Scope;
+         Error_Msg_NE
+           ("circular Instantiation: & instantiated in &!", N, Gen_Unit);
+         Circularity_Detected := True;
+         return;
+
+      else
+         Save_Env (Gen_Unit, Act_Decl_Id);
+         Gen_Decl := Unit_Declaration_Node (Gen_Unit);
+
+         --  Initialize renamings map, for error checking, and the list
+         --  that holds private entities whose views have changed between
+         --  generic definition and instantiation. If this is the instance
+         --  created to validate an actual package, the instantiation
+         --  environment is that of the enclosing instance.
+
+         Generic_Renamings.Set_Last (0);
+         Generic_Renamings_HTable.Reset;
+
+         Create_Instantiation_Source (N, Gen_Unit, S_Adjustment);
+
+         --  Copy original generic tree, to produce text for instantiation.
+
+         Act_Tree :=
+           Copy_Generic_Node
+             (Original_Node (Gen_Decl), Empty, Instantiating => True);
+
+         Act_Spec := Specification (Act_Tree);
+
+         --  If this is the instance created to validate an actual package,
+         --  only the formals matter, do not examine the package spec itself.
+
+         if Is_Actual_Pack then
+            Set_Visible_Declarations (Act_Spec, New_List);
+            Set_Private_Declarations (Act_Spec, New_List);
+         end if;
+
+         Renaming_List :=
+           Analyze_Associations
+             (N,
+              Generic_Formal_Declarations (Act_Tree),
+              Generic_Formal_Declarations (Gen_Decl));
+
+         Set_Defining_Unit_Name (Act_Spec, Act_Decl_Name);
+         Set_Is_Generic_Instance (Act_Decl_Id);
+
+         Set_Generic_Parent (Act_Spec, Gen_Unit);
+
+         --  References to the generic in its own declaration or its body
+         --  are references to the instance. Add a renaming declaration for
+         --  the generic unit itself. This declaration, as well as the renaming
+         --  declarations for the generic formals, must remain private to the
+         --  unit: the formals, because this is the language semantics, and
+         --  the unit because its use is an artifact of the implementation.
+
+         Unit_Renaming :=
+           Make_Package_Renaming_Declaration (Loc,
+             Defining_Unit_Name =>
+               Make_Defining_Identifier (Loc, Chars (Gen_Unit)),
+             Name => New_Reference_To (Act_Decl_Id, Loc));
+
+         Append (Unit_Renaming, Renaming_List);
+
+         --  The renaming declarations are the first local declarations of
+         --  the new unit.
+
+         if Is_Non_Empty_List (Visible_Declarations (Act_Spec)) then
+            Insert_List_Before
+              (First (Visible_Declarations (Act_Spec)), Renaming_List);
+         else
+            Set_Visible_Declarations (Act_Spec, Renaming_List);
+         end if;
+
+         Act_Decl :=
+           Make_Package_Declaration (Loc,
+             Specification => Act_Spec);
+
+         --  Save the instantiation node, for subsequent instantiation
+         --  of the body, if there is one and we are generating code for
+         --  the current unit. Mark the unit as having a body, to avoid
+         --  a premature error message.
+
+         --  We instantiate the body if we are generating code, if we are
+         --  generating cross-reference information, or if we are building
+         --  trees for ASIS use.
+
+         declare
+            Enclosing_Body_Present : Boolean := False;
+            Scop : Entity_Id;
+
+         begin
+            if Scope (Gen_Unit) /= Standard_Standard
+              and then not Is_Child_Unit (Gen_Unit)
+            then
+               Scop := Scope (Gen_Unit);
+
+               while Present (Scop)
+                 and then Scop /= Standard_Standard
+               loop
+                  if Unit_Requires_Body (Scop) then
+                     Enclosing_Body_Present := True;
+                     exit;
+                  end if;
+
+                  Scop := Scope (Scop);
+               end loop;
+            end if;
+
+            --  If front-end inlining is enabled, and this is a unit for which
+            --  code will be generated, we instantiate the body at once.
+            --  This is done if the instance is not the main unit, and if the
+            --  generic is not a child unit, to avoid scope problems.
+
+            if Front_End_Inlining
+              and then Expander_Active
+              and then not Is_Child_Unit (Gen_Unit)
+              and then Is_In_Main_Unit (N)
+              and then Nkind (Parent (N)) /= N_Compilation_Unit
+              and then Might_Inline_Subp
+            then
+               Inline_Now := True;
+            end if;
+
+            Needs_Body :=
+              (Unit_Requires_Body (Gen_Unit)
+                  or else Enclosing_Body_Present
+                  or else Present (Corresponding_Body (Gen_Decl)))
+                and then (Is_In_Main_Unit (N)
+                           or else Might_Inline_Subp)
+                and then not Is_Actual_Pack
+                and then not Inline_Now
+
+                and then (Operating_Mode = Generate_Code
+                            or else (Operating_Mode = Check_Semantics
+                                      and then Tree_Output));
+
+            --  If front_end_inlining is enabled, do not instantiate a
+            --  body if within a generic context.
+
+            if Front_End_Inlining
+              and then not Expander_Active
+            then
+               Needs_Body := False;
+            end if;
+
+         end;
+
+         --  If we are generating the calling stubs from the instantiation
+         --  of a generic RCI package, we will not use the body of the
+         --  generic package.
+
+         if Distribution_Stub_Mode = Generate_Caller_Stub_Body
+           and then Is_Compilation_Unit (Defining_Entity (N))
+         then
+            Needs_Body := False;
+         end if;
+
+         if Needs_Body then
+
+            --  Here is a defence against a ludicrous number of instantiations
+            --  caused by a circular set of instantiation attempts.
+
+            if Pending_Instantiations.Last >
+                 Hostparm.Max_Instantiations
+            then
+               Error_Msg_N ("too many instantiations", N);
+               raise Unrecoverable_Error;
+            end if;
+
+            --  Indicate that the enclosing scopes contain an instantiation,
+            --  and that cleanup actions should be delayed until after the
+            --  instance body is expanded.
+
+            Check_Forward_Instantiation (N, Gen_Decl);
+            if Nkind (N) = N_Package_Instantiation then
+               declare
+                  Enclosing_Master : Entity_Id := Current_Scope;
+
+               begin
+                  while Enclosing_Master /= Standard_Standard loop
+
+                     if Ekind (Enclosing_Master) = E_Package then
+                        if Is_Compilation_Unit (Enclosing_Master) then
+                           if In_Package_Body (Enclosing_Master) then
+                              Delay_Descriptors
+                                (Body_Entity (Enclosing_Master));
+                           else
+                              Delay_Descriptors
+                                (Enclosing_Master);
+                           end if;
+
+                           exit;
+
+                        else
+                           Enclosing_Master := Scope (Enclosing_Master);
+                        end if;
+
+                     elsif Ekind (Enclosing_Master) = E_Generic_Package then
+                        Enclosing_Master := Scope (Enclosing_Master);
+
+                     elsif Ekind (Enclosing_Master) = E_Generic_Function
+                       or else Ekind (Enclosing_Master) = E_Generic_Procedure
+                       or else Ekind (Enclosing_Master) = E_Void
+                     then
+                        --  Cleanup actions will eventually be performed on
+                        --  the enclosing instance, if any. enclosing scope
+                        --  is void in the formal part of a generic subp.
+
+                        exit;
+
+                     else
+                        if Ekind (Enclosing_Master) = E_Entry
+                          and then
+                            Ekind (Scope (Enclosing_Master)) = E_Protected_Type
+                        then
+                           Enclosing_Master :=
+                             Protected_Body_Subprogram (Enclosing_Master);
+                        end if;
+
+                        Set_Delay_Cleanups (Enclosing_Master);
+
+                        while Ekind (Enclosing_Master) = E_Block loop
+                           Enclosing_Master := Scope (Enclosing_Master);
+                        end loop;
+
+                        if Is_Subprogram (Enclosing_Master) then
+                           Delay_Descriptors (Enclosing_Master);
+
+                        elsif Is_Task_Type (Enclosing_Master) then
+                           declare
+                              TBP : constant Node_Id :=
+                                      Get_Task_Body_Procedure
+                                        (Enclosing_Master);
+
+                           begin
+                              if Present (TBP) then
+                                 Delay_Descriptors  (TBP);
+                                 Set_Delay_Cleanups (TBP);
+                              end if;
+                           end;
+                        end if;
+
+                        exit;
+                     end if;
+                  end loop;
+               end;
+
+               --  Make entry in table
+
+               Pending_Instantiations.Increment_Last;
+               Pending_Instantiations.Table (Pending_Instantiations.Last) :=
+                 (N, Act_Decl, Expander_Active, Current_Sem_Unit);
+            end if;
+         end if;
+
+         Set_Categorization_From_Pragmas (Act_Decl);
+
+         if Parent_Installed then
+            Hide_Current_Scope;
+         end if;
+
+         Set_Instance_Spec (N, Act_Decl);
+
+         --  Case of not a compilation unit
+
+         if Nkind (Parent (N)) /= N_Compilation_Unit then
+            Mark_Rewrite_Insertion (Act_Decl);
+            Insert_Before (N, Act_Decl);
+            Analyze (Act_Decl);
+
+         --  Case of compilation unit that is generic instantiation
+
+         --  Place declaration on current node so context is complete
+         --  for analysis (including nested instantiations).
+
+         else
+            if Cunit_Entity (Current_Sem_Unit) = Defining_Entity (N) then
+
+               --  The entity for the current unit is the newly created one,
+               --  and all semantic information is attached to it.
+
+               Set_Cunit_Entity (Current_Sem_Unit, Act_Decl_Id);
+
+               --  If this is the main unit, replace the main entity as well.
+
+               if Current_Sem_Unit = Main_Unit then
+                  Main_Unit_Entity := Act_Decl_Id;
+               end if;
+            end if;
+
+            Set_Unit (Parent (N), Act_Decl);
+            Set_Parent_Spec (Act_Decl, Parent_Spec (N));
+            Analyze (Act_Decl);
+            Set_Unit (Parent (N), N);
+            Set_Body_Required (Parent (N), False);
+
+            --  We never need elaboration checks on instantiations, since
+            --  by definition, the body instantiation is elaborated at the
+            --  same time as the spec instantiation.
+
+            Set_Suppress_Elaboration_Warnings (Act_Decl_Id);
+            Set_Suppress_Elaboration_Checks   (Act_Decl_Id);
+         end if;
+
+         Check_Elab_Instantiation (N);
+
+         if ABE_Is_Certain (N) and then Needs_Body then
+            Pending_Instantiations.Decrement_Last;
+         end if;
+         Check_Hidden_Child_Unit (N, Gen_Unit, Act_Decl_Id);
+
+         Set_First_Private_Entity (Defining_Unit_Name (Unit_Renaming),
+           First_Private_Entity (Act_Decl_Id));
+
+         if Nkind (Parent (N)) = N_Compilation_Unit
+           and  then not Needs_Body
+         then
+            Rewrite (N, Act_Decl);
+         end if;
+
+         if Present (Corresponding_Body (Gen_Decl))
+           or else Unit_Requires_Body (Gen_Unit)
+         then
+            Set_Has_Completion (Act_Decl_Id);
+         end if;
+
+         Check_Formal_Packages (Act_Decl_Id);
+
+         Restore_Private_Views (Act_Decl_Id);
+
+         if not Generic_Separately_Compiled (Gen_Unit) then
+            Inherit_Context (Gen_Decl, N);
+         end if;
+
+         if Parent_Installed then
+            Remove_Parent;
+         end if;
+
+         Restore_Env;
+      end if;
+
+      Validate_Categorization_Dependency (N, Act_Decl_Id);
+
+      --  Check restriction, but skip this if something went wrong in
+      --  the above analysis, indicated by Act_Decl_Id being void.
+
+      if Ekind (Act_Decl_Id) /= E_Void
+        and then not Is_Library_Level_Entity (Act_Decl_Id)
+      then
+         Check_Restriction (No_Local_Allocators, N);
+      end if;
+
+      if Inline_Now then
+         Inline_Instance_Body (N, Gen_Unit, Act_Decl);
+      end if;
+
+   exception
+      when Instantiation_Error =>
+         if Parent_Installed then
+            Remove_Parent;
+         end if;
+
+   end Analyze_Package_Instantiation;
+
+   ---------------------------
+   --  Inline_Instance_Body --
+   ---------------------------
+
+   procedure Inline_Instance_Body
+     (N        : Node_Id;
+      Gen_Unit : Entity_Id;
+      Act_Decl : Node_Id)
+   is
+      Vis          : Boolean;
+      Gen_Comp     : constant Entity_Id :=
+                      Cunit_Entity (Get_Source_Unit (Gen_Unit));
+      Curr_Comp    : constant Node_Id := Cunit (Current_Sem_Unit);
+      Curr_Scope   : Entity_Id := Empty;
+      Curr_Unit    : constant Entity_Id :=
+                       Cunit_Entity (Current_Sem_Unit);
+      Removed      : Boolean := False;
+      Num_Scopes   : Int := 0;
+      Use_Clauses  : array (1 .. Scope_Stack.Last) of Node_Id;
+      Instances    : array (1 .. Scope_Stack.Last) of Entity_Id;
+      Inner_Scopes : array (1 .. Scope_Stack.Last) of Entity_Id;
+      Num_Inner    : Int := 0;
+      N_Instances  : Int := 0;
+      S            : Entity_Id;
+
+   begin
+      --  Case of generic unit defined in another unit
+
+      if Gen_Comp /= Cunit_Entity (Current_Sem_Unit) then
+         Vis := Is_Immediately_Visible (Gen_Comp);
+
+         S := Current_Scope;
+
+         while Present (S)
+           and then S /= Standard_Standard
+         loop
+            Num_Scopes := Num_Scopes + 1;
+
+            Use_Clauses (Num_Scopes) :=
+              (Scope_Stack.Table
+                 (Scope_Stack.Last - Num_Scopes + 1).
+                    First_Use_Clause);
+            End_Use_Clauses (Use_Clauses (Num_Scopes));
+
+            exit when Is_Generic_Instance (S)
+              and then (In_Package_Body (S)
+                          or else Ekind (S) = E_Procedure
+                          or else Ekind (S) = E_Function);
+            S := Scope (S);
+         end loop;
+
+         --  Find and save all enclosing instances.
+
+         S := Current_Scope;
+
+         while Present (S)
+           and then S /= Standard_Standard
+         loop
+            if Is_Generic_Instance (S) then
+               N_Instances := N_Instances + 1;
+               Instances (N_Instances) := S;
+            end if;
+
+            S := Scope (S);
+         end loop;
+
+         --  Remove context of current compilation unit, unless we
+         --  are within a nested package instantiation, in which case
+         --  the context has been removed previously.
+         --  If current scope is the body of a child unit, remove context
+         --  of spec as well.
+
+         S := Current_Scope;
+
+         while Present (S)
+           and then S /= Standard_Standard
+         loop
+            exit when Is_Generic_Instance (S)
+                 and then In_Package_Body (S);
+
+            if S = Curr_Unit
+              or else (Ekind (Curr_Unit) = E_Package_Body
+                        and then S = Spec_Entity (Curr_Unit))
+            then
+               Removed := True;
+
+               if Is_Child_Unit (S) then
+                  --  Remove child unit from stack, as well as inner scopes.
+                  --  Removing its context of child unit will remove parent
+                  --  units as well.
+
+                  while Current_Scope /= S loop
+                     Num_Inner := Num_Inner + 1;
+                     Inner_Scopes (Num_Inner) := Current_Scope;
+                     Pop_Scope;
+                  end loop;
+
+                  Pop_Scope;
+                  Remove_Context (Curr_Comp);
+                  Curr_Scope := S;
+
+               else
+                  Remove_Context (Curr_Comp);
+               end if;
+
+               if Ekind (Curr_Unit) = E_Package_Body then
+                  Remove_Context (Library_Unit (Curr_Comp));
+               end if;
+            end if;
+
+            S := Scope (S);
+         end loop;
+
+         Instantiate_Package_Body
+           ((N, Act_Decl, Expander_Active, Current_Sem_Unit));
+
+         --  Restore context.
+
+         Set_Is_Immediately_Visible (Gen_Comp, Vis);
+
+         --  Reset Generic_Instance flag so that use clauses can be installed
+         --  in the proper order. (See Use_One_Package for effect of enclosing
+         --  instances on processing of use clauses).
+
+         for J in 1 .. N_Instances loop
+            Set_Is_Generic_Instance (Instances (J), False);
+         end loop;
+
+         if Removed then
+            --  Make local entities not visible, so that when the context of
+            --  unit is restored, there are not spurious hidings of use-
+            --  visible entities (which appear in the environment before the
+            --  current scope).
+
+            if Current_Scope /= Standard_Standard then
+               S := First_Entity (Current_Scope);
+
+               while Present (S) loop
+                  if Is_Overloadable (S) then
+                     Set_Is_Immediately_Visible (S, False);
+                  end if;
+
+                  Next_Entity (S);
+               end loop;
+            end if;
+
+            Install_Context (Curr_Comp);
+
+            if Current_Scope /= Standard_Standard then
+               S := First_Entity (Current_Scope);
+
+               while Present (S) loop
+                  if Is_Overloadable (S) then
+                     Set_Is_Immediately_Visible (S);
+                  end if;
+
+                  Next_Entity (S);
+               end loop;
+            end if;
+
+            if Present (Curr_Scope)
+              and then Is_Child_Unit (Curr_Scope)
+            then
+               New_Scope (Curr_Scope);
+               Set_Is_Immediately_Visible (Curr_Scope);
+
+               --  Finally, restore inner scopes as well.
+
+               for J in reverse 1 .. Num_Inner loop
+                  New_Scope (Inner_Scopes (J));
+               end loop;
+            end if;
+         end if;
+
+         for J in reverse 1 .. Num_Scopes loop
+            Install_Use_Clauses (Use_Clauses (J));
+         end  loop;
+
+         for J in 1 .. N_Instances loop
+            Set_Is_Generic_Instance (Instances (J), True);
+         end loop;
+
+      --  If generic unit is in current unit, current context is correct.
+
+      else
+         Instantiate_Package_Body
+           ((N, Act_Decl, Expander_Active, Current_Sem_Unit));
+      end if;
+   end Inline_Instance_Body;
+
+   -------------------------------------
+   -- Analyze_Procedure_Instantiation --
+   -------------------------------------
+
+   procedure Analyze_Procedure_Instantiation (N : Node_Id) is
+   begin
+      Analyze_Subprogram_Instantiation (N, E_Procedure);
+   end Analyze_Procedure_Instantiation;
+
+   --------------------------------------
+   -- Analyze_Subprogram_Instantiation --
+   --------------------------------------
+
+   procedure Analyze_Subprogram_Instantiation
+     (N : Node_Id;
+      K : Entity_Kind)
+   is
+      Loc              : constant Source_Ptr := Sloc (N);
+      Gen_Id           : constant Node_Id    := Name (N);
+
+      Act_Decl_Id      : Entity_Id;
+      Anon_Id          : Entity_Id :=
+                           Make_Defining_Identifier
+                             (Sloc (Defining_Entity (N)),
+                             New_External_Name
+                               (Chars (Defining_Entity (N)), 'R'));
+      Act_Decl         : Node_Id;
+      Act_Spec         : Node_Id;
+      Act_Tree         : Node_Id;
+
+      Gen_Unit         : Entity_Id;
+      Gen_Decl         : Node_Id;
+      Pack_Id          : Entity_Id;
+      Parent_Installed : Boolean := False;
+      Renaming_List    : List_Id;
+      Spec             : Node_Id;
+
+      procedure Analyze_Instance_And_Renamings;
+      --  The instance must be analyzed in a context that includes the
+      --  mappings of generic parameters into actuals. We create a package
+      --  declaration for this purpose, and a subprogram with an internal
+      --  name within the package. The subprogram instance is simply an
+      --  alias for the internal subprogram, declared in the current scope.
+
+      ------------------------------------
+      -- Analyze_Instance_And_Renamings --
+      ------------------------------------
+
+      procedure Analyze_Instance_And_Renamings is
+         Def_Ent   : constant Entity_Id := Defining_Entity (N);
+         Pack_Decl : Node_Id;
+
+      begin
+         if Nkind (Parent (N)) = N_Compilation_Unit then
+
+            --  For the case of a compilation unit, the container package
+            --  has the same name as the instantiation, to insure that the
+            --  binder calls the elaboration procedure with the right name.
+            --  Copy the entity of the instance, which may have compilation
+            --  level flags (eg. is_child_unit) set.
+
+            Pack_Id := New_Copy (Def_Ent);
+
+         else
+            --  Otherwise we use the name of the instantiation concatenated
+            --  with its source position to ensure uniqueness if there are
+            --  several instantiations with the same name.
+
+            Pack_Id :=
+              Make_Defining_Identifier (Loc,
+                Chars => New_External_Name
+                           (Related_Id   => Chars (Def_Ent),
+                            Suffix       => "GP",
+                            Suffix_Index => Source_Offset (Sloc (Def_Ent))));
+         end if;
+
+         Pack_Decl := Make_Package_Declaration (Loc,
+           Specification => Make_Package_Specification (Loc,
+             Defining_Unit_Name   => Pack_Id,
+             Visible_Declarations => Renaming_List,
+             End_Label            => Empty));
+
+         Set_Instance_Spec (N, Pack_Decl);
+         Set_Is_Generic_Instance (Pack_Id);
+
+         --  Case of not a compilation unit
+
+         if Nkind (Parent (N)) /= N_Compilation_Unit then
+            Mark_Rewrite_Insertion (Pack_Decl);
+            Insert_Before (N, Pack_Decl);
+            Set_Has_Completion (Pack_Id);
+
+         --  Case of an instantiation that is a compilation unit
+
+         --  Place declaration on current node so context is complete
+         --  for analysis (including nested instantiations), and for
+         --  use in a context_clause (see Analyze_With_Clause).
+
+         else
+            Set_Unit (Parent (N), Pack_Decl);
+            Set_Parent_Spec (Pack_Decl, Parent_Spec (N));
+         end if;
+
+         Analyze (Pack_Decl);
+         Check_Formal_Packages (Pack_Id);
+         Set_Is_Generic_Instance (Pack_Id, False);
+
+         --  Body of the enclosing package is supplied when instantiating
+         --  the subprogram body, after semantic  analysis is completed.
+
+         if Nkind (Parent (N)) = N_Compilation_Unit then
+
+            --  Remove package itself from visibility, so it does not
+            --  conflict with subprogram.
+
+            Set_Name_Entity_Id (Chars (Pack_Id), Homonym (Pack_Id));
+
+            --  Set name and scope of internal subprogram so that the
+            --  proper external name will be generated. The proper scope
+            --  is the scope of the wrapper package.
+
+            Set_Chars (Anon_Id, Chars (Defining_Entity (N)));
+            Set_Scope (Anon_Id, Scope (Pack_Id));
+         end if;
+
+         Set_Is_Generic_Instance (Anon_Id);
+         Act_Decl_Id := New_Copy (Anon_Id);
+
+         Set_Parent            (Act_Decl_Id, Parent (Anon_Id));
+         Set_Chars             (Act_Decl_Id, Chars (Defining_Entity (N)));
+         Set_Sloc              (Act_Decl_Id, Sloc (Defining_Entity (N)));
+         Set_Comes_From_Source (Act_Decl_Id, True);
+
+         --  The signature may involve types that are not frozen yet, but
+         --  the subprogram will be frozen at the point the wrapper package
+         --  is frozen, so it does not need its own freeze node. In fact, if
+         --  one is created, it might conflict with the freezing actions from
+         --  the wrapper package (see 7206-013).
+
+         Set_Has_Delayed_Freeze (Anon_Id, False);
+
+         --  If the instance is a child unit, mark the Id accordingly. Mark
+         --  the anonymous entity as well, which is the real subprogram and
+         --  which is used when the instance appears in a context clause.
+
+         Set_Is_Child_Unit (Act_Decl_Id, Is_Child_Unit (Defining_Entity (N)));
+         Set_Is_Child_Unit (Anon_Id, Is_Child_Unit (Defining_Entity (N)));
+         New_Overloaded_Entity (Act_Decl_Id);
+         Check_Eliminated  (Act_Decl_Id);
+
+         --  In compilation unit case, kill elaboration checks on the
+         --  instantiation, since they are never needed -- the body is
+         --  instantiated at the same point as the spec.
+
+         if Nkind (Parent (N)) = N_Compilation_Unit then
+            Set_Suppress_Elaboration_Warnings (Act_Decl_Id);
+            Set_Suppress_Elaboration_Checks   (Act_Decl_Id);
+            Set_Is_Compilation_Unit (Anon_Id);
+
+            Set_Cunit_Entity (Current_Sem_Unit, Pack_Id);
+         end if;
+
+         --  The instance is not a freezing point for the new subprogram.
+
+         Set_Is_Frozen (Act_Decl_Id, False);
+
+         if Nkind (Defining_Entity (N)) = N_Defining_Operator_Symbol then
+            Valid_Operator_Definition (Act_Decl_Id);
+         end if;
+
+         Set_Alias  (Act_Decl_Id, Anon_Id);
+         Set_Parent (Act_Decl_Id, Parent (Anon_Id));
+         Set_Has_Completion (Act_Decl_Id);
+         Set_Related_Instance (Pack_Id, Act_Decl_Id);
+
+         if Nkind (Parent (N)) = N_Compilation_Unit then
+            Set_Body_Required (Parent (N), False);
+         end if;
+
+      end Analyze_Instance_And_Renamings;
+
+   --  Start of processing for Analyze_Subprogram_Instantiation
+
+   begin
+      --  Very first thing: apply the special kludge for Text_IO processing
+      --  in case we are instantiating one of the children of [Wide_]Text_IO.
+      --  Of course such an instantiation is bogus (these are packages, not
+      --  subprograms), but we get a better error message if we do this.
+
+      Text_IO_Kludge (Gen_Id);
+
+      --  Make node global for error reporting.
+
+      Instantiation_Node := N;
+      Pre_Analyze_Actuals (N);
+
+      Check_Generic_Child_Unit (Gen_Id, Parent_Installed);
+      Gen_Unit := Entity (Gen_Id);
+
+      Generate_Reference (Gen_Unit, Gen_Id);
+
+      if Nkind (Gen_Id) = N_Identifier
+        and then Chars (Gen_Unit) = Chars (Defining_Entity (N))
+      then
+         Error_Msg_NE
+           ("& is hidden within declaration of instance", Gen_Id, Gen_Unit);
+      end if;
+
+      if Etype (Gen_Unit) = Any_Type then return; end if;
+
+      --  Verify that it is a generic subprogram of the right kind, and that
+      --  it does not lead to a circular instantiation.
+
+      if Ekind (Gen_Unit) /= E_Generic_Procedure
+        and then Ekind (Gen_Unit) /= E_Generic_Function
+      then
+         Error_Msg_N ("expect generic subprogram in instantiation", Gen_Id);
+
+      elsif In_Open_Scopes (Gen_Unit) then
+         Error_Msg_NE ("instantiation of & within itself", N, Gen_Unit);
+
+      elsif Contains_Instance_Of (Gen_Unit, Current_Scope, Gen_Id) then
+         Error_Msg_Node_2 := Current_Scope;
+         Error_Msg_NE
+           ("circular Instantiation: & instantiated in &!", N, Gen_Unit);
+         Circularity_Detected := True;
+
+      elsif K = E_Procedure
+        and then Ekind (Gen_Unit) /= E_Generic_Procedure
+      then
+         if Ekind (Gen_Unit) = E_Generic_Function then
+            Error_Msg_N
+              ("cannot instantiate generic function as procedure", Gen_Id);
+         else
+            Error_Msg_N
+              ("expect name of generic procedure in instantiation", Gen_Id);
+         end if;
+
+      elsif K = E_Function
+        and then Ekind (Gen_Unit) /= E_Generic_Function
+      then
+         if Ekind (Gen_Unit) = E_Generic_Procedure then
+            Error_Msg_N
+              ("cannot instantiate generic procedure as function", Gen_Id);
+         else
+            Error_Msg_N
+              ("expect name of generic function in instantiation", Gen_Id);
+         end if;
+
+      else
+         --  If renaming, indicate that this is instantiation of renamed unit
+
+         if Present (Renamed_Object (Gen_Unit))
+           and then (Ekind (Renamed_Object (Gen_Unit)) = E_Generic_Procedure
+                       or else
+                     Ekind (Renamed_Object (Gen_Unit)) = E_Generic_Function)
+         then
+            Gen_Unit := Renamed_Object (Gen_Unit);
+            Set_Entity (Gen_Id, Gen_Unit);
+         end if;
+
+         if In_Extended_Main_Source_Unit (N) then
+            Set_Is_Instantiated (Gen_Unit);
+            Generate_Reference  (Gen_Unit, N);
+         end if;
+
+         Gen_Decl := Unit_Declaration_Node (Gen_Unit);
+         Spec     := Specification (Gen_Decl);
+
+         --  The subprogram itself cannot contain a nested instance, so
+         --  the current parent is left empty.
+
+         Save_Env (Gen_Unit, Empty);
+
+         --  Initialize renamings map, for error checking.
+
+         Generic_Renamings.Set_Last (0);
+         Generic_Renamings_HTable.Reset;
+
+         Create_Instantiation_Source (N, Gen_Unit, S_Adjustment);
+
+         --  Copy original generic tree, to produce text for instantiation.
+
+         Act_Tree :=
+           Copy_Generic_Node
+             (Original_Node (Gen_Decl), Empty, Instantiating => True);
+
+         Act_Spec := Specification (Act_Tree);
+         Renaming_List :=
+           Analyze_Associations
+             (N,
+              Generic_Formal_Declarations (Act_Tree),
+              Generic_Formal_Declarations (Gen_Decl));
+
+         --  Build the subprogram declaration, which does not appear
+         --  in the generic template, and give it a sloc consistent
+         --  with that of the template.
+
+         Set_Defining_Unit_Name (Act_Spec, Anon_Id);
+         Set_Generic_Parent (Act_Spec, Gen_Unit);
+         Act_Decl :=
+           Make_Subprogram_Declaration (Sloc (Act_Spec),
+             Specification => Act_Spec);
+
+         Set_Categorization_From_Pragmas (Act_Decl);
+
+         if Parent_Installed then
+            Hide_Current_Scope;
+         end if;
+
+         Append (Act_Decl, Renaming_List);
+         Analyze_Instance_And_Renamings;
+
+         --  If the generic is marked Import (Intrinsic), then so is the
+         --  instance. This indicates that there is no body to instantiate.
+         --  If generic is marked inline, so it the instance, and the
+         --  anonymous subprogram it renames. If inlined, or else if inlining
+         --  is enabled for the compilation, we generate the instance body
+         --  even if it is not within the main unit.
+
+         --  Any other  pragmas might also be inherited ???
+
+         if Is_Intrinsic_Subprogram (Gen_Unit) then
+            Set_Is_Intrinsic_Subprogram (Anon_Id);
+            Set_Is_Intrinsic_Subprogram (Act_Decl_Id);
+
+            if Chars (Gen_Unit) = Name_Unchecked_Conversion then
+               Validate_Unchecked_Conversion (N, Act_Decl_Id);
+            end if;
+         end if;
+
+         Generate_Definition (Act_Decl_Id);
+
+         Set_Is_Inlined (Act_Decl_Id, Is_Inlined (Gen_Unit));
+         Set_Is_Inlined (Anon_Id,     Is_Inlined (Gen_Unit));
+
+         Check_Elab_Instantiation (N);
+         Check_Hidden_Child_Unit (N, Gen_Unit, Act_Decl_Id);
+
+         --  Subject to change, pending on if other pragmas are inherited ???
+
+         Validate_Categorization_Dependency (N, Act_Decl_Id);
+
+         if not Is_Intrinsic_Subprogram (Act_Decl_Id) then
+
+            if not Generic_Separately_Compiled (Gen_Unit) then
+               Inherit_Context (Gen_Decl, N);
+            end if;
+
+            Restore_Private_Views (Pack_Id, False);
+
+            --  If the context requires a full instantiation, mark node for
+            --  subsequent construction of the body.
+
+            if (Is_In_Main_Unit (N)
+                  or else Is_Inlined (Act_Decl_Id))
+              and then (Operating_Mode = Generate_Code
+                          or else (Operating_Mode = Check_Semantics
+                                    and then Tree_Output))
+              and then (Expander_Active or else Tree_Output)
+              and then not ABE_Is_Certain (N)
+              and then not Is_Eliminated (Act_Decl_Id)
+            then
+               Pending_Instantiations.Increment_Last;
+               Pending_Instantiations.Table (Pending_Instantiations.Last) :=
+                 (N, Act_Decl, Expander_Active, Current_Sem_Unit);
+               Check_Forward_Instantiation (N, Gen_Decl);
+
+               --  The wrapper package is always delayed, because it does
+               --  not constitute a freeze point, but to insure that the
+               --  freeze node is placed properly, it is created directly
+               --  when instantiating the body (otherwise the freeze node
+               --  might appear to early for nested instantiations).
+
+            elsif Nkind (Parent (N)) = N_Compilation_Unit then
+
+               --  For ASIS purposes, indicate that the wrapper package has
+               --  replaced the instantiation node.
+
+               Rewrite (N, Unit (Parent (N)));
+               Set_Unit (Parent (N), N);
+            end if;
+
+         elsif Nkind (Parent (N)) = N_Compilation_Unit then
+
+               --  Replace instance node for library-level instantiations
+               --  of intrinsic subprograms, for ASIS use.
+
+               Rewrite (N, Unit (Parent (N)));
+               Set_Unit (Parent (N), N);
+         end if;
+
+         if Parent_Installed then
+            Remove_Parent;
+         end if;
+
+         Restore_Env;
+         Generic_Renamings.Set_Last (0);
+         Generic_Renamings_HTable.Reset;
+      end if;
+
+   exception
+      when Instantiation_Error =>
+         if Parent_Installed then
+            Remove_Parent;
+         end if;
+
+   end Analyze_Subprogram_Instantiation;
+
+   ---------------------
+   -- Associated_Node --
+   ---------------------
+
+   function Associated_Node (N : Node_Id) return Node_Id is
+      Assoc : Node_Id := Node4 (N);
+      --  ??? what is Node4 being used for here?
+
+   begin
+      if Nkind (Assoc) /= Nkind (N) then
+         return Assoc;
+
+      elsif Nkind (Assoc) = N_Aggregate
+        or else Nkind (Assoc) = N_Extension_Aggregate
+      then
+         return Assoc;
+      else
+         --  If the node is part of an inner generic, it may itself have been
+         --  remapped into a further generic copy. Node4 is otherwise used for
+         --  the entity of the node, and will be of a different node kind, or
+         --  else N has been rewritten as a literal or function call.
+
+         while Present (Node4 (Assoc))
+           and then Nkind (Node4 (Assoc)) = Nkind (Assoc)
+         loop
+            Assoc := Node4 (Assoc);
+         end loop;
+
+         --  Follow and additional link in case the final node was rewritten.
+         --  This can only happen with nested generic units.
+
+         if (Nkind (Assoc) = N_Identifier or else Nkind (Assoc) in N_Op)
+           and then Present (Node4 (Assoc))
+           and then (Nkind (Node4 (Assoc)) = N_Function_Call
+                       or else Nkind (Node4 (Assoc)) = N_Explicit_Dereference
+                       or else Nkind (Node4 (Assoc)) = N_Integer_Literal
+                       or else Nkind (Node4 (Assoc)) = N_Real_Literal
+                       or else Nkind (Node4 (Assoc)) = N_String_Literal)
+         then
+            Assoc := Node4 (Assoc);
+         end if;
+
+         return Assoc;
+      end if;
+   end Associated_Node;
+
+   -------------------------------------------
+   -- Build_Instance_Compilation_Unit_Nodes --
+   -------------------------------------------
+
+   procedure Build_Instance_Compilation_Unit_Nodes
+     (N        : Node_Id;
+      Act_Body : Node_Id;
+      Act_Decl : Node_Id)
+   is
+      Decl_Cunit : Node_Id;
+      Body_Cunit : Node_Id;
+      Citem      : Node_Id;
+      New_Main   : constant Entity_Id := Defining_Entity (Act_Decl);
+      Old_Main   : constant Entity_Id := Cunit_Entity (Main_Unit);
+
+   begin
+      --  A new compilation unit node is built for the instance declaration
+
+      Decl_Cunit :=
+        Make_Compilation_Unit (Sloc (N),
+          Context_Items  => Empty_List,
+          Unit           => Act_Decl,
+          Aux_Decls_Node =>
+            Make_Compilation_Unit_Aux (Sloc (N)));
+
+      Set_Parent_Spec   (Act_Decl, Parent_Spec (N));
+      Set_Body_Required (Decl_Cunit, True);
+
+      --  We use the original instantiation compilation unit as the resulting
+      --  compilation unit of the instance, since this is the main unit.
+
+      Rewrite (N, Act_Body);
+      Body_Cunit := Parent (N);
+
+      --  The two compilation unit nodes are linked by the Library_Unit field
+
+      Set_Library_Unit  (Decl_Cunit, Body_Cunit);
+      Set_Library_Unit  (Body_Cunit, Decl_Cunit);
+
+      --  The context clause items on the instantiation, which are now
+      --  attached to the body compilation unit (since the body overwrote
+      --  the original instantiation node), semantically belong on the spec,
+      --  so copy them there. It's harmless to leave them on the body as well.
+      --  In fact one could argue that they belong in both places.
+
+      Citem := First (Context_Items (Body_Cunit));
+      while Present (Citem) loop
+         Append (New_Copy (Citem), Context_Items (Decl_Cunit));
+         Next (Citem);
+      end loop;
+
+      --  Propagate categorization flags on packages, so that they appear
+      --  in ali file for the spec of the unit.
+
+      if Ekind (New_Main) = E_Package then
+         Set_Is_Pure           (Old_Main, Is_Pure (New_Main));
+         Set_Is_Preelaborated  (Old_Main, Is_Preelaborated (New_Main));
+         Set_Is_Remote_Types   (Old_Main, Is_Remote_Types (New_Main));
+         Set_Is_Shared_Passive (Old_Main, Is_Shared_Passive (New_Main));
+         Set_Is_Remote_Call_Interface
+           (Old_Main, Is_Remote_Call_Interface (New_Main));
+      end if;
+
+      --  Make entry in Units table, so that binder can generate call to
+      --  elaboration procedure for body, if any.
+
+      Make_Instance_Unit (Body_Cunit);
+      Main_Unit_Entity := New_Main;
+      Set_Cunit_Entity (Main_Unit, Main_Unit_Entity);
+
+      --  Build elaboration entity, since the instance may certainly
+      --  generate elaboration code requiring a flag for protection.
+
+      Build_Elaboration_Entity (Decl_Cunit, New_Main);
+   end Build_Instance_Compilation_Unit_Nodes;
+
+   -----------------------------------
+   -- Check_Formal_Package_Instance --
+   -----------------------------------
+
+   --  If the formal has specific parameters, they must match those of the
+   --  actual. Both of them are instances, and the renaming declarations
+   --  for their formal parameters appear in the same order in both. The
+   --  analyzed formal has been analyzed in the context of the current
+   --  instance.
+
+   procedure Check_Formal_Package_Instance
+     (Formal_Pack : Entity_Id;
+      Actual_Pack : Entity_Id)
+   is
+      E1 : Entity_Id := First_Entity (Actual_Pack);
+      E2 : Entity_Id := First_Entity (Formal_Pack);
+
+      Expr1 : Node_Id;
+      Expr2 : Node_Id;
+
+      procedure Check_Mismatch (B : Boolean);
+      --  Common error routine for mismatch between the parameters of
+      --  the actual instance and those of the formal package.
+
+      procedure Check_Mismatch (B : Boolean) is
+      begin
+         if B then
+            Error_Msg_NE
+              ("actual for & in actual instance does not match formal",
+               Parent (Actual_Pack), E1);
+         end if;
+      end Check_Mismatch;
+
+   --  Start of processing for Check_Formal_Package_Instance
+
+   begin
+      while Present (E1)
+        and then Present (E2)
+      loop
+         exit when Ekind (E1) = E_Package
+           and then Renamed_Entity (E1) = Renamed_Entity (Actual_Pack);
+
+         if Is_Type (E1) then
+
+            --  Subtypes must statically match. E1 and E2 are the
+            --  local entities that are subtypes of the actuals.
+            --  Itypes generated for other parameters need not be checked,
+            --  the check will be performed on the parameters themselves.
+
+            if not Is_Itype (E1)
+              and then not Is_Itype (E2)
+            then
+               Check_Mismatch
+                 (not Is_Type (E2)
+                   or else Etype (E1) /= Etype (E2)
+                   or else not Subtypes_Statically_Match (E1, E2));
+            end if;
+
+         elsif Ekind (E1) = E_Constant then
+
+            --  IN parameters must denote the same static value, or
+            --  the same constant, or the literal null.
+
+            Expr1 := Expression (Parent (E1));
+
+            if Ekind (E2) /= E_Constant then
+               Check_Mismatch (True);
+               goto Next_E;
+            else
+               Expr2 := Expression (Parent (E2));
+            end if;
+
+            if Is_Static_Expression (Expr1) then
+
+               if not Is_Static_Expression (Expr2) then
+                  Check_Mismatch (True);
+
+               elsif Is_Integer_Type (Etype (E1)) then
+
+                  declare
+                     V1 : Uint := Expr_Value (Expr1);
+                     V2 : Uint := Expr_Value (Expr2);
+                  begin
+                     Check_Mismatch (V1 /= V2);
+                  end;
+
+               elsif Is_Real_Type (Etype (E1)) then
+
+                  declare
+                     V1 : Ureal := Expr_Value_R (Expr1);
+                     V2 : Ureal := Expr_Value_R (Expr2);
+                  begin
+                     Check_Mismatch (V1 /= V2);
+                  end;
+
+               elsif Is_String_Type (Etype (E1))
+                 and then Nkind (Expr1) = N_String_Literal
+               then
+
+                  if Nkind (Expr2) /= N_String_Literal then
+                     Check_Mismatch (True);
+                  else
+                     Check_Mismatch
+                       (not String_Equal (Strval (Expr1), Strval (Expr2)));
+                  end if;
+               end if;
+
+            elsif Is_Entity_Name (Expr1) then
+               if Is_Entity_Name (Expr2) then
+                  if Entity (Expr1) = Entity (Expr2) then
+                     null;
+
+                  elsif Ekind (Entity (Expr2)) = E_Constant
+                     and then Is_Entity_Name (Constant_Value (Entity (Expr2)))
+                     and then
+                      Entity (Constant_Value (Entity (Expr2))) = Entity (Expr1)
+                  then
+                     null;
+                  else
+                     Check_Mismatch (True);
+                  end if;
+               else
+                  Check_Mismatch (True);
+               end if;
+
+            elsif Nkind (Expr1) = N_Null then
+               Check_Mismatch (Nkind (Expr1) /= N_Null);
+
+            else
+               Check_Mismatch (True);
+            end if;
+
+         elsif Ekind (E1) = E_Variable
+           or else Ekind (E1) = E_Package
+         then
+            Check_Mismatch
+              (Ekind (E1) /= Ekind (E2)
+                or else Renamed_Object (E1) /= Renamed_Object (E2));
+
+         elsif Is_Overloadable (E1) then
+
+            --  Verify that the names of the  entities match.
+            --  What if actual is an attribute ???
+
+            Check_Mismatch
+              (Ekind (E2) /= Ekind (E1) or else (Alias (E1)) /= Alias (E2));
+
+         else
+            raise Program_Error;
+         end if;
+
+         <<Next_E>>
+            Next_Entity (E1);
+            Next_Entity (E2);
+      end loop;
+   end Check_Formal_Package_Instance;
+
+   ---------------------------
+   -- Check_Formal_Packages --
+   ---------------------------
+
+   procedure Check_Formal_Packages (P_Id : Entity_Id) is
+      E        : Entity_Id;
+      Formal_P : Entity_Id;
+
+   begin
+      --  Iterate through the declarations in the instance, looking for
+      --  package renaming declarations that denote instances of formal
+      --  packages. Stop when we find the renaming of the current package
+      --  itself. The declaration for a formal package without a box is
+      --  followed by an internal entity that repeats the instantiation.
+
+      E := First_Entity (P_Id);
+      while Present (E) loop
+         if Ekind (E) = E_Package then
+            if Renamed_Object (E) = P_Id then
+               exit;
+
+            elsif Nkind (Parent (E)) /= N_Package_Renaming_Declaration then
+               null;
+
+            elsif not Box_Present (Parent (Associated_Formal_Package (E))) then
+               Formal_P := Next_Entity (E);
+               Check_Formal_Package_Instance (Formal_P, E);
+            end if;
+         end if;
+
+         Next_Entity (E);
+      end loop;
+   end Check_Formal_Packages;
+
+   ---------------------------------
+   -- Check_Forward_Instantiation --
+   ---------------------------------
+
+   procedure Check_Forward_Instantiation (N : Node_Id; Decl : Node_Id) is
+      S        : Entity_Id;
+      Gen_Comp : Entity_Id := Cunit_Entity (Get_Source_Unit (Decl));
+
+   begin
+      --  The instantiation appears before the generic body if we are in the
+      --  scope of the unit containing the generic, either in its spec or in
+      --  the package body. and before the generic body.
+
+      if Ekind (Gen_Comp) = E_Package_Body then
+         Gen_Comp := Spec_Entity (Gen_Comp);
+      end if;
+
+      if In_Open_Scopes (Gen_Comp)
+        and then No (Corresponding_Body (Decl))
+      then
+         S := Current_Scope;
+
+         while Present (S)
+           and then not Is_Compilation_Unit (S)
+           and then not Is_Child_Unit (S)
+         loop
+            if Ekind (S) = E_Package then
+               Set_Has_Forward_Instantiation (S);
+            end if;
+
+            S := Scope (S);
+         end loop;
+      end if;
+   end Check_Forward_Instantiation;
+
+   ---------------------------
+   -- Check_Generic_Actuals --
+   ---------------------------
+
+   --  The visibility of the actuals may be different between the
+   --  point of generic instantiation and the instantiation of the body.
+
+   procedure Check_Generic_Actuals
+     (Instance      : Entity_Id;
+      Is_Formal_Box : Boolean)
+   is
+      E      : Entity_Id;
+      Astype : Entity_Id;
+
+   begin
+      E := First_Entity (Instance);
+      while Present (E) loop
+         if Is_Type (E)
+           and then Nkind (Parent (E)) = N_Subtype_Declaration
+           and then Scope (Etype (E)) /= Instance
+           and then Is_Entity_Name (Subtype_Indication (Parent (E)))
+         then
+            Check_Private_View (Subtype_Indication (Parent (E)));
+            Set_Is_Generic_Actual_Type (E, True);
+            Set_Is_Hidden (E, False);
+
+            --  We constructed the generic actual type as a subtype of
+            --  the supplied type. This means that it normally would not
+            --  inherit subtype specific attributes of the actual, which
+            --  is wrong for the generic case.
+
+            Astype := Ancestor_Subtype (E);
+
+            if No (Astype) then
+
+               --  can happen when E is an itype that is the full view of
+               --  a private type completed, e.g. with a constrained array.
+
+               Astype := Base_Type (E);
+            end if;
+
+            Set_Size_Info      (E,                (Astype));
+            Set_RM_Size        (E, RM_Size        (Astype));
+            Set_First_Rep_Item (E, First_Rep_Item (Astype));
+
+            if Is_Discrete_Or_Fixed_Point_Type (E) then
+               Set_RM_Size (E, RM_Size (Astype));
+
+            --  In  nested instances, the base type of an access actual
+            --  may itself be private, and need to be exchanged.
+
+            elsif Is_Access_Type (E)
+              and then Is_Private_Type (Etype (E))
+            then
+               Check_Private_View
+                 (New_Occurrence_Of (Etype (E), Sloc (Instance)));
+            end if;
+
+         elsif Ekind (E) = E_Package then
+
+            --  If this is the renaming for the current instance, we're done.
+            --  Otherwise it is a formal package. If the corresponding formal
+            --  was declared with a box, the (instantiations of the) generic
+            --  formal part are also visible. Otherwise, ignore the entity
+            --  created to validate the actuals.
+
+            if Renamed_Object (E) = Instance then
+               exit;
+
+            elsif Nkind (Parent (E)) /= N_Package_Renaming_Declaration then
+               null;
+
+            --  The visibility of a formal of an enclosing generic is already
+            --  correct.
+
+            elsif Denotes_Formal_Package (E) then
+               null;
+
+            elsif Present (Associated_Formal_Package (E))
+              and then Box_Present (Parent (Associated_Formal_Package (E)))
+            then
+               Check_Generic_Actuals (Renamed_Object (E), True);
+               Set_Is_Hidden (E, False);
+            end if;
+
+         else
+            Set_Is_Hidden (E, not Is_Formal_Box);
+         end if;
+
+         Next_Entity (E);
+      end loop;
+
+   end Check_Generic_Actuals;
+
+   ------------------------------
+   -- Check_Generic_Child_Unit --
+   ------------------------------
+
+   procedure Check_Generic_Child_Unit
+     (Gen_Id           : Node_Id;
+      Parent_Installed : in out Boolean)
+   is
+      Loc      : constant Source_Ptr := Sloc (Gen_Id);
+      Gen_Par  : Entity_Id := Empty;
+      Inst_Par : Entity_Id;
+      E        : Entity_Id;
+      S        : Node_Id;
+
+      function Find_Generic_Child
+        (Scop : Entity_Id;
+         Id   : Node_Id)
+         return Entity_Id;
+      --  Search generic parent for possible child unit.
+
+      function In_Enclosing_Instance return Boolean;
+      --  Within an instance of the parent, the child unit may be denoted
+      --  by a simple name. Examine enclosing scopes to locate a possible
+      --  parent instantiation.
+
+      function Find_Generic_Child
+        (Scop : Entity_Id;
+         Id   : Node_Id)
+         return Entity_Id
+      is
+         E : Entity_Id;
+
+      begin
+         --  If entity of name is already set, instance has already been
+         --  resolved, e.g. in an enclosing instantiation.
+
+         if Present (Entity (Id)) then
+            if Scope (Entity (Id)) = Scop then
+               return Entity (Id);
+            else
+               return Empty;
+            end if;
+
+         else
+            E := First_Entity (Scop);
+            while Present (E) loop
+               if Chars (E) = Chars (Id)
+                 and then Is_Child_Unit (E)
+               then
+                  if Is_Child_Unit (E)
+                    and then not Is_Visible_Child_Unit (E)
+                  then
+                     Error_Msg_NE
+                       ("generic child unit& is not visible", Gen_Id, E);
+                  end if;
+
+                  Set_Entity (Id, E);
+                  return E;
+               end if;
+
+               Next_Entity (E);
+            end loop;
+
+            return Empty;
+         end if;
+      end Find_Generic_Child;
+
+      function In_Enclosing_Instance return Boolean is
+         Enclosing_Instance : Node_Id;
+
+      begin
+         Enclosing_Instance := Current_Scope;
+
+         while Present (Enclosing_Instance) loop
+            exit when Ekind (Enclosing_Instance) = E_Package
+              and then Nkind (Parent (Enclosing_Instance)) =
+                N_Package_Specification
+              and then Present
+                (Generic_Parent (Parent (Enclosing_Instance)));
+
+            Enclosing_Instance := Scope (Enclosing_Instance);
+         end loop;
+
+         if Present (Enclosing_Instance) then
+            E := Find_Generic_Child
+             (Generic_Parent (Parent (Enclosing_Instance)), Gen_Id);
+         else
+            return False;
+         end if;
+
+         if Present (E) then
+            Rewrite (Gen_Id,
+              Make_Expanded_Name (Loc,
+                Chars         => Chars (E),
+                Prefix        => New_Occurrence_Of (Enclosing_Instance, Loc),
+                Selector_Name => New_Occurrence_Of (E, Loc)));
+
+            Set_Entity (Gen_Id, E);
+            Set_Etype  (Gen_Id, Etype (E));
+            Parent_Installed := False;      -- Already in scope.
+            return True;
+         else
+            Analyze (Gen_Id);
+            return False;
+         end if;
+      end In_Enclosing_Instance;
+
+   --  Start of processing for Check_Generic_Child_Unit
+
+   begin
+      --  If the name of the generic is given by a selected component, it
+      --  may be the name of a generic child unit, and the prefix is the name
+      --  of an instance of the parent, in which case the child unit must be
+      --  visible. If this instance is not in scope, it must be placed there
+      --  and removed after instantiation, because what is being instantiated
+      --  is not the original child, but the corresponding child present in
+      --  the instance of the parent.
+
+      --  If the child is instantiated within the parent, it can be given by
+      --  a simple name. In this case the instance is already in scope, but
+      --  the child generic must be recovered from the generic parent as well.
+
+      if Nkind (Gen_Id) = N_Selected_Component then
+         S := Selector_Name (Gen_Id);
+         Analyze (Prefix (Gen_Id));
+         Inst_Par := Entity (Prefix (Gen_Id));
+
+         if Ekind (Inst_Par) = E_Package
+           and then Present (Renamed_Object (Inst_Par))
+         then
+            Inst_Par := Renamed_Object (Inst_Par);
+         end if;
+
+         if Ekind (Inst_Par) = E_Package then
+            if Nkind (Parent (Inst_Par)) = N_Package_Specification then
+               Gen_Par := Generic_Parent (Parent (Inst_Par));
+
+            elsif Nkind (Parent (Inst_Par)) = N_Defining_Program_Unit_Name
+              and then
+                Nkind (Parent (Parent (Inst_Par))) = N_Package_Specification
+            then
+               Gen_Par := Generic_Parent (Parent (Parent (Inst_Par)));
+            end if;
+
+         elsif Ekind (Inst_Par) = E_Generic_Package
+           and then Nkind (Parent (Gen_Id)) = N_Formal_Package_Declaration
+         then
+
+            --  A formal package may be a real child package, and not the
+            --  implicit instance within a parent. In this case the child is
+            --  not visible and has to be retrieved explicitly as well.
+
+            Gen_Par := Inst_Par;
+         end if;
+
+         if Present (Gen_Par) then
+
+            --  The prefix denotes an instantiation. The entity itself
+            --  may be a nested generic, or a child unit.
+
+            E := Find_Generic_Child (Gen_Par, S);
+
+            if Present (E) then
+               Change_Selected_Component_To_Expanded_Name (Gen_Id);
+               Set_Entity (Gen_Id, E);
+               Set_Etype (Gen_Id, Etype (E));
+               Set_Entity (S, E);
+               Set_Etype (S, Etype (E));
+
+               --  Indicate that this is a reference to the parent.
+
+               if In_Extended_Main_Source_Unit (Gen_Id) then
+                  Set_Is_Instantiated (Inst_Par);
+               end if;
+
+               --  A common mistake is to replicate the naming scheme of
+               --  a hierarchy by instantiating a generic child directly,
+               --  rather than the implicit child in a parent instance:
+               --
+               --  generic .. package Gpar is ..
+               --  generic .. package Gpar.Child is ..
+               --  package Par is new Gpar ();
+
+               --  with Gpar.Child;
+               --  package Par.Child is new Gpar.Child ();
+               --                           rather than Par.Child
+               --
+               --  In this case the instantiation is within Par, which is
+               --  an instance, but Gpar does not denote Par because we are
+               --  not IN the instance of Gpar, so this is illegal. The test
+               --  below recognizes this particular case.
+
+               if Is_Child_Unit (E)
+                 and then not Comes_From_Source (Entity (Prefix (Gen_Id)))
+                 and then (not In_Instance
+                             or else Nkind (Parent (Parent (Gen_Id))) =
+                                                         N_Compilation_Unit)
+               then
+                  Error_Msg_N
+                    ("prefix of generic child unit must be instance of parent",
+                      Gen_Id);
+               end if;
+
+               if not In_Open_Scopes (Inst_Par)
+                 and then Nkind (Parent (Gen_Id))
+                   not in N_Generic_Renaming_Declaration
+               then
+                  Install_Parent (Inst_Par);
+                  Parent_Installed := True;
+               end if;
+
+            else
+               --  If the generic parent does not contain an entity that
+               --  corresponds to the selector, the instance doesn't either.
+               --  Analyzing the node will yield the appropriate error message.
+               --  If the entity is not a child unit, then it is an inner
+               --  generic in the parent.
+
+               Analyze (Gen_Id);
+            end if;
+
+         else
+            Analyze (Gen_Id);
+
+            if Is_Child_Unit (Entity (Gen_Id))
+              and then Nkind (Parent (Gen_Id))
+                not in N_Generic_Renaming_Declaration
+              and then not In_Open_Scopes (Inst_Par)
+            then
+               Install_Parent (Inst_Par);
+               Parent_Installed := True;
+            end if;
+         end if;
+
+      elsif Nkind (Gen_Id) = N_Expanded_Name then
+
+         --  Entity already present, analyze prefix, whose meaning may be
+         --  an instance in the current context. If it is an instance of
+         --  a relative within another, the proper parent may still have
+         --  to be installed, if they are not of the same generation.
+
+         Analyze (Prefix (Gen_Id));
+         Inst_Par := Entity (Prefix (Gen_Id));
+
+         if In_Enclosing_Instance then
+            null;
+
+         elsif Present (Entity (Gen_Id))
+           and then Is_Child_Unit (Entity (Gen_Id))
+           and then not In_Open_Scopes (Inst_Par)
+         then
+            Install_Parent (Inst_Par);
+            Parent_Installed := True;
+         end if;
+
+      elsif In_Enclosing_Instance then
+         --  The child unit is found in some enclosing scope.
+         null;
+
+      else
+         Analyze (Gen_Id);
+
+         --  If this is the renaming of the implicit child in a parent
+         --  instance, recover the parent name and install it.
+
+         if Is_Entity_Name (Gen_Id) then
+            E := Entity (Gen_Id);
+
+            if Is_Generic_Unit (E)
+              and then Nkind (Parent (E)) in N_Generic_Renaming_Declaration
+              and then Is_Child_Unit (Renamed_Object (E))
+              and then Is_Generic_Unit (Scope (Renamed_Object (E)))
+              and then Nkind (Name (Parent (E))) = N_Expanded_Name
+            then
+               Rewrite (Gen_Id,
+                 New_Copy_Tree (Name (Parent (E))));
+               Inst_Par := Entity (Prefix (Gen_Id));
+
+               if not In_Open_Scopes (Inst_Par) then
+                  Install_Parent (Inst_Par);
+                  Parent_Installed := True;
+               end if;
+
+            --  If it is a child unit of a non-generic parent, it may be
+            --  use-visible and given by a direct name. Install parent as
+            --  for other cases.
+
+            elsif Is_Generic_Unit (E)
+              and then Is_Child_Unit (E)
+              and then
+                Nkind (Parent (Gen_Id)) not in N_Generic_Renaming_Declaration
+              and then not Is_Generic_Unit (Scope (E))
+            then
+               if not In_Open_Scopes (Scope (E)) then
+                  Install_Parent (Scope (E));
+                  Parent_Installed := True;
+               end if;
+            end if;
+         end if;
+      end if;
+   end Check_Generic_Child_Unit;
+
+   -----------------------------
+   -- Check_Hidden_Child_Unit --
+   -----------------------------
+
+   procedure Check_Hidden_Child_Unit
+     (N           : Node_Id;
+      Gen_Unit    : Entity_Id;
+      Act_Decl_Id : Entity_Id)
+   is
+      Gen_Id : Node_Id := Name (N);
+
+   begin
+      if Is_Child_Unit (Gen_Unit)
+        and then Is_Child_Unit (Act_Decl_Id)
+        and then Nkind (Gen_Id) = N_Expanded_Name
+        and then Entity (Prefix (Gen_Id)) = Scope (Act_Decl_Id)
+        and then Chars (Gen_Unit) = Chars (Act_Decl_Id)
+      then
+         Error_Msg_Node_2 := Scope (Act_Decl_Id);
+         Error_Msg_NE
+           ("generic unit & is implicitly declared in &",
+             Defining_Unit_Name (N), Gen_Unit);
+         Error_Msg_N ("\instance must have different name",
+           Defining_Unit_Name (N));
+      end if;
+   end Check_Hidden_Child_Unit;
+
+   ------------------------
+   -- Check_Private_View --
+   ------------------------
+
+   procedure Check_Private_View (N : Node_Id) is
+      T : constant Entity_Id := Etype (N);
+      BT : Entity_Id;
+
+   begin
+      --  Exchange views if the type was not private in the generic but is
+      --  private at the point of instantiation. Do not exchange views if
+      --  the scope of the type is in scope. This can happen if both generic
+      --  and instance are sibling units, or if type is defined in a parent.
+      --  In this case the visibility of the type will be correct for all
+      --  semantic checks.
+
+      if Present (T) then
+         BT := Base_Type (T);
+
+         if Is_Private_Type (T)
+           and then not Has_Private_View (N)
+           and then Present (Full_View (T))
+           and then not In_Open_Scopes (Scope (T))
+         then
+            --  In the generic, the full type was visible. Save the
+            --  private entity, for subsequent exchange.
+
+            Switch_View (T);
+
+         elsif Has_Private_View (N)
+           and then not Is_Private_Type (T)
+           and then not Has_Been_Exchanged (T)
+           and then Etype (Associated_Node (N)) /= T
+         then
+            --  Only the private declaration was visible in the generic. If
+            --  the type appears in a subtype declaration, the subtype in the
+            --  instance must have a view compatible with that of its parent,
+            --  which must be exchanged (see corresponding code in Restore_
+            --  Private_Views). Otherwise, if the type is defined in a parent
+            --  unit, leave full visibility within instance, which is safe.
+
+            if In_Open_Scopes (Scope (Base_Type (T)))
+              and then not Is_Private_Type (Base_Type (T))
+              and then Comes_From_Source (Base_Type (T))
+            then
+               null;
+
+            elsif Nkind (Parent (N)) = N_Subtype_Declaration
+              or else not In_Private_Part (Scope (Base_Type (T)))
+            then
+               Append_Elmt (T, Exchanged_Views);
+               Exchange_Declarations (Etype (Associated_Node (N)));
+            end if;
+
+         --  For composite types with inconsistent representation
+         --  exchange component types accordingly.
+
+         elsif Is_Access_Type (T)
+           and then Is_Private_Type (Designated_Type (T))
+           and then Present (Full_View (Designated_Type (T)))
+         then
+            Switch_View (Designated_Type (T));
+
+         elsif Is_Array_Type (T)
+           and then Is_Private_Type (Component_Type (T))
+           and then not Has_Private_View (N)
+           and then Present (Full_View (Component_Type (T)))
+         then
+            Switch_View (Component_Type (T));
+
+         elsif Is_Private_Type (T)
+           and then Present (Full_View (T))
+           and then Is_Array_Type (Full_View (T))
+           and then Is_Private_Type (Component_Type (Full_View (T)))
+         then
+            Switch_View (T);
+
+         --  Finally, a non-private subtype may have a private base type,
+         --  which must be exchanged for consistency. This can happen when
+         --  instantiating a package body, when the scope stack is empty but
+         --  in fact the subtype and the base type are declared in an enclosing
+         --  scope.
+
+         elsif not Is_Private_Type (T)
+           and then not Has_Private_View (N)
+           and then Is_Private_Type (Base_Type (T))
+           and then Present (Full_View (BT))
+           and then not Is_Generic_Type (BT)
+           and then not In_Open_Scopes (BT)
+         then
+            Append_Elmt (Full_View (BT), Exchanged_Views);
+            Exchange_Declarations (BT);
+         end if;
+      end if;
+   end Check_Private_View;
+
+   --------------------------
+   -- Contains_Instance_Of --
+   --------------------------
+
+   function Contains_Instance_Of
+     (Inner : Entity_Id;
+      Outer : Entity_Id;
+      N     : Node_Id)
+      return  Boolean
+   is
+      Elmt : Elmt_Id;
+      Scop : Entity_Id;
+
+   begin
+      Scop := Outer;
+
+      --  Verify that there are no circular instantiations. We check whether
+      --  the unit contains an instance of the current scope or some enclosing
+      --  scope (in case one of the instances appears in a subunit). Longer
+      --  circularities involving subunits might seem too pathological to
+      --  consider, but they were not too pathological for the authors of
+      --  DEC bc30vsq, so we loop over all enclosing scopes, and mark all
+      --  enclosing generic scopes as containing an instance.
+
+      loop
+         --  Within a generic subprogram body, the scope is not generic, to
+         --  allow for recursive subprograms. Use the declaration to determine
+         --  whether this is a generic unit.
+
+         if Ekind (Scop) = E_Generic_Package
+           or else (Is_Subprogram (Scop)
+                      and then Nkind (Unit_Declaration_Node (Scop)) =
+                                        N_Generic_Subprogram_Declaration)
+         then
+            Elmt := First_Elmt (Inner_Instances (Inner));
+
+            while Present (Elmt) loop
+               if Node (Elmt) = Scop then
+                  Error_Msg_Node_2 := Inner;
+                  Error_Msg_NE
+                    ("circular Instantiation: & instantiated within &!",
+                       N, Scop);
+                  return True;
+
+               elsif Node (Elmt) = Inner then
+                  return True;
+
+               elsif Contains_Instance_Of (Node (Elmt), Scop, N) then
+                  Error_Msg_Node_2 := Inner;
+                  Error_Msg_NE
+                    ("circular Instantiation: & instantiated within &!",
+                      N, Node (Elmt));
+                  return True;
+               end if;
+
+               Next_Elmt (Elmt);
+            end loop;
+
+            --  Indicate that Inner is being instantiated within  Scop.
+
+            Append_Elmt (Inner, Inner_Instances (Scop));
+         end if;
+
+         if Scop = Standard_Standard then
+            exit;
+         else
+            Scop := Scope (Scop);
+         end if;
+      end loop;
+
+      return False;
+   end Contains_Instance_Of;
+
+   -----------------------
+   -- Copy_Generic_Node --
+   -----------------------
+
+   function Copy_Generic_Node
+     (N             : Node_Id;
+      Parent_Id     : Node_Id;
+      Instantiating : Boolean)
+      return          Node_Id
+   is
+      Ent   : Entity_Id;
+      New_N : Node_Id;
+
+      function Copy_Generic_Descendant (D : Union_Id) return Union_Id;
+      --  Check the given value of one of the Fields referenced by the
+      --  current node to determine whether to copy it recursively. The
+      --  field may hold a Node_Id, a List_Id, or an Elist_Id, or a plain
+      --  value (Sloc, Uint, Char) in which case it need not be copied.
+
+      function Copy_Generic_Elist (E : Elist_Id) return Elist_Id;
+      --  Make copy of element list.
+
+      function Copy_Generic_List
+        (L         : List_Id;
+         Parent_Id : Node_Id)
+         return      List_Id;
+      --  Apply Copy_Node recursively to the members of a node list.
+
+      -----------------------------
+      -- Copy_Generic_Descendant --
+      -----------------------------
+
+      function Copy_Generic_Descendant (D : Union_Id) return Union_Id is
+      begin
+         if D = Union_Id (Empty) then
+            return D;
+
+         elsif D in Node_Range then
+            return Union_Id
+              (Copy_Generic_Node (Node_Id (D), New_N, Instantiating));
+
+         elsif D in List_Range then
+            return Union_Id (Copy_Generic_List (List_Id (D), New_N));
+
+         elsif D in Elist_Range then
+            return Union_Id (Copy_Generic_Elist (Elist_Id (D)));
+
+         --  Nothing else is copyable (e.g. Uint values), return as is
+
+         else
+            return D;
+         end if;
+      end Copy_Generic_Descendant;
+
+      ------------------------
+      -- Copy_Generic_Elist --
+      ------------------------
+
+      function Copy_Generic_Elist (E : Elist_Id) return Elist_Id is
+         M : Elmt_Id;
+         L : Elist_Id;
+
+      begin
+         if Present (E) then
+            L := New_Elmt_List;
+            M := First_Elmt (E);
+            while Present (M) loop
+               Append_Elmt
+                 (Copy_Generic_Node (Node (M), Empty, Instantiating), L);
+               Next_Elmt (M);
+            end loop;
+
+            return L;
+
+         else
+            return No_Elist;
+         end if;
+      end Copy_Generic_Elist;
+
+      -----------------------
+      -- Copy_Generic_List --
+      -----------------------
+
+      function Copy_Generic_List
+        (L         : List_Id;
+         Parent_Id : Node_Id)
+         return      List_Id
+      is
+         N     : Node_Id;
+         New_L : List_Id;
+
+      begin
+         if Present (L) then
+            New_L := New_List;
+            Set_Parent (New_L, Parent_Id);
+
+            N := First (L);
+            while Present (N) loop
+               Append (Copy_Generic_Node (N, Empty, Instantiating), New_L);
+               Next (N);
+            end loop;
+
+            return New_L;
+
+         else
+            return No_List;
+         end if;
+      end Copy_Generic_List;
+
+   --  Start of processing for Copy_Generic_Node
+
+   begin
+      if N = Empty then
+         return N;
+      end if;
+
+      New_N := New_Copy (N);
+
+      if Instantiating then
+         Adjust_Instantiation_Sloc (New_N, S_Adjustment);
+      end if;
+
+      if not Is_List_Member (N) then
+         Set_Parent (New_N, Parent_Id);
+      end if;
+
+      --  If defining identifier, then all fields have been copied already
+
+      if Nkind (New_N) in N_Entity then
+         null;
+
+      --  Special casing for identifiers and other entity names and operators
+
+      elsif    (Nkind (New_N) = N_Identifier
+        or else Nkind (New_N) = N_Character_Literal
+        or else Nkind (New_N) = N_Expanded_Name
+        or else Nkind (New_N) = N_Operator_Symbol
+        or else Nkind (New_N) in N_Op)
+      then
+         if not Instantiating then
+
+            --  Link both nodes in order to assign subsequently the
+            --  entity of the copy to the original node, in case this
+            --  is a global reference.
+
+            Set_Associated_Node (N, New_N);
+
+            --  If we are within an instantiation, this is a nested generic
+            --  that has already been analyzed at the point of definition. We
+            --  must preserve references that were global to the enclosing
+            --  parent at that point. Other occurrences, whether global or
+            --  local to the current generic, must be resolved anew, so we
+            --  reset the entity in the generic copy. A global reference has
+            --  a smaller depth than the parent, or else the same depth in
+            --  case both are distinct compilation units.
+
+            --  It is also possible for Current_Instantiated_Parent to be
+            --  defined, and for this not to be a nested generic, namely
+            --  if the unit is loaded through Rtsfind. In that case, the
+            --  entity of New_N is only a link to the associated node, and
+            --  not a defining occurrence.
+
+            --  The entities for parent units in the defining_program_unit
+            --  of a generic child unit are established when the context of
+            --  the unit is first analyzed, before the generic copy is made.
+            --  They are preserved in the copy for use in ASIS queries.
+
+            Ent := Entity (New_N);
+
+            if No (Current_Instantiated_Parent.Gen_Id) then
+               if No (Ent)
+                 or else Nkind (Ent) /= N_Defining_Identifier
+                 or else Nkind (Parent (N)) /= N_Defining_Program_Unit_Name
+               then
+                  Set_Associated_Node (New_N, Empty);
+               end if;
+
+            elsif No (Ent)
+              or else
+                not (Nkind (Ent) = N_Defining_Identifier
+                       or else
+                     Nkind (Ent) = N_Defining_Character_Literal
+                       or else
+                     Nkind (Ent) = N_Defining_Operator_Symbol)
+              or else No (Scope (Ent))
+              or else Scope (Ent) = Current_Instantiated_Parent.Gen_Id
+              or else (Scope_Depth (Scope (Ent)) >
+                             Scope_Depth (Current_Instantiated_Parent.Gen_Id)
+                         and then
+                       Get_Source_Unit (Ent) =
+                       Get_Source_Unit (Current_Instantiated_Parent.Gen_Id))
+            then
+               Set_Associated_Node (New_N, Empty);
+            end if;
+
+         --  Case of instantiating identifier or some other name or operator
+
+         else
+            --  If the associated node is still defined, the entity in
+            --  it is global, and must be copied to the instance.
+
+            if Present (Associated_Node (N)) then
+               if Nkind (Associated_Node (N)) = Nkind (N) then
+                  Set_Entity (New_N, Entity (Associated_Node (N)));
+                  Check_Private_View (N);
+
+               elsif Nkind (Associated_Node (N)) = N_Function_Call then
+                  Set_Entity (New_N, Entity (Name (Associated_Node (N))));
+
+               else
+                  Set_Entity (New_N, Empty);
+               end if;
+            end if;
+         end if;
+
+         --  For expanded name, we must copy the Prefix and Selector_Name
+
+         if Nkind (N) = N_Expanded_Name then
+
+            Set_Prefix
+              (New_N, Copy_Generic_Node (Prefix (N), New_N, Instantiating));
+
+            Set_Selector_Name (New_N,
+              Copy_Generic_Node (Selector_Name (N), New_N, Instantiating));
+
+         --  For operators, we must copy the right operand
+
+         elsif Nkind (N) in N_Op then
+
+            Set_Right_Opnd (New_N,
+              Copy_Generic_Node (Right_Opnd (N), New_N, Instantiating));
+
+            --  And for binary operators, the left operand as well
+
+            if Nkind (N) in N_Binary_Op then
+               Set_Left_Opnd (New_N,
+                 Copy_Generic_Node (Left_Opnd (N), New_N, Instantiating));
+            end if;
+         end if;
+
+      --  Special casing for stubs
+
+      elsif Nkind (N) in N_Body_Stub then
+
+         --  In any case, we must copy the specification or defining
+         --  identifier as appropriate.
+
+         if Nkind (N) = N_Subprogram_Body_Stub then
+            Set_Specification (New_N,
+              Copy_Generic_Node (Specification (N), New_N, Instantiating));
+
+         else
+            Set_Defining_Identifier (New_N,
+              Copy_Generic_Node
+                (Defining_Identifier (N), New_N, Instantiating));
+         end if;
+
+         --  If we are not instantiating, then this is where we load and
+         --  analyze subunits, i.e. at the point where the stub occurs. A
+         --  more permissivle system might defer this analysis to the point
+         --  of instantiation, but this seems to complicated for now.
+
+         if not Instantiating then
+            declare
+               Subunit_Name : constant Unit_Name_Type := Get_Unit_Name (N);
+               Subunit      : Node_Id;
+               Unum         : Unit_Number_Type;
+               New_Body     : Node_Id;
+
+            begin
+               Unum :=
+                 Load_Unit
+                   (Load_Name  => Subunit_Name,
+                    Required   => False,
+                    Subunit    => True,
+                    Error_Node => N);
+
+               --  If the proper body is not found, a warning message will
+               --  be emitted when analyzing the stub, or later at the the
+               --  point of instantiation. Here we just leave the stub as is.
+
+               if Unum = No_Unit then
+                  Subunits_Missing := True;
+                  goto Subunit_Not_Found;
+               end if;
+
+               Subunit := Cunit (Unum);
+
+               --  We must create a generic copy of the subunit, in order
+               --  to perform semantic analysis on it, and we must replace
+               --  the stub in the original generic unit with the subunit,
+               --  in order to preserve non-local references within.
+
+               --  Only the proper body needs to be copied. Library_Unit and
+               --  context clause are simply inherited by the generic copy.
+               --  Note that the copy (which may be recursive if there are
+               --  nested subunits) must be done first, before attaching it
+               --  to the enclosing generic.
+
+               New_Body :=
+                 Copy_Generic_Node
+                   (Proper_Body (Unit (Subunit)),
+                    Empty, Instantiating => False);
+
+               --  Now place the original proper body in the original
+               --  generic unit.
+
+               Rewrite (N, Proper_Body (Unit (Subunit)));
+               Set_Was_Originally_Stub (N);
+
+               --  Finally replace the body of the subunit with its copy,
+               --  and make this new subunit into the library unit of the
+               --  generic copy, which does not have stubs any longer.
+
+               Set_Proper_Body (Unit (Subunit), New_Body);
+               Set_Library_Unit (New_N, Subunit);
+               Inherit_Context (Unit (Subunit), N);
+
+            end;
+
+         --  If we are instantiating, this must be an error case, since
+         --  otherwise we would have replaced the stub node by the proper
+         --  body that corresponds. So just ignore it in the copy (i.e.
+         --  we have copied it, and that is good enough).
+
+         else
+            null;
+         end if;
+
+         <<Subunit_Not_Found>> null;
+
+      --  If the node is a compilation unit, it is the subunit of a stub,
+      --  which has been loaded already (see code below). In this case,
+      --  the library unit field of N points to the parent unit (which
+      --  is a compilation unit) and need not (and cannot!) be copied.
+
+      --  When the proper body of the stub is analyzed, thie library_unit
+      --  link is used to establish the proper context (see sem_ch10).
+
+      --  The other fields of a compilation unit are copied as usual
+
+      elsif Nkind (N) = N_Compilation_Unit then
+
+         --  This code can only be executed when not instantiating, because
+         --  in the copy made for an instantiation, the compilation unit
+         --  node has disappeared at the point that a stub is replaced by
+         --  its proper body.
+
+         pragma Assert (not Instantiating);
+
+         Set_Context_Items (New_N,
+           Copy_Generic_List (Context_Items (N), New_N));
+
+         Set_Unit (New_N,
+           Copy_Generic_Node (Unit (N), New_N, False));
+
+         Set_First_Inlined_Subprogram (New_N,
+           Copy_Generic_Node
+             (First_Inlined_Subprogram (N), New_N, False));
+
+         Set_Aux_Decls_Node (New_N,
+           Copy_Generic_Node (Aux_Decls_Node (N), New_N, False));
+
+      --  For an assignment node, the assignment is known to be semantically
+      --  legal if we are instantiating the template. This avoids incorrect
+      --  diagnostics in generated code.
+
+      elsif Nkind (N) = N_Assignment_Statement then
+
+         --  Copy name and expression fields in usual manner
+
+         Set_Name (New_N,
+           Copy_Generic_Node (Name (N), New_N, Instantiating));
+
+         Set_Expression (New_N,
+           Copy_Generic_Node (Expression (N), New_N, Instantiating));
+
+         if Instantiating then
+            Set_Assignment_OK (Name (New_N), True);
+         end if;
+
+      elsif Nkind (N) = N_Aggregate
+              or else Nkind (N) = N_Extension_Aggregate
+      then
+
+         if not Instantiating then
+            Set_Associated_Node (N, New_N);
+
+         else
+            if Present (Associated_Node (N))
+              and then Nkind (Associated_Node (N)) = Nkind (N)
+            then
+               --  In the generic the aggregate has some composite type.
+               --  If at the point of instantiation the type has a private
+               --  view, install the full view (and that of its ancestors,
+               --  if any).
+
+               declare
+                  T   : Entity_Id := (Etype (Associated_Node (New_N)));
+                  Rt  : Entity_Id;
+
+               begin
+                  if Present (T)
+                    and then Is_Private_Type (T)
+                  then
+                     Switch_View (T);
+                  end if;
+
+                  if Present (T)
+                    and then Is_Tagged_Type (T)
+                    and then Is_Derived_Type (T)
+                  then
+                     Rt := Root_Type (T);
+
+                     loop
+                        T := Etype (T);
+
+                        if Is_Private_Type (T) then
+                           Switch_View (T);
+                        end if;
+
+                        exit when T = Rt;
+                     end loop;
+                  end if;
+               end;
+            end if;
+         end if;
+
+         Set_Field1 (New_N, Copy_Generic_Descendant (Field1 (N)));
+         Set_Field2 (New_N, Copy_Generic_Descendant (Field2 (N)));
+         Set_Field3 (New_N, Copy_Generic_Descendant (Field3 (N)));
+         Set_Field5 (New_N, Copy_Generic_Descendant (Field5 (N)));
+
+      --  For a proper body, we must catch the case of a proper body that
+      --  replaces a stub. This represents the point at which a separate
+      --  compilation unit, and hence template file, may be referenced, so
+      --  we must make a new source instantiation entry for the template
+      --  of the subunit, and ensure that all nodes in the subunit are
+      --  adjusted using this new source instantiation entry.
+
+      elsif Nkind (N) in N_Proper_Body then
+
+         declare
+            Save_Adjustment : constant Sloc_Adjustment := S_Adjustment;
+
+         begin
+            if Instantiating and then Was_Originally_Stub (N) then
+               Create_Instantiation_Source
+                 (Instantiation_Node, Defining_Entity (N), S_Adjustment);
+            end if;
+
+            --  Now copy the fields of the proper body, using the new
+            --  adjustment factor if one was needed as per test above.
+
+            Set_Field1 (New_N, Copy_Generic_Descendant (Field1 (N)));
+            Set_Field2 (New_N, Copy_Generic_Descendant (Field2 (N)));
+            Set_Field3 (New_N, Copy_Generic_Descendant (Field3 (N)));
+            Set_Field4 (New_N, Copy_Generic_Descendant (Field4 (N)));
+            Set_Field5 (New_N, Copy_Generic_Descendant (Field5 (N)));
+
+            --  Restore the original adjustment factor in case changed
+
+            S_Adjustment := Save_Adjustment;
+         end;
+
+      --  Don't copy Ident or Comment pragmas, since the comment belongs
+      --  to the generic unit, not to the instantiating unit.
+
+      elsif Nkind (N) = N_Pragma
+        and then Instantiating
+      then
+         declare
+            Prag_Id : constant Pragma_Id := Get_Pragma_Id (Chars (N));
+
+         begin
+            if Prag_Id = Pragma_Ident
+              or else Prag_Id = Pragma_Comment
+            then
+               New_N := Make_Null_Statement (Sloc (N));
+
+            else
+               Set_Field1 (New_N, Copy_Generic_Descendant (Field1 (N)));
+               Set_Field2 (New_N, Copy_Generic_Descendant (Field2 (N)));
+               Set_Field3 (New_N, Copy_Generic_Descendant (Field3 (N)));
+               Set_Field4 (New_N, Copy_Generic_Descendant (Field4 (N)));
+               Set_Field5 (New_N, Copy_Generic_Descendant (Field5 (N)));
+            end if;
+         end;
+
+      --  For the remaining nodes, copy recursively their descendants.
+
+      else
+         Set_Field1 (New_N, Copy_Generic_Descendant (Field1 (N)));
+         Set_Field2 (New_N, Copy_Generic_Descendant (Field2 (N)));
+         Set_Field3 (New_N, Copy_Generic_Descendant (Field3 (N)));
+         Set_Field4 (New_N, Copy_Generic_Descendant (Field4 (N)));
+         Set_Field5 (New_N, Copy_Generic_Descendant (Field5 (N)));
+
+         if Instantiating
+           and then Nkind (N) = N_Subprogram_Body
+         then
+            Set_Generic_Parent (Specification (New_N), N);
+         end if;
+      end if;
+
+      return New_N;
+   end Copy_Generic_Node;
+
+   ----------------------------
+   -- Denotes_Formal_Package --
+   ----------------------------
+
+   function Denotes_Formal_Package (Pack : Entity_Id) return Boolean is
+      Par  : constant Entity_Id := Current_Instantiated_Parent.Act_Id;
+      Scop : Entity_Id := Scope (Pack);
+      E    : Entity_Id;
+
+   begin
+      if Ekind (Scop) = E_Generic_Package
+        or else Nkind (Unit_Declaration_Node (Scop))
+          = N_Generic_Subprogram_Declaration
+      then
+         return True;
+
+      elsif Nkind (Parent (Pack)) = N_Formal_Package_Declaration then
+         return True;
+
+      elsif No (Par) then
+         return False;
+
+      else
+         --  Check whether this package is associated with a formal
+         --  package of the enclosing instantiation. Iterate over the
+         --  list of renamings.
+
+         E := First_Entity (Par);
+         while Present (E) loop
+
+            if Ekind (E) /= E_Package
+              or else Nkind (Parent (E)) /= N_Package_Renaming_Declaration
+            then
+               null;
+            elsif Renamed_Object (E) = Par then
+               return False;
+
+            elsif Renamed_Object (E) = Pack then
+               return True;
+            end if;
+
+            Next_Entity (E);
+         end loop;
+
+         return False;
+      end if;
+   end Denotes_Formal_Package;
+
+   -----------------
+   -- End_Generic --
+   -----------------
+
+   procedure End_Generic is
+   begin
+      --  ??? More things could be factored out in this
+      --  routine. Should probably be done at a later stage.
+
+      Inside_A_Generic := Generic_Flags.Table (Generic_Flags.Last);
+      Generic_Flags.Decrement_Last;
+
+      Expander_Mode_Restore;
+   end End_Generic;
+
+   ----------------------
+   -- Find_Actual_Type --
+   ----------------------
+
+   function Find_Actual_Type
+     (Typ       : Entity_Id;
+      Gen_Scope : Entity_Id)
+      return      Entity_Id
+   is
+      T : Entity_Id;
+
+   begin
+      if not Is_Child_Unit (Gen_Scope) then
+         return Get_Instance_Of (Typ);
+
+      elsif not Is_Generic_Type (Typ)
+        or else Scope (Typ) = Gen_Scope
+      then
+         return Get_Instance_Of (Typ);
+
+      else
+         T := Current_Entity (Typ);
+         while Present (T) loop
+            if In_Open_Scopes (Scope (T)) then
+               return T;
+            end if;
+
+            T := Homonym (T);
+         end loop;
+
+         return Typ;
+      end if;
+   end Find_Actual_Type;
+
+   ----------------------------
+   -- Freeze_Subprogram_Body --
+   ----------------------------
+
+   procedure Freeze_Subprogram_Body
+     (Inst_Node : Node_Id;
+      Gen_Body  : Node_Id;
+      Pack_Id   : Entity_Id)
+  is
+      F_Node   : Node_Id;
+      Gen_Unit : constant Entity_Id := Entity (Name (Inst_Node));
+      Par      : constant Entity_Id := Scope (Gen_Unit);
+      Enc_G    : Entity_Id;
+      Enc_I    : Node_Id;
+      E_G_Id   : Entity_Id;
+
+      function Earlier (N1, N2 : Node_Id) return Boolean;
+      --  Yields True if N1 and N2 appear in the same compilation unit,
+      --  ignoring subunits, and if N1 is to the left of N2 in a left-to-right
+      --  traversal of the tree for the unit.
+
+      function Enclosing_Body (N : Node_Id) return Node_Id;
+      --  Find innermost package body that encloses the given node, and which
+      --  is not a compilation unit. Freeze nodes for the instance, or for its
+      --  enclosing body, may be inserted after the enclosing_body of the
+      --  generic unit.
+
+      function Package_Freeze_Node (B : Node_Id) return Node_Id;
+      --  Find entity for given package body, and locate or create a freeze
+      --  node for it.
+
+      function True_Parent (N : Node_Id) return Node_Id;
+      --  For a subunit, return parent of corresponding stub.
+
+      -------------
+      -- Earlier --
+      -------------
+
+      function Earlier (N1, N2 : Node_Id) return Boolean is
+         D1 : Integer := 0;
+         D2 : Integer := 0;
+         P1 : Node_Id := N1;
+         P2 : Node_Id := N2;
+
+         procedure Find_Depth (P : in out Node_Id; D : in out Integer);
+         --  Find distance from given node to enclosing compilation unit.
+
+         procedure Find_Depth (P : in out Node_Id; D : in out Integer) is
+         begin
+            while Present (P)
+              and then Nkind (P) /= N_Compilation_Unit
+            loop
+               P := True_Parent (P);
+               D := D + 1;
+            end loop;
+         end Find_Depth;
+
+      begin
+         Find_Depth (P1, D1);
+         Find_Depth (P2, D2);
+
+         if P1 /= P2 then
+            return False;
+         else
+            P1 := N1;
+            P2 := N2;
+         end if;
+
+         while D1 > D2 loop
+            P1 := True_Parent (P1);
+            D1 := D1 - 1;
+         end loop;
+
+         while D2 > D1 loop
+            P2 := True_Parent (P2);
+            D2 := D2 - 1;
+         end loop;
+
+         --  At this point P1 and P2 are at the same distance from the root.
+         --  We examine their parents until we find a common declarative
+         --  list, at which point we can establish their relative placement
+         --  by comparing their ultimate slocs. If we reach the root,
+         --  N1 and N2 do not descend from the same declarative list (e.g.
+         --  one is nested in the declarative part and the other is in a block
+         --  in the statement part) and the earlier one is already frozen.
+
+         while not Is_List_Member (P1)
+           or else not Is_List_Member (P2)
+           or else List_Containing (P1) /= List_Containing (P2)
+         loop
+            P1 := True_Parent (P1);
+            P2 := True_Parent (P2);
+
+            if Nkind (Parent (P1)) = N_Subunit then
+               P1 := Corresponding_Stub (Parent (P1));
+            end if;
+
+            if Nkind (Parent (P2)) = N_Subunit then
+               P2 := Corresponding_Stub (Parent (P2));
+            end if;
+
+            if P1 = P2 then
+               return False;
+            end if;
+         end loop;
+
+         return
+           Top_Level_Location (Sloc (P1)) < Top_Level_Location (Sloc (P2));
+      end Earlier;
+
+      --------------------
+      -- Enclosing_Body --
+      --------------------
+
+      function Enclosing_Body (N : Node_Id) return Node_Id is
+         P : Node_Id := Parent (N);
+
+      begin
+         while Present (P)
+           and then Nkind (Parent (P)) /= N_Compilation_Unit
+         loop
+            if Nkind (P) = N_Package_Body then
+
+               if Nkind (Parent (P)) = N_Subunit then
+                  return Corresponding_Stub (Parent (P));
+               else
+                  return P;
+               end if;
+            end if;
+
+            P := True_Parent (P);
+         end loop;
+
+         return Empty;
+      end Enclosing_Body;
+
+      -------------------------
+      -- Package_Freeze_Node --
+      -------------------------
+
+      function Package_Freeze_Node (B : Node_Id) return Node_Id is
+         Id : Entity_Id;
+
+      begin
+         if Nkind (B) = N_Package_Body then
+            Id := Corresponding_Spec (B);
+
+         else pragma Assert (Nkind (B) = N_Package_Body_Stub);
+            Id := Corresponding_Spec (Proper_Body (Unit (Library_Unit (B))));
+         end if;
+
+         Ensure_Freeze_Node (Id);
+         return Freeze_Node (Id);
+      end Package_Freeze_Node;
+
+      -----------------
+      -- True_Parent --
+      -----------------
+
+      function True_Parent (N : Node_Id) return Node_Id is
+      begin
+         if Nkind (Parent (N)) = N_Subunit then
+            return Parent (Corresponding_Stub (Parent (N)));
+         else
+            return Parent (N);
+         end if;
+      end True_Parent;
+
+   --  Start of processing of Freeze_Subprogram_Body
+
+   begin
+      --  If the instance and the generic body appear within the same
+      --  unit, and the instance preceeds the generic, the freeze node for
+      --  the instance must appear after that of the generic. If the generic
+      --  is nested within another instance I2, then current instance must
+      --  be frozen after I2. In both cases, the freeze nodes are those of
+      --  enclosing packages. Otherwise, the freeze node is placed at the end
+      --  of the current declarative part.
+
+      Enc_G  := Enclosing_Body (Gen_Body);
+      Enc_I  := Enclosing_Body (Inst_Node);
+      Ensure_Freeze_Node (Pack_Id);
+      F_Node := Freeze_Node (Pack_Id);
+
+      if Is_Generic_Instance (Par)
+        and then Present (Freeze_Node (Par))
+        and then
+          In_Same_Declarative_Part (Freeze_Node (Par), Inst_Node)
+      then
+         Insert_After (Freeze_Node (Par), F_Node);
+
+      --  The body enclosing the instance should be frozen after the body
+      --  that includes the generic, because the body of the instance may
+      --  make references to entities therein. If the two are not in the
+      --  same declarative part, or if the one enclosing the instance is
+      --  frozen already, freeze the instance at the end of the current
+      --  declarative part.
+
+      elsif Is_Generic_Instance (Par)
+        and then Present (Freeze_Node (Par))
+        and then Present (Enc_I)
+      then
+         if In_Same_Declarative_Part (Freeze_Node (Par), Enc_I)
+           or else
+             (Nkind (Enc_I) = N_Package_Body
+               and then
+             In_Same_Declarative_Part (Freeze_Node (Par), Parent (Enc_I)))
+         then
+
+            --  The enclosing package may contain several instances. Rather
+            --  than computing the earliest point at which to insert its
+            --  freeze node, we place it at the end of the declarative part
+            --  of the parent of the generic.
+
+            Insert_After_Last_Decl
+              (Freeze_Node (Par), Package_Freeze_Node (Enc_I));
+         end if;
+
+         Insert_After_Last_Decl (Inst_Node, F_Node);
+
+      elsif Present (Enc_G)
+        and then Present (Enc_I)
+        and then Enc_G /= Enc_I
+        and then Earlier (Inst_Node, Gen_Body)
+      then
+         if Nkind (Enc_G) = N_Package_Body then
+            E_G_Id := Corresponding_Spec (Enc_G);
+         else pragma Assert (Nkind (Enc_G) = N_Package_Body_Stub);
+            E_G_Id :=
+              Corresponding_Spec (Proper_Body (Unit (Library_Unit (Enc_G))));
+         end if;
+
+         --  Freeze package that encloses instance, and place node after
+         --  package that encloses generic. If enclosing package is already
+         --  frozen we have to assume it is at the proper place. This may
+         --  be a potential ABE that requires dynamic checking.
+
+         Insert_After_Last_Decl (Enc_G, Package_Freeze_Node (Enc_I));
+
+         --  Freeze enclosing subunit before instance
+
+         Ensure_Freeze_Node (E_G_Id);
+
+         if not Is_List_Member (Freeze_Node (E_G_Id)) then
+            Insert_After (Enc_G, Freeze_Node (E_G_Id));
+         end if;
+
+         Insert_After_Last_Decl (Inst_Node, F_Node);
+
+      else
+
+         --  If none of the above, insert freeze node at the end of the
+         --  current declarative part.
+
+         Insert_After_Last_Decl (Inst_Node, F_Node);
+      end if;
+   end Freeze_Subprogram_Body;
+
+   ----------------
+   -- Get_Gen_Id --
+   ----------------
+
+   function Get_Gen_Id (E : Assoc_Ptr) return Entity_Id is
+   begin
+      return Generic_Renamings.Table (E).Gen_Id;
+   end Get_Gen_Id;
+
+   ---------------------
+   -- Get_Instance_Of --
+   ---------------------
+
+   function Get_Instance_Of (A : Entity_Id) return Entity_Id is
+      Res : Assoc_Ptr := Generic_Renamings_HTable.Get (A);
+   begin
+      if Res /= Assoc_Null then
+         return Generic_Renamings.Table (Res).Act_Id;
+      else
+         --  On exit, entity is not instantiated: not a generic parameter,
+         --  or else parameter of an inner generic unit.
+
+         return A;
+      end if;
+   end Get_Instance_Of;
+
+   ------------------------------------
+   -- Get_Package_Instantiation_Node --
+   ------------------------------------
+
+   function Get_Package_Instantiation_Node (A : Entity_Id) return Node_Id is
+      Decl : Node_Id := Unit_Declaration_Node (A);
+      Inst : Node_Id;
+
+   begin
+      --  If the instantiation is a compilation unit that does not need a
+      --  body then the instantiation node has been rewritten as a package
+      --  declaration for the instance, and we return the original node.
+      --  If it is a compilation unit and the instance node has not been
+      --  rewritten, then it is still the unit of the compilation.
+      --  Otherwise the instantiation node appears after the declaration.
+      --  If the entity is a formal package, the declaration may have been
+      --  rewritten as a generic declaration (in the case of a formal with a
+      --  box) or left as a formal package declaration if it has actuals, and
+      --  is found with a forward search.
+
+      if Nkind (Parent (Decl)) = N_Compilation_Unit then
+         if Nkind (Original_Node (Decl)) = N_Package_Instantiation then
+            return Original_Node (Decl);
+         else
+            return Unit (Parent (Decl));
+         end if;
+
+      elsif Nkind (Decl) = N_Generic_Package_Declaration
+        and then Nkind (Original_Node (Decl)) = N_Formal_Package_Declaration
+      then
+         return Original_Node (Decl);
+
+      else
+         Inst := Next (Decl);
+         while Nkind (Inst) /= N_Package_Instantiation
+           and then Nkind (Inst) /= N_Formal_Package_Declaration
+         loop
+            Next (Inst);
+         end loop;
+
+         return Inst;
+      end if;
+   end Get_Package_Instantiation_Node;
+
+   ------------------------
+   -- Has_Been_Exchanged --
+   ------------------------
+
+   function Has_Been_Exchanged (E : Entity_Id) return Boolean is
+      Next : Elmt_Id := First_Elmt (Exchanged_Views);
+
+   begin
+      while Present (Next) loop
+         if Full_View (Node (Next)) = E then
+            return True;
+         end if;
+
+         Next_Elmt (Next);
+      end loop;
+
+      return False;
+   end Has_Been_Exchanged;
+
+   ----------
+   -- Hash --
+   ----------
+
+   function Hash (F : Entity_Id) return HTable_Range is
+   begin
+      return HTable_Range (F mod HTable_Size);
+   end Hash;
+
+   ------------------------
+   -- Hide_Current_Scope --
+   ------------------------
+
+   procedure Hide_Current_Scope is
+      C : constant Entity_Id := Current_Scope;
+      E : Entity_Id;
+
+   begin
+      Set_Is_Hidden_Open_Scope (C);
+      E := First_Entity (C);
+
+      while Present (E) loop
+         if Is_Immediately_Visible (E) then
+            Set_Is_Immediately_Visible (E, False);
+            Append_Elmt (E, Hidden_Entities);
+         end if;
+
+         Next_Entity (E);
+      end loop;
+
+      --  Make the scope name invisible as well. This is necessary, but
+      --  might conflict with calls to Rtsfind later on, in case the scope
+      --  is a predefined one. There is no clean solution to this problem, so
+      --  for now we depend on the user not redefining Standard itself in one
+      --  of the parent units.
+
+      if Is_Immediately_Visible (C)
+        and then C /= Standard_Standard
+      then
+         Set_Is_Immediately_Visible (C, False);
+         Append_Elmt (C, Hidden_Entities);
+      end if;
+
+   end Hide_Current_Scope;
+
+   ------------------------------
+   -- In_Same_Declarative_Part --
+   ------------------------------
+
+   function In_Same_Declarative_Part
+     (F_Node : Node_Id;
+      Inst   : Node_Id)
+      return   Boolean
+   is
+      Decls : Node_Id := Parent (F_Node);
+      Nod   : Node_Id := Parent (Inst);
+
+   begin
+      while Present (Nod) loop
+         if Nod = Decls then
+            return True;
+
+         elsif Nkind (Nod) = N_Subprogram_Body
+           or else Nkind (Nod) = N_Package_Body
+           or else Nkind (Nod) = N_Task_Body
+           or else Nkind (Nod) = N_Protected_Body
+           or else Nkind (Nod) = N_Block_Statement
+         then
+            return False;
+
+         elsif Nkind (Nod) = N_Subunit then
+            Nod :=  Corresponding_Stub (Nod);
+
+         elsif Nkind (Nod) = N_Compilation_Unit then
+            return False;
+         else
+            Nod := Parent (Nod);
+         end if;
+      end loop;
+
+      return False;
+   end In_Same_Declarative_Part;
+
+   ---------------------
+   -- Inherit_Context --
+   ---------------------
+
+   procedure Inherit_Context (Gen_Decl : Node_Id; Inst : Node_Id) is
+      Current_Context : List_Id;
+      Current_Unit    : Node_Id;
+      Item            : Node_Id;
+      New_I           : Node_Id;
+
+   begin
+      if Nkind (Parent (Gen_Decl)) = N_Compilation_Unit then
+
+         --  The inherited context is attached to the enclosing compilation
+         --  unit. This is either the main unit, or the declaration for the
+         --  main unit (in case the instantation appears within the package
+         --  declaration and the main unit is its body).
+
+         Current_Unit := Parent (Inst);
+         while Present (Current_Unit)
+           and then Nkind (Current_Unit) /= N_Compilation_Unit
+         loop
+            Current_Unit := Parent (Current_Unit);
+         end loop;
+
+         Current_Context := Context_Items (Current_Unit);
+
+         Item := First (Context_Items (Parent (Gen_Decl)));
+         while Present (Item) loop
+            if Nkind (Item) = N_With_Clause then
+               New_I := New_Copy (Item);
+               Set_Implicit_With (New_I, True);
+               Append (New_I, Current_Context);
+            end if;
+
+            Next (Item);
+         end loop;
+      end if;
+   end Inherit_Context;
+
+   ----------------------------
+   -- Insert_After_Last_Decl --
+   ----------------------------
+
+   procedure Insert_After_Last_Decl (N : Node_Id; F_Node : Node_Id) is
+      L : List_Id := List_Containing (N);
+      P : Node_Id := Parent (L);
+
+   begin
+      if not Is_List_Member (F_Node) then
+         if Nkind (P) = N_Package_Specification
+           and then L = Visible_Declarations (P)
+           and then Present (Private_Declarations (P))
+           and then not Is_Empty_List (Private_Declarations (P))
+         then
+            L := Private_Declarations (P);
+         end if;
+
+         Insert_After (Last (L), F_Node);
+      end if;
+   end Insert_After_Last_Decl;
+
+   ------------------
+   -- Install_Body --
+   ------------------
+
+   procedure Install_Body
+     (Act_Body : Node_Id;
+      N        : Node_Id;
+      Gen_Body : Node_Id;
+      Gen_Decl : Node_Id)
+   is
+      Act_Id    : Entity_Id := Corresponding_Spec (Act_Body);
+      Act_Unit  : constant Node_Id :=
+                    Unit (Cunit (Get_Source_Unit (N)));
+      F_Node    : Node_Id;
+      Gen_Id    : Entity_Id := Corresponding_Spec (Gen_Body);
+      Gen_Unit  : constant Node_Id :=
+                    Unit (Cunit (Get_Source_Unit (Gen_Decl)));
+      Orig_Body : Node_Id := Gen_Body;
+      Par       : constant Entity_Id := Scope (Gen_Id);
+      Body_Unit : Node_Id;
+
+      Must_Delay : Boolean;
+
+      function Enclosing_Subp (Id : Entity_Id) return Entity_Id;
+      --  Find subprogram (if any) that encloses instance and/or generic body.
+
+      function True_Sloc (N : Node_Id) return Source_Ptr;
+      --  If the instance is nested inside a generic unit, the Sloc of the
+      --  instance indicates the place of the original definition, not the
+      --  point of the current enclosing instance. Pending a better usage of
+      --  Slocs to indicate instantiation places, we determine the place of
+      --  origin of a node by finding the maximum sloc of any ancestor node.
+      --  Why is this not equivalent fo Top_Level_Location ???
+
+      function Enclosing_Subp (Id : Entity_Id) return Entity_Id is
+         Scop : Entity_Id := Scope (Id);
+
+      begin
+         while Scop /= Standard_Standard
+           and then not Is_Overloadable (Scop)
+         loop
+            Scop := Scope (Scop);
+         end loop;
+
+         return Scop;
+      end Enclosing_Subp;
+
+      function True_Sloc (N : Node_Id) return Source_Ptr is
+         Res : Source_Ptr;
+         N1  : Node_Id;
+
+      begin
+         Res := Sloc (N);
+         N1 := N;
+         while Present (N1) and then N1 /= Act_Unit loop
+            if Sloc (N1) > Res then
+               Res := Sloc (N1);
+            end if;
+
+            N1 := Parent (N1);
+         end loop;
+
+         return Res;
+      end True_Sloc;
+
+   --  Start of processing for Install_Body
+
+   begin
+      --  If the body is a subunit, the freeze point is the corresponding
+      --  stub in the current compilation, not the subunit itself.
+
+      if Nkind (Parent (Gen_Body)) = N_Subunit then
+         Orig_Body :=  Corresponding_Stub (Parent (Gen_Body));
+      else
+         Orig_Body := Gen_Body;
+      end if;
+
+      Body_Unit := Unit (Cunit (Get_Source_Unit (Orig_Body)));
+
+      --  If the instantiation and the generic definition appear in the
+      --  same package declaration, this is an early instantiation.
+      --  If they appear in the same declarative part, it is an early
+      --  instantiation only if the generic body appears textually later,
+      --  and the generic body is also in the main unit.
+
+      --  If instance is nested within a subprogram, and the generic body is
+      --  not, the instance is delayed because the enclosing body is. If
+      --  instance and body are within the same scope, or the same sub-
+      --  program body, indicate explicitly that the instance is delayed.
+
+      Must_Delay :=
+        (Gen_Unit = Act_Unit
+          and then ((Nkind (Gen_Unit) = N_Package_Declaration)
+                      or else Nkind (Gen_Unit) = N_Generic_Package_Declaration
+                      or else (Gen_Unit = Body_Unit
+                                and then True_Sloc (N) < Sloc (Orig_Body)))
+          and then Is_In_Main_Unit (Gen_Unit)
+          and then (Scope (Act_Id) = Scope (Gen_Id)
+                      or else
+                    Enclosing_Subp (Act_Id) = Enclosing_Subp (Gen_Id)));
+
+      --  If this is an early instantiation, the freeze node is placed after
+      --  the generic body. Otherwise, if the generic appears in an instance,
+      --  we cannot freeze the current instance until the outer one is frozen.
+      --  This is only relevant if the current instance is nested within some
+      --  inner scope not itself within the outer instance. If this scope is
+      --  a package body in the same declarative part as the outer instance,
+      --  then that body needs to be frozen after the outer instance. Finally,
+      --  if no delay is needed, we place the freeze node at the end of the
+      --  current declarative part.
+
+      if Expander_Active then
+         Ensure_Freeze_Node (Act_Id);
+         F_Node := Freeze_Node (Act_Id);
+
+         if Must_Delay then
+            Insert_After (Orig_Body, F_Node);
+
+         elsif Is_Generic_Instance (Par)
+           and then Present (Freeze_Node (Par))
+           and then Scope (Act_Id) /= Par
+         then
+            --  Freeze instance of inner generic after instance of enclosing
+            --  generic.
+
+            if In_Same_Declarative_Part (Freeze_Node (Par), N) then
+               Insert_After (Freeze_Node (Par), F_Node);
+
+            --  Freeze package enclosing instance of inner generic after
+            --  instance of enclosing generic.
+
+            elsif Nkind (Parent (N)) = N_Package_Body
+              and then In_Same_Declarative_Part (Freeze_Node (Par), Parent (N))
+            then
+
+               declare
+                  Enclosing : Entity_Id := Corresponding_Spec (Parent (N));
+
+               begin
+                  Insert_After_Last_Decl (N, F_Node);
+                  Ensure_Freeze_Node (Enclosing);
+
+                  if not Is_List_Member (Freeze_Node (Enclosing)) then
+                     Insert_After (Freeze_Node (Par), Freeze_Node (Enclosing));
+                  end if;
+               end;
+
+            else
+               Insert_After_Last_Decl (N, F_Node);
+            end if;
+
+         else
+            Insert_After_Last_Decl (N, F_Node);
+         end if;
+      end if;
+
+      Set_Is_Frozen (Act_Id);
+      Insert_Before (N, Act_Body);
+      Mark_Rewrite_Insertion (Act_Body);
+   end Install_Body;
+
+   --------------------
+   -- Install_Parent --
+   --------------------
+
+   procedure Install_Parent (P : Entity_Id; In_Body : Boolean := False) is
+      S : Entity_Id := Current_Scope;
+      Inst_Par  : Entity_Id;
+      First_Par : Entity_Id;
+      Inst_Node : Node_Id;
+      Gen_Par   : Entity_Id;
+      First_Gen : Entity_Id;
+      Ancestors : Elist_Id := New_Elmt_List;
+      Elmt      : Elmt_Id;
+
+      procedure Install_Formal_Packages (Par : Entity_Id);
+      --  If any of the formals of the parent are formal packages with box,
+      --  their formal parts are visible in the parent and thus in the child
+      --  unit as well. Analogous to what is done in Check_Generic_Actuals
+      --  for the unit itself.
+
+      procedure Install_Noninstance_Specs (Par : Entity_Id);
+      --  Install the scopes of noninstance parent units ending with Par.
+
+      procedure Install_Spec (Par : Entity_Id);
+      --  The child unit is within the declarative part of the parent, so
+      --  the declarations within the parent are immediately visible.
+
+      -----------------------------
+      -- Install_Formal_Packages --
+      -----------------------------
+
+      procedure Install_Formal_Packages (Par : Entity_Id) is
+         E : Entity_Id;
+
+      begin
+         E := First_Entity (Par);
+
+         while Present (E) loop
+
+            if Ekind (E) = E_Package
+              and then Nkind (Parent (E)) = N_Package_Renaming_Declaration
+            then
+               --  If this is the renaming for the parent instance, done.
+
+               if Renamed_Object (E) = Par then
+                  exit;
+
+               --  The visibility of a formal of an enclosing generic is
+               --  already correct.
+
+               elsif Denotes_Formal_Package (E) then
+                  null;
+
+               elsif Present (Associated_Formal_Package (E))
+                 and then Box_Present (Parent (Associated_Formal_Package (E)))
+               then
+                  Check_Generic_Actuals (Renamed_Object (E), True);
+                  Set_Is_Hidden (E, False);
+               end if;
+            end if;
+
+            Next_Entity (E);
+         end loop;
+      end Install_Formal_Packages;
+
+      -------------------------------
+      -- Install_Noninstance_Specs --
+      -------------------------------
+
+      procedure Install_Noninstance_Specs (Par : Entity_Id) is
+      begin
+         if Present (Par)
+           and then Par /= Standard_Standard
+           and then not In_Open_Scopes (Par)
+         then
+            Install_Noninstance_Specs (Scope (Par));
+            Install_Spec (Par);
+         end if;
+      end Install_Noninstance_Specs;
+
+      ------------------
+      -- Install_Spec --
+      ------------------
+
+      procedure Install_Spec (Par : Entity_Id) is
+         Spec : constant Node_Id :=
+                  Specification (Unit_Declaration_Node (Par));
+
+      begin
+         New_Scope (Par);
+         Set_Is_Immediately_Visible   (Par);
+         Install_Visible_Declarations (Par);
+         Install_Private_Declarations (Par);
+         Set_Use (Visible_Declarations (Spec));
+         Set_Use (Private_Declarations (Spec));
+      end Install_Spec;
+
+   --  Start of processing for Install_Parent
+
+   begin
+      --  We need to install the parent instance to compile the instantiation
+      --  of the child, but the child instance must appear in the current
+      --  scope. Given that we cannot place the parent above the current
+      --  scope in the scope stack, we duplicate the current scope and unstack
+      --  both after the instantiation is complete.
+
+      --  If the parent is itself the instantiation of a child unit, we must
+      --  also stack the instantiation of its parent, and so on. Each such
+      --  ancestor is the prefix of the name in a prior instantiation.
+
+      --  If this is a nested instance, the parent unit itself resolves to
+      --  a renaming of the parent instance, whose declaration we need.
+
+      --  Finally, the parent may be a generic (not an instance) when the
+      --  child unit appears as a formal package.
+
+      Inst_Par := P;
+
+      if Present (Renamed_Entity (Inst_Par)) then
+         Inst_Par := Renamed_Entity (Inst_Par);
+      end if;
+
+      First_Par := Inst_Par;
+
+      Gen_Par :=
+        Generic_Parent (Specification (Unit_Declaration_Node (Inst_Par)));
+
+      First_Gen := Gen_Par;
+
+      while Present (Gen_Par)
+        and then Is_Child_Unit (Gen_Par)
+      loop
+         --  Load grandparent instance as well.
+
+         Inst_Node := Get_Package_Instantiation_Node (Inst_Par);
+
+         if Nkind (Name (Inst_Node)) = N_Expanded_Name then
+            Inst_Par := Entity (Prefix (Name (Inst_Node)));
+
+            if Present (Renamed_Entity (Inst_Par)) then
+               Inst_Par := Renamed_Entity (Inst_Par);
+            end if;
+
+            Gen_Par :=
+              Generic_Parent
+                (Specification (Unit_Declaration_Node (Inst_Par)));
+
+            if Present (Gen_Par) then
+               Prepend_Elmt (Inst_Par, Ancestors);
+
+            else
+               --  Parent is not the name of an instantiation.
+
+               Install_Noninstance_Specs (Inst_Par);
+
+               exit;
+            end if;
+
+         else
+            --  Previous error.
+
+            exit;
+         end if;
+      end loop;
+
+      if Present (First_Gen) then
+         Append_Elmt (First_Par, Ancestors);
+
+      else
+         Install_Noninstance_Specs (First_Par);
+      end if;
+
+      if not Is_Empty_Elmt_List (Ancestors) then
+         Elmt := First_Elmt (Ancestors);
+
+         while Present (Elmt) loop
+            Install_Spec (Node (Elmt));
+            Install_Formal_Packages (Node (Elmt));
+
+            Next_Elmt (Elmt);
+         end loop;
+      end if;
+
+      if not In_Body then
+         New_Scope (S);
+      end if;
+   end Install_Parent;
+
+   --------------------------------
+   -- Instantiate_Formal_Package --
+   --------------------------------
+
+   function Instantiate_Formal_Package
+     (Formal          : Node_Id;
+      Actual          : Node_Id;
+      Analyzed_Formal : Node_Id)
+      return            List_Id
+   is
+      Loc         : constant Source_Ptr := Sloc (Actual);
+      Actual_Pack : Entity_Id;
+      Formal_Pack : Entity_Id;
+      Gen_Parent  : Entity_Id;
+      Decls       : List_Id;
+      Nod         : Node_Id;
+      Parent_Spec : Node_Id;
+
+      function Formal_Entity
+        (F       : Node_Id;
+         Act_Ent : Entity_Id)
+         return    Entity_Id;
+      --  Returns the entity associated with the given formal F. In the
+      --  case where F is a formal package, this function will iterate
+      --  through all of F's formals and enter map associations from the
+      --  actuals occurring in the formal package's corresponding actual
+      --  package (obtained via Act_Ent) to the formal package's formal
+      --  parameters. This function is called recursively for arbitrary
+      --  levels of formal packages.
+
+      procedure Map_Entities (Form : Entity_Id; Act : Entity_Id);
+      --  Within the generic part, entities in the formal package are
+      --  visible. To validate subsequent type declarations, indicate
+      --  the correspondence betwen the entities in the analyzed formal,
+      --  and the entities in  the actual package. There are three packages
+      --  involved in the instantiation of a formal package: the parent
+      --  generic P1 which appears in the generic declaration, the fake
+      --  instantiation P2 which appears in the analyzed generic, and whose
+      --  visible entities may be used in subsequent formals, and the actual
+      --  P3 in the instance. To validate subsequent formals, me indicate
+      --  that the entities in P2 are mapped into those of P3. The mapping of
+      --  entities has to be done recursively for nested packages.
+
+      -------------------
+      -- Formal_Entity --
+      -------------------
+
+      function Formal_Entity
+        (F       : Node_Id;
+         Act_Ent : Entity_Id)
+         return    Entity_Id
+      is
+         Orig_Node : Node_Id := F;
+
+      begin
+         case Nkind (F) is
+            when N_Formal_Object_Declaration =>
+               return Defining_Identifier (F);
+
+            when N_Formal_Type_Declaration =>
+               return Defining_Identifier (F);
+
+            when N_Formal_Subprogram_Declaration =>
+               return Defining_Unit_Name (Specification (F));
+
+            when N_Formal_Package_Declaration |
+                 N_Generic_Package_Declaration =>
+
+               if Nkind (F) = N_Generic_Package_Declaration then
+                  Orig_Node := Original_Node (F);
+               end if;
+
+               declare
+                  Actual_Ent  : Entity_Id := First_Entity (Act_Ent);
+                  Formal_Node : Node_Id;
+                  Formal_Ent  : Entity_Id;
+
+                  Gen_Decl : Node_Id :=
+                               Unit_Declaration_Node
+                                 (Entity (Name (Orig_Node)));
+                  Formals  : List_Id :=
+                               Generic_Formal_Declarations (Gen_Decl);
+
+               begin
+                  if Present (Formals) then
+                     Formal_Node := First_Non_Pragma (Formals);
+                  else
+                     Formal_Node := Empty;
+                  end if;
+
+                  --  As for the loop further below, this loop is making
+                  --  a probably invalid assumption about the correspondence
+                  --  between formals and actuals and eventually needs to
+                  --  corrected to account for cases where the formals are
+                  --  not synchronized and in one-to-one correspondence
+                  --  with actuals. ???
+
+                  --  What is certain is that for a legal program the
+                  --  presence of actual entities guarantees the existing
+                  --  of formal ones.
+
+                  while Present (Actual_Ent)
+                    and then Present (Formal_Node)
+                    and then Actual_Ent /= First_Private_Entity (Act_Ent)
+                  loop
+                     --  ???  Are the following calls also needed here:
+                     --
+                     --  Set_Is_Hidden (Actual_Ent, False);
+                     --  Set_Is_Potentially_Use_Visible
+                     --    (Actual_Ent, In_Use (Act_Ent));
+
+                     Formal_Ent := Formal_Entity (Formal_Node, Actual_Ent);
+                     if Present (Formal_Ent) then
+                        Set_Instance_Of (Formal_Ent, Actual_Ent);
+                     end if;
+                     Next_Non_Pragma (Formal_Node);
+
+                     Next_Entity (Actual_Ent);
+                  end loop;
+               end;
+
+               return Defining_Identifier (Orig_Node);
+
+            when N_Use_Package_Clause =>
+               return Empty;
+
+            when N_Use_Type_Clause =>
+               return Empty;
+
+            --  We return Empty for all other encountered forms of
+            --  declarations because there are some cases of nonformal
+            --  sorts of declaration that can show up (e.g., when array
+            --  formals are present). Since it's not clear what kinds
+            --  can appear among the formals, we won't raise failure here.
+
+            when others =>
+               return Empty;
+
+         end case;
+      end Formal_Entity;
+
+      ------------------
+      -- Map_Entities --
+      ------------------
+
+      procedure Map_Entities (Form : Entity_Id; Act : Entity_Id) is
+         E1 : Entity_Id;
+         E2 : Entity_Id;
+
+      begin
+         Set_Instance_Of (Form, Act);
+
+         E1 := First_Entity (Form);
+         E2 := First_Entity (Act);
+         while Present (E1)
+           and then E1 /= First_Private_Entity (Form)
+         loop
+            if not Is_Internal (E1)
+              and then not Is_Class_Wide_Type (E1)
+            then
+
+               while Present (E2)
+                 and then Chars (E2) /= Chars (E1)
+               loop
+                  Next_Entity (E2);
+               end loop;
+
+               if No (E2) then
+                  exit;
+               else
+                  Set_Instance_Of (E1, E2);
+
+                  if Is_Type (E1)
+                    and then Is_Tagged_Type (E2)
+                  then
+                     Set_Instance_Of
+                       (Class_Wide_Type (E1), Class_Wide_Type (E2));
+                  end if;
+
+                  if Ekind (E1) = E_Package
+                    and then No (Renamed_Object (E1))
+                  then
+                     Map_Entities (E1, E2);
+                  end if;
+               end if;
+            end if;
+
+            Next_Entity (E1);
+         end loop;
+      end Map_Entities;
+
+   --  Start of processing for Instantiate_Formal_Package
+
+   begin
+      Analyze (Actual);
+
+      if not Is_Entity_Name (Actual)
+        or else  Ekind (Entity (Actual)) /= E_Package
+      then
+         Error_Msg_N
+           ("expect package instance to instantiate formal", Actual);
+         Abandon_Instantiation (Actual);
+         raise Program_Error;
+
+      else
+         Actual_Pack := Entity (Actual);
+         Set_Is_Instantiated (Actual_Pack);
+
+         --  The actual may be a renamed package, or an outer generic
+         --  formal package whose instantiation is converted into a renaming.
+
+         if Present (Renamed_Object (Actual_Pack)) then
+            Actual_Pack := Renamed_Object (Actual_Pack);
+         end if;
+
+         if Nkind (Analyzed_Formal) = N_Formal_Package_Declaration then
+            Gen_Parent  := Get_Instance_Of (Entity (Name (Analyzed_Formal)));
+            Formal_Pack := Defining_Identifier (Analyzed_Formal);
+         else
+            Gen_Parent :=
+              Generic_Parent (Specification (Analyzed_Formal));
+            Formal_Pack :=
+              Defining_Unit_Name (Specification (Analyzed_Formal));
+         end if;
+
+         if Nkind (Parent (Actual_Pack)) = N_Defining_Program_Unit_Name then
+            Parent_Spec := Specification (Unit_Declaration_Node (Actual_Pack));
+         else
+            Parent_Spec := Parent (Actual_Pack);
+         end if;
+
+         if Gen_Parent = Any_Id then
+            Error_Msg_N
+              ("previous error in declaration of formal package", Actual);
+            Abandon_Instantiation (Actual);
+
+         elsif
+           Generic_Parent (Parent_Spec) /= Get_Instance_Of (Gen_Parent)
+         then
+            Error_Msg_NE
+              ("actual parameter must be instance of&", Actual, Gen_Parent);
+            Abandon_Instantiation (Actual);
+         end if;
+
+         Set_Instance_Of (Defining_Identifier (Formal), Actual_Pack);
+         Map_Entities (Formal_Pack, Actual_Pack);
+
+         Nod :=
+           Make_Package_Renaming_Declaration (Loc,
+             Defining_Unit_Name => New_Copy (Defining_Identifier (Formal)),
+             Name               => New_Reference_To (Actual_Pack, Loc));
+
+         Set_Associated_Formal_Package (Defining_Unit_Name (Nod),
+           Defining_Identifier (Formal));
+         Decls := New_List (Nod);
+
+         --  If the formal F has a box, then the generic declarations are
+         --  visible in the generic G. In an instance of G, the corresponding
+         --  entities in the actual for F (which are the actuals for the
+         --  instantiation of the generic that F denotes) must also be made
+         --  visible for analysis of the current instance. On exit from the
+         --  current instance, those entities are made private again. If the
+         --  actual is currently in use, these entities are also use-visible.
+
+         --  The loop through the actual entities also steps through the
+         --  formal entities and enters associations from formals to
+         --  actuals into the renaming map. This is necessary to properly
+         --  handle checking of actual parameter associations for later
+         --  formals that depend on actuals declared in the formal package.
+         --
+         --  This processing needs to be reviewed at some point because
+         --  it is probably not entirely correct as written. For example
+         --  there may not be a strict one-to-one correspondence between
+         --  actuals and formals and this loop is currently assuming that
+         --  there is. ???
+
+         if Box_Present (Formal) then
+            declare
+               Actual_Ent  : Entity_Id := First_Entity (Actual_Pack);
+               Formal_Node : Node_Id := Empty;
+               Formal_Ent  : Entity_Id;
+               Gen_Decl    : Node_Id := Unit_Declaration_Node (Gen_Parent);
+               Formals     : List_Id := Generic_Formal_Declarations (Gen_Decl);
+
+            begin
+               if Present (Formals) then
+                  Formal_Node := First_Non_Pragma (Formals);
+               end if;
+
+               while Present (Actual_Ent)
+                 and then Actual_Ent /= First_Private_Entity (Actual_Pack)
+               loop
+                  Set_Is_Hidden (Actual_Ent, False);
+                  Set_Is_Potentially_Use_Visible
+                    (Actual_Ent, In_Use (Actual_Pack));
+
+                  if Present (Formal_Node) then
+                     Formal_Ent := Formal_Entity (Formal_Node, Actual_Ent);
+
+                     if Present (Formal_Ent) then
+                        Set_Instance_Of (Formal_Ent, Actual_Ent);
+                     end if;
+
+                     Next_Non_Pragma (Formal_Node);
+                  end if;
+
+                  Next_Entity (Actual_Ent);
+               end loop;
+            end;
+
+         --  If the formal is not declared with a box, reanalyze it as
+         --  an instantiation, to verify the matching rules of 12.7. The
+         --  actual checks are performed after the generic associations
+         --  been analyzed.
+
+         else
+            declare
+               I_Pack : constant Entity_Id :=
+                          Make_Defining_Identifier (Sloc (Actual),
+                            Chars => New_Internal_Name  ('P'));
+
+            begin
+               Set_Is_Internal (I_Pack);
+
+               Append_To (Decls,
+                 Make_Package_Instantiation (Sloc (Actual),
+                   Defining_Unit_Name => I_Pack,
+                   Name => New_Occurrence_Of (Gen_Parent, Sloc (Actual)),
+                   Generic_Associations =>
+                     Generic_Associations (Formal)));
+            end;
+         end if;
+
+         return Decls;
+      end if;
+
+   end Instantiate_Formal_Package;
+
+   -----------------------------------
+   -- Instantiate_Formal_Subprogram --
+   -----------------------------------
+
+   function Instantiate_Formal_Subprogram
+     (Formal          : Node_Id;
+      Actual          : Node_Id;
+      Analyzed_Formal : Node_Id)
+      return Node_Id
+   is
+      Loc        : Source_Ptr := Sloc (Instantiation_Node);
+      Formal_Sub : constant Entity_Id :=
+                     Defining_Unit_Name (Specification (Formal));
+      Analyzed_S : constant Entity_Id :=
+                     Defining_Unit_Name (Specification (Analyzed_Formal));
+      Decl_Node  : Node_Id;
+      Nam        : Node_Id;
+      New_Spec   : Node_Id;
+
+      function From_Parent_Scope (Subp : Entity_Id) return Boolean;
+      --  If the generic is a child unit, the parent has been installed
+      --  on the scope stack, but a default subprogram cannot resolve to
+      --  something on the parent because that parent is not really part
+      --  of the visible context (it is there to resolve explicit local
+      --  entities). If the default has resolved in this way, we remove
+      --  the entity from immediate visibility and analyze the node again
+      --  to emit an error message or find another visible candidate.
+
+      procedure Valid_Actual_Subprogram (Act : Node_Id);
+      --  Perform legality check and raise exception on failure.
+
+      -----------------------
+      -- From_Parent_Scope --
+      -----------------------
+
+      function From_Parent_Scope (Subp : Entity_Id) return Boolean is
+         Gen_Scope : Node_Id := Scope (Analyzed_S);
+
+      begin
+         while Present (Gen_Scope)
+           and then  Is_Child_Unit (Gen_Scope)
+         loop
+            if Scope (Subp) = Scope (Gen_Scope) then
+               return True;
+            end if;
+
+            Gen_Scope := Scope (Gen_Scope);
+         end loop;
+
+         return False;
+      end From_Parent_Scope;
+
+      -----------------------------
+      -- Valid_Actual_Subprogram --
+      -----------------------------
+
+      procedure Valid_Actual_Subprogram (Act : Node_Id) is
+      begin
+         if not Is_Entity_Name (Act)
+           and then Nkind (Act) /= N_Operator_Symbol
+           and then Nkind (Act) /= N_Attribute_Reference
+           and then Nkind (Act) /= N_Selected_Component
+           and then Nkind (Act) /= N_Indexed_Component
+           and then Nkind (Act) /= N_Character_Literal
+           and then Nkind (Act) /= N_Explicit_Dereference
+         then
+            if Etype (Act) /= Any_Type then
+               Error_Msg_NE
+                 ("Expect subprogram name to instantiate &",
+                  Instantiation_Node, Formal_Sub);
+            end if;
+
+            --  In any case, instantiation cannot continue.
+
+            Abandon_Instantiation (Instantiation_Node);
+         end if;
+      end Valid_Actual_Subprogram;
+
+   --  Start of processing for Instantiate_Formal_Subprogram
+
+   begin
+      New_Spec := New_Copy_Tree (Specification (Formal));
+
+      --  Create new entity for the actual (New_Copy_Tree does not).
+
+      Set_Defining_Unit_Name
+        (New_Spec, Make_Defining_Identifier (Loc, Chars (Formal_Sub)));
+
+      --  Find entity of actual. If the actual is an attribute reference, it
+      --  cannot be resolved here (its formal is missing) but is handled
+      --  instead in Attribute_Renaming. If the actual is overloaded, it is
+      --  fully resolved subsequently, when the renaming declaration for the
+      --  formal is analyzed. If it is an explicit dereference, resolve the
+      --  prefix but not the actual itself, to prevent interpretation as a
+      --  call.
+
+      if Present (Actual) then
+         Loc := Sloc (Actual);
+         Set_Sloc (New_Spec, Loc);
+
+         if Nkind (Actual) = N_Operator_Symbol then
+            Find_Direct_Name (Actual);
+
+         elsif Nkind (Actual) = N_Explicit_Dereference then
+            Analyze (Prefix (Actual));
+
+         elsif Nkind (Actual) /= N_Attribute_Reference then
+            Analyze (Actual);
+         end if;
+
+         Valid_Actual_Subprogram (Actual);
+         Nam := Actual;
+
+      elsif Present (Default_Name (Formal)) then
+
+         if Nkind (Default_Name (Formal)) /= N_Attribute_Reference
+           and then Nkind (Default_Name (Formal)) /= N_Selected_Component
+           and then Nkind (Default_Name (Formal)) /= N_Indexed_Component
+           and then Nkind (Default_Name (Formal)) /= N_Character_Literal
+           and then Present (Entity (Default_Name (Formal)))
+         then
+            Nam := New_Occurrence_Of (Entity (Default_Name (Formal)), Loc);
+         else
+            Nam := New_Copy (Default_Name (Formal));
+            Set_Sloc (Nam, Loc);
+         end if;
+
+      elsif Box_Present (Formal) then
+
+         --  Actual is resolved at the point of instantiation. Create
+         --  an identifier or operator with the same name as the formal.
+
+         if Nkind (Formal_Sub) = N_Defining_Operator_Symbol then
+            Nam := Make_Operator_Symbol (Loc,
+              Chars =>  Chars (Formal_Sub),
+              Strval => No_String);
+         else
+            Nam := Make_Identifier (Loc, Chars (Formal_Sub));
+         end if;
+
+      else
+         Error_Msg_NE
+           ("missing actual for instantiation of &",
+                                 Instantiation_Node, Formal_Sub);
+         Abandon_Instantiation (Instantiation_Node);
+      end if;
+
+      Decl_Node :=
+        Make_Subprogram_Renaming_Declaration (Loc,
+          Specification => New_Spec,
+          Name => Nam);
+
+      --  Gather possible interpretations for the actual before analyzing the
+      --  instance. If overloaded, it will be resolved when analyzing the
+      --  renaming declaration.
+
+      if Box_Present (Formal)
+        and then No (Actual)
+      then
+         Analyze (Nam);
+
+         if Is_Child_Unit (Scope (Analyzed_S))
+           and then Present (Entity (Nam))
+         then
+            if not Is_Overloaded (Nam) then
+
+               if From_Parent_Scope (Entity (Nam)) then
+                  Set_Is_Immediately_Visible (Entity (Nam), False);
+                  Set_Entity (Nam, Empty);
+                  Set_Etype (Nam, Empty);
+
+                  Analyze (Nam);
+
+                  Set_Is_Immediately_Visible (Entity (Nam));
+               end if;
+
+            else
+               declare
+                  I  : Interp_Index;
+                  It : Interp;
+
+               begin
+                  Get_First_Interp (Nam, I, It);
+
+                  while Present (It.Nam) loop
+                     if From_Parent_Scope (It.Nam) then
+                        Remove_Interp (I);
+                     end if;
+
+                     Get_Next_Interp (I, It);
+                  end loop;
+               end;
+            end if;
+         end if;
+      end if;
+
+      --  The generic instantiation freezes the actual. This can only be
+      --  done once the actual is resolved, in the analysis of the renaming
+      --  declaration. To indicate that must be done, we set the corresponding
+      --  spec of the node to point to the formal subprogram declaration.
+
+      Set_Corresponding_Spec (Decl_Node, Analyzed_Formal);
+
+      --  We cannot analyze the renaming declaration, and thus find the
+      --  actual, until the all the actuals are assembled in the instance.
+      --  For subsequent checks of other actuals, indicate the node that
+      --  will hold the instance of this formal.
+
+      Set_Instance_Of (Analyzed_S, Nam);
+
+      if Nkind (Actual) = N_Selected_Component
+        and then Is_Task_Type (Etype (Prefix (Actual)))
+        and then not Is_Frozen (Etype (Prefix (Actual)))
+      then
+         --  The renaming declaration will create a body, which must appear
+         --  outside of the instantiation, We move the renaming declaration
+         --  out of the instance, and create an additional renaming inside,
+         --  to prevent freezing anomalies.
+
+         declare
+            Anon_Id : constant Entity_Id :=
+                        Make_Defining_Identifier
+                          (Loc, New_Internal_Name ('E'));
+         begin
+            Set_Defining_Unit_Name (New_Spec, Anon_Id);
+            Insert_Before (Instantiation_Node, Decl_Node);
+            Analyze (Decl_Node);
+
+            --  Now create renaming within the instance.
+
+            Decl_Node :=
+              Make_Subprogram_Renaming_Declaration (Loc,
+                Specification => New_Copy_Tree (New_Spec),
+                Name => New_Occurrence_Of (Anon_Id, Loc));
+
+            Set_Defining_Unit_Name (Specification (Decl_Node),
+              Make_Defining_Identifier (Loc, Chars (Formal_Sub)));
+         end;
+      end if;
+
+      return Decl_Node;
+   end Instantiate_Formal_Subprogram;
+
+   ------------------------
+   -- Instantiate_Object --
+   ------------------------
+
+   function Instantiate_Object
+     (Formal          : Node_Id;
+      Actual          : Node_Id;
+      Analyzed_Formal : Node_Id)
+      return            List_Id
+   is
+      Formal_Id : constant Entity_Id  := Defining_Identifier (Formal);
+      Type_Id   : constant Node_Id    := Subtype_Mark (Formal);
+      Loc       : constant Source_Ptr := Sloc (Actual);
+      Act_Assoc : constant Node_Id    := Parent (Actual);
+      Orig_Ftyp : constant Entity_Id  :=
+                    Etype (Defining_Identifier (Analyzed_Formal));
+      Ftyp      : Entity_Id;
+      Decl_Node : Node_Id;
+      Subt_Decl : Node_Id := Empty;
+      List      : List_Id := New_List;
+
+   begin
+      if Get_Instance_Of (Formal_Id) /= Formal_Id then
+         Error_Msg_N ("duplicate instantiation of generic parameter", Actual);
+      end if;
+
+      Set_Parent (List, Parent (Actual));
+
+      --  OUT present
+
+      if Out_Present (Formal) then
+
+         --  An IN OUT generic actual must be a name. The instantiation is
+         --  a renaming declaration. The actual is the name being renamed.
+         --  We use the actual directly, rather than a copy, because it is not
+         --  used further in the list of actuals, and because a copy or a use
+         --  of relocate_node is incorrect if the instance is nested within
+         --  a generic. In order to simplify ASIS searches, the Generic_Parent
+         --  field links the declaration to the generic association.
+
+         if No (Actual) then
+            Error_Msg_NE
+              ("missing actual for instantiation of &",
+               Instantiation_Node, Formal_Id);
+            Abandon_Instantiation (Instantiation_Node);
+         end if;
+
+         Decl_Node :=
+           Make_Object_Renaming_Declaration (Loc,
+             Defining_Identifier => New_Copy (Formal_Id),
+             Subtype_Mark        => New_Copy_Tree (Type_Id),
+             Name                => Actual);
+
+         Set_Corresponding_Generic_Association (Decl_Node, Act_Assoc);
+
+         --  The analysis of the actual may produce insert_action nodes, so
+         --  the declaration must have a context in which to attach them.
+
+         Append (Decl_Node, List);
+         Analyze (Actual);
+
+         --  This check is performed here because Analyze_Object_Renaming
+         --  will not check it when Comes_From_Source is False. Note
+         --  though that the check for the actual being the name of an
+         --  object will be performed in Analyze_Object_Renaming.
+
+         if Is_Object_Reference (Actual)
+           and then Is_Dependent_Component_Of_Mutable_Object (Actual)
+         then
+            Error_Msg_N
+              ("illegal discriminant-dependent component for in out parameter",
+               Actual);
+         end if;
+
+         --  The actual has to be resolved in order to check that it is
+         --  a variable (due to cases such as F(1), where F returns
+         --  access to an array, and for overloaded prefixes).
+
+         Ftyp :=
+           Get_Instance_Of (Etype (Defining_Identifier (Analyzed_Formal)));
+
+         if Is_Private_Type (Ftyp)
+           and then not Is_Private_Type (Etype (Actual))
+           and then (Base_Type (Full_View (Ftyp)) = Base_Type (Etype (Actual))
+                      or else Base_Type (Etype (Actual)) = Ftyp)
+         then
+            --  If the actual has the type of the full view of the formal,
+            --  or else a non-private subtype of the formal, then
+            --  the visibility of the formal type has changed. Add to the
+            --  actuals a subtype declaration that will force the exchange
+            --  of views in the body of the instance as well.
+
+            Subt_Decl :=
+              Make_Subtype_Declaration (Loc,
+                 Defining_Identifier =>
+                   Make_Defining_Identifier (Loc, New_Internal_Name ('P')),
+                 Subtype_Indication  => New_Occurrence_Of (Ftyp, Loc));
+
+            Prepend (Subt_Decl, List);
+
+            Append_Elmt (Full_View (Ftyp), Exchanged_Views);
+            Exchange_Declarations (Ftyp);
+         end if;
+
+         Resolve (Actual, Ftyp);
+
+         if not Is_Variable (Actual) or else Paren_Count (Actual) > 0 then
+            Error_Msg_NE
+              ("actual for& must be a variable", Actual, Formal_Id);
+
+         elsif Base_Type (Ftyp) /= Base_Type (Etype (Actual)) then
+            Error_Msg_NE (
+              "type of actual does not match type of&", Actual, Formal_Id);
+
+         end if;
+
+         Note_Possible_Modification (Actual);
+
+         --  Check for instantiation of atomic/volatile actual for
+         --  non-atomic/volatile formal (RM C.6 (12)).
+
+         if Is_Atomic_Object (Actual)
+           and then not Is_Atomic (Orig_Ftyp)
+         then
+            Error_Msg_N
+              ("cannot instantiate non-atomic formal object " &
+               "with atomic actual", Actual);
+
+         elsif Is_Volatile_Object (Actual)
+           and then not Is_Volatile (Orig_Ftyp)
+         then
+            Error_Msg_N
+              ("cannot instantiate non-volatile formal object " &
+               "with volatile actual", Actual);
+         end if;
+
+      --  OUT not present
+
+      else
+         --  The instantiation of a generic formal in-parameter
+         --  is a constant declaration. The actual is the expression for
+         --  that declaration.
+
+         if Present (Actual) then
+
+            Decl_Node := Make_Object_Declaration (Loc,
+              Defining_Identifier => New_Copy (Formal_Id),
+              Constant_Present => True,
+              Object_Definition => New_Copy_Tree (Type_Id),
+              Expression => Actual);
+
+            Set_Corresponding_Generic_Association (Decl_Node, Act_Assoc);
+
+            --  A generic formal object of a tagged type is defined
+            --  to be aliased so the new constant must also be treated
+            --  as aliased.
+
+            if Is_Tagged_Type
+                 (Etype (Defining_Identifier (Analyzed_Formal)))
+            then
+               Set_Aliased_Present (Decl_Node);
+            end if;
+
+            Append (Decl_Node, List);
+            Analyze (Actual);
+
+            declare
+               Typ : Entity_Id
+                      := Get_Instance_Of
+                           (Etype (Defining_Identifier (Analyzed_Formal)));
+            begin
+               Freeze_Before (Instantiation_Node, Typ);
+
+               --  If the actual is an aggregate, perform name resolution
+               --  on its components (the analysis of an aggregate does not
+               --  do it) to capture local names that may be hidden if the
+               --  generic is a child unit.
+
+               if Nkind (Actual) = N_Aggregate then
+                     Pre_Analyze_And_Resolve (Actual, Typ);
+               end if;
+            end;
+
+         elsif Present (Expression (Formal)) then
+
+            --  Use default to construct declaration.
+
+            Decl_Node :=
+              Make_Object_Declaration (Sloc (Formal),
+                Defining_Identifier => New_Copy (Formal_Id),
+                Constant_Present    => True,
+                Object_Definition   => New_Copy (Type_Id),
+                Expression          => New_Copy_Tree (Expression (Formal)));
+
+            Append (Decl_Node, List);
+            Set_Analyzed (Expression (Decl_Node), False);
+
+         else
+            Error_Msg_NE
+              ("missing actual for instantiation of &",
+               Instantiation_Node, Formal_Id);
+            Abandon_Instantiation (Instantiation_Node);
+         end if;
+
+      end if;
+
+      return List;
+   end Instantiate_Object;
+
+   ------------------------------
+   -- Instantiate_Package_Body --
+   ------------------------------
+
+   procedure Instantiate_Package_Body
+     (Body_Info : Pending_Body_Info)
+   is
+      Act_Decl    : constant Node_Id    := Body_Info.Act_Decl;
+      Inst_Node   : constant Node_Id    := Body_Info.Inst_Node;
+      Loc         : constant Source_Ptr := Sloc (Inst_Node);
+
+      Gen_Id      : constant Node_Id    := Name (Inst_Node);
+      Gen_Unit    : constant Entity_Id  := Entity (Name (Inst_Node));
+      Gen_Decl    : constant Node_Id    := Unit_Declaration_Node (Gen_Unit);
+      Act_Spec    : constant Node_Id    := Specification (Act_Decl);
+      Act_Decl_Id : constant Entity_Id  := Defining_Entity (Act_Spec);
+
+      Act_Body_Name : Node_Id;
+      Gen_Body      : Node_Id;
+      Gen_Body_Id   : Node_Id;
+      Act_Body      : Node_Id;
+      Act_Body_Id   : Entity_Id;
+
+      Parent_Installed : Boolean := False;
+      Save_Style_Check : Boolean := Style_Check;
+
+   begin
+      Gen_Body_Id := Corresponding_Body (Gen_Decl);
+      Expander_Mode_Save_And_Set (Body_Info.Expander_Status);
+
+      if No (Gen_Body_Id) then
+         Load_Parent_Of_Generic (Inst_Node, Specification (Gen_Decl));
+         Gen_Body_Id := Corresponding_Body (Gen_Decl);
+      end if;
+
+      --  Establish global variable for sloc adjustment and for error
+      --  recovery.
+
+      Instantiation_Node := Inst_Node;
+
+      if Present (Gen_Body_Id) then
+         Save_Env (Gen_Unit, Act_Decl_Id);
+         Style_Check := False;
+         Current_Sem_Unit := Body_Info.Current_Sem_Unit;
+
+         Gen_Body := Unit_Declaration_Node (Gen_Body_Id);
+
+         Create_Instantiation_Source
+          (Inst_Node, Gen_Body_Id, S_Adjustment);
+
+         Act_Body :=
+           Copy_Generic_Node
+             (Original_Node (Gen_Body), Empty, Instantiating => True);
+
+         --  Build new name (possibly qualified) for body declaration.
+
+         Act_Body_Id := New_Copy (Act_Decl_Id);
+
+         --  Some attributes of the spec entity are not inherited by the
+         --  body entity.
+
+         Set_Handler_Records (Act_Body_Id, No_List);
+
+         if Nkind (Defining_Unit_Name (Act_Spec)) =
+                                           N_Defining_Program_Unit_Name
+         then
+            Act_Body_Name :=
+              Make_Defining_Program_Unit_Name (Loc,
+                Name => New_Copy_Tree (Name (Defining_Unit_Name (Act_Spec))),
+                Defining_Identifier => Act_Body_Id);
+         else
+            Act_Body_Name :=  Act_Body_Id;
+         end if;
+
+         Set_Defining_Unit_Name (Act_Body, Act_Body_Name);
+
+         Set_Corresponding_Spec (Act_Body, Act_Decl_Id);
+         Check_Generic_Actuals (Act_Decl_Id, False);
+
+         --  If it is a child unit, make the parent instance (which is an
+         --  instance of the parent of the generic) visible. The parent
+         --  instance is the prefix of the name of the generic unit.
+
+         if Ekind (Scope (Gen_Unit)) = E_Generic_Package
+           and then Nkind (Gen_Id) = N_Expanded_Name
+         then
+            Install_Parent (Entity (Prefix (Gen_Id)), In_Body => True);
+            Parent_Installed := True;
+
+         elsif Is_Child_Unit (Gen_Unit) then
+            Install_Parent (Scope (Gen_Unit), In_Body => True);
+            Parent_Installed := True;
+         end if;
+
+         --  If the instantiation is a library unit, and this is the main
+         --  unit, then build the resulting compilation unit nodes for the
+         --  instance. If this is a compilation unit but it is not the main
+         --  unit, then it is the body of a unit in the context, that is being
+         --  compiled because it is encloses some inlined unit or another
+         --  generic unit being instantiated. In that case, this body is not
+         --  part of the current compilation, and is not attached to the tree,
+         --  but its parent must be set for analysis.
+
+         if Nkind (Parent (Inst_Node)) = N_Compilation_Unit then
+
+            if Parent (Inst_Node) = Cunit (Main_Unit) then
+               Build_Instance_Compilation_Unit_Nodes
+                 (Inst_Node, Act_Body, Act_Decl);
+               Analyze (Inst_Node);
+
+               --  If the instance is a child unit itself, then set the
+               --  scope of the expanded body to be the parent of the
+               --  instantiation (ensuring that the fully qualified name
+               --  will be generated for the elaboration subprogram).
+
+               if Nkind (Defining_Unit_Name (Act_Spec)) =
+                                              N_Defining_Program_Unit_Name
+               then
+                  Set_Scope
+                    (Defining_Entity (Inst_Node), Scope (Act_Decl_Id));
+               end if;
+
+            else
+               Set_Parent (Act_Body, Parent (Inst_Node));
+               Analyze (Act_Body);
+            end if;
+
+         --  Case where instantiation is not a library unit
+
+         else
+            --  If this is an early instantiation, i.e. appears textually
+            --  before the corresponding body and must be elaborated first,
+            --  indicate that the body instance is to be delayed.
+
+            Install_Body (Act_Body, Inst_Node, Gen_Body, Gen_Decl);
+
+            --  Now analyze the body. We turn off all checks if this is
+            --  an internal unit, since there is no reason to have checks
+            --  on for any predefined run-time library code. All such
+            --  code is designed to be compiled with checks off.
+
+            --  Note that we do NOT apply this criterion to children of
+            --  GNAT (or on VMS, children of DEC). The latter units must
+            --  suppress checks explicitly if this is needed.
+
+            if Is_Predefined_File_Name
+                 (Unit_File_Name (Get_Source_Unit (Gen_Decl)))
+            then
+               Analyze (Act_Body, Suppress => All_Checks);
+            else
+               Analyze (Act_Body);
+            end if;
+         end if;
+
+         if not Generic_Separately_Compiled (Gen_Unit) then
+            Inherit_Context (Gen_Body, Inst_Node);
+         end if;
+
+         Restore_Private_Views (Act_Decl_Id);
+         Restore_Env;
+         Style_Check := Save_Style_Check;
+
+      --  If we have no body, and the unit requires a body, then complain.
+      --  This complaint is suppressed if we have detected other errors
+      --  (since a common reason for missing the body is that it had errors).
+
+      elsif Unit_Requires_Body (Gen_Unit) then
+         if Errors_Detected = 0 then
+            Error_Msg_NE
+              ("cannot find body of generic package &", Inst_Node, Gen_Unit);
+
+         --  Don't attempt to perform any cleanup actions if some other
+         --  error was aready detected, since this can cause blowups.
+
+         else
+            return;
+         end if;
+
+      --  Case of package that does not need a body
+
+      else
+         --  If the instantiation of the declaration is a library unit,
+         --  rewrite the original package instantiation as a package
+         --  declaration in the compilation unit node.
+
+         if Nkind (Parent (Inst_Node)) = N_Compilation_Unit then
+            Set_Parent_Spec (Act_Decl, Parent_Spec (Inst_Node));
+            Rewrite (Inst_Node, Act_Decl);
+
+         --  If the instantiation is not a library unit, then append the
+         --  declaration to the list of implicitly generated entities.
+         --  unless it is already a list member which means that it was
+         --  already processed
+
+         elsif not Is_List_Member (Act_Decl) then
+            Mark_Rewrite_Insertion (Act_Decl);
+            Insert_Before (Inst_Node, Act_Decl);
+         end if;
+      end if;
+
+      Expander_Mode_Restore;
+
+      --  Remove the parent instances if they have been placed on the
+      --  scope stack to compile the body.
+
+      if Parent_Installed then
+         Remove_Parent (In_Body => True);
+      end if;
+   end Instantiate_Package_Body;
+
+   ---------------------------------
+   -- Instantiate_Subprogram_Body --
+   ---------------------------------
+
+   procedure Instantiate_Subprogram_Body
+     (Body_Info : Pending_Body_Info)
+   is
+      Act_Decl      : constant Node_Id    := Body_Info.Act_Decl;
+      Inst_Node     : constant Node_Id    := Body_Info.Inst_Node;
+      Loc           : constant Source_Ptr := Sloc (Inst_Node);
+
+      Decls         : List_Id;
+      Gen_Id        : constant Node_Id   := Name (Inst_Node);
+      Gen_Unit      : constant Entity_Id := Entity (Name (Inst_Node));
+      Gen_Decl      : constant Node_Id   := Unit_Declaration_Node (Gen_Unit);
+      Anon_Id       : constant Entity_Id :=
+                        Defining_Unit_Name (Specification (Act_Decl));
+      Gen_Body      : Node_Id;
+      Gen_Body_Id   : Node_Id;
+      Act_Body      : Node_Id;
+      Act_Body_Id   : Entity_Id;
+      Pack_Id       : Entity_Id := Defining_Unit_Name (Parent (Act_Decl));
+      Pack_Body     : Node_Id;
+      Prev_Formal   : Entity_Id;
+      Unit_Renaming : Node_Id;
+
+      Parent_Installed : Boolean := False;
+      Save_Style_Check : Boolean := Style_Check;
+
+   begin
+      Gen_Body_Id := Corresponding_Body (Gen_Decl);
+
+      Expander_Mode_Save_And_Set (Body_Info.Expander_Status);
+
+      if No (Gen_Body_Id) then
+         Load_Parent_Of_Generic (Inst_Node, Specification (Gen_Decl));
+         Gen_Body_Id := Corresponding_Body (Gen_Decl);
+      end if;
+
+      Instantiation_Node := Inst_Node;
+
+      if Present (Gen_Body_Id) then
+         Gen_Body := Unit_Declaration_Node (Gen_Body_Id);
+
+         if Nkind (Gen_Body) = N_Subprogram_Body_Stub then
+
+            --  Either body is not present, or context is non-expanding, as
+            --  when compiling a subunit. Mark the instance as completed.
+
+            Set_Has_Completion (Anon_Id);
+            return;
+         end if;
+
+         Save_Env (Gen_Unit, Anon_Id);
+         Style_Check := False;
+         Current_Sem_Unit := Body_Info.Current_Sem_Unit;
+         Create_Instantiation_Source (Inst_Node, Gen_Body_Id, S_Adjustment);
+
+         Act_Body :=
+           Copy_Generic_Node
+             (Original_Node (Gen_Body), Empty, Instantiating => True);
+         Act_Body_Id := Defining_Entity (Act_Body);
+         Set_Chars (Act_Body_Id, Chars (Anon_Id));
+         Set_Sloc (Act_Body_Id, Sloc (Defining_Entity (Inst_Node)));
+         Set_Corresponding_Spec (Act_Body, Anon_Id);
+         Set_Has_Completion (Anon_Id);
+         Check_Generic_Actuals (Pack_Id, False);
+
+         --  If it is a child unit, make the parent instance (which is an
+         --  instance of the parent of the generic) visible. The parent
+         --  instance is the prefix of the name of the generic unit.
+
+         if Ekind (Scope (Gen_Unit)) = E_Generic_Package
+           and then Nkind (Gen_Id) = N_Expanded_Name
+         then
+            Install_Parent (Entity (Prefix (Gen_Id)), In_Body => True);
+            Parent_Installed := True;
+
+         elsif Is_Child_Unit (Gen_Unit) then
+            Install_Parent (Scope (Gen_Unit), In_Body => True);
+            Parent_Installed := True;
+         end if;
+
+         --  Inside its body, a reference to the generic unit is a reference
+         --  to the instance. The corresponding renaming is the first
+         --  declaration in the body.
+
+         Unit_Renaming :=
+           Make_Subprogram_Renaming_Declaration (Loc,
+             Specification =>
+               Copy_Generic_Node (
+                 Specification (Original_Node (Gen_Body)),
+                 Empty,
+                 Instantiating => True),
+             Name => New_Occurrence_Of (Anon_Id, Loc));
+
+         --  If there is a formal subprogram with the same name as the
+         --  unit itself, do not add this renaming declaration. This is
+         --  a temporary fix for one ACVC test. ???
+
+         Prev_Formal := First_Entity (Pack_Id);
+         while Present (Prev_Formal) loop
+            if Chars (Prev_Formal) = Chars (Gen_Unit)
+              and then Is_Overloadable (Prev_Formal)
+            then
+               exit;
+            end if;
+
+            Next_Entity (Prev_Formal);
+         end loop;
+
+         if Present (Prev_Formal) then
+            Decls :=  New_List (Act_Body);
+         else
+            Decls :=  New_List (Unit_Renaming, Act_Body);
+         end if;
+
+         --  The subprogram body is placed in the body of a dummy package
+         --  body, whose spec contains the subprogram declaration as well
+         --  as the renaming declarations for the generic parameters.
+
+         Pack_Body := Make_Package_Body (Loc,
+           Defining_Unit_Name => New_Copy (Pack_Id),
+           Declarations       => Decls);
+
+         Set_Corresponding_Spec (Pack_Body, Pack_Id);
+
+         --  If the instantiation is a library unit, then build resulting
+         --  compilation unit nodes for the instance. The declaration of
+         --  the enclosing package is the grandparent of the subprogram
+         --  declaration. First replace the instantiation node as the unit
+         --  of the corresponding compilation.
+
+         if Nkind (Parent (Inst_Node)) = N_Compilation_Unit then
+
+            if Parent (Inst_Node) = Cunit (Main_Unit) then
+               Set_Unit (Parent (Inst_Node), Inst_Node);
+               Build_Instance_Compilation_Unit_Nodes
+                 (Inst_Node, Pack_Body, Parent (Parent (Act_Decl)));
+               Analyze (Inst_Node);
+            else
+               Set_Parent (Pack_Body, Parent (Inst_Node));
+               Analyze (Pack_Body);
+            end if;
+
+         else
+            Insert_Before (Inst_Node, Pack_Body);
+            Mark_Rewrite_Insertion (Pack_Body);
+            Analyze (Pack_Body);
+
+            if Expander_Active then
+               Freeze_Subprogram_Body (Inst_Node, Gen_Body, Pack_Id);
+            end if;
+         end if;
+
+         if not Generic_Separately_Compiled (Gen_Unit) then
+            Inherit_Context (Gen_Body, Inst_Node);
+         end if;
+
+         Restore_Private_Views (Pack_Id, False);
+
+         if Parent_Installed then
+            Remove_Parent (In_Body => True);
+         end if;
+
+         Restore_Env;
+         Style_Check := Save_Style_Check;
+
+      --  Body not found. Error was emitted already. If there were no
+      --  previous errors, this may be an instance whose scope is a premature
+      --  instance. In that case we must insure that the (legal) program does
+      --  raise program error if executed. We generate a subprogram body for
+      --  this purpose. See DEC ac30vso.
+
+      elsif Errors_Detected = 0
+        and then Nkind (Parent (Inst_Node)) /= N_Compilation_Unit
+      then
+         if Ekind (Anon_Id) = E_Procedure then
+            Act_Body :=
+              Make_Subprogram_Body (Loc,
+                 Specification              =>
+                   Make_Procedure_Specification (Loc,
+                     Defining_Unit_Name         => New_Copy (Anon_Id),
+                       Parameter_Specifications =>
+                       New_Copy_List
+                         (Parameter_Specifications (Parent (Anon_Id)))),
+
+                 Declarations               => Empty_List,
+                 Handled_Statement_Sequence =>
+                   Make_Handled_Sequence_Of_Statements (Loc,
+                     Statements =>
+                       New_List (Make_Raise_Program_Error (Loc))));
+         else
+            Act_Body :=
+              Make_Subprogram_Body (Loc,
+                Specification =>
+                  Make_Function_Specification (Loc,
+                     Defining_Unit_Name         => New_Copy (Anon_Id),
+                       Parameter_Specifications =>
+                       New_Copy_List
+                         (Parameter_Specifications (Parent (Anon_Id))),
+                     Subtype_Mark =>
+                       New_Occurrence_Of (Etype (Anon_Id), Loc)),
+
+                  Declarations               => Empty_List,
+                  Handled_Statement_Sequence =>
+                    Make_Handled_Sequence_Of_Statements (Loc,
+                      Statements => New_List (
+                        Make_Return_Statement (Loc,
+                          Expression => Make_Raise_Program_Error (Loc)))));
+         end if;
+
+         Pack_Body := Make_Package_Body (Loc,
+           Defining_Unit_Name => New_Copy (Pack_Id),
+           Declarations       => New_List (Act_Body));
+
+         Insert_After (Inst_Node, Pack_Body);
+         Set_Corresponding_Spec (Pack_Body, Pack_Id);
+         Analyze (Pack_Body);
+      end if;
+
+      Expander_Mode_Restore;
+   end Instantiate_Subprogram_Body;
+
+   ----------------------
+   -- Instantiate_Type --
+   ----------------------
+
+   function Instantiate_Type
+     (Formal          : Node_Id;
+      Actual          : Node_Id;
+      Analyzed_Formal : Node_Id)
+      return            Node_Id
+   is
+      Loc       : constant Source_Ptr := Sloc (Actual);
+      Gen_T     : constant Entity_Id  := Defining_Identifier (Formal);
+      A_Gen_T   : constant Entity_Id  := Defining_Identifier (Analyzed_Formal);
+      Ancestor  : Entity_Id;
+      Def       : constant Node_Id    := Formal_Type_Definition (Formal);
+      Act_T     : Entity_Id;
+      Decl_Node : Node_Id;
+
+      procedure Validate_Array_Type_Instance;
+      procedure Validate_Access_Subprogram_Instance;
+      procedure Validate_Access_Type_Instance;
+      procedure Validate_Derived_Type_Instance;
+      procedure Validate_Private_Type_Instance;
+      --  These procedures perform validation tests for the named case
+
+      function Subtypes_Match (Gen_T, Act_T : Entity_Id) return Boolean;
+      --  Check that base types are the same and that the subtypes match
+      --  statically. Used in several of the above.
+
+      --------------------
+      -- Subtypes_Match --
+      --------------------
+
+      function Subtypes_Match (Gen_T, Act_T : Entity_Id) return Boolean is
+         T : constant Entity_Id := Get_Instance_Of (Gen_T);
+
+      begin
+         return (Base_Type (T) = Base_Type (Act_T)
+--  why is the and then commented out here???
+--                  and then Is_Constrained (T) = Is_Constrained (Act_T)
+                  and then Subtypes_Statically_Match (T, Act_T))
+
+           or else (Is_Class_Wide_Type (Gen_T)
+                     and then Is_Class_Wide_Type (Act_T)
+                     and then
+                       Subtypes_Match (
+                         Get_Instance_Of (Root_Type (Gen_T)),
+                         Root_Type (Act_T)));
+      end Subtypes_Match;
+
+      -----------------------------------------
+      -- Validate_Access_Subprogram_Instance --
+      -----------------------------------------
+
+      procedure Validate_Access_Subprogram_Instance is
+      begin
+         if not Is_Access_Type (Act_T)
+           or else Ekind (Designated_Type (Act_T)) /= E_Subprogram_Type
+         then
+            Error_Msg_NE
+              ("expect access type in instantiation of &", Actual, Gen_T);
+            Abandon_Instantiation (Actual);
+         end if;
+
+         Check_Mode_Conformant
+           (Designated_Type (Act_T),
+            Designated_Type (A_Gen_T),
+            Actual,
+            Get_Inst => True);
+
+         if Ekind (Base_Type (Act_T)) = E_Access_Protected_Subprogram_Type then
+            if Ekind (A_Gen_T) = E_Access_Subprogram_Type then
+               Error_Msg_NE
+                 ("protected access type not allowed for formal &",
+                  Actual, Gen_T);
+            end if;
+
+         elsif Ekind (A_Gen_T) = E_Access_Protected_Subprogram_Type then
+            Error_Msg_NE
+              ("expect protected access type for formal &",
+               Actual, Gen_T);
+         end if;
+      end Validate_Access_Subprogram_Instance;
+
+      -----------------------------------
+      -- Validate_Access_Type_Instance --
+      -----------------------------------
+
+      procedure Validate_Access_Type_Instance is
+         Desig_Type : Entity_Id :=
+           Find_Actual_Type (Designated_Type (A_Gen_T), Scope (A_Gen_T));
+
+      begin
+         if not Is_Access_Type (Act_T) then
+            Error_Msg_NE
+              ("expect access type in instantiation of &", Actual, Gen_T);
+            Abandon_Instantiation (Actual);
+         end if;
+
+         if Is_Access_Constant (A_Gen_T) then
+            if not Is_Access_Constant (Act_T) then
+               Error_Msg_N
+                 ("actual type must be access-to-constant type", Actual);
+               Abandon_Instantiation (Actual);
+            end if;
+         else
+            if Is_Access_Constant (Act_T) then
+               Error_Msg_N
+                 ("actual type must be access-to-variable type", Actual);
+               Abandon_Instantiation (Actual);
+
+            elsif Ekind (A_Gen_T) = E_General_Access_Type
+              and then Ekind (Base_Type (Act_T)) /= E_General_Access_Type
+            then
+               Error_Msg_N ("actual must be general access type!", Actual);
+               Error_Msg_NE ("add ALL to }!", Actual, Act_T);
+               Abandon_Instantiation (Actual);
+            end if;
+         end if;
+
+         --  The designated subtypes, that is to say the subtypes introduced
+         --  by an access type declaration (and not by a subtype declaration)
+         --  must match.
+
+         if not Subtypes_Match
+           (Desig_Type, Designated_Type (Base_Type (Act_T)))
+         then
+            Error_Msg_NE
+              ("designated type of actual does not match that of formal &",
+                 Actual, Gen_T);
+            Abandon_Instantiation (Actual);
+
+         elsif Is_Access_Type (Designated_Type (Act_T))
+           and then Is_Constrained (Designated_Type (Designated_Type (Act_T)))
+                      /=
+                  Is_Constrained (Designated_Type (Desig_Type))
+         then
+            Error_Msg_NE
+              ("designated type of actual does not match that of formal &",
+                 Actual, Gen_T);
+            Abandon_Instantiation (Actual);
+         end if;
+      end Validate_Access_Type_Instance;
+
+      ----------------------------------
+      -- Validate_Array_Type_Instance --
+      ----------------------------------
+
+      procedure Validate_Array_Type_Instance is
+         I1 : Node_Id;
+         I2 : Node_Id;
+         T2 : Entity_Id;
+
+         function Formal_Dimensions return Int;
+         --  Count number of dimensions in array type formal
+
+         function Formal_Dimensions return Int is
+            Num   : Int := 0;
+            Index : Node_Id;
+
+         begin
+            if Nkind (Def) = N_Constrained_Array_Definition then
+               Index := First (Discrete_Subtype_Definitions (Def));
+            else
+               Index := First (Subtype_Marks (Def));
+            end if;
+
+            while Present (Index) loop
+               Num := Num + 1;
+               Next_Index (Index);
+            end loop;
+
+            return Num;
+         end Formal_Dimensions;
+
+      --  Start of processing for Validate_Array_Type_Instance
+
+      begin
+         if not Is_Array_Type (Act_T) then
+            Error_Msg_NE
+              ("expect array type in instantiation of &", Actual, Gen_T);
+            Abandon_Instantiation (Actual);
+
+         elsif Nkind (Def) = N_Constrained_Array_Definition then
+            if not (Is_Constrained (Act_T)) then
+               Error_Msg_NE
+                 ("expect constrained array in instantiation of &",
+                  Actual, Gen_T);
+               Abandon_Instantiation (Actual);
+            end if;
+
+         else
+            if Is_Constrained (Act_T) then
+               Error_Msg_NE
+                 ("expect unconstrained array in instantiation of &",
+                  Actual, Gen_T);
+               Abandon_Instantiation (Actual);
+            end if;
+         end if;
+
+         if Formal_Dimensions /= Number_Dimensions (Act_T) then
+            Error_Msg_NE
+              ("dimensions of actual do not match formal &", Actual, Gen_T);
+            Abandon_Instantiation (Actual);
+         end if;
+
+         I1 := First_Index (A_Gen_T);
+         I2 := First_Index (Act_T);
+         for J in 1 .. Formal_Dimensions loop
+
+            --  If the indices of the actual were given by a subtype_mark,
+            --  the index was transformed into a range attribute. Retrieve
+            --  the original type mark for checking.
+
+            if Is_Entity_Name (Original_Node (I2)) then
+               T2 := Entity (Original_Node (I2));
+            else
+               T2 := Etype (I2);
+            end if;
+
+            if not Subtypes_Match
+              (Find_Actual_Type (Etype (I1), Scope (A_Gen_T)), T2)
+            then
+               Error_Msg_NE
+                 ("index types of actual do not match those of formal &",
+                  Actual, Gen_T);
+               Abandon_Instantiation (Actual);
+            end if;
+
+            Next_Index (I1);
+            Next_Index (I2);
+         end loop;
+
+         if not Subtypes_Match (
+            Find_Actual_Type (Component_Type (A_Gen_T), Scope (A_Gen_T)),
+            Component_Type (Act_T))
+         then
+            Error_Msg_NE
+              ("component subtype of actual does not match that of formal &",
+               Actual, Gen_T);
+            Abandon_Instantiation (Actual);
+         end if;
+
+         if Has_Aliased_Components (A_Gen_T)
+           and then not Has_Aliased_Components (Act_T)
+         then
+            Error_Msg_NE
+              ("actual must have aliased components to match formal type &",
+               Actual, Gen_T);
+         end if;
+
+      end Validate_Array_Type_Instance;
+
+      ------------------------------------
+      -- Validate_Derived_Type_Instance --
+      ------------------------------------
+
+      procedure Validate_Derived_Type_Instance is
+         Actual_Discr   : Entity_Id;
+         Ancestor_Discr : Entity_Id;
+
+      begin
+         --  If the parent type in the generic declaration is itself
+         --  a previous formal type, then it is local to the generic
+         --  and absent from the analyzed generic definition. In  that
+         --  case the ancestor is the instance of the formal (which must
+         --  have been instantiated previously). Otherwise, the analyzed
+         --  generic carries the parent type. If the parent type is defined
+         --  in a previous formal package, then the scope of that formal
+         --  package is that of the generic type itself, and it has already
+         --  been mapped into the corresponding type in the actual package.
+
+         --  Common case: parent type defined outside of the generic.
+
+         if Is_Entity_Name (Subtype_Mark (Def))
+           and then Present (Entity (Subtype_Mark (Def)))
+         then
+            Ancestor := Get_Instance_Of (Entity (Subtype_Mark (Def)));
+
+         --  Check whether parent is defined in a previous formal package.
+
+         elsif
+           Scope (Scope (Base_Type (Etype (A_Gen_T)))) = Scope (A_Gen_T)
+         then
+            Ancestor :=
+              Get_Instance_Of (Base_Type (Etype (A_Gen_T)));
+
+         elsif Is_Derived_Type (Get_Instance_Of (A_Gen_T)) then
+            Ancestor :=
+              Get_Instance_Of (Base_Type (Get_Instance_Of (A_Gen_T)));
+
+         else
+            Ancestor := Get_Instance_Of (Etype (Base_Type (A_Gen_T)));
+         end if;
+
+         if not Is_Ancestor (Base_Type (Ancestor), Act_T) then
+            Error_Msg_NE
+              ("expect type derived from & in instantiation",
+               Actual, First_Subtype (Ancestor));
+            Abandon_Instantiation (Actual);
+         end if;
+
+         --  Perform atomic/volatile checks (RM C.6(12))
+
+         if Is_Atomic (Act_T) and then not Is_Atomic (Ancestor) then
+            Error_Msg_N
+              ("cannot have atomic actual type for non-atomic formal type",
+               Actual);
+
+         elsif Is_Volatile (Act_T)
+           and then not Is_Volatile (Ancestor)
+           and then Is_By_Reference_Type (Ancestor)
+         then
+            Error_Msg_N
+              ("cannot have volatile actual type for non-volatile formal type",
+               Actual);
+         end if;
+
+         --  It should not be necessary to check for unknown discriminants
+         --  on Formal, but for some reason Has_Unknown_Discriminants is
+         --  false for A_Gen_T, so Is_Indefinite_Subtype incorrectly
+         --  returns False. This needs fixing. ???
+
+         if not Is_Indefinite_Subtype (A_Gen_T)
+           and then not Unknown_Discriminants_Present (Formal)
+           and then Is_Indefinite_Subtype (Act_T)
+         then
+            Error_Msg_N
+              ("actual subtype must be constrained", Actual);
+            Abandon_Instantiation (Actual);
+         end if;
+
+         if not Unknown_Discriminants_Present (Formal) then
+            if Is_Constrained (Ancestor) then
+               if not Is_Constrained (Act_T) then
+                  Error_Msg_N
+                    ("actual subtype must be constrained", Actual);
+                  Abandon_Instantiation (Actual);
+               end if;
+
+            --  Ancestor is unconstrained
+
+            elsif Is_Constrained (Act_T) then
+               if Ekind (Ancestor) = E_Access_Type
+                 or else Is_Composite_Type (Ancestor)
+               then
+                  Error_Msg_N
+                    ("actual subtype must be unconstrained", Actual);
+                  Abandon_Instantiation (Actual);
+               end if;
+
+            --  A class-wide type is only allowed if the formal has
+            --  unknown discriminants.
+
+            elsif Is_Class_Wide_Type (Act_T)
+              and then not Has_Unknown_Discriminants (Ancestor)
+            then
+               Error_Msg_NE
+                 ("actual for & cannot be a class-wide type", Actual, Gen_T);
+               Abandon_Instantiation (Actual);
+
+            --  Otherwise, the formal and actual shall have the same
+            --  number of discriminants and each discriminant of the
+            --  actual must correspond to a discriminant of the formal.
+
+            elsif Has_Discriminants (Act_T)
+              and then Has_Discriminants (Ancestor)
+            then
+               Actual_Discr   := First_Discriminant (Act_T);
+               Ancestor_Discr := First_Discriminant (Ancestor);
+               while Present (Actual_Discr)
+                 and then Present (Ancestor_Discr)
+               loop
+                  if Base_Type (Act_T) /= Base_Type (Ancestor) and then
+                    not Present (Corresponding_Discriminant (Actual_Discr))
+                  then
+                     Error_Msg_NE
+                       ("discriminant & does not correspond " &
+                        "to ancestor discriminant", Actual, Actual_Discr);
+                     Abandon_Instantiation (Actual);
+                  end if;
+
+                  Next_Discriminant (Actual_Discr);
+                  Next_Discriminant (Ancestor_Discr);
+               end loop;
+
+               if Present (Actual_Discr) or else Present (Ancestor_Discr) then
+                  Error_Msg_NE
+                    ("actual for & must have same number of discriminants",
+                     Actual, Gen_T);
+                  Abandon_Instantiation (Actual);
+               end if;
+
+            --  This case should be caught by the earlier check for
+            --  for constrainedness, but the check here is added for
+            --  completeness.
+
+            elsif Has_Discriminants (Act_T) then
+               Error_Msg_NE
+                 ("actual for & must not have discriminants", Actual, Gen_T);
+               Abandon_Instantiation (Actual);
+
+            elsif Has_Discriminants (Ancestor) then
+               Error_Msg_NE
+                 ("actual for & must have known discriminants", Actual, Gen_T);
+               Abandon_Instantiation (Actual);
+            end if;
+
+            if not Subtypes_Statically_Compatible (Act_T, Ancestor) then
+               Error_Msg_N
+                 ("constraint on actual is incompatible with formal", Actual);
+               Abandon_Instantiation (Actual);
+            end if;
+         end if;
+
+      end Validate_Derived_Type_Instance;
+
+      ------------------------------------
+      -- Validate_Private_Type_Instance --
+      ------------------------------------
+
+      procedure Validate_Private_Type_Instance is
+         Formal_Discr : Entity_Id;
+         Actual_Discr : Entity_Id;
+         Formal_Subt  : Entity_Id;
+
+      begin
+         if (Is_Limited_Type (Act_T)
+              or else Is_Limited_Composite (Act_T))
+           and then not Is_Limited_Type (A_Gen_T)
+         then
+            Error_Msg_NE
+              ("actual for non-limited  & cannot be a limited type", Actual,
+               Gen_T);
+            Abandon_Instantiation (Actual);
+
+         elsif Is_Indefinite_Subtype (Act_T)
+            and then not Is_Indefinite_Subtype (A_Gen_T)
+            and then Ada_95
+         then
+            Error_Msg_NE
+              ("actual for & must be a definite subtype", Actual, Gen_T);
+
+         elsif not Is_Tagged_Type (Act_T)
+           and then Is_Tagged_Type (A_Gen_T)
+         then
+            Error_Msg_NE
+              ("actual for & must be a tagged type", Actual, Gen_T);
+
+         elsif Has_Discriminants (A_Gen_T) then
+            if not Has_Discriminants (Act_T) then
+               Error_Msg_NE
+                 ("actual for & must have discriminants", Actual, Gen_T);
+               Abandon_Instantiation (Actual);
+
+            elsif Is_Constrained (Act_T) then
+               Error_Msg_NE
+                 ("actual for & must be unconstrained", Actual, Gen_T);
+               Abandon_Instantiation (Actual);
+
+            else
+               Formal_Discr := First_Discriminant (A_Gen_T);
+               Actual_Discr := First_Discriminant (Act_T);
+               while Formal_Discr /= Empty loop
+                  if Actual_Discr = Empty then
+                     Error_Msg_NE
+                       ("discriminants on actual do not match formal",
+                        Actual, Gen_T);
+                     Abandon_Instantiation (Actual);
+                  end if;
+
+                  Formal_Subt := Get_Instance_Of (Etype (Formal_Discr));
+
+                  --  access discriminants match if designated types do.
+
+                  if Ekind (Base_Type (Formal_Subt)) = E_Anonymous_Access_Type
+                    and then (Ekind (Base_Type (Etype (Actual_Discr))))
+                      = E_Anonymous_Access_Type
+                    and then Get_Instance_Of (
+                      Designated_Type (Base_Type (Formal_Subt)))
+                      = Designated_Type (Base_Type (Etype (Actual_Discr)))
+                  then
+                     null;
+
+                  elsif Base_Type (Formal_Subt) /=
+                                       Base_Type (Etype (Actual_Discr))
+                  then
+                     Error_Msg_NE
+                       ("types of actual discriminants must match formal",
+                        Actual, Gen_T);
+                     Abandon_Instantiation (Actual);
+
+                  elsif not Subtypes_Statically_Match
+                              (Formal_Subt, Etype (Actual_Discr))
+                    and then Ada_95
+                  then
+                     Error_Msg_NE
+                       ("subtypes of actual discriminants must match formal",
+                        Actual, Gen_T);
+                     Abandon_Instantiation (Actual);
+                  end if;
+
+                  Next_Discriminant (Formal_Discr);
+                  Next_Discriminant (Actual_Discr);
+               end loop;
+
+               if Actual_Discr /= Empty then
+                  Error_Msg_NE
+                    ("discriminants on actual do not match formal",
+                     Actual, Gen_T);
+                  Abandon_Instantiation (Actual);
+               end if;
+            end if;
+
+         end if;
+
+         Ancestor := Gen_T;
+      end Validate_Private_Type_Instance;
+
+   --  Start of processing for Instantiate_Type
+
+   begin
+      if Get_Instance_Of (A_Gen_T) /= A_Gen_T then
+         Error_Msg_N ("duplicate instantiation of generic type", Actual);
+         return Error;
+
+      elsif not Is_Entity_Name (Actual)
+        or else not Is_Type (Entity (Actual))
+      then
+         Error_Msg_NE
+           ("expect valid subtype mark to instantiate &", Actual, Gen_T);
+         Abandon_Instantiation (Actual);
+
+      else
+         Act_T := Entity (Actual);
+
+         if Ekind (Act_T) = E_Incomplete_Type then
+            if No (Underlying_Type (Act_T)) then
+               Error_Msg_N ("premature use of incomplete type", Actual);
+               Abandon_Instantiation (Actual);
+            else
+               Act_T := Full_View (Act_T);
+               Set_Entity (Actual, Act_T);
+
+               if Has_Private_Component (Act_T) then
+                  Error_Msg_N
+                    ("premature use of type with private component", Actual);
+               end if;
+            end if;
+
+         elsif Is_Private_Type (Act_T)
+           and then Is_Private_Type (Base_Type (Act_T))
+           and then not Is_Generic_Type (Act_T)
+           and then not Is_Derived_Type (Act_T)
+           and then No (Full_View (Root_Type (Act_T)))
+         then
+            Error_Msg_N ("premature use of private type", Actual);
+
+         elsif Has_Private_Component (Act_T) then
+            Error_Msg_N
+              ("premature use of type with private component", Actual);
+         end if;
+
+         Set_Instance_Of (A_Gen_T, Act_T);
+
+         --  If the type is generic, the class-wide type may also be used
+
+         if Is_Tagged_Type (A_Gen_T)
+           and then Is_Tagged_Type (Act_T)
+           and then not Is_Class_Wide_Type (A_Gen_T)
+         then
+            Set_Instance_Of (Class_Wide_Type (A_Gen_T),
+              Class_Wide_Type (Act_T));
+         end if;
+
+         if not Is_Abstract (A_Gen_T)
+           and then Is_Abstract (Act_T)
+         then
+            Error_Msg_N
+              ("actual of non-abstract formal cannot be abstract", Actual);
+         end if;
+
+         if Is_Scalar_Type (Gen_T) then
+            Set_Instance_Of (Etype (A_Gen_T), Etype (Act_T));
+         end if;
+      end if;
+
+      case Nkind (Def) is
+         when N_Formal_Private_Type_Definition =>
+            Validate_Private_Type_Instance;
+
+         when N_Formal_Derived_Type_Definition =>
+            Validate_Derived_Type_Instance;
+
+         when N_Formal_Discrete_Type_Definition =>
+            if not Is_Discrete_Type (Act_T) then
+               Error_Msg_NE
+                 ("expect discrete type in instantiation of&", Actual, Gen_T);
+               Abandon_Instantiation (Actual);
+            end if;
+
+         when N_Formal_Signed_Integer_Type_Definition =>
+            if not Is_Signed_Integer_Type (Act_T) then
+               Error_Msg_NE
+                 ("expect signed integer type in instantiation of&",
+                  Actual, Gen_T);
+               Abandon_Instantiation (Actual);
+            end if;
+
+         when N_Formal_Modular_Type_Definition =>
+            if not Is_Modular_Integer_Type (Act_T) then
+               Error_Msg_NE
+                 ("expect modular type in instantiation of &", Actual, Gen_T);
+               Abandon_Instantiation (Actual);
+            end if;
+
+         when N_Formal_Floating_Point_Definition =>
+            if not Is_Floating_Point_Type (Act_T) then
+               Error_Msg_NE
+                 ("expect float type in instantiation of &", Actual, Gen_T);
+               Abandon_Instantiation (Actual);
+            end if;
+
+         when N_Formal_Ordinary_Fixed_Point_Definition =>
+            if not Is_Ordinary_Fixed_Point_Type (Act_T) then
+               Error_Msg_NE
+                 ("expect ordinary fixed point type in instantiation of &",
+                  Actual, Gen_T);
+               Abandon_Instantiation (Actual);
+            end if;
+
+         when N_Formal_Decimal_Fixed_Point_Definition =>
+            if not Is_Decimal_Fixed_Point_Type (Act_T) then
+               Error_Msg_NE
+                 ("expect decimal type in instantiation of &",
+                  Actual, Gen_T);
+               Abandon_Instantiation (Actual);
+            end if;
+
+         when N_Array_Type_Definition =>
+            Validate_Array_Type_Instance;
+
+         when N_Access_To_Object_Definition =>
+            Validate_Access_Type_Instance;
+
+         when N_Access_Function_Definition |
+              N_Access_Procedure_Definition =>
+            Validate_Access_Subprogram_Instance;
+
+         when others =>
+            raise Program_Error;
+
+      end case;
+
+      Decl_Node :=
+        Make_Subtype_Declaration (Loc,
+          Defining_Identifier => New_Copy (Gen_T),
+          Subtype_Indication  => New_Reference_To (Act_T, Loc));
+
+      if Is_Private_Type (Act_T) then
+         Set_Has_Private_View (Subtype_Indication (Decl_Node));
+      end if;
+
+      --  Flag actual derived types so their elaboration produces the
+      --  appropriate renamings for the primitive operations of the ancestor.
+      --  Flag actual for formal private types as well, to determine whether
+      --  operations in the private part may override inherited operations.
+
+      if Nkind (Def) = N_Formal_Derived_Type_Definition
+        or else Nkind (Def) = N_Formal_Private_Type_Definition
+      then
+         Set_Generic_Parent_Type (Decl_Node, Ancestor);
+      end if;
+
+      return Decl_Node;
+   end Instantiate_Type;
+
+   ---------------------
+   -- Is_In_Main_Unit --
+   ---------------------
+
+   function Is_In_Main_Unit (N : Node_Id) return Boolean is
+      Unum : constant Unit_Number_Type := Get_Source_Unit (N);
+
+      Current_Unit : Node_Id;
+
+   begin
+      if Unum = Main_Unit then
+         return True;
+
+      --  If the current unit is a subunit then it is either the main unit
+      --  or is being compiled as part of the main unit.
+
+      elsif Nkind (N) = N_Compilation_Unit then
+         return Nkind (Unit (N)) = N_Subunit;
+      end if;
+
+      Current_Unit := Parent (N);
+      while Present (Current_Unit)
+        and then Nkind (Current_Unit) /= N_Compilation_Unit
+      loop
+         Current_Unit := Parent (Current_Unit);
+      end loop;
+
+      --  The instantiation node is in the main unit, or else the current
+      --  node (perhaps as the result of nested instantiations) is in the
+      --  main unit, or in the declaration of the main unit, which in this
+      --  last case must be a body.
+
+      return Unum = Main_Unit
+        or else Current_Unit = Cunit (Main_Unit)
+        or else Current_Unit = Library_Unit (Cunit (Main_Unit))
+        or else (Present (Library_Unit (Current_Unit))
+                  and then Is_In_Main_Unit (Library_Unit (Current_Unit)));
+   end Is_In_Main_Unit;
+
+   ----------------------------
+   -- Load_Parent_Of_Generic --
+   ----------------------------
+
+   procedure Load_Parent_Of_Generic (N : Node_Id; Spec : Node_Id) is
+      Comp_Unit        : constant Node_Id := Cunit (Get_Source_Unit (Spec));
+      True_Parent      : Node_Id;
+      Inst_Node        : Node_Id;
+      OK               : Boolean;
+      Save_Style_Check : Boolean := Style_Check;
+
+   begin
+      if not In_Same_Source_Unit (N, Spec)
+        or else Nkind (Unit (Comp_Unit)) = N_Package_Declaration
+        or else (Nkind (Unit (Comp_Unit)) = N_Package_Body
+                   and then not Is_In_Main_Unit (Spec))
+      then
+         --  Find body of parent of spec, and analyze it. A special case
+         --  arises when the parent is an instantiation, that is to say when
+         --  we are currently instantiating a nested generic. In that case,
+         --  there is no separate file for the body of the enclosing instance.
+         --  Instead, the enclosing body must be instantiated as if it were
+         --  a pending instantiation, in order to produce the body for the
+         --  nested generic we require now. Note that in that case the
+         --  generic may be defined in a package body, the instance defined
+         --  in the same package body, and the original enclosing body may not
+         --  be in the main unit.
+
+         True_Parent := Parent (Spec);
+         Inst_Node   := Empty;
+
+         while Present (True_Parent)
+           and then Nkind (True_Parent) /= N_Compilation_Unit
+         loop
+            if Nkind (True_Parent) = N_Package_Declaration
+              and then
+                Nkind (Original_Node (True_Parent)) = N_Package_Instantiation
+            then
+               --  Parent is a compilation unit that is an instantiation.
+               --  Instantiation node has been replaced with package decl.
+
+               Inst_Node := Original_Node (True_Parent);
+               exit;
+
+            elsif Nkind (True_Parent) = N_Package_Declaration
+              and then Present (Generic_Parent (Specification (True_Parent)))
+            then
+               --  Parent is an instantiation within another specification.
+               --  Declaration for instance has been inserted before original
+               --  instantiation node. A direct link would be preferable?
+
+               Inst_Node := Next (True_Parent);
+
+               while Present (Inst_Node)
+                 and then Nkind (Inst_Node) /= N_Package_Instantiation
+               loop
+                  Next (Inst_Node);
+               end loop;
+
+               --  If the instance appears within a generic, and the generic
+               --  unit is defined within a formal package of the enclosing
+               --  generic, there is no generic body available, and none
+               --  needed. A more precise test should be used ???
+
+               if No (Inst_Node) then
+                  return;
+               end if;
+
+               exit;
+            else
+               True_Parent := Parent (True_Parent);
+            end if;
+         end loop;
+
+         if Present (Inst_Node) then
+
+            if Nkind (Parent (True_Parent)) = N_Compilation_Unit then
+
+               --  Instantiation node and declaration of instantiated package
+               --  were exchanged when only the declaration was needed.
+               --  Restore instantiation node before proceeding with body.
+
+               Set_Unit (Parent (True_Parent), Inst_Node);
+            end if;
+
+            --  Now complete instantiation of enclosing body, if it appears
+            --  in some other unit. If it appears in the current unit, the
+            --  body will have been instantiated already.
+
+            if No (Corresponding_Body (Instance_Spec (Inst_Node))) then
+               Instantiate_Package_Body
+                 (Pending_Body_Info'(
+                    Inst_Node, True_Parent, Expander_Active,
+                      Get_Code_Unit (Sloc (Inst_Node))));
+            end if;
+
+         else
+            Opt.Style_Check := False;
+            Load_Needed_Body (Comp_Unit, OK);
+            Opt.Style_Check := Save_Style_Check;
+
+            if not OK
+              and then Unit_Requires_Body (Defining_Entity (Spec))
+            then
+               declare
+                  Bname : constant Unit_Name_Type :=
+                            Get_Body_Name (Get_Unit_Name (Unit (Comp_Unit)));
+
+               begin
+                  Error_Msg_Unit_1 := Bname;
+                  Error_Msg_N ("this instantiation requires$!", N);
+                  Error_Msg_Name_1 :=
+                    Get_File_Name (Bname, Subunit => False);
+                  Error_Msg_N ("\but file{ was not found!", N);
+                  raise Unrecoverable_Error;
+               end;
+            end if;
+         end if;
+      end if;
+
+      --  If loading the parent of the generic caused an instantiation
+      --  circularity, we abandon compilation at this point, because
+      --  otherwise in some cases we get into trouble with infinite
+      --  recursions after this point.
+
+      if Circularity_Detected then
+         raise Unrecoverable_Error;
+      end if;
+
+   end Load_Parent_Of_Generic;
+
+   -----------------------
+   -- Move_Freeze_Nodes --
+   -----------------------
+
+   procedure Move_Freeze_Nodes
+     (Out_Of : Entity_Id;
+      After  : Node_Id;
+      L      : List_Id)
+   is
+      Decl      : Node_Id;
+      Next_Decl : Node_Id;
+      Next_Node : Node_Id := After;
+      Spec      : Node_Id;
+
+      function Is_Outer_Type (T : Entity_Id) return Boolean;
+      --  Check whether entity is declared in a scope external to that
+      --  of the generic unit.
+
+      -------------------
+      -- Is_Outer_Type --
+      -------------------
+
+      function Is_Outer_Type (T : Entity_Id) return Boolean is
+         Scop : Entity_Id := Scope (T);
+
+      begin
+         if Scope_Depth (Scop) < Scope_Depth (Out_Of) then
+            return True;
+
+         else
+            while Scop /= Standard_Standard loop
+
+               if Scop = Out_Of then
+                  return False;
+               else
+                  Scop := Scope (Scop);
+               end if;
+            end loop;
+
+            return True;
+         end if;
+      end Is_Outer_Type;
+
+   --  Start of processing for Move_Freeze_Nodes
+
+   begin
+      if No (L) then
+         return;
+      end if;
+
+      --  First remove the freeze nodes that may appear before all other
+      --  declarations.
+
+      Decl := First (L);
+      while Present (Decl)
+        and then Nkind (Decl) = N_Freeze_Entity
+        and then Is_Outer_Type (Entity (Decl))
+      loop
+         Decl := Remove_Head (L);
+         Insert_After (Next_Node, Decl);
+         Set_Analyzed (Decl, False);
+         Next_Node := Decl;
+         Decl := First (L);
+      end loop;
+
+      --  Next scan the list of declarations and remove each freeze node that
+      --  appears ahead of the current node.
+
+      while Present (Decl) loop
+         while Present (Next (Decl))
+           and then Nkind (Next (Decl)) = N_Freeze_Entity
+           and then Is_Outer_Type (Entity (Next (Decl)))
+         loop
+            Next_Decl := Remove_Next (Decl);
+            Insert_After (Next_Node, Next_Decl);
+            Set_Analyzed (Next_Decl, False);
+            Next_Node := Next_Decl;
+         end loop;
+
+         --  If the declaration is a nested package or concurrent type, then
+         --  recurse. Nested generic packages will have been processed from the
+         --  inside out.
+
+         if Nkind (Decl) = N_Package_Declaration then
+            Spec := Specification (Decl);
+
+         elsif Nkind (Decl) = N_Task_Type_Declaration then
+            Spec := Task_Definition (Decl);
+
+         elsif Nkind (Decl) = N_Protected_Type_Declaration then
+            Spec := Protected_Definition (Decl);
+
+         else
+            Spec := Empty;
+         end if;
+
+         if Present (Spec) then
+            Move_Freeze_Nodes (Out_Of, Next_Node,
+              Visible_Declarations (Spec));
+            Move_Freeze_Nodes (Out_Of, Next_Node,
+              Private_Declarations (Spec));
+         end if;
+
+         Next (Decl);
+      end loop;
+   end Move_Freeze_Nodes;
+
+   ----------------
+   -- Next_Assoc --
+   ----------------
+
+   function Next_Assoc (E : Assoc_Ptr) return Assoc_Ptr is
+   begin
+      return Generic_Renamings.Table (E).Next_In_HTable;
+   end Next_Assoc;
+
+   ------------------------
+   -- Preanalyze_Actuals --
+   ------------------------
+
+   procedure Pre_Analyze_Actuals (N : Node_Id) is
+      Assoc : Node_Id;
+      Act   : Node_Id;
+      Errs  : Int := Errors_Detected;
+
+   begin
+      Assoc := First (Generic_Associations (N));
+
+      while Present (Assoc) loop
+         Act := Explicit_Generic_Actual_Parameter (Assoc);
+
+         --  Within a nested instantiation, a defaulted actual is an
+         --  empty association, so nothing to analyze. If the actual for
+         --  a subprogram is an attribute, analyze prefix only, because
+         --  actual is not a complete attribute reference.
+         --  String literals may be operators, but at this point we do not
+         --  know whether the actual is a formal subprogram or a string.
+
+         if No (Act) then
+            null;
+
+         elsif Nkind (Act) = N_Attribute_Reference then
+            Analyze (Prefix (Act));
+
+         elsif Nkind (Act) = N_Explicit_Dereference then
+            Analyze (Prefix (Act));
+
+         elsif Nkind (Act) /= N_Operator_Symbol then
+            Analyze (Act);
+         end if;
+
+         if Errs /= Errors_Detected then
+            Abandon_Instantiation (Act);
+         end if;
+
+         Next (Assoc);
+      end loop;
+   end Pre_Analyze_Actuals;
+
+   -------------------
+   -- Remove_Parent --
+   -------------------
+
+   procedure Remove_Parent (In_Body : Boolean := False) is
+      S      : Entity_Id := Current_Scope;
+      E      : Entity_Id;
+      P      : Entity_Id;
+      Hidden : Elmt_Id;
+
+   begin
+      --  After child instantiation is complete, remove from scope stack
+      --  the extra copy of the current scope, and then remove parent
+      --  instances.
+
+      if not In_Body then
+         Pop_Scope;
+
+         while Current_Scope /= S loop
+            P := Current_Scope;
+            End_Package_Scope (Current_Scope);
+
+            if In_Open_Scopes (P) then
+               E := First_Entity (P);
+
+               while Present (E) loop
+                  Set_Is_Immediately_Visible (E, True);
+                  Next_Entity (E);
+               end loop;
+
+            elsif not In_Open_Scopes (Scope (P)) then
+               Set_Is_Immediately_Visible (P, False);
+            end if;
+         end loop;
+
+         --  Reset visibility of entities in the enclosing scope.
+
+         Set_Is_Hidden_Open_Scope (Current_Scope, False);
+         Hidden := First_Elmt (Hidden_Entities);
+
+         while Present (Hidden) loop
+            Set_Is_Immediately_Visible (Node (Hidden), True);
+            Next_Elmt (Hidden);
+         end loop;
+
+      else
+         --  Each body is analyzed separately, and there is no context
+         --  that needs preserving from one body instance to the next,
+         --  so remove all parent scopes that have been installed.
+
+         while Present (S) loop
+            End_Package_Scope (S);
+            S := Current_Scope;
+            exit when S = Standard_Standard;
+         end loop;
+      end if;
+
+   end Remove_Parent;
+
+   -----------------
+   -- Restore_Env --
+   -----------------
+
+   procedure Restore_Env is
+      Saved : Instance_Env renames Instance_Envs.Table (Instance_Envs.Last);
+
+   begin
+      Ada_83                       := Saved.Ada_83;
+
+      if No (Current_Instantiated_Parent.Act_Id) then
+
+         --  Restore environment after subprogram inlining
+
+         Restore_Private_Views (Empty);
+      end if;
+
+      Current_Instantiated_Parent  := Saved.Instantiated_Parent;
+      Exchanged_Views              := Saved.Exchanged_Views;
+      Hidden_Entities              := Saved.Hidden_Entities;
+      Current_Sem_Unit             := Saved.Current_Sem_Unit;
+
+      Instance_Envs.Decrement_Last;
+   end Restore_Env;
+
+   ---------------------------
+   -- Restore_Private_Views --
+   ---------------------------
+
+   procedure Restore_Private_Views
+     (Pack_Id    : Entity_Id;
+      Is_Package : Boolean := True)
+   is
+      M        : Elmt_Id;
+      E        : Entity_Id;
+      Typ      : Entity_Id;
+      Dep_Elmt : Elmt_Id;
+      Dep_Typ  : Node_Id;
+
+   begin
+      M := First_Elmt (Exchanged_Views);
+      while Present (M) loop
+         Typ := Node (M);
+
+         --  Subtypes of types whose views have been exchanged, and that
+         --  are defined within the instance, were not on the list of
+         --  Private_Dependents on entry to the instance, so they have to
+         --  be exchanged explicitly now, in order to remain consistent with
+         --  the view of the parent type.
+
+         if Ekind (Typ) = E_Private_Type
+           or else Ekind (Typ) = E_Limited_Private_Type
+           or else Ekind (Typ) = E_Record_Type_With_Private
+         then
+            Dep_Elmt := First_Elmt (Private_Dependents (Typ));
+
+            while Present (Dep_Elmt) loop
+               Dep_Typ := Node (Dep_Elmt);
+
+               if Scope (Dep_Typ) = Pack_Id
+                 and then Present (Full_View (Dep_Typ))
+               then
+                  Replace_Elmt (Dep_Elmt, Full_View (Dep_Typ));
+                  Exchange_Declarations (Dep_Typ);
+               end if;
+
+               Next_Elmt (Dep_Elmt);
+            end loop;
+         end if;
+
+         Exchange_Declarations (Node (M));
+         Next_Elmt (M);
+      end loop;
+
+      if No (Pack_Id) then
+         return;
+      end if;
+
+      --  Make the generic formal parameters private, and make the formal
+      --  types into subtypes of the actuals again.
+
+      E := First_Entity (Pack_Id);
+
+      while Present (E) loop
+         Set_Is_Hidden (E, True);
+
+         if Is_Type (E)
+           and then Nkind (Parent (E)) = N_Subtype_Declaration
+         then
+            Set_Is_Generic_Actual_Type (E, False);
+
+            --  An unusual case of aliasing: the actual may also be directly
+            --  visible in the generic, and be private there, while it is
+            --  fully visible in the context of the instance. The internal
+            --  subtype is private in the instance, but has full visibility
+            --  like its parent in the enclosing scope. This enforces the
+            --  invariant that the privacy status of all private dependents of
+            --  a type coincide with that of the parent type. This can only
+            --  happen when a generic child unit is instantiated within a
+            --  sibling.
+
+            if Is_Private_Type (E)
+              and then not Is_Private_Type (Etype (E))
+            then
+               Exchange_Declarations (E);
+            end if;
+
+         elsif Ekind (E) = E_Package then
+
+            --  The end of the renaming list is the renaming of the generic
+            --  package itself. If the instance is a subprogram, all entities
+            --  in the corresponding package are renamings. If this entity is
+            --  a formal package, make its own formals private as well. The
+            --  actual in this case is itself the renaming of an instantation.
+            --  If the entity is not a package renaming, it is the entity
+            --  created to validate formal package actuals: ignore.
+
+            --  If the actual is itself a formal package for the enclosing
+            --  generic, or the actual for such a formal package, it remains
+            --  visible after the current instance, and therefore nothing
+            --  needs to be done either, except to keep it accessible.
+
+            if Is_Package
+              and then Renamed_Object (E) = Pack_Id
+            then
+               exit;
+
+            elsif Nkind (Parent (E)) /= N_Package_Renaming_Declaration then
+               null;
+
+            elsif Denotes_Formal_Package (Renamed_Object (E)) then
+               Set_Is_Hidden (E, False);
+
+            else
+               declare
+                  Act_P : Entity_Id := Renamed_Object (E);
+                  Id    : Entity_Id := First_Entity (Act_P);
+
+               begin
+                  while Present (Id)
+                    and then Id /= First_Private_Entity (Act_P)
+                  loop
+                     Set_Is_Hidden (Id, True);
+                     Set_Is_Potentially_Use_Visible (Id, In_Use (Act_P));
+                     exit when Ekind (Id) = E_Package
+                                 and then Renamed_Object (Id) = Act_P;
+
+                     Next_Entity (Id);
+                  end loop;
+               end;
+               null;
+            end if;
+         end if;
+
+         Next_Entity (E);
+      end loop;
+   end Restore_Private_Views;
+
+   --------------
+   -- Save_Env --
+   --------------
+
+   procedure Save_Env
+     (Gen_Unit : Entity_Id;
+      Act_Unit : Entity_Id)
+   is
+      Saved : Instance_Env;
+
+   begin
+      Saved.Ada_83              := Ada_83;
+      Saved.Instantiated_Parent := Current_Instantiated_Parent;
+      Saved.Exchanged_Views     := Exchanged_Views;
+      Saved.Hidden_Entities     := Hidden_Entities;
+      Saved.Current_Sem_Unit    := Current_Sem_Unit;
+      Instance_Envs.Increment_Last;
+      Instance_Envs.Table (Instance_Envs.Last) := Saved;
+
+      --  Regardless of the current mode, predefined units are analyzed in
+      --  Ada95 mode, and Ada83 checks don't apply.
+
+      if Is_Internal_File_Name
+          (Fname => Unit_File_Name (Get_Source_Unit (Gen_Unit)),
+           Renamings_Included => True) then
+         Ada_83 := False;
+      end if;
+
+      Current_Instantiated_Parent := (Gen_Unit, Act_Unit, Assoc_Null);
+      Exchanged_Views := New_Elmt_List;
+      Hidden_Entities := New_Elmt_List;
+   end Save_Env;
+
+   ----------------------------
+   -- Save_Global_References --
+   ----------------------------
+
+   procedure Save_Global_References (N : Node_Id) is
+      Gen_Scope : Entity_Id;
+      E         : Entity_Id;
+      N2        : Node_Id;
+
+      function Is_Global (E : Entity_Id) return Boolean;
+      --  Check whether entity is defined outside of generic unit.
+      --  Examine the scope of an entity, and the scope of the scope,
+      --  etc, until we find either Standard, in which case the entity
+      --  is global, or the generic unit itself, which indicates that
+      --  the entity is local. If the entity is the generic unit itself,
+      --  as in the case of a recursive call, or the enclosing generic unit,
+      --  if different from the current scope, then it is local as well,
+      --  because it will be replaced at the point of instantiation. On
+      --  the other hand, if it is a reference to a child unit of a common
+      --  ancestor, which appears in an instantiation, it is global because
+      --  it is used to denote a specific compilation unit at the time the
+      --  instantiations will be analyzed.
+
+      procedure Reset_Entity (N : Node_Id);
+      --  Save semantic information on global entity, so that it is not
+      --  resolved again at instantiation time.
+
+      procedure Save_Global_Defaults (N1, N2 : Node_Id);
+      --  Default actuals in nested instances must be handled specially
+      --  because there is no link to them from the original tree. When an
+      --  actual subprogram is given by a default, we add an explicit generic
+      --  association for it in the instantiation node. When we save the
+      --  global references on the name of the instance, we recover the list
+      --  of generic associations, and add an explicit one to the original
+      --  generic tree, through which a global actual can be preserved.
+      --  Similarly, if a child unit is instantiated within a sibling, in the
+      --  context of the parent, we must preserve the identifier of the parent
+      --  so that it can be properly resolved in a subsequent instantiation.
+
+      procedure Save_Global_Descendant (D : Union_Id);
+      --  Apply Save_Global_References recursively to the descendents of
+      --  current node.
+
+      procedure Save_References (N : Node_Id);
+      --  This is the recursive procedure that does the work, once the
+      --  enclosing generic scope has been established.
+
+      ---------------
+      -- Is_Global --
+      ---------------
+
+      function Is_Global (E : Entity_Id) return Boolean is
+         Se  : Entity_Id := Scope (E);
+
+         function Is_Instance_Node (Decl : Node_Id) return Boolean;
+         --  Determine whether the parent node of a reference to a child unit
+         --  denotes an instantiation or a formal package, in which case the
+         --  reference to the child unit is global, even if it appears within
+         --  the current scope (e.g. when the instance appears within the body
+         --  of an ancestor).
+
+         function Is_Instance_Node (Decl : Node_Id) return Boolean is
+         begin
+            return (Nkind (Decl) in N_Generic_Instantiation
+              or else
+                Nkind (Original_Node (Decl)) = N_Formal_Package_Declaration);
+         end Is_Instance_Node;
+
+      --  Start of processing for Is_Global
+
+      begin
+         if E = Gen_Scope then
+            return False;
+
+         elsif E = Standard_Standard then
+            return True;
+
+         elsif Is_Child_Unit (E)
+           and then (Is_Instance_Node (Parent (N2))
+             or else (Nkind (Parent (N2)) = N_Expanded_Name
+                       and then N2 = Selector_Name (Parent (N2))
+                       and then Is_Instance_Node (Parent (Parent (N2)))))
+         then
+            return True;
+
+         else
+            while Se /= Gen_Scope loop
+               if Se = Standard_Standard then
+                  return True;
+               else
+                  Se := Scope (Se);
+               end if;
+            end loop;
+
+            return False;
+         end if;
+      end Is_Global;
+
+      ------------------
+      -- Reset_Entity --
+      ------------------
+
+      procedure Reset_Entity (N : Node_Id) is
+
+         procedure Set_Global_Type (N : Node_Id; N2 : Node_Id);
+         --  The type of N2 is global to the generic unit. Save the
+         --  type in the generic node.
+
+         procedure Set_Global_Type (N : Node_Id; N2 : Node_Id) is
+            Typ : constant Entity_Id := Etype (N2);
+
+         begin
+            Set_Etype (N, Typ);
+
+            if Entity (N) /= N2
+              and then Has_Private_View (Entity (N))
+            then
+               --  If the entity of N is not the associated node, this is
+               --  a nested generic and it has an associated node as well,
+               --  whose type is already the full view (see below). Indicate
+               --  that the original node has a private view.
+
+               Set_Has_Private_View (N);
+            end if;
+
+            --  If not a private type, nothing else to do
+
+            if not Is_Private_Type (Typ) then
+               if Is_Array_Type (Typ)
+                 and then Is_Private_Type (Component_Type (Typ))
+               then
+                  Set_Has_Private_View (N);
+               end if;
+
+            --  If it is a derivation of a private type in a context where
+            --  no full view is needed, nothing to do either.
+
+            elsif No (Full_View (Typ)) and then Typ /= Etype (Typ) then
+               null;
+
+            --  Otherwise mark the type for flipping and use the full_view
+            --  when available.
+
+            else
+               Set_Has_Private_View (N);
+
+               if Present (Full_View (Typ)) then
+                  Set_Etype (N2, Full_View (Typ));
+               end if;
+            end if;
+         end Set_Global_Type;
+
+      --  Start of processing for Reset_Entity
+
+      begin
+         N2 := Associated_Node (N);
+         E := Entity (N2);
+
+         if Present (E) then
+            if Is_Global (E) then
+               Set_Global_Type (N, N2);
+
+            elsif Nkind (N) = N_Op_Concat
+              and then Is_Generic_Type (Etype (N2))
+              and then
+               (Base_Type (Etype (Right_Opnd (N2))) = Etype (N2)
+                  or else Base_Type (Etype (Left_Opnd (N2))) = Etype (N2))
+              and then Is_Intrinsic_Subprogram (E)
+            then
+               null;
+
+            else
+               --  Entity is local. Mark generic node as unresolved.
+               --  Note that now it does not have an entity.
+
+               Set_Associated_Node (N, Empty);
+               Set_Etype  (N, Empty);
+            end if;
+
+            if (Nkind (Parent (N)) = N_Package_Instantiation
+                 or else Nkind (Parent (N)) = N_Function_Instantiation
+                 or else Nkind (Parent (N)) = N_Procedure_Instantiation)
+              and then N = Name (Parent (N))
+            then
+               Save_Global_Defaults (Parent (N), Parent (N2));
+            end if;
+
+         elsif Nkind (Parent (N)) = N_Selected_Component
+           and then Nkind (Parent (N2)) = N_Expanded_Name
+         then
+
+            if Is_Global (Entity (Parent (N2))) then
+               Change_Selected_Component_To_Expanded_Name (Parent (N));
+               Set_Associated_Node (Parent (N), Parent (N2));
+               Set_Global_Type (Parent (N), Parent (N2));
+
+               Save_Global_Descendant (Field2 (N));
+               Save_Global_Descendant (Field3 (N));
+
+               --  If this is a reference to the current generic entity,
+               --  replace it with a simple name. This is to avoid anomalies
+               --  when the enclosing scope is also a generic unit, in which
+               --  case the selected component will not resolve to the current
+               --  unit within an instance of the outer one. Ditto if the
+               --  entity is an enclosing scope, e.g. a parent unit.
+
+            elsif In_Open_Scopes (Entity (Parent (N2)))
+              and then not Is_Generic_Unit (Entity (Prefix (Parent (N2))))
+            then
+               Rewrite (Parent (N),
+                 Make_Identifier (Sloc (N),
+                   Chars => Chars (Selector_Name (Parent (N2)))));
+            end if;
+
+            if (Nkind (Parent (Parent (N))) = N_Package_Instantiation
+                 or else Nkind (Parent (Parent (N)))
+                   = N_Function_Instantiation
+                 or else Nkind (Parent (Parent (N)))
+                   = N_Procedure_Instantiation)
+              and then Parent (N) = Name (Parent (Parent (N)))
+            then
+               Save_Global_Defaults
+                 (Parent (Parent (N)), Parent (Parent ((N2))));
+            end if;
+
+         --  A selected component may denote a static constant that has
+         --  been folded. Make the same replacement in original tree.
+
+         elsif Nkind (Parent (N)) = N_Selected_Component
+           and then (Nkind (Parent (N2)) = N_Integer_Literal
+                      or else Nkind (Parent (N2)) = N_Real_Literal)
+         then
+            Rewrite (Parent (N),
+              New_Copy (Parent (N2)));
+            Set_Analyzed (Parent (N), False);
+
+         --  a selected component may be transformed into a parameterless
+         --  function call. If the called entity is global, rewrite the
+         --  node appropriately, i.e. as an extended name for the global
+         --  entity.
+
+         elsif Nkind (Parent (N)) = N_Selected_Component
+           and then Nkind (Parent (N2)) = N_Function_Call
+           and then Is_Global (Entity (Name (Parent (N2))))
+         then
+            Change_Selected_Component_To_Expanded_Name (Parent (N));
+            Set_Associated_Node (Parent (N), Name (Parent (N2)));
+            Set_Global_Type (Parent (N), Name (Parent (N2)));
+
+            Save_Global_Descendant (Field2 (N));
+            Save_Global_Descendant (Field3 (N));
+
+         else
+            --  Entity is local. Reset in generic unit, so that node
+            --  is resolved anew at the point of instantiation.
+
+            Set_Associated_Node (N, Empty);
+            Set_Etype (N, Empty);
+         end if;
+      end Reset_Entity;
+
+      --------------------------
+      -- Save_Global_Defaults --
+      --------------------------
+
+      procedure Save_Global_Defaults (N1, N2 : Node_Id) is
+         Loc    : constant Source_Ptr := Sloc (N1);
+         Assoc1 : List_Id := Generic_Associations (N1);
+         Assoc2 : List_Id := Generic_Associations (N2);
+         Act1   : Node_Id;
+         Act2   : Node_Id;
+         Def    : Node_Id;
+         Gen_Id : Entity_Id := Entity (Name (N2));
+         Ndec   : Node_Id;
+         Subp   : Entity_Id;
+         Actual : Entity_Id;
+
+      begin
+         if Present (Assoc1) then
+            Act1 := First (Assoc1);
+         else
+            Act1 := Empty;
+            Set_Generic_Associations (N1, New_List);
+            Assoc1 := Generic_Associations (N1);
+         end if;
+
+         if Present (Assoc2) then
+            Act2 := First (Assoc2);
+         else
+            return;
+         end if;
+
+         while Present (Act1) and then Present (Act2) loop
+            Next (Act1);
+            Next (Act2);
+         end loop;
+
+         --  Find the associations added for default suprograms.
+
+         if Present (Act2) then
+            while Nkind (Act2) /= N_Generic_Association
+              or else No (Entity (Selector_Name (Act2)))
+              or else not Is_Overloadable (Entity (Selector_Name (Act2)))
+            loop
+               Next (Act2);
+            end loop;
+
+            --  Add a similar association if the default is global. The
+            --  renaming declaration for the actual has been analyzed, and
+            --  its alias is the program it renames. Link the actual in the
+            --  original generic tree with the node in the analyzed tree.
+
+            while Present (Act2) loop
+               Subp := Entity (Selector_Name (Act2));
+               Def  := Explicit_Generic_Actual_Parameter (Act2);
+
+               --  Following test is defence against rubbish errors
+
+               if No (Alias (Subp)) then
+                  return;
+               end if;
+
+               --  Retrieve the resolved actual from the renaming declaration
+               --  created for the instantiated formal.
+
+               Actual := Entity (Name (Parent (Parent (Subp))));
+               Set_Entity (Def, Actual);
+               Set_Etype (Def, Etype (Actual));
+
+               if Is_Global (Actual) then
+                  Ndec :=
+                    Make_Generic_Association (Loc,
+                      Selector_Name => New_Occurrence_Of (Subp, Loc),
+                        Explicit_Generic_Actual_Parameter =>
+                          New_Occurrence_Of (Actual, Loc));
+
+                  Set_Associated_Node
+                    (Explicit_Generic_Actual_Parameter (Ndec), Def);
+
+                  Append (Ndec, Assoc1);
+
+               --  If there are other defaults, add a dummy association
+               --  in case there are other defaulted formals with the same
+               --  name.
+
+               elsif Present (Next (Act2)) then
+                  Ndec :=
+                    Make_Generic_Association (Loc,
+                      Selector_Name => New_Occurrence_Of (Subp, Loc),
+                        Explicit_Generic_Actual_Parameter => Empty);
+
+                  Append (Ndec, Assoc1);
+               end if;
+
+               Next (Act2);
+            end loop;
+         end if;
+
+         if Nkind (Name (N1)) = N_Identifier
+           and then Is_Child_Unit (Gen_Id)
+           and then Is_Global (Gen_Id)
+           and then Is_Generic_Unit (Scope (Gen_Id))
+           and then In_Open_Scopes (Scope (Gen_Id))
+         then
+            --  This is an instantiation of a child unit within a sibling,
+            --  so that the generic parent is in scope. An eventual instance
+            --  must occur within the scope of an instance of the parent.
+            --  Make name in instance into an expanded name, to preserve the
+            --  identifier of the parent, so it can be resolved subsequently.
+
+            Rewrite (Name (N2),
+              Make_Expanded_Name (Loc,
+                Chars         => Chars (Gen_Id),
+                Prefix        => New_Occurrence_Of (Scope (Gen_Id), Loc),
+                Selector_Name => New_Occurrence_Of (Gen_Id, Loc)));
+            Set_Entity (Name (N2), Gen_Id);
+
+            Rewrite (Name (N1),
+               Make_Expanded_Name (Loc,
+                Chars         => Chars (Gen_Id),
+                Prefix        => New_Occurrence_Of (Scope (Gen_Id), Loc),
+                Selector_Name => New_Occurrence_Of (Gen_Id, Loc)));
+
+            Set_Associated_Node (Name (N1), Name (N2));
+            Set_Associated_Node (Prefix (Name (N1)), Empty);
+            Set_Associated_Node
+              (Selector_Name (Name (N1)), Selector_Name (Name (N2)));
+            Set_Etype (Name (N1), Etype (Gen_Id));
+         end if;
+
+      end Save_Global_Defaults;
+
+      ----------------------------
+      -- Save_Global_Descendant --
+      ----------------------------
+
+      procedure Save_Global_Descendant (D : Union_Id) is
+         N1 : Node_Id;
+
+      begin
+         if D in Node_Range then
+            if D = Union_Id (Empty) then
+               null;
+
+            elsif Nkind (Node_Id (D)) /= N_Compilation_Unit then
+               Save_References (Node_Id (D));
+            end if;
+
+         elsif D in List_Range then
+            if D = Union_Id (No_List)
+              or else Is_Empty_List (List_Id (D))
+            then
+               null;
+
+            else
+               N1 := First (List_Id (D));
+               while Present (N1) loop
+                  Save_References (N1);
+                  Next (N1);
+               end loop;
+            end if;
+
+         --  Element list or other non-node field, nothing to do
+
+         else
+            null;
+         end if;
+      end Save_Global_Descendant;
+
+      ---------------------
+      -- Save_References --
+      ---------------------
+
+      --  This is the recursive procedure that does the work, once the
+      --  enclosing generic scope has been established. We have to treat
+      --  specially a number of node rewritings that are required by semantic
+      --  processing and which change the kind of nodes in the generic copy:
+      --  typically constant-folding, replacing an operator node by a string
+      --  literal, or a selected component by an expanded name. In  each of
+      --  those cases, the transformation is propagated to the generic unit.
+
+      procedure Save_References (N : Node_Id) is
+      begin
+         if N = Empty then
+            null;
+
+         elsif (Nkind (N) = N_Character_Literal
+                 or else Nkind (N) = N_Operator_Symbol)
+         then
+            if Nkind (N) = Nkind (Associated_Node (N)) then
+               Reset_Entity (N);
+
+            elsif Nkind (N) = N_Operator_Symbol
+              and then Nkind (Associated_Node (N)) = N_String_Literal
+            then
+               Change_Operator_Symbol_To_String_Literal (N);
+            end if;
+
+         elsif Nkind (N) in N_Op then
+
+            if Nkind (N) = Nkind (Associated_Node (N)) then
+
+               if Nkind (N) = N_Op_Concat then
+                  Set_Is_Component_Left_Opnd (N,
+                    Is_Component_Left_Opnd (Associated_Node (N)));
+
+                  Set_Is_Component_Right_Opnd (N,
+                    Is_Component_Right_Opnd (Associated_Node (N)));
+               end if;
+
+               Reset_Entity (N);
+            else
+               --  Node may be transformed into call to a user-defined operator
+
+               N2 := Associated_Node (N);
+
+               if Nkind (N2) = N_Function_Call then
+                  E := Entity (Name (N2));
+
+                  if Present (E)
+                    and then Is_Global (E)
+                  then
+                     Set_Etype (N, Etype (N2));
+                  else
+                     Set_Associated_Node (N, Empty);
+                     Set_Etype (N, Empty);
+                  end if;
+
+               elsif Nkind (N2) = N_Integer_Literal
+                 or else Nkind (N2) = N_Real_Literal
+                 or else Nkind (N2) = N_String_Literal
+                 or else (Nkind (N2) = N_Identifier
+                           and then
+                          Ekind (Entity (N2)) = E_Enumeration_Literal)
+               then
+                  --  Operation was constant-folded, perform the same
+                  --  replacement in generic.
+
+                  --  Note: we do a Replace here rather than a Rewrite,
+                  --  which is a definite violation of the standard rules
+                  --  with regard to retrievability of the original tree,
+                  --  and likely ASIS bugs or at least irregularities are
+                  --  caused by this choice.
+
+                  --  The reason we do this is that the appropriate original
+                  --  nodes are never constructed (we don't go applying the
+                  --  generic instantiation to rewritten nodes in general).
+                  --  We could try to create an appropriate copy but it would
+                  --  be hard work and does not seem worth while, because
+                  --  the original expression is accessible in the generic,
+                  --  and ASIS rules for traversing instances are fuzzy.
+
+                  Replace (N, New_Copy (N2));
+                  Set_Analyzed (N, False);
+               end if;
+            end if;
+
+            --  Complete the check on operands.
+
+            Save_Global_Descendant (Field2 (N));
+            Save_Global_Descendant (Field3 (N));
+
+         elsif Nkind (N) = N_Identifier then
+            if Nkind (N) = Nkind (Associated_Node (N)) then
+
+               --  If this is a discriminant reference, always save it.
+               --  It is used in the instance to find the corresponding
+               --  discriminant positionally rather than  by name.
+
+               Set_Original_Discriminant
+                 (N, Original_Discriminant (Associated_Node (N)));
+               Reset_Entity (N);
+
+            else
+               N2 := Associated_Node (N);
+
+               if Nkind (N2) = N_Function_Call then
+                  E := Entity (Name (N2));
+
+                  --  Name resolves to a call to parameterless function.
+                  --  If original entity is global, mark node as resolved.
+
+                  if Present (E)
+                    and then Is_Global (E)
+                  then
+                     Set_Etype (N, Etype (N2));
+                  else
+                     Set_Associated_Node (N, Empty);
+                     Set_Etype (N, Empty);
+                  end if;
+
+               elsif
+                 Nkind (N2) = N_Integer_Literal or else
+                 Nkind (N2) = N_Real_Literal    or else
+                 Nkind (N2) = N_String_Literal
+               then
+                  --  Name resolves to named number that is constant-folded,
+                  --  or to string literal from concatenation.
+                  --  Perform the same replacement in generic.
+
+                  Rewrite (N, New_Copy (N2));
+                  Set_Analyzed (N, False);
+
+               elsif Nkind (N2) = N_Explicit_Dereference then
+
+                  --  An identifier is rewritten as a dereference if it is
+                  --  the prefix in a selected component, and it denotes an
+                  --  access to a composite type, or a parameterless function
+                  --  call that returns an access type.
+
+                  --  Check whether corresponding entity in prefix is global.
+
+                  if Is_Entity_Name (Prefix (N2))
+                    and then Present (Entity (Prefix (N2)))
+                    and then Is_Global (Entity (Prefix (N2)))
+                  then
+                     Rewrite (N,
+                       Make_Explicit_Dereference (Sloc (N),
+                          Prefix => Make_Identifier (Sloc (N),
+                            Chars => Chars (N))));
+                     Set_Associated_Node (Prefix (N), Prefix (N2));
+
+                  elsif Nkind (Prefix (N2)) = N_Function_Call
+                    and then Is_Global (Entity (Name (Prefix (N2))))
+                  then
+                     Rewrite (N,
+                       Make_Explicit_Dereference (Sloc (N),
+                          Prefix => Make_Function_Call (Sloc (N),
+                            Name  =>
+                              Make_Identifier (Sloc (N),
+                              Chars => Chars (N)))));
+
+                     Set_Associated_Node
+                      (Name (Prefix (N)), Name (Prefix (N2)));
+
+                  else
+                     Set_Associated_Node (N, Empty);
+                     Set_Etype (N, Empty);
+                  end if;
+
+               --  The subtype mark of a nominally unconstrained object
+               --  is rewritten as a subtype indication using the bounds
+               --  of the expression. Recover the original subtype mark.
+
+               elsif Nkind (N2) = N_Subtype_Indication
+                 and then Is_Entity_Name (Original_Node (N2))
+               then
+                  Set_Associated_Node (N, Original_Node (N2));
+                  Reset_Entity (N);
+
+               else
+                  null;
+               end if;
+            end if;
+
+         elsif Nkind (N) in N_Entity then
+            null;
+
+         elsif Nkind (N) = N_Aggregate
+                 or else Nkind (N) = N_Extension_Aggregate
+         then
+            N2 := Associated_Node (N);
+            if No (N2)
+              or else No (Etype (N2))
+              or else not Is_Global (Etype (N2))
+            then
+               Set_Associated_Node (N, Empty);
+            end if;
+
+            Save_Global_Descendant (Field1 (N));
+            Save_Global_Descendant (Field2 (N));
+            Save_Global_Descendant (Field3 (N));
+            Save_Global_Descendant (Field5 (N));
+
+         else
+            Save_Global_Descendant (Field1 (N));
+            Save_Global_Descendant (Field2 (N));
+            Save_Global_Descendant (Field3 (N));
+            Save_Global_Descendant (Field4 (N));
+            Save_Global_Descendant (Field5 (N));
+
+         end if;
+      end Save_References;
+
+   --  Start of processing for Save_Global_References
+
+   begin
+      Gen_Scope := Current_Scope;
+
+      --  If the generic unit is a child unit, references to entities in
+      --  the parent are treated as local, because they will be resolved
+      --  anew in the context of the instance of the parent.
+
+      while Is_Child_Unit (Gen_Scope)
+        and then Ekind (Scope (Gen_Scope)) = E_Generic_Package
+      loop
+         Gen_Scope := Scope (Gen_Scope);
+      end loop;
+
+      Save_References (N);
+   end Save_Global_References;
+
+   -------------------------
+   -- Set_Associated_Node --
+   -------------------------
+
+   --  Note from RBKD: the uncommented use of Set_Node4 below is ugly ???
+
+   procedure Set_Associated_Node
+     (Gen_Node  : Node_Id;
+      Copy_Node : Node_Id)
+   is
+   begin
+      Set_Node4 (Gen_Node, Copy_Node);
+   end Set_Associated_Node;
+
+   ---------------------
+   -- Set_Copied_Sloc --
+   ---------------------
+
+   procedure Set_Copied_Sloc (N : Node_Id; E : Entity_Id) is
+   begin
+      Create_Instantiation_Source (N, E, S_Adjustment);
+   end Set_Copied_Sloc;
+
+   ---------------------
+   -- Set_Instance_Of --
+   ---------------------
+
+   procedure Set_Instance_Of (A : Entity_Id; B : Entity_Id) is
+   begin
+      Generic_Renamings.Table (Generic_Renamings.Last) := (A, B, Assoc_Null);
+      Generic_Renamings_HTable.Set (Generic_Renamings.Last);
+      Generic_Renamings.Increment_Last;
+   end Set_Instance_Of;
+
+   --------------------
+   -- Set_Next_Assoc --
+   --------------------
+
+   procedure Set_Next_Assoc (E : Assoc_Ptr; Next : Assoc_Ptr) is
+   begin
+      Generic_Renamings.Table (E).Next_In_HTable := Next;
+   end Set_Next_Assoc;
+
+   -------------------
+   -- Start_Generic --
+   -------------------
+
+   procedure Start_Generic is
+   begin
+      --  ??? I am sure more things could be factored out in this
+      --  routine. Should probably be done at a later stage.
+
+      Generic_Flags.Increment_Last;
+      Generic_Flags.Table (Generic_Flags.Last) := Inside_A_Generic;
+      Inside_A_Generic := True;
+
+      Expander_Mode_Save_And_Set (False);
+   end Start_Generic;
+
+   -----------------
+   -- Switch_View --
+   -----------------
+
+   procedure Switch_View (T : Entity_Id) is
+      Priv_Elmt : Elmt_Id := No_Elmt;
+      Priv_Sub  : Entity_Id;
+      BT        : Entity_Id := Base_Type (T);
+
+   begin
+      --  T may be private but its base type may have been exchanged through
+      --  some other occurrence, in which case there is nothing to switch.
+
+      if not Is_Private_Type (BT) then
+         return;
+      end if;
+
+      Priv_Elmt := First_Elmt (Private_Dependents (BT));
+
+      if Present (Full_View (BT)) then
+         Append_Elmt (Full_View (BT), Exchanged_Views);
+         Exchange_Declarations (BT);
+      end if;
+
+      while Present (Priv_Elmt) loop
+         Priv_Sub := (Node (Priv_Elmt));
+
+         --  We avoid flipping the subtype if the Etype of its full
+         --  view is private because this would result in a malformed
+         --  subtype. This occurs when the Etype of the subtype full
+         --  view is the full view of the base type (and since the
+         --  base types were just switched, the subtype is pointing
+         --  to the wrong view). This is currently the case for
+         --  tagged record types, access types (maybe more?) and
+         --  needs to be resolved. ???
+
+         if Present (Full_View (Priv_Sub))
+           and then not Is_Private_Type (Etype (Full_View (Priv_Sub)))
+         then
+            Append_Elmt (Full_View (Priv_Sub), Exchanged_Views);
+            Exchange_Declarations (Priv_Sub);
+         end if;
+
+         Next_Elmt (Priv_Elmt);
+      end loop;
+   end Switch_View;
+
+   -----------------------------
+   -- Valid_Default_Attribute --
+   -----------------------------
+
+   procedure Valid_Default_Attribute (Nam : Entity_Id; Def : Node_Id) is
+      Attr_Id : constant Attribute_Id :=
+                  Get_Attribute_Id (Attribute_Name (Def));
+      F       : Entity_Id;
+      Num_F   : Int;
+      T       : Entity_Id := Entity (Prefix (Def));
+      OK      : Boolean;
+      Is_Fun  : constant Boolean := (Ekind (Nam) = E_Function);
+
+   begin
+      if No (T)
+        or else T = Any_Id
+      then
+         return;
+      end if;
+
+      Num_F := 0;
+      F := First_Formal (Nam);
+      while Present (F) loop
+         Num_F := Num_F + 1;
+         Next_Formal (F);
+      end loop;
+
+      case Attr_Id is
+      when Attribute_Adjacent |  Attribute_Ceiling   | Attribute_Copy_Sign |
+           Attribute_Floor    |  Attribute_Fraction  | Attribute_Machine   |
+           Attribute_Model    |  Attribute_Remainder | Attribute_Rounding  |
+           Attribute_Unbiased_Rounding  =>
+         OK := (Is_Fun and then Num_F = 1 and then Is_Floating_Point_Type (T));
+
+      when Attribute_Image    | Attribute_Pred       | Attribute_Succ |
+           Attribute_Value    | Attribute_Wide_Image |
+           Attribute_Wide_Value  =>
+         OK := (Is_Fun and then Num_F = 1 and then Is_Scalar_Type (T));
+
+      when Attribute_Max      |  Attribute_Min  =>
+         OK := (Is_Fun and then Num_F = 2 and then Is_Scalar_Type (T));
+
+      when Attribute_Input =>
+         OK := (Is_Fun and then Num_F = 1);
+
+      when Attribute_Output | Attribute_Read | Attribute_Write =>
+         OK := (not Is_Fun and then Num_F = 2);
+
+      when others => OK := False;
+      end case;
+
+      if not OK then
+         Error_Msg_N ("attribute reference has wrong profile for subprogram",
+           Def);
+      end if;
+   end Valid_Default_Attribute;
+
+end Sem_Ch12;
diff --git a/gcc/ada/sem_ch12.ads b/gcc/ada/sem_ch12.ads
new file mode 100644 (file)
index 0000000..80af1ae
--- /dev/null
@@ -0,0 +1,109 @@
+------------------------------------------------------------------------------
+--                                                                          --
+--                         GNAT COMPILER COMPONENTS                         --
+--                                                                          --
+--                             S E M _ C H 1 2                              --
+--                                                                          --
+--                                 S p e c                                  --
+--                                                                          --
+--                            $Revision: 1.19 $
+--                                                                          --
+--          Copyright (C) 1992-2000 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- --
+-- ware  Foundation;  either version 2,  or (at your option) any later ver- --
+-- sion.  GNAT is distributed in the hope that it will be useful, but WITH- --
+-- OUT ANY WARRANTY;  without even the  implied warranty of MERCHANTABILITY --
+-- or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License --
+-- for  more details.  You should have  received  a copy of the GNU General --
+-- Public License  distributed with GNAT;  see file COPYING.  If not, write --
+-- to  the Free Software Foundation,  59 Temple Place - Suite 330,  Boston, --
+-- MA 02111-1307, USA.                                                      --
+--                                                                          --
+-- GNAT was originally developed  by the GNAT team at  New York University. --
+-- It is now maintained by Ada Core Technologies Inc (http://www.gnat.com). --
+--                                                                          --
+------------------------------------------------------------------------------
+
+with Inline; use Inline;
+with Types;  use Types;
+
+package Sem_Ch12 is
+   procedure Analyze_Generic_Package_Declaration        (N : Node_Id);
+   procedure Analyze_Generic_Subprogram_Declaration     (N : Node_Id);
+   procedure Analyze_Package_Instantiation              (N : Node_Id);
+   procedure Analyze_Procedure_Instantiation            (N : Node_Id);
+   procedure Analyze_Function_Instantiation             (N : Node_Id);
+   procedure Analyze_Formal_Object_Declaration          (N : Node_Id);
+   procedure Analyze_Formal_Type_Declaration            (N : Node_Id);
+   procedure Analyze_Formal_Subprogram                  (N : Node_Id);
+   procedure Analyze_Formal_Package                     (N : Node_Id);
+
+   procedure Start_Generic;
+   --  Must be invoked before starting to process a generic spec or body.
+
+   procedure End_Generic;
+   --  Must be invoked just at the end of the end of the processing of a
+   --  generic spec or body.
+
+   procedure Check_Generic_Child_Unit
+     (Gen_Id           : Node_Id;
+      Parent_Installed : in out Boolean);
+   --  If the name of the generic unit in an instantiation or a renaming
+   --  is a selected component, then the prefix may be an instance and the
+   --  selector may  designate a child unit. Retrieve the parent generic
+   --  and search for the child unit that must be declared within. Similarly,
+   --  if this is the name of a generic child unit within an instantiation of
+   --  its own parent, retrieve the parent generic.
+
+   function Copy_Generic_Node
+     (N             : Node_Id;
+      Parent_Id     : Node_Id;
+      Instantiating : Boolean)
+      return          Node_Id;
+   --  Copy the tree for a generic unit or its body. The unit is copied
+   --  repeatedly: once to produce a copy on which semantic analysis of
+   --  the generic is performed, and once for each instantiation. The tree
+   --  being copied is not semantically analyzed, except that references to
+   --  global entities are marked on terminal nodes.
+
+   function Get_Instance_Of (A : Entity_Id) return Entity_Id;
+   --  Retrieve actual associated with given generic parameter.
+   --  If A is uninstantiated or not a generic parameter, return A.
+
+   procedure Instantiate_Package_Body
+     (Body_Info : Pending_Body_Info);
+   --  Called after semantic analysis, to complete the instantiation of
+   --  package instances.
+
+   procedure Instantiate_Subprogram_Body
+     (Body_Info : Pending_Body_Info);
+   --  Called after semantic analysis, to complete the instantiation of
+   --  function and procedure instances.
+
+   procedure Save_Global_References (N : Node_Id);
+   --  Traverse the original generic unit, and capture all references to
+   --  entities that are defined outside of the generic in the analyzed
+   --  tree for the template. These references are copied into the original
+   --  tree, so that they appear automatically in  every instantiation.
+   --  A critical invariant in this approach is that if an id in the generic
+   --  resolves to a local entity, the corresponding id in the instance
+   --  will resolve to the homologous entity in the instance, even though
+   --  the enclosing context for resolution is different, as long as the
+   --  global references have been captured as described here.
+
+   --  Because instantiations can be nested, the environment of the instance,
+   --  involving the actuals and other data-structures, must be saved and
+   --  restored in stack-like fashion. Front-end inlining also uses these
+   --  structures for the management of private/full views.
+
+   procedure Set_Copied_Sloc (N : Node_Id; E : Entity_Id);
+
+   procedure Save_Env
+     (Gen_Unit : Entity_Id;
+      Act_Unit : Entity_Id);
+
+   procedure Restore_Env;
+
+end Sem_Ch12;
diff --git a/gcc/ada/sem_ch13.adb b/gcc/ada/sem_ch13.adb
new file mode 100644 (file)
index 0000000..ae67441
--- /dev/null
@@ -0,0 +1,3912 @@
+------------------------------------------------------------------------------
+--                                                                          --
+--                         GNAT COMPILER COMPONENTS                         --
+--                                                                          --
+--                             S E M _ C H 1 3                              --
+--                                                                          --
+--                                 B o d y                                  --
+--                                                                          --
+--                            $Revision: 1.390 $
+--                                                                          --
+--          Copyright (C) 1992-2001, 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- --
+-- ware  Foundation;  either version 2,  or (at your option) any later ver- --
+-- sion.  GNAT is distributed in the hope that it will be useful, but WITH- --
+-- OUT ANY WARRANTY;  without even the  implied warranty of MERCHANTABILITY --
+-- or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License --
+-- for  more details.  You should have  received  a copy of the GNU General --
+-- Public License  distributed with GNAT;  see file COPYING.  If not, write --
+-- to  the Free Software Foundation,  59 Temple Place - Suite 330,  Boston, --
+-- MA 02111-1307, USA.                                                      --
+--                                                                          --
+-- GNAT was originally developed  by the GNAT team at  New York University. --
+-- It is now maintained by Ada Core Technologies Inc (http://www.gnat.com). --
+--                                                                          --
+------------------------------------------------------------------------------
+
+with Atree;    use Atree;
+with Einfo;    use Einfo;
+with Errout;   use Errout;
+with Exp_Tss;  use Exp_Tss;
+with Exp_Util; use Exp_Util;
+with Hostparm; use Hostparm;
+with Lib;      use Lib;
+with Nlists;   use Nlists;
+with Nmake;    use Nmake;
+with Opt;      use Opt;
+with Rtsfind;  use Rtsfind;
+with Sem;      use Sem;
+with Sem_Ch8;  use Sem_Ch8;
+with Sem_Eval; use Sem_Eval;
+with Sem_Res;  use Sem_Res;
+with Sem_Type; use Sem_Type;
+with Sem_Util; use Sem_Util;
+with Stand;    use Stand;
+with Sinfo;    use Sinfo;
+with Snames;   use Snames;
+with Table;
+with Ttypes;   use Ttypes;
+with Tbuild;   use Tbuild;
+with Urealp;   use Urealp;
+
+with GNAT.Heap_Sort_A; use GNAT.Heap_Sort_A;
+
+package body Sem_Ch13 is
+
+   SSU : constant Pos := System_Storage_Unit;
+   --  Convenient short hand for commonly used constant
+
+   -----------------------
+   -- Local Subprograms --
+   -----------------------
+
+   procedure Alignment_Check_For_Esize_Change (Typ : Entity_Id);
+   --  This routine is called after setting the Esize of type entity Typ.
+   --  The purpose is to deal with the situation where an aligment has been
+   --  inherited from a derived type that is no longer appropriate for the
+   --  new Esize value. In this case, we reset the Alignment to unknown.
+
+   procedure Check_Address_Alignment (E : Entity_Id; Expr : Node_Id);
+   --  Given an object entity E, for which the alignment is known, checks
+   --  to see if Expr (the expression from an Address clause) is a known
+   --  at compile time value, and if so posts a warning if the value is
+   --  not consistent with the known alignment requirement. This is not
+   --  an error, but rather leads to erroneous behavior, but we certainly
+   --  may as well give a warning if we detect this situation.
+
+   procedure Check_Component_Overlap (C1_Ent, C2_Ent : Entity_Id);
+   --  Given two entities for record components or discriminants, checks
+   --  if they hav overlapping component clauses and issues errors if so.
+
+   function Get_Alignment_Value (Expr : Node_Id) return Uint;
+   --  Given the expression for an alignment value, returns the corresponding
+   --  Uint value. If the value is inappropriate, then error messages are
+   --  posted as required, and a value of No_Uint is returned.
+
+   function Is_Operational_Item (N : Node_Id) return Boolean;
+   --  A specification for a stream attribute is allowed before the full
+   --  type is declared, as explained in AI-00137 and the corrigendum.
+   --  Attributes that do not specify a representation characteristic are
+   --  operational attributes.
+
+   procedure New_Stream_Function
+     (N    : Node_Id;
+      Ent  : Entity_Id;
+      Subp : Entity_Id;
+      Nam  : Name_Id);
+   --  Create a function renaming of a given stream attribute to the
+   --  designated subprogram and then in the tagged case, provide this as
+   --  a primitive operation, or in the non-tagged case make an appropriate
+   --  TSS entry. Used for Input. This is more properly an expansion activity
+   --  than just semantics, but the presence of user-defined stream functions
+   --  for limited types is a legality check, which is why this takes place
+   --  here rather than in exp_ch13, where it was previously.
+
+   procedure New_Stream_Procedure
+     (N     : Node_Id;
+      Ent   : Entity_Id;
+      Subp  : Entity_Id;
+      Nam   : Name_Id;
+      Out_P : Boolean := False);
+   --  Create a procedure renaming of a given stream attribute to the
+   --  designated subprogram and then in the tagged case, provide this as
+   --  a primitive operation, or in the non-tagged case make an appropriate
+   --  TSS entry. Used for Read, Output, Write.
+
+   procedure Check_Constant_Address_Clause (Expr : Node_Id; U_Ent : Entity_Id);
+   --  Expr is an expression for an address clause. This procedure checks
+   --  that the expression is constant, in the limited sense that it is safe
+   --  to evaluate it at the point the object U_Ent is declared, rather than
+   --  at the point of the address clause. The condition for this to be true
+   --  is that the expression has no variables, no constants declared after
+   --  U_Ent, and no calls to non-pure functions. If this condition is not
+   --  met, then an appropriate error message is posted.
+
+   procedure Warn_Overlay
+     (Expr : Node_Id;
+      Typ  : Entity_Id;
+      Nam  : Node_Id);
+   --  Expr is the expression for an address clause for entity Nam whose type
+   --  is Typ. If Typ has a default initialization, check whether the address
+   --  clause might overlay two entities, and emit a warning on the side effect
+   --  that the initialization will cause.
+
+   ----------------------------------------------
+   -- Table for Validate_Unchecked_Conversions --
+   ----------------------------------------------
+
+   --  The following table collects unchecked conversions for validation.
+   --  Entries are made by Validate_Unchecked_Conversion and then the
+   --  call to Validate_Unchecked_Conversions does the actual error
+   --  checking and posting of warnings. The reason for this delayed
+   --  processing is to take advantage of back-annotations of size and
+   --  alignment values peformed by the back end.
+
+   type UC_Entry is record
+      Enode  : Node_Id;   -- node used for posting warnings
+      Source : Entity_Id; -- source type for unchecked conversion
+      Target : Entity_Id; -- target type for unchecked conversion
+   end record;
+
+   package Unchecked_Conversions is new Table.Table (
+     Table_Component_Type => UC_Entry,
+     Table_Index_Type     => Int,
+     Table_Low_Bound      => 1,
+     Table_Initial        => 50,
+     Table_Increment      => 200,
+     Table_Name           => "Unchecked_Conversions");
+
+   --------------------------------------
+   -- Alignment_Check_For_Esize_Change --
+   --------------------------------------
+
+   procedure Alignment_Check_For_Esize_Change (Typ : Entity_Id) is
+   begin
+      --  If the alignment is known, and not set by a rep clause, and is
+      --  inconsistent with the size being set, then reset it to unknown,
+      --  we assume in this case that the size overrides the inherited
+      --  alignment, and that the alignment must be recomputed.
+
+      if Known_Alignment (Typ)
+        and then not Has_Alignment_Clause (Typ)
+        and then Esize (Typ) mod (Alignment (Typ) * SSU) /= 0
+      then
+         Init_Alignment (Typ);
+      end if;
+   end Alignment_Check_For_Esize_Change;
+
+   -----------------------
+   -- Analyze_At_Clause --
+   -----------------------
+
+   --  An at clause is replaced by the corresponding Address attribute
+   --  definition clause that is the preferred approach in Ada 95.
+
+   procedure Analyze_At_Clause (N : Node_Id) is
+   begin
+      Rewrite (N,
+        Make_Attribute_Definition_Clause (Sloc (N),
+          Name  => Identifier (N),
+          Chars => Name_Address,
+          Expression => Expression (N)));
+      Analyze_Attribute_Definition_Clause (N);
+   end Analyze_At_Clause;
+
+   -----------------------------------------
+   -- Analyze_Attribute_Definition_Clause --
+   -----------------------------------------
+
+   procedure Analyze_Attribute_Definition_Clause (N : Node_Id) is
+      Loc   : constant Source_Ptr   := Sloc (N);
+      Nam   : constant Node_Id      := Name (N);
+      Attr  : constant Name_Id      := Chars (N);
+      Expr  : constant Node_Id      := Expression (N);
+      Id    : constant Attribute_Id := Get_Attribute_Id (Attr);
+      Ent   : Entity_Id;
+      U_Ent : Entity_Id;
+
+      FOnly : Boolean := False;
+      --  Reset to True for subtype specific attribute (Alignment, Size)
+      --  and for stream attributes, i.e. those cases where in the call
+      --  to Rep_Item_Too_Late, FOnly is set True so that only the freezing
+      --  rules are checked. Note that the case of stream attributes is not
+      --  clear from the RM, but see AI95-00137. Also, the RM seems to
+      --  disallow Storage_Size for derived task types, but that is also
+      --  clearly unintentional.
+
+   begin
+      Analyze (Nam);
+      Ent := Entity (Nam);
+
+      if Rep_Item_Too_Early (Ent, N) then
+         return;
+      end if;
+
+      --  Rep clause applies to full view of incomplete type or private type
+      --  if we have one (if not, this is a premature use of the type).
+      --  However, certain semantic checks need to be done on the specified
+      --  entity (i.e. the private view), so we save it in Ent.
+
+      if Is_Private_Type (Ent)
+        and then Is_Derived_Type (Ent)
+        and then not Is_Tagged_Type (Ent)
+        and then No (Full_View (Ent))
+      then
+         --  If this is a private type whose completion is a derivation
+         --  from another private type, there is no full view, and the
+         --  attribute belongs to the type itself, not its underlying parent.
+
+         U_Ent := Ent;
+
+      elsif Ekind (Ent) = E_Incomplete_Type then
+         Ent := Underlying_Type (Ent);
+         U_Ent := Ent;
+      else
+         U_Ent := Underlying_Type (Ent);
+      end if;
+
+      --  Complete other routine error checks
+
+      if Etype (Nam) = Any_Type then
+         return;
+
+      elsif Scope (Ent) /= Current_Scope then
+         Error_Msg_N ("entity must be declared in this scope", Nam);
+         return;
+
+      elsif Is_Type (U_Ent)
+        and then not Is_First_Subtype (U_Ent)
+        and then Id /= Attribute_Object_Size
+        and then Id /= Attribute_Value_Size
+        and then not From_At_Mod (N)
+      then
+         Error_Msg_N ("cannot specify attribute for subtype", Nam);
+         return;
+
+      end if;
+
+      --  Switch on particular attribute
+
+      case Id is
+
+         -------------
+         -- Address --
+         -------------
+
+         --  Address attribute definition clause
+
+         when Attribute_Address => Address : begin
+            Analyze_And_Resolve (Expr, RTE (RE_Address));
+
+            if Present (Address_Clause (U_Ent)) then
+               Error_Msg_N ("address already given for &", Nam);
+
+            --  Case of address clause for subprogram
+
+            elsif Is_Subprogram (U_Ent) then
+
+               if Has_Homonym (U_Ent) then
+                  Error_Msg_N
+                    ("address clause cannot be given " &
+                     "for overloaded subprogram",
+                     Nam);
+               end if;
+
+               --  For subprograms, all address clauses are permitted,
+               --  and we mark the subprogram as having a deferred freeze
+               --  so that Gigi will not elaborate it too soon.
+
+               --  Above needs more comments, what is too soon about???
+
+               Set_Has_Delayed_Freeze (U_Ent);
+
+            --  Case of address clause for entry
+
+            elsif Ekind (U_Ent) = E_Entry then
+
+               if Nkind (Parent (N)) = N_Task_Body then
+                  Error_Msg_N
+                    ("entry address must be specified in task spec", Nam);
+               end if;
+
+               --  For entries, we require a constant address
+
+               Check_Constant_Address_Clause (Expr, U_Ent);
+
+            --  Case of address clause for variable or constant
+
+            elsif
+              Ekind (U_Ent) = E_Variable
+                or else
+              Ekind (U_Ent) = E_Constant
+            then
+               declare
+                  Decl : constant Node_Id   := Declaration_Node (U_Ent);
+                  Expr : constant Node_Id   := Expression (N);
+                  Typ  : constant Entity_Id := Etype (U_Ent);
+
+               begin
+                  --  Exported variables cannot have an address clause,
+                  --  because this cancels the effect of the pragma Export
+
+                  if Is_Exported (U_Ent) then
+                     Error_Msg_N
+                       ("cannot export object with address clause", Nam);
+
+                  --  Imported variables can have an address clause, but then
+                  --  the import is pretty meaningless except to suppress
+                  --  initializations, so we do not need such variables to
+                  --  be statically allocated (and in fact it causes trouble
+                  --  if the address clause is a local value).
+
+                  elsif Is_Imported (U_Ent) then
+                     Set_Is_Statically_Allocated (U_Ent, False);
+                  end if;
+
+                  --  We mark a possible modification of a variable with an
+                  --  address clause, since it is likely aliasing is occurring.
+
+                  Note_Possible_Modification (Nam);
+
+                  --  If we have no initialization of any kind, then we can
+                  --  safely defer the elaboration of the variable to its
+                  --  freezing point, so that the address clause will be
+                  --  computed at the proper point.
+
+                  --  The same processing applies to all initialized scalar
+                  --  types and all access types. Packed bit arrays of size
+                  --  up to 64 are represented using a modular type with an
+                  --  initialization (to zero) and can be processed like
+                  --  other initialized scalar types.
+
+                  if (No (Expression (Decl))
+                       and then not Has_Non_Null_Base_Init_Proc (Typ))
+
+                    or else
+                      (Present (Expression (Decl))
+                        and then Is_Scalar_Type (Typ))
+
+                    or else
+                      Is_Access_Type (Typ)
+
+                    or else
+                      (Is_Bit_Packed_Array (Base_Type (Typ))
+                        and then
+                          Is_Modular_Integer_Type (Packed_Array_Type (Typ)))
+                  then
+                     Set_Has_Delayed_Freeze (U_Ent);
+
+                  --  Otherwise, we require the address clause to be constant
+
+                  else
+                     Check_Constant_Address_Clause (Expr, U_Ent);
+                  end if;
+
+                  if Is_Exported (U_Ent) then
+                     Error_Msg_N
+                       ("& cannot be exported if an address clause is given",
+                        Nam);
+                     Error_Msg_N
+                       ("\define and export a variable " &
+                        "that holds its address instead",
+                        Nam);
+                  end if;
+
+                  if not Error_Posted (Expr) then
+                     Warn_Overlay (Expr, Typ, Nam);
+                  end if;
+
+                  --  Check for bad alignment
+
+                  if Known_Alignment (U_Ent) then
+                     Check_Address_Alignment (U_Ent, Expr);
+                  end if;
+
+                  --  Kill the size check code, since we are not allocating
+                  --  the variable, it is somewhere else.
+
+                  Kill_Size_Check_Code (U_Ent);
+               end;
+
+            --  Not a valid entity for an address clause
+
+            else
+               Error_Msg_N ("address cannot be given for &", Nam);
+            end if;
+         end Address;
+
+         ---------------
+         -- Alignment --
+         ---------------
+
+         --  Alignment attribute definition clause
+
+         when Attribute_Alignment => Alignment_Block : declare
+            Align : Uint := Get_Alignment_Value (Expr);
+
+         begin
+            FOnly := True;
+
+            if not Is_Type (U_Ent)
+              and then Ekind (U_Ent) /= E_Variable
+              and then Ekind (U_Ent) /= E_Constant
+            then
+               Error_Msg_N ("alignment cannot be given for &", Nam);
+
+            elsif Has_Alignment_Clause (U_Ent) then
+               Error_Msg_Sloc := Sloc (Alignment_Clause (U_Ent));
+               Error_Msg_N ("alignment clause previously given#", N);
+
+            elsif Align /= No_Uint then
+               Set_Has_Alignment_Clause (U_Ent);
+               Set_Alignment            (U_Ent, Align);
+            end if;
+         end Alignment_Block;
+
+         ---------------
+         -- Bit_Order --
+         ---------------
+
+         --  Bit_Order attribute definition clause
+
+         when Attribute_Bit_Order => Bit_Order : declare
+         begin
+            if not Is_Record_Type (U_Ent) then
+               Error_Msg_N
+                 ("Bit_Order can only be defined for record type", Nam);
+
+            else
+               Analyze_And_Resolve (Expr, RTE (RE_Bit_Order));
+
+               if Etype (Expr) = Any_Type then
+                  return;
+
+               elsif not Is_Static_Expression (Expr) then
+                  Error_Msg_N ("Bit_Order requires static expression", Expr);
+
+               else
+                  if (Expr_Value (Expr) = 0) /= Bytes_Big_Endian then
+                     Set_Reverse_Bit_Order (U_Ent, True);
+                  end if;
+               end if;
+            end if;
+         end Bit_Order;
+
+         --------------------
+         -- Component_Size --
+         --------------------
+
+         --  Component_Size attribute definition clause
+
+         when Attribute_Component_Size => Component_Size_Case : declare
+            Csize    : constant Uint := Static_Integer (Expr);
+            Btype    : Entity_Id;
+            Biased   : Boolean;
+            New_Ctyp : Entity_Id;
+            Decl     : Node_Id;
+
+         begin
+            if not Is_Array_Type (U_Ent) then
+               Error_Msg_N ("component size requires array type", Nam);
+               return;
+            end if;
+
+            Btype := Base_Type (U_Ent);
+
+            if Has_Component_Size_Clause (Btype) then
+               Error_Msg_N
+                 ("component size clase for& previously given", Nam);
+
+            elsif Csize /= No_Uint then
+               Check_Size (Expr, Component_Type (Btype), Csize, Biased);
+
+               if Has_Aliased_Components (Btype)
+                 and then Csize < 32
+                 and then Csize /= 8
+                 and then Csize /= 16
+               then
+                  Error_Msg_N
+                    ("component size incorrect for aliased components", N);
+                  return;
+               end if;
+
+               --  For the biased case, build a declaration for a subtype
+               --  that will be used to represent the biased subtype that
+               --  reflects the biased representation of components. We need
+               --  this subtype to get proper conversions on referencing
+               --  elements of the array.
+
+               if Biased then
+                  New_Ctyp :=
+                    Make_Defining_Identifier (Loc,
+                      Chars => New_External_Name (Chars (U_Ent), 'C', 0, 'T'));
+
+                  Decl :=
+                    Make_Subtype_Declaration (Loc,
+                      Defining_Identifier => New_Ctyp,
+                      Subtype_Indication  =>
+                        New_Occurrence_Of (Component_Type (Btype), Loc));
+
+                  Set_Parent (Decl, N);
+                  Analyze (Decl, Suppress => All_Checks);
+
+                  Set_Has_Delayed_Freeze        (New_Ctyp, False);
+                  Set_Esize                     (New_Ctyp, Csize);
+                  Set_RM_Size                   (New_Ctyp, Csize);
+                  Init_Alignment                (New_Ctyp);
+                  Set_Has_Biased_Representation (New_Ctyp, True);
+                  Set_Is_Itype                  (New_Ctyp, True);
+                  Set_Associated_Node_For_Itype (New_Ctyp, U_Ent);
+
+                  Set_Component_Type (Btype, New_Ctyp);
+               end if;
+
+               Set_Component_Size            (Btype, Csize);
+               Set_Has_Component_Size_Clause (Btype, True);
+               Set_Has_Non_Standard_Rep      (Btype, True);
+            end if;
+         end Component_Size_Case;
+
+         ------------------
+         -- External_Tag --
+         ------------------
+
+         when Attribute_External_Tag => External_Tag :
+         begin
+            if not Is_Tagged_Type (U_Ent) then
+               Error_Msg_N ("should be a tagged type", Nam);
+            end if;
+
+            Analyze_And_Resolve (Expr, Standard_String);
+
+            if not Is_Static_Expression (Expr) then
+               Error_Msg_N ("must be a static string", Nam);
+            end if;
+
+            Set_Has_External_Tag_Rep_Clause (U_Ent);
+         end External_Tag;
+
+         -----------
+         -- Input --
+         -----------
+
+         when Attribute_Input => Input : declare
+            Subp : Entity_Id := Empty;
+            I    : Interp_Index;
+            It   : Interp;
+            Pnam : Entity_Id;
+
+            function Has_Good_Profile (Subp : Entity_Id) return Boolean;
+            --  Return true if the entity is a function with an appropriate
+            --  profile for the Input attribute.
+
+            function Has_Good_Profile (Subp : Entity_Id) return Boolean is
+               F  : Entity_Id;
+               Ok : Boolean := False;
+
+            begin
+               if Ekind (Subp) = E_Function then
+                  F := First_Formal (Subp);
+
+                  if Present (F) and then No (Next_Formal (F)) then
+                     if Ekind (Etype (F)) = E_Anonymous_Access_Type
+                       and then
+                         Designated_Type (Etype (F)) =
+                           Class_Wide_Type (RTE (RE_Root_Stream_Type))
+                     then
+                        Ok := Base_Type (Etype (Subp)) = Base_Type (Ent);
+                     end if;
+                  end if;
+               end if;
+
+               return Ok;
+            end Has_Good_Profile;
+
+         --  Start of processing for Input attribute definition
+
+         begin
+            FOnly := True;
+
+            if not Is_Type (U_Ent) then
+               Error_Msg_N ("local name must be a subtype", Nam);
+               return;
+
+            else
+               Pnam := TSS (Base_Type (U_Ent), Name_uInput);
+
+               if Present (Pnam)
+                 and then Base_Type (Etype (Pnam)) = Base_Type (U_Ent)
+               then
+                  Error_Msg_Sloc := Sloc (Pnam);
+                  Error_Msg_N ("input attribute already defined #", Nam);
+                  return;
+               end if;
+            end if;
+
+            Analyze (Expr);
+
+            if Is_Entity_Name (Expr) then
+               if not Is_Overloaded (Expr) then
+                  if Has_Good_Profile (Entity (Expr)) then
+                     Subp := Entity (Expr);
+                  end if;
+
+               else
+                  Get_First_Interp (Expr, I, It);
+
+                  while Present (It.Nam) loop
+                     if Has_Good_Profile (It.Nam) then
+                        Subp := It.Nam;
+                        exit;
+                     end if;
+
+                     Get_Next_Interp (I, It);
+                  end loop;
+               end if;
+            end if;
+
+            if Present (Subp) then
+               Set_Entity (Expr, Subp);
+               Set_Etype (Expr, Etype (Subp));
+               New_Stream_Function (N, U_Ent, Subp,  Name_uInput);
+            else
+               Error_Msg_N ("incorrect expression for input attribute", Expr);
+               return;
+            end if;
+         end Input;
+
+         -------------------
+         -- Machine_Radix --
+         -------------------
+
+         --  Machine radix attribute definition clause
+
+         when Attribute_Machine_Radix => Machine_Radix : declare
+            Radix : constant Uint := Static_Integer (Expr);
+
+         begin
+            if not Is_Decimal_Fixed_Point_Type (U_Ent) then
+               Error_Msg_N ("decimal fixed-point type expected for &", Nam);
+
+            elsif Has_Machine_Radix_Clause (U_Ent) then
+               Error_Msg_Sloc := Sloc (Alignment_Clause (U_Ent));
+               Error_Msg_N ("machine radix clause previously given#", N);
+
+            elsif Radix /= No_Uint then
+               Set_Has_Machine_Radix_Clause (U_Ent);
+               Set_Has_Non_Standard_Rep (Base_Type (U_Ent));
+
+               if Radix = 2 then
+                  null;
+               elsif Radix = 10 then
+                  Set_Machine_Radix_10 (U_Ent);
+               else
+                  Error_Msg_N ("machine radix value must be 2 or 10", Expr);
+               end if;
+            end if;
+         end Machine_Radix;
+
+         -----------------
+         -- Object_Size --
+         -----------------
+
+         --  Object_Size attribute definition clause
+
+         when Attribute_Object_Size => Object_Size : declare
+            Size   : constant Uint := Static_Integer (Expr);
+            Biased : Boolean;
+
+         begin
+            if not Is_Type (U_Ent) then
+               Error_Msg_N ("Object_Size cannot be given for &", Nam);
+
+            elsif Has_Object_Size_Clause (U_Ent) then
+               Error_Msg_N ("Object_Size already given for &", Nam);
+
+            else
+               Check_Size (Expr, U_Ent, Size, Biased);
+
+               if Size /= 8
+                    and then
+                  Size /= 16
+                    and then
+                  Size /= 32
+                    and then
+                  UI_Mod (Size, 64) /= 0
+               then
+                  Error_Msg_N
+                    ("Object_Size must be 8, 16, 32, or multiple of 64",
+                     Expr);
+               end if;
+
+               Set_Esize (U_Ent, Size);
+               Set_Has_Object_Size_Clause (U_Ent);
+               Alignment_Check_For_Esize_Change (U_Ent);
+            end if;
+         end Object_Size;
+
+         ------------
+         -- Output --
+         ------------
+
+         when Attribute_Output => Output : declare
+            Subp : Entity_Id := Empty;
+            I    : Interp_Index;
+            It   : Interp;
+            Pnam : Entity_Id;
+
+            function Has_Good_Profile (Subp : Entity_Id) return Boolean;
+            --  Return true if the entity is a procedure with an
+            --  appropriate profile for the output attribute.
+
+            function Has_Good_Profile (Subp : Entity_Id) return Boolean is
+               F  : Entity_Id;
+               Ok : Boolean := False;
+
+            begin
+               if Ekind (Subp) = E_Procedure then
+                  F := First_Formal (Subp);
+
+                  if Present (F) then
+                     if Ekind (Etype (F)) = E_Anonymous_Access_Type
+                       and then
+                         Designated_Type (Etype (F)) =
+                           Class_Wide_Type (RTE (RE_Root_Stream_Type))
+                     then
+                        Next_Formal (F);
+                        Ok :=  Present (F)
+                          and then Parameter_Mode (F) = E_In_Parameter
+                          and then Base_Type (Etype (F)) = Base_Type (Ent)
+                          and then No (Next_Formal (F));
+                     end if;
+                  end if;
+               end if;
+
+               return Ok;
+            end Has_Good_Profile;
+
+         begin
+            FOnly := True;
+
+            if not Is_Type (U_Ent) then
+               Error_Msg_N ("local name must be a subtype", Nam);
+               return;
+
+            else
+               Pnam := TSS (Base_Type (U_Ent), Name_uOutput);
+
+               if Present (Pnam)
+                 and then
+                   Base_Type (Etype (Next_Formal (First_Formal (Pnam))))
+                                                        = Base_Type (U_Ent)
+               then
+                  Error_Msg_Sloc := Sloc (Pnam);
+                  Error_Msg_N ("output attribute already defined #", Nam);
+                  return;
+               end if;
+            end if;
+
+            Analyze (Expr);
+
+            if Is_Entity_Name (Expr) then
+               if not Is_Overloaded (Expr) then
+                  if Has_Good_Profile (Entity (Expr)) then
+                     Subp := Entity (Expr);
+                  end if;
+
+               else
+                  Get_First_Interp (Expr, I, It);
+
+                  while Present (It.Nam) loop
+                     if Has_Good_Profile (It.Nam) then
+                        Subp := It.Nam;
+                        exit;
+                     end if;
+
+                     Get_Next_Interp (I, It);
+                  end loop;
+               end if;
+            end if;
+
+            if Present (Subp) then
+               Set_Entity (Expr, Subp);
+               Set_Etype (Expr, Etype (Subp));
+               New_Stream_Procedure (N, U_Ent, Subp, Name_uOutput);
+            else
+               Error_Msg_N ("incorrect expression for output attribute", Expr);
+               return;
+            end if;
+         end Output;
+
+         ----------
+         -- Read --
+         ----------
+
+         when Attribute_Read => Read : declare
+            Subp : Entity_Id := Empty;
+            I    : Interp_Index;
+            It   : Interp;
+            Pnam : Entity_Id;
+
+            function Has_Good_Profile (Subp : Entity_Id) return Boolean;
+            --  Return true if the entity is a procedure with an appropriate
+            --  profile for the Read attribute.
+
+            function Has_Good_Profile (Subp : Entity_Id) return Boolean is
+               F     : Entity_Id;
+               Ok    : Boolean := False;
+
+            begin
+               if Ekind (Subp) = E_Procedure then
+                  F := First_Formal (Subp);
+
+                  if Present (F) then
+                     if Ekind (Etype (F)) = E_Anonymous_Access_Type
+                       and then
+                         Designated_Type (Etype (F)) =
+                           Class_Wide_Type (RTE (RE_Root_Stream_Type))
+                     then
+                        Next_Formal (F);
+                        Ok :=  Present (F)
+                          and then Parameter_Mode (F) = E_Out_Parameter
+                          and then Base_Type (Etype (F)) = Base_Type (Ent)
+                          and then No (Next_Formal (F));
+                     end if;
+                  end if;
+               end if;
+
+               return Ok;
+            end Has_Good_Profile;
+
+         --  Start of processing for Read attribute definition
+
+         begin
+            FOnly := True;
+
+            if not Is_Type (U_Ent) then
+               Error_Msg_N ("local name must be a subtype", Nam);
+               return;
+
+            else
+               Pnam := TSS (Base_Type (U_Ent), Name_uRead);
+
+               if Present (Pnam)
+                 and then Base_Type (Etype (Next_Formal (First_Formal (Pnam))))
+                   = Base_Type (U_Ent)
+               then
+                  Error_Msg_Sloc := Sloc (Pnam);
+                  Error_Msg_N ("read attribute already defined #", Nam);
+                  return;
+               end if;
+            end if;
+
+            Analyze (Expr);
+
+            if Is_Entity_Name (Expr) then
+               if not Is_Overloaded (Expr) then
+                  if Has_Good_Profile (Entity (Expr)) then
+                     Subp := Entity (Expr);
+                  end if;
+
+               else
+                  Get_First_Interp (Expr, I, It);
+
+                  while Present (It.Nam) loop
+                     if Has_Good_Profile (It.Nam) then
+                        Subp := It.Nam;
+                        exit;
+                     end if;
+
+                     Get_Next_Interp (I, It);
+                  end loop;
+               end if;
+            end if;
+
+            if Present (Subp) then
+               Set_Entity (Expr, Subp);
+               Set_Etype (Expr, Etype (Subp));
+               New_Stream_Procedure (N, U_Ent, Subp, Name_uRead, True);
+            else
+               Error_Msg_N ("incorrect expression for read attribute", Expr);
+               return;
+            end if;
+         end Read;
+
+         ----------
+         -- Size --
+         ----------
+
+         --  Size attribute definition clause
+
+         when Attribute_Size => Size : declare
+            Size   : constant Uint := Static_Integer (Expr);
+            Etyp   : Entity_Id;
+            Biased : Boolean;
+
+         begin
+            FOnly := True;
+
+            if Has_Size_Clause (U_Ent) then
+               Error_Msg_N ("size already given for &", Nam);
+
+            elsif not Is_Type (U_Ent)
+              and then Ekind (U_Ent) /= E_Variable
+              and then Ekind (U_Ent) /= E_Constant
+            then
+               Error_Msg_N ("size cannot be given for &", Nam);
+
+            elsif Is_Array_Type (U_Ent)
+              and then not Is_Constrained (U_Ent)
+            then
+               Error_Msg_N
+                 ("size cannot be given for unconstrained array", Nam);
+
+            elsif Size /= No_Uint then
+
+               if Is_Type (U_Ent) then
+                  Etyp := U_Ent;
+               else
+                  Etyp := Etype (U_Ent);
+               end if;
+
+               --  Check size, note that Gigi is in charge of checking
+               --  that the size of an array or record type is OK. Also
+               --  we do not check the size in the ordinary fixed-point
+               --  case, since it is too early to do so (there may be a
+               --  subsequent small clause that affects the size). We can
+               --  check the size if a small clause has already been given.
+
+               if not Is_Ordinary_Fixed_Point_Type (U_Ent)
+                 or else Has_Small_Clause (U_Ent)
+               then
+                  Check_Size (Expr, Etyp, Size, Biased);
+                  Set_Has_Biased_Representation (U_Ent, Biased);
+               end if;
+
+               --  For types set RM_Size and Esize if possible
+
+               if Is_Type (U_Ent) then
+                  Set_RM_Size (U_Ent, Size);
+
+                  --  For scalar types, increase Object_Size to power of 2,
+                  --  but not less than 8 in any case, i.e. byte addressable.
+
+                  if Is_Scalar_Type (U_Ent) then
+                     if Size <= 8 then
+                        Init_Esize (U_Ent, 8);
+                     elsif Size <= 16 then
+                        Init_Esize (U_Ent, 16);
+                     elsif Size <= 32 then
+                        Init_Esize (U_Ent, 32);
+                     else
+                        Set_Esize  (U_Ent, (Size + 63) / 64 * 64);
+                     end if;
+
+                  --  For all other types, object size = value size. The
+                  --  backend will adjust as needed.
+
+                  else
+                     Set_Esize (U_Ent, Size);
+                  end if;
+
+                  Alignment_Check_For_Esize_Change (U_Ent);
+
+               --  For objects, set Esize only
+
+               else
+                  Set_Esize (U_Ent, Size);
+               end if;
+
+               Set_Has_Size_Clause (U_Ent);
+            end if;
+         end Size;
+
+         -----------
+         -- Small --
+         -----------
+
+         --  Small attribute definition clause
+
+         when Attribute_Small => Small : declare
+            Implicit_Base : constant Entity_Id := Base_Type (U_Ent);
+            Small         : Ureal;
+
+         begin
+            Analyze_And_Resolve (Expr, Any_Real);
+
+            if Etype (Expr) = Any_Type then
+               return;
+
+            elsif not Is_Static_Expression (Expr) then
+               Error_Msg_N ("small requires static expression", Expr);
+               return;
+
+            else
+               Small := Expr_Value_R (Expr);
+
+               if Small <= Ureal_0 then
+                  Error_Msg_N ("small value must be greater than zero", Expr);
+                  return;
+               end if;
+
+            end if;
+
+            if not Is_Ordinary_Fixed_Point_Type (U_Ent) then
+               Error_Msg_N
+                 ("small requires an ordinary fixed point type", Nam);
+
+            elsif Has_Small_Clause (U_Ent) then
+               Error_Msg_N ("small already given for &", Nam);
+
+            elsif Small > Delta_Value (U_Ent) then
+               Error_Msg_N
+                 ("small value must not be greater then delta value", Nam);
+
+            else
+               Set_Small_Value (U_Ent, Small);
+               Set_Small_Value (Implicit_Base, Small);
+               Set_Has_Small_Clause (U_Ent);
+               Set_Has_Small_Clause (Implicit_Base);
+               Set_Has_Non_Standard_Rep (Implicit_Base);
+            end if;
+         end Small;
+
+         ------------------
+         -- Storage_Size --
+         ------------------
+
+         --  Storage_Size attribute definition clause
+
+         when Attribute_Storage_Size => Storage_Size : declare
+            Btype : constant Entity_Id := Base_Type (U_Ent);
+            Sprag : Node_Id;
+
+         begin
+            if Is_Task_Type (U_Ent) then
+               FOnly := True;
+            end if;
+
+            if not Is_Access_Type (U_Ent)
+              and then Ekind (U_Ent) /= E_Task_Type
+            then
+               Error_Msg_N ("storage size cannot be given for &", Nam);
+
+            elsif Is_Access_Type (U_Ent) and Is_Derived_Type (U_Ent) then
+               Error_Msg_N
+                 ("storage size cannot be given for a derived access type",
+                  Nam);
+
+            elsif Has_Storage_Size_Clause (Btype) then
+               Error_Msg_N ("storage size already given for &", Nam);
+
+            else
+               Analyze_And_Resolve (Expr, Any_Integer);
+
+               if Is_Access_Type (U_Ent) then
+
+                  if Present (Associated_Storage_Pool (U_Ent)) then
+                     Error_Msg_N ("storage pool already given for &", Nam);
+                     return;
+                  end if;
+
+                  if Compile_Time_Known_Value (Expr)
+                    and then Expr_Value (Expr) = 0
+                  then
+                     Set_No_Pool_Assigned (Btype);
+                  end if;
+
+               else -- Is_Task_Type (U_Ent)
+                  Sprag := Get_Rep_Pragma (Btype, Name_Storage_Size);
+
+                  if Present (Sprag) then
+                     Error_Msg_Sloc := Sloc (Sprag);
+                     Error_Msg_N
+                       ("Storage_Size already specified#", Nam);
+                     return;
+                  end if;
+               end if;
+
+               Set_Has_Storage_Size_Clause (Btype);
+            end if;
+         end Storage_Size;
+
+         ------------------
+         -- Storage_Pool --
+         ------------------
+
+         --  Storage_Pool attribute definition clause
+
+         when Attribute_Storage_Pool => Storage_Pool : declare
+            Pool : Entity_Id;
+
+         begin
+            if Ekind (U_Ent) /= E_Access_Type
+              and then Ekind (U_Ent) /= E_General_Access_Type
+            then
+               Error_Msg_N (
+                 "storage pool can only be given for access types", Nam);
+               return;
+
+            elsif Is_Derived_Type (U_Ent) then
+               Error_Msg_N
+                 ("storage pool cannot be given for a derived access type",
+                  Nam);
+
+            elsif Has_Storage_Size_Clause (U_Ent) then
+               Error_Msg_N ("storage size already given for &", Nam);
+               return;
+
+            elsif Present (Associated_Storage_Pool (U_Ent)) then
+               Error_Msg_N ("storage pool already given for &", Nam);
+               return;
+            end if;
+
+            Analyze_And_Resolve
+              (Expr, Class_Wide_Type (RTE (RE_Root_Storage_Pool)));
+
+            --  If the argument is a name that is not an entity name, then
+            --  we construct a renaming operation to define an entity of
+            --  type storage pool.
+
+            if not Is_Entity_Name (Expr)
+              and then Is_Object_Reference (Expr)
+            then
+               Pool :=
+                 Make_Defining_Identifier (Loc,
+                   Chars => New_Internal_Name ('P'));
+
+               declare
+                  Rnode : constant Node_Id :=
+                            Make_Object_Renaming_Declaration (Loc,
+                              Defining_Identifier => Pool,
+                              Subtype_Mark        =>
+                                New_Occurrence_Of (Etype (Expr), Loc),
+                              Name => Expr);
+
+               begin
+                  Insert_Before (N, Rnode);
+                  Analyze (Rnode);
+                  Set_Associated_Storage_Pool (U_Ent, Pool);
+               end;
+
+            elsif Is_Entity_Name (Expr) then
+               Pool := Entity (Expr);
+
+               --  If pool is a renamed object, get original one. This can
+               --  happen with an explicit renaming, and within instances.
+
+               while Present (Renamed_Object (Pool))
+                 and then Is_Entity_Name (Renamed_Object (Pool))
+               loop
+                  Pool := Entity (Renamed_Object (Pool));
+               end loop;
+
+               if Present (Renamed_Object (Pool))
+                 and then Nkind (Renamed_Object (Pool)) = N_Type_Conversion
+                 and then Is_Entity_Name (Expression (Renamed_Object (Pool)))
+               then
+                  Pool := Entity (Expression (Renamed_Object (Pool)));
+               end if;
+
+               if Present (Etype (Pool))
+                 and then Etype (Pool) /= RTE (RE_Stack_Bounded_Pool)
+                 and then Etype (Pool) /= RTE (RE_Unbounded_Reclaim_Pool)
+               then
+                  Set_Associated_Storage_Pool (U_Ent, Pool);
+               else
+                  Error_Msg_N ("Non sharable GNAT Pool", Expr);
+               end if;
+
+            --  The pool may be specified as the Storage_Pool of some other
+            --  type. It is rewritten as a class_wide conversion of the
+            --  corresponding pool entity.
+
+            elsif Nkind (Expr) = N_Type_Conversion
+              and then Is_Entity_Name (Expression (Expr))
+              and then Nkind (Original_Node (Expr)) = N_Attribute_Reference
+            then
+               Pool := Entity (Expression (Expr));
+
+               if Present (Etype (Pool))
+                 and then Etype (Pool) /= RTE (RE_Stack_Bounded_Pool)
+                 and then Etype (Pool) /= RTE (RE_Unbounded_Reclaim_Pool)
+               then
+                  Set_Associated_Storage_Pool (U_Ent, Pool);
+               else
+                  Error_Msg_N ("Non sharable GNAT Pool", Expr);
+               end if;
+
+            else
+               Error_Msg_N ("incorrect reference to a Storage Pool", Expr);
+               return;
+            end if;
+         end Storage_Pool;
+
+         ----------------
+         -- Value_Size --
+         ----------------
+
+         --  Value_Size attribute definition clause
+
+         when Attribute_Value_Size => Value_Size : declare
+            Size   : constant Uint := Static_Integer (Expr);
+            Biased : Boolean;
+
+         begin
+            if not Is_Type (U_Ent) then
+               Error_Msg_N ("Value_Size cannot be given for &", Nam);
+
+            elsif Present
+                   (Get_Attribute_Definition_Clause
+                     (U_Ent, Attribute_Value_Size))
+            then
+               Error_Msg_N ("Value_Size already given for &", Nam);
+
+            else
+               if Is_Elementary_Type (U_Ent) then
+                  Check_Size (Expr, U_Ent, Size, Biased);
+                  Set_Has_Biased_Representation (U_Ent, Biased);
+               end if;
+
+               Set_RM_Size (U_Ent, Size);
+            end if;
+         end Value_Size;
+
+         -----------
+         -- Write --
+         -----------
+
+         --  Write attribute definition clause
+         --  check for class-wide case will be performed later
+
+         when Attribute_Write => Write : declare
+            Subp : Entity_Id := Empty;
+            I    : Interp_Index;
+            It   : Interp;
+            Pnam : Entity_Id;
+
+            function Has_Good_Profile (Subp : Entity_Id) return Boolean;
+            --  Return true if the entity is a procedure with an
+            --  appropriate profile for the write attribute.
+
+            function Has_Good_Profile (Subp : Entity_Id) return Boolean is
+               F     : Entity_Id;
+               Ok    : Boolean := False;
+
+            begin
+               if Ekind (Subp) = E_Procedure then
+                  F := First_Formal (Subp);
+
+                  if Present (F) then
+                     if Ekind (Etype (F)) = E_Anonymous_Access_Type
+                       and then
+                         Designated_Type (Etype (F)) =
+                           Class_Wide_Type (RTE (RE_Root_Stream_Type))
+                     then
+                        Next_Formal (F);
+                        Ok :=  Present (F)
+                          and then Parameter_Mode (F) = E_In_Parameter
+                          and then Base_Type (Etype (F)) = Base_Type (Ent)
+                          and then No (Next_Formal (F));
+                     end if;
+                  end if;
+               end if;
+
+               return Ok;
+            end Has_Good_Profile;
+
+         --  Start of processing for Write attribute definition
+
+         begin
+            FOnly := True;
+
+            if not Is_Type (U_Ent) then
+               Error_Msg_N ("local name must be a subtype", Nam);
+               return;
+            end if;
+
+            Pnam := TSS (Base_Type (U_Ent), Name_uWrite);
+
+            if Present (Pnam)
+              and then Base_Type (Etype (Next_Formal (First_Formal (Pnam))))
+                = Base_Type (U_Ent)
+            then
+               Error_Msg_Sloc := Sloc (Pnam);
+               Error_Msg_N ("write attribute already defined #", Nam);
+               return;
+            end if;
+
+            Analyze (Expr);
+
+            if Is_Entity_Name (Expr) then
+               if not Is_Overloaded (Expr) then
+                  if Has_Good_Profile (Entity (Expr)) then
+                     Subp := Entity (Expr);
+                  end if;
+
+               else
+                  Get_First_Interp (Expr, I, It);
+
+                  while Present (It.Nam) loop
+                     if Has_Good_Profile (It.Nam) then
+                        Subp := It.Nam;
+                        exit;
+                     end if;
+
+                     Get_Next_Interp (I, It);
+                  end loop;
+               end if;
+            end if;
+
+            if Present (Subp) then
+               Set_Entity (Expr, Subp);
+               Set_Etype (Expr, Etype (Subp));
+               New_Stream_Procedure (N, U_Ent, Subp, Name_uWrite);
+            else
+               Error_Msg_N ("incorrect expression for write attribute", Expr);
+               return;
+            end if;
+         end Write;
+
+         --  All other attributes cannot be set
+
+         when others =>
+            Error_Msg_N
+              ("attribute& cannot be set with definition clause", N);
+
+      end case;
+
+      --  The test for the type being frozen must be performed after
+      --  any expression the clause has been analyzed since the expression
+      --  itself might cause freezing that makes the clause illegal.
+
+      if Rep_Item_Too_Late (U_Ent, N, FOnly) then
+         return;
+      end if;
+   end Analyze_Attribute_Definition_Clause;
+
+   ----------------------------
+   -- Analyze_Code_Statement --
+   ----------------------------
+
+   procedure Analyze_Code_Statement (N : Node_Id) is
+      HSS   : constant Node_Id   := Parent (N);
+      SBody : constant Node_Id   := Parent (HSS);
+      Subp  : constant Entity_Id := Current_Scope;
+      Stmt  : Node_Id;
+      Decl  : Node_Id;
+      StmtO : Node_Id;
+      DeclO : Node_Id;
+
+   begin
+      --  Analyze and check we get right type, note that this implements the
+      --  requirement (RM 13.8(1)) that Machine_Code be with'ed, since that
+      --  is the only way that Asm_Insn could possibly be visible.
+
+      Analyze_And_Resolve (Expression (N));
+
+      if Etype (Expression (N)) = Any_Type then
+         return;
+      elsif Etype (Expression (N)) /= RTE (RE_Asm_Insn) then
+         Error_Msg_N ("incorrect type for code statement", N);
+         return;
+      end if;
+
+      --  Make sure we appear in the handled statement sequence of a
+      --  subprogram (RM 13.8(3)).
+
+      if Nkind (HSS) /= N_Handled_Sequence_Of_Statements
+        or else Nkind (SBody) /= N_Subprogram_Body
+      then
+         Error_Msg_N
+           ("code statement can only appear in body of subprogram", N);
+         return;
+      end if;
+
+      --  Do remaining checks (RM 13.8(3)) if not already done
+
+      if not Is_Machine_Code_Subprogram (Subp) then
+         Set_Is_Machine_Code_Subprogram (Subp);
+
+         --  No exception handlers allowed
+
+         if Present (Exception_Handlers (HSS)) then
+            Error_Msg_N
+              ("exception handlers not permitted in machine code subprogram",
+               First (Exception_Handlers (HSS)));
+         end if;
+
+         --  No declarations other than use clauses and pragmas (we allow
+         --  certain internally generated declarations as well).
+
+         Decl := First (Declarations (SBody));
+         while Present (Decl) loop
+            DeclO := Original_Node (Decl);
+            if Comes_From_Source (DeclO)
+              and then Nkind (DeclO) /= N_Pragma
+              and then Nkind (DeclO) /= N_Use_Package_Clause
+              and then Nkind (DeclO) /= N_Use_Type_Clause
+              and then Nkind (DeclO) /= N_Implicit_Label_Declaration
+            then
+               Error_Msg_N
+                 ("this declaration not allowed in machine code subprogram",
+                  DeclO);
+            end if;
+
+            Next (Decl);
+         end loop;
+
+         --  No statements other than code statements, pragmas, and labels.
+         --  Again we allow certain internally generated statements.
+
+         Stmt := First (Statements (HSS));
+         while Present (Stmt) loop
+            StmtO := Original_Node (Stmt);
+            if Comes_From_Source (StmtO)
+              and then Nkind (StmtO) /= N_Pragma
+              and then Nkind (StmtO) /= N_Label
+              and then Nkind (StmtO) /= N_Code_Statement
+            then
+               Error_Msg_N
+                 ("this statement is not allowed in machine code subprogram",
+                  StmtO);
+            end if;
+
+            Next (Stmt);
+         end loop;
+      end if;
+
+   end Analyze_Code_Statement;
+
+   -----------------------------------------------
+   -- Analyze_Enumeration_Representation_Clause --
+   -----------------------------------------------
+
+   procedure Analyze_Enumeration_Representation_Clause (N : Node_Id) is
+      Ident    : constant Node_Id    := Identifier (N);
+      Aggr     : constant Node_Id    := Array_Aggregate (N);
+      Enumtype : Entity_Id;
+      Elit     : Entity_Id;
+      Expr     : Node_Id;
+      Assoc    : Node_Id;
+      Choice   : Node_Id;
+      Val      : Uint;
+      Err      : Boolean := False;
+
+      Lo  : constant Uint := Expr_Value (Type_Low_Bound (Universal_Integer));
+      Hi  : constant Uint := Expr_Value (Type_High_Bound (Universal_Integer));
+      Min : Uint;
+      Max : Uint;
+
+   begin
+      --  First some basic error checks
+
+      Find_Type (Ident);
+      Enumtype := Entity (Ident);
+
+      if Enumtype = Any_Type
+        or else Rep_Item_Too_Early (Enumtype, N)
+      then
+         return;
+      else
+         Enumtype := Underlying_Type (Enumtype);
+      end if;
+
+      if not Is_Enumeration_Type (Enumtype) then
+         Error_Msg_NE
+           ("enumeration type required, found}",
+            Ident, First_Subtype (Enumtype));
+         return;
+      end if;
+
+      if Scope (Enumtype) /= Current_Scope then
+         Error_Msg_N ("type must be declared in this scope", Ident);
+         return;
+
+      elsif not Is_First_Subtype (Enumtype) then
+         Error_Msg_N ("cannot give enumeration rep clause for subtype", N);
+         return;
+
+      elsif Has_Enumeration_Rep_Clause (Enumtype) then
+         Error_Msg_N ("duplicate enumeration rep clause ignored", N);
+         return;
+
+      elsif Root_Type (Enumtype) = Standard_Character
+        or else Root_Type (Enumtype) = Standard_Wide_Character
+      then
+         Error_Msg_N ("enumeration rep clause not allowed for this type", N);
+
+      else
+         Set_Has_Enumeration_Rep_Clause (Enumtype);
+         Set_Has_Enumeration_Rep_Clause (Base_Type (Enumtype));
+      end if;
+
+      --  Now we process the aggregate. Note that we don't use the normal
+      --  aggregate code for this purpose, because we don't want any of the
+      --  normal expansion activities, and a number of special semantic
+      --  rules apply (including the component type being any integer type)
+
+      --  Badent signals that we found some incorrect entries processing
+      --  the list. The final checks for completeness and ordering are
+      --  skipped in this case.
+
+      Elit := First_Literal (Enumtype);
+
+      --  First the positional entries if any
+
+      if Present (Expressions (Aggr)) then
+         Expr := First (Expressions (Aggr));
+         while Present (Expr) loop
+            if No (Elit) then
+               Error_Msg_N ("too many entries in aggregate", Expr);
+               return;
+            end if;
+
+            Val := Static_Integer (Expr);
+
+            if Val = No_Uint then
+               Err := True;
+
+            elsif Val < Lo or else Hi < Val then
+               Error_Msg_N ("value outside permitted range", Expr);
+               Err := True;
+            end if;
+
+            Set_Enumeration_Rep (Elit, Val);
+            Set_Enumeration_Rep_Expr (Elit, Expr);
+            Next (Expr);
+            Next (Elit);
+         end loop;
+      end if;
+
+      --  Now process the named entries if present
+
+      if Present (Component_Associations (Aggr)) then
+         Assoc := First (Component_Associations (Aggr));
+         while Present (Assoc) loop
+            Choice := First (Choices (Assoc));
+
+            if Present (Next (Choice)) then
+               Error_Msg_N
+                 ("multiple choice not allowed here", Next (Choice));
+               Err := True;
+            end if;
+
+            if Nkind (Choice) = N_Others_Choice then
+               Error_Msg_N ("others choice not allowed here", Choice);
+               Err := True;
+
+            elsif Nkind (Choice) = N_Range then
+               --  ??? should allow zero/one element range here
+               Error_Msg_N ("range not allowed here", Choice);
+               Err := True;
+
+            else
+               Analyze_And_Resolve (Choice, Enumtype);
+
+               if Is_Entity_Name (Choice)
+                 and then Is_Type (Entity (Choice))
+               then
+                  Error_Msg_N ("subtype name not allowed here", Choice);
+                  Err := True;
+                  --  ??? should allow static subtype with zero/one entry
+
+               elsif Etype (Choice) = Base_Type (Enumtype) then
+                  if not Is_Static_Expression (Choice) then
+                     Error_Msg_N
+                       ("non-static expression used for choice", Choice);
+                     Err := True;
+
+                  else
+                     Elit := Expr_Value_E (Choice);
+
+                     if Present (Enumeration_Rep_Expr (Elit)) then
+                        Error_Msg_Sloc := Sloc (Enumeration_Rep_Expr (Elit));
+                        Error_Msg_NE
+                          ("representation for& previously given#",
+                           Choice, Elit);
+                        Err := True;
+                     end if;
+
+                     Set_Enumeration_Rep_Expr (Elit, Choice);
+
+                     Expr := Expression (Assoc);
+                     Val := Static_Integer (Expr);
+
+                     if Val = No_Uint then
+                        Err := True;
+
+                     elsif Val < Lo or else Hi < Val then
+                        Error_Msg_N ("value outside permitted range", Expr);
+                        Err := True;
+                     end if;
+
+                     Set_Enumeration_Rep (Elit, Val);
+                  end if;
+               end if;
+            end if;
+
+            Next (Assoc);
+         end loop;
+      end if;
+
+      --  Aggregate is fully processed. Now we check that a full set of
+      --  representations was given, and that they are in range and in order.
+      --  These checks are only done if no other errors occurred.
+
+      if not Err then
+         Min  := No_Uint;
+         Max  := No_Uint;
+
+         Elit := First_Literal (Enumtype);
+         while Present (Elit) loop
+            if No (Enumeration_Rep_Expr (Elit)) then
+               Error_Msg_NE ("missing representation for&!", N, Elit);
+
+            else
+               Val := Enumeration_Rep (Elit);
+
+               if Min = No_Uint then
+                  Min := Val;
+               end if;
+
+               if Val /= No_Uint then
+                  if Max /= No_Uint and then Val <= Max then
+                     Error_Msg_NE
+                       ("enumeration value for& not ordered!",
+                                       Enumeration_Rep_Expr (Elit), Elit);
+                  end if;
+
+                  Max := Val;
+               end if;
+
+               --  If there is at least one literal whose representation
+               --  is not equal to the Pos value, then note that this
+               --  enumeration type has a non-standard representation.
+
+               if Val /= Enumeration_Pos (Elit) then
+                  Set_Has_Non_Standard_Rep (Base_Type (Enumtype));
+               end if;
+            end if;
+
+            Next (Elit);
+         end loop;
+
+         --  Now set proper size information
+
+         declare
+            Minsize : Uint := UI_From_Int (Minimum_Size (Enumtype));
+
+         begin
+            if Has_Size_Clause (Enumtype) then
+               if Esize (Enumtype) >= Minsize then
+                  null;
+
+               else
+                  Minsize :=
+                    UI_From_Int (Minimum_Size (Enumtype, Biased => True));
+
+                  if Esize (Enumtype) < Minsize then
+                     Error_Msg_N ("previously given size is too small", N);
+
+                  else
+                     Set_Has_Biased_Representation (Enumtype);
+                  end if;
+               end if;
+
+            else
+               Set_RM_Size    (Enumtype, Minsize);
+               Set_Enum_Esize (Enumtype);
+            end if;
+
+            Set_RM_Size   (Base_Type (Enumtype), RM_Size   (Enumtype));
+            Set_Esize     (Base_Type (Enumtype), Esize     (Enumtype));
+            Set_Alignment (Base_Type (Enumtype), Alignment (Enumtype));
+         end;
+      end if;
+
+      --  We repeat the too late test in case it froze itself!
+
+      if Rep_Item_Too_Late (Enumtype, N) then
+         null;
+      end if;
+
+   end Analyze_Enumeration_Representation_Clause;
+
+   ----------------------------
+   -- Analyze_Free_Statement --
+   ----------------------------
+
+   procedure Analyze_Free_Statement (N : Node_Id) is
+   begin
+      Analyze (Expression (N));
+   end Analyze_Free_Statement;
+
+   ------------------------------------------
+   -- Analyze_Record_Representation_Clause --
+   ------------------------------------------
+
+   procedure Analyze_Record_Representation_Clause (N : Node_Id) is
+      Loc     : constant Source_Ptr := Sloc (N);
+      Ident   : constant Node_Id    := Identifier (N);
+      Rectype : Entity_Id;
+      Fent    : Entity_Id;
+      CC      : Node_Id;
+      Posit   : Uint;
+      Fbit    : Uint;
+      Lbit    : Uint;
+      Hbit    : Uint := Uint_0;
+      Comp    : Entity_Id;
+      Ocomp   : Entity_Id;
+      Biased  : Boolean;
+
+      Max_Bit_So_Far : Uint;
+      --  Records the maximum bit position so far. If all field positoins
+      --  are monotonically increasing, then we can skip the circuit for
+      --  checking for overlap, since no overlap is possible.
+
+      Overlap_Check_Required : Boolean;
+      --  Used to keep track of whether or not an overlap check is required
+
+      Ccount : Natural := 0;
+      --  Number of component clauses in record rep clause
+
+   begin
+      Find_Type (Ident);
+      Rectype := Entity (Ident);
+
+      if Rectype = Any_Type
+        or else Rep_Item_Too_Early (Rectype, N)
+      then
+         return;
+      else
+         Rectype := Underlying_Type (Rectype);
+      end if;
+
+      --  First some basic error checks
+
+      if not Is_Record_Type (Rectype) then
+         Error_Msg_NE
+           ("record type required, found}", Ident, First_Subtype (Rectype));
+         return;
+
+      elsif Is_Unchecked_Union (Rectype) then
+         Error_Msg_N
+           ("record rep clause not allowed for Unchecked_Union", N);
+
+      elsif Scope (Rectype) /= Current_Scope then
+         Error_Msg_N ("type must be declared in this scope", N);
+         return;
+
+      elsif not Is_First_Subtype (Rectype) then
+         Error_Msg_N ("cannot give record rep clause for subtype", N);
+         return;
+
+      elsif Has_Record_Rep_Clause (Rectype) then
+         Error_Msg_N ("duplicate record rep clause ignored", N);
+         return;
+
+      elsif Rep_Item_Too_Late (Rectype, N) then
+         return;
+      end if;
+
+      if Present (Mod_Clause (N)) then
+         declare
+            Loc     : constant Source_Ptr := Sloc (N);
+            M       : constant Node_Id := Mod_Clause (N);
+            P       : constant List_Id := Pragmas_Before (M);
+            Mod_Val : Uint;
+            AtM_Nod : Node_Id;
+
+         begin
+            if Present (P) then
+               Analyze_List (P);
+            end if;
+
+            --  In Tree_Output mode, expansion is disabled, but we must
+            --  convert the Mod clause into an alignment clause anyway, so
+            --  that the back-end can compute and back-annotate properly the
+            --  size and alignment of types that may include this record.
+
+            if Operating_Mode = Check_Semantics
+              and then Tree_Output
+            then
+               AtM_Nod :=
+                 Make_Attribute_Definition_Clause (Loc,
+                   Name       => New_Reference_To (Base_Type (Rectype), Loc),
+                   Chars      => Name_Alignment,
+                   Expression => Relocate_Node (Expression (M)));
+
+               Set_From_At_Mod (AtM_Nod);
+               Insert_After (N, AtM_Nod);
+               Mod_Val := Get_Alignment_Value (Expression (AtM_Nod));
+               Set_Mod_Clause (N, Empty);
+
+            else
+               --  Get the alignment value to perform error checking
+
+               Mod_Val := Get_Alignment_Value (Expression (M));
+
+            end if;
+         end;
+      end if;
+
+      --  Clear any existing component clauses for the type (this happens
+      --  with derived types, where we are now overriding the original)
+
+      Fent := First_Entity (Rectype);
+
+      Comp := Fent;
+      while Present (Comp) loop
+         if Ekind (Comp) = E_Component
+           or else Ekind (Comp) = E_Discriminant
+         then
+            Set_Component_Clause (Comp, Empty);
+         end if;
+
+         Next_Entity (Comp);
+      end loop;
+
+      --  All done if no component clauses
+
+      CC := First (Component_Clauses (N));
+
+      if No (CC) then
+         return;
+      end if;
+
+      --  If a tag is present, then create a component clause that places
+      --  it at the start of the record (otherwise gigi may place it after
+      --  other fields that have rep clauses).
+
+      if Nkind (Fent) = N_Defining_Identifier
+        and then Chars (Fent) = Name_uTag
+      then
+         Set_Component_Bit_Offset    (Fent, Uint_0);
+         Set_Normalized_Position     (Fent, Uint_0);
+         Set_Normalized_First_Bit    (Fent, Uint_0);
+         Set_Normalized_Position_Max (Fent, Uint_0);
+         Init_Esize                  (Fent, System_Address_Size);
+
+         Set_Component_Clause    (Fent,
+           Make_Component_Clause (Loc,
+             Component_Name =>
+               Make_Identifier (Loc,
+                 Chars => Name_uTag),
+
+             Position  =>
+               Make_Integer_Literal (Loc,
+                 Intval => Uint_0),
+
+             First_Bit =>
+               Make_Integer_Literal (Loc,
+                 Intval => Uint_0),
+
+             Last_Bit  =>
+               Make_Integer_Literal (Loc,
+                 UI_From_Int (System_Address_Size))));
+
+         Ccount := Ccount + 1;
+      end if;
+
+      Set_Has_Record_Rep_Clause (Rectype);
+      Set_Has_Specified_Layout  (Rectype);
+
+      --  A representation like this applies to the base type as well
+
+      Set_Has_Record_Rep_Clause (Base_Type (Rectype));
+      Set_Has_Non_Standard_Rep  (Base_Type (Rectype));
+      Set_Has_Specified_Layout  (Base_Type (Rectype));
+
+      Max_Bit_So_Far := Uint_Minus_1;
+      Overlap_Check_Required := False;
+
+      --  Process the component clauses
+
+      while Present (CC) loop
+
+         --  If pragma, just analyze it
+
+         if Nkind (CC) = N_Pragma then
+            Analyze (CC);
+
+         --  Processing for real component clause
+
+         else
+            Ccount := Ccount + 1;
+            Posit := Static_Integer (Position  (CC));
+            Fbit  := Static_Integer (First_Bit (CC));
+            Lbit  := Static_Integer (Last_Bit  (CC));
+
+            if Posit /= No_Uint
+              and then Fbit /= No_Uint
+              and then Lbit /= No_Uint
+            then
+               if Posit < 0 then
+                  Error_Msg_N
+                    ("position cannot be negative", Position (CC));
+
+               elsif Fbit < 0 then
+                  Error_Msg_N
+                    ("first bit cannot be negative", First_Bit (CC));
+
+               --  Values look OK, so find the corresponding record component
+               --  Even though the syntax allows an attribute reference for
+               --  implementation-defined components, GNAT does not allow the
+               --  tag to get an explicit position.
+
+               elsif Nkind (Component_Name (CC)) = N_Attribute_Reference then
+
+                  if Attribute_Name (Component_Name (CC)) = Name_Tag then
+                     Error_Msg_N ("position of tag cannot be specified", CC);
+                  else
+                     Error_Msg_N ("illegal component name", CC);
+                  end if;
+
+               else
+                  Comp := First_Entity (Rectype);
+                  while Present (Comp) loop
+                     exit when Chars (Comp) = Chars (Component_Name (CC));
+                     Next_Entity (Comp);
+                  end loop;
+
+                  if No (Comp) then
+
+                     --  Maybe component of base type that is absent from
+                     --  statically constrained first subtype.
+
+                     Comp := First_Entity (Base_Type (Rectype));
+                     while Present (Comp) loop
+                        exit when Chars (Comp) = Chars (Component_Name (CC));
+                        Next_Entity (Comp);
+                     end loop;
+                  end if;
+
+                  if No (Comp) then
+                     Error_Msg_N
+                       ("component clause is for non-existent field", CC);
+
+                  elsif Present (Component_Clause (Comp)) then
+                     Error_Msg_Sloc := Sloc (Component_Clause (Comp));
+                     Error_Msg_N
+                       ("component clause previously given#", CC);
+
+                  else
+                     --  Update Fbit and Lbit to the actual bit number.
+
+                     Fbit := Fbit + UI_From_Int (SSU) * Posit;
+                     Lbit := Lbit + UI_From_Int (SSU) * Posit;
+
+                     if Fbit <= Max_Bit_So_Far then
+                        Overlap_Check_Required := True;
+                     else
+                        Max_Bit_So_Far := Lbit;
+                     end if;
+
+                     if Has_Size_Clause (Rectype)
+                       and then Esize (Rectype) <= Lbit
+                     then
+                        Error_Msg_N
+                          ("bit number out of range of specified size",
+                           Last_Bit (CC));
+                     else
+                        Set_Component_Clause     (Comp, CC);
+                        Set_Component_Bit_Offset (Comp, Fbit);
+                        Set_Esize                (Comp, 1 + (Lbit - Fbit));
+                        Set_Normalized_First_Bit (Comp, Fbit mod SSU);
+                        Set_Normalized_Position  (Comp, Fbit / SSU);
+
+                        Set_Normalized_Position_Max
+                          (Fent, Normalized_Position (Fent));
+
+                        if Is_Tagged_Type (Rectype)
+                          and then Fbit < System_Address_Size
+                        then
+                           Error_Msg_NE
+                             ("component overlaps tag field of&",
+                              CC, Rectype);
+                        end if;
+
+                        --  Test for large object that is not on a byte
+                        --  boundary, defined as a large packed array not
+                        --  represented by a modular type, or an object for
+                        --  which a size of greater than 64 bits is specified.
+
+                        if Fbit mod SSU /= 0 then
+                           if (Is_Packed_Array_Type (Etype (Comp))
+                                and then Is_Array_Type
+                                     (Packed_Array_Type (Etype (Comp))))
+                             or else Esize (Etype (Comp)) > 64
+                           then
+                              Error_Msg_N
+                                ("large component must be on byte boundary",
+                                 First_Bit (CC));
+                           end if;
+                        end if;
+
+                        --  This information is also set in the
+                        --  corresponding component of the base type,
+                        --  found by accessing the Original_Record_Component
+                        --  link if it is present.
+
+                        Ocomp := Original_Record_Component (Comp);
+
+                        if Hbit < Lbit then
+                           Hbit := Lbit;
+                        end if;
+
+                        Check_Size
+                          (Component_Name (CC),
+                           Etype (Comp),
+                           Esize (Comp),
+                           Biased);
+
+                        Set_Has_Biased_Representation (Comp, Biased);
+
+                        if Present (Ocomp) then
+                           Set_Component_Clause     (Ocomp, CC);
+                           Set_Component_Bit_Offset (Ocomp, Fbit);
+                           Set_Normalized_First_Bit (Ocomp, Fbit mod SSU);
+                           Set_Normalized_Position  (Ocomp, Fbit / SSU);
+                           Set_Esize                (Ocomp, 1 + (Lbit - Fbit));
+
+                           Set_Normalized_Position_Max
+                             (Ocomp, Normalized_Position (Ocomp));
+
+                           Set_Has_Biased_Representation
+                             (Ocomp, Has_Biased_Representation (Comp));
+                        end if;
+
+                        if Esize (Comp) < 0 then
+                           Error_Msg_N ("component size is negative", CC);
+                        end if;
+                     end if;
+                  end if;
+               end if;
+            end if;
+         end if;
+
+         Next (CC);
+      end loop;
+
+      --  Now that we have processed all the component clauses, check for
+      --  overlap. We have to leave this till last, since the components
+      --  can appear in any arbitrary order in the representation clause.
+
+      --  We do not need this check if all specified ranges were monotonic,
+      --  as recorded by Overlap_Check_Required being False at this stage.
+
+      --  This first section checks if there are any overlapping entries
+      --  at all. It does this by sorting all entries and then seeing if
+      --  there are any overlaps. If there are none, then that is decisive,
+      --  but if there are overlaps, they may still be OK (they may result
+      --  from fields in different variants).
+
+      if Overlap_Check_Required then
+         Overlap_Check1 : declare
+
+            OC_Fbit : array (0 .. Ccount) of Uint;
+            --  First-bit values for component clauses, the value is the
+            --  offset of the first bit of the field from start of record.
+            --  The zero entry is for use in sorting.
+
+            OC_Lbit : array (0 .. Ccount) of Uint;
+            --  Last-bit values for component clauses, the value is the
+            --  offset of the last bit of the field from start of record.
+            --  The zero entry is for use in sorting.
+
+            OC_Count : Natural := 0;
+            --  Count of entries in OC_Fbit and OC_Lbit
+
+            function OC_Lt (Op1, Op2 : Natural) return Boolean;
+            --  Compare routine for Sort (See GNAT.Heap_Sort_A)
+
+            procedure OC_Move (From : Natural; To : Natural);
+            --  Move routine for Sort (see GNAT.Heap_Sort_A)
+
+            function OC_Lt (Op1, Op2 : Natural) return Boolean is
+            begin
+               return OC_Fbit (Op1) < OC_Fbit (Op2);
+            end OC_Lt;
+
+            procedure OC_Move (From : Natural; To : Natural) is
+            begin
+               OC_Fbit (To) := OC_Fbit (From);
+               OC_Lbit (To) := OC_Lbit (From);
+            end OC_Move;
+
+         begin
+            CC := First (Component_Clauses (N));
+            while Present (CC) loop
+               if Nkind (CC) /= N_Pragma then
+                  Posit := Static_Integer (Position  (CC));
+                  Fbit  := Static_Integer (First_Bit (CC));
+                  Lbit  := Static_Integer (Last_Bit  (CC));
+
+                  if Posit /= No_Uint
+                    and then Fbit /= No_Uint
+                    and then Lbit /= No_Uint
+                  then
+                     OC_Count := OC_Count + 1;
+                     Posit := Posit * SSU;
+                     OC_Fbit (OC_Count) := Fbit + Posit;
+                     OC_Lbit (OC_Count) := Lbit + Posit;
+                  end if;
+               end if;
+
+               Next (CC);
+            end loop;
+
+            Sort
+              (OC_Count,
+               OC_Move'Unrestricted_Access,
+               OC_Lt'Unrestricted_Access);
+
+            Overlap_Check_Required := False;
+            for J in 1 .. OC_Count - 1 loop
+               if OC_Lbit (J) >= OC_Fbit (J + 1) then
+                  Overlap_Check_Required := True;
+                  exit;
+               end if;
+            end loop;
+         end Overlap_Check1;
+      end if;
+
+      --  If Overlap_Check_Required is still True, then we have to do
+      --  the full scale overlap check, since we have at least two fields
+      --  that do overlap, and we need to know if that is OK since they
+      --  are in the same variant, or whether we have a definite problem
+
+      if Overlap_Check_Required then
+         Overlap_Check2 : declare
+            C1_Ent, C2_Ent : Entity_Id;
+            --  Entities of components being checked for overlap
+
+            Clist : Node_Id;
+            --  Component_List node whose Component_Items are being checked
+
+            Citem : Node_Id;
+            --  Component declaration for component being checked
+
+         begin
+            C1_Ent := First_Entity (Base_Type (Rectype));
+
+            --  Loop through all components in record. For each component check
+            --  for overlap with any of the preceding elements on the component
+            --  list containing the component, and also, if the component is in
+            --  a variant, check against components outside the case structure.
+            --  This latter test is repeated recursively up the variant tree.
+
+            Main_Component_Loop : while Present (C1_Ent) loop
+               if Ekind (C1_Ent) /= E_Component
+                 and then Ekind (C1_Ent) /= E_Discriminant
+               then
+                  goto Continue_Main_Component_Loop;
+               end if;
+
+               --  Skip overlap check if entity has no declaration node. This
+               --  happens with discriminants in constrained derived types.
+               --  Probably we are missing some checks as a result, but that
+               --  does not seem terribly serious ???
+
+               if No (Declaration_Node (C1_Ent)) then
+                  goto Continue_Main_Component_Loop;
+               end if;
+
+               Clist := Parent (List_Containing (Declaration_Node (C1_Ent)));
+
+               --  Loop through component lists that need checking. Check the
+               --  current component list and all lists in variants above us.
+
+               Component_List_Loop : loop
+
+                  --  If derived type definition, go to full declaration
+                  --  If at outer level, check discriminants if there are any
+
+                  if Nkind (Clist) = N_Derived_Type_Definition then
+                     Clist := Parent (Clist);
+                  end if;
+
+                  --  Outer level of record definition, check discriminants
+
+                  if Nkind (Clist) = N_Full_Type_Declaration
+                    or else Nkind (Clist) = N_Private_Type_Declaration
+                  then
+                     if Has_Discriminants (Defining_Identifier (Clist)) then
+                        C2_Ent :=
+                          First_Discriminant (Defining_Identifier (Clist));
+
+                        while Present (C2_Ent) loop
+                           exit when C1_Ent = C2_Ent;
+                           Check_Component_Overlap (C1_Ent, C2_Ent);
+                           Next_Discriminant (C2_Ent);
+                        end loop;
+                     end if;
+
+                  --  Record extension case
+
+                  elsif Nkind (Clist) = N_Derived_Type_Definition then
+                     Clist := Empty;
+
+                  --  Otherwise check one component list
+
+                  else
+                     Citem := First (Component_Items (Clist));
+
+                     while Present (Citem) loop
+                        if Nkind (Citem) = N_Component_Declaration then
+                           C2_Ent := Defining_Identifier (Citem);
+                           exit when C1_Ent = C2_Ent;
+                           Check_Component_Overlap (C1_Ent, C2_Ent);
+                        end if;
+
+                        Next (Citem);
+                     end loop;
+                  end if;
+
+                  --  Check for variants above us (the parent of the Clist can
+                  --  be a variant, in which case its parent is a variant part,
+                  --  and the parent of the variant part is a component list
+                  --  whose components must all be checked against the current
+                  --  component for overlap.
+
+                  if Nkind (Parent (Clist)) = N_Variant then
+                     Clist := Parent (Parent (Parent (Clist)));
+
+                  --  Check for possible discriminant part in record, this is
+                  --  treated essentially as another level in the recursion.
+                  --  For this case we have the parent of the component list
+                  --  is the record definition, and its parent is the full
+                  --  type declaration which contains the discriminant
+                  --  specifications.
+
+                  elsif Nkind (Parent (Clist)) = N_Record_Definition then
+                     Clist := Parent (Parent ((Clist)));
+
+                  --  If neither of these two cases, we are at the top of
+                  --  the tree
+
+                  else
+                     exit Component_List_Loop;
+                  end if;
+               end loop Component_List_Loop;
+
+               <<Continue_Main_Component_Loop>>
+                  Next_Entity (C1_Ent);
+
+            end loop Main_Component_Loop;
+         end Overlap_Check2;
+      end if;
+
+      --  For records that have component clauses for all components, and
+      --  whose size is less than or equal to 32, we need to know the size
+      --  in the front end to activate possible packed array processing
+      --  where the component type is a record.
+
+      --  At this stage Hbit + 1 represents the first unused bit from all
+      --  the component clauses processed, so if the component clauses are
+      --  complete, then this is the length of the record.
+
+      --  For records longer than System.Storage_Unit, and for those where
+      --  not all components have component clauses, the back end determines
+      --  the length (it may for example be appopriate to round up the size
+      --  to some convenient boundary, based on alignment considerations etc).
+
+      if Unknown_RM_Size (Rectype)
+        and then Hbit + 1 <= 32
+      then
+         --  Nothing to do if at least one component with no component clause
+
+         Comp := First_Entity (Rectype);
+         while Present (Comp) loop
+            if Ekind (Comp) = E_Component
+              or else Ekind (Comp) = E_Discriminant
+            then
+               if No (Component_Clause (Comp)) then
+                  return;
+               end if;
+            end if;
+
+            Next_Entity (Comp);
+         end loop;
+
+         --  If we fall out of loop, all components have component clauses
+         --  and so we can set the size to the maximum value.
+
+         Set_RM_Size (Rectype, Hbit + 1);
+      end if;
+
+   end Analyze_Record_Representation_Clause;
+
+   -----------------------------
+   -- Check_Address_Alignment --
+   -----------------------------
+
+   procedure Check_Address_Alignment (E : Entity_Id; Expr : Node_Id) is
+      Arg : Node_Id;
+
+   begin
+      if Nkind (Expr) = N_Unchecked_Type_Conversion then
+         Arg := Expression (Expr);
+
+      elsif Nkind (Expr) = N_Function_Call
+        and then Is_RTE (Entity (Name (Expr)), RE_To_Address)
+      then
+         Arg := First (Parameter_Associations (Expr));
+
+         if Nkind (Arg) = N_Parameter_Association then
+            Arg := Explicit_Actual_Parameter (Arg);
+         end if;
+
+      else
+         return;
+      end if;
+
+      --  Here Arg is the address value
+
+      if Compile_Time_Known_Value (Arg) then
+         if Expr_Value (Arg) mod Alignment (E) /= 0 then
+            Error_Msg_NE
+              ("?specified address for& not consistent with alignment",
+               Arg, E);
+         end if;
+      end if;
+   end Check_Address_Alignment;
+
+   -----------------------------
+   -- Check_Component_Overlap --
+   -----------------------------
+
+   procedure Check_Component_Overlap (C1_Ent, C2_Ent : Entity_Id) is
+   begin
+      if Present (Component_Clause (C1_Ent))
+        and then Present (Component_Clause (C2_Ent))
+      then
+         --  Exclude odd case where we have two tag fields in the same
+         --  record, both at location zero. This seems a bit strange,
+         --  but it seems to happen in some circumstances ???
+
+         if Chars (C1_Ent) = Name_uTag
+           and then Chars (C2_Ent) = Name_uTag
+         then
+            return;
+         end if;
+
+         --  Here we check if the two fields overlap
+
+         declare
+            S1 : constant Uint := Component_Bit_Offset (C1_Ent);
+            S2 : constant Uint := Component_Bit_Offset (C2_Ent);
+            E1 : constant Uint := S1 + Esize (C1_Ent);
+            E2 : constant Uint := S2 + Esize (C2_Ent);
+
+         begin
+            if E2 <= S1 or else E1 <= S2 then
+               null;
+            else
+               Error_Msg_Node_2 :=
+                 Component_Name (Component_Clause (C2_Ent));
+               Error_Msg_Sloc := Sloc (Error_Msg_Node_2);
+               Error_Msg_Node_1 :=
+                 Component_Name (Component_Clause (C1_Ent));
+               Error_Msg_N
+                 ("component& overlaps & #",
+                  Component_Name (Component_Clause (C1_Ent)));
+            end if;
+         end;
+      end if;
+   end Check_Component_Overlap;
+
+   -----------------------------------
+   -- Check_Constant_Address_Clause --
+   -----------------------------------
+
+   procedure Check_Constant_Address_Clause
+     (Expr  : Node_Id;
+      U_Ent : Entity_Id)
+   is
+      procedure Check_At_Constant_Address (Nod : Node_Id);
+      --  Checks that the given node N represents a name whose 'Address
+      --  is constant (in the same sense as OK_Constant_Address_Clause,
+      --  i.e. the address value is the same at the point of declaration
+      --  of U_Ent and at the time of elaboration of the address clause.
+
+      procedure Check_Expr_Constants (Nod : Node_Id);
+      --  Checks that Nod meets the requirements for a constant address
+      --  clause in the sense of the enclosing procedure.
+
+      procedure Check_List_Constants (Lst : List_Id);
+      --  Check that all elements of list Lst meet the requirements for a
+      --  constant address clause in the sense of the enclosing procedure.
+
+      -------------------------------
+      -- Check_At_Constant_Address --
+      -------------------------------
+
+      procedure Check_At_Constant_Address (Nod : Node_Id) is
+      begin
+         if Is_Entity_Name (Nod) then
+            if Present (Address_Clause (Entity ((Nod)))) then
+               Error_Msg_NE
+                 ("invalid address clause for initialized object &!",
+                           Nod, U_Ent);
+               Error_Msg_NE
+                 ("address for& cannot" &
+                    " depend on another address clause! ('R'M 13.1(22))!",
+                  Nod, U_Ent);
+
+            elsif In_Same_Source_Unit (Entity (Nod), U_Ent)
+              and then Sloc (U_Ent) < Sloc (Entity (Nod))
+            then
+               Error_Msg_NE
+                 ("invalid address clause for initialized object &!",
+                  Nod, U_Ent);
+               Error_Msg_Name_1 := Chars (Entity (Nod));
+               Error_Msg_Name_2 := Chars (U_Ent);
+               Error_Msg_N
+                 ("\% must be defined before % ('R'M 13.1(22))!",
+                  Nod);
+            end if;
+
+         elsif Nkind (Nod) = N_Selected_Component then
+            declare
+               T : constant Entity_Id := Etype (Prefix (Nod));
+
+            begin
+               if (Is_Record_Type (T)
+                    and then Has_Discriminants (T))
+                 or else
+                  (Is_Access_Type (T)
+                     and then Is_Record_Type (Designated_Type (T))
+                     and then Has_Discriminants (Designated_Type (T)))
+               then
+                  Error_Msg_NE
+                    ("invalid address clause for initialized object &!",
+                     Nod, U_Ent);
+                  Error_Msg_N
+                    ("\address cannot depend on component" &
+                     " of discriminated record ('R'M 13.1(22))!",
+                     Nod);
+               else
+                  Check_At_Constant_Address (Prefix (Nod));
+               end if;
+            end;
+
+         elsif Nkind (Nod) = N_Indexed_Component then
+            Check_At_Constant_Address (Prefix (Nod));
+            Check_List_Constants (Expressions (Nod));
+
+         else
+            Check_Expr_Constants (Nod);
+         end if;
+      end Check_At_Constant_Address;
+
+      --------------------------
+      -- Check_Expr_Constants --
+      --------------------------
+
+      procedure Check_Expr_Constants (Nod : Node_Id) is
+      begin
+         if Nkind (Nod) in N_Has_Etype
+           and then Etype (Nod) = Any_Type
+         then
+            return;
+         end if;
+
+         case Nkind (Nod) is
+            when N_Empty | N_Error =>
+               return;
+
+            when N_Identifier | N_Expanded_Name =>
+               declare
+                  Ent       : constant Entity_Id  := Entity (Nod);
+                  Loc_Ent   : constant Source_Ptr := Sloc (Ent);
+                  Loc_U_Ent : constant Source_Ptr := Sloc (U_Ent);
+
+               begin
+                  if Ekind (Ent) = E_Named_Integer
+                       or else
+                     Ekind (Ent) = E_Named_Real
+                       or else
+                     Is_Type (Ent)
+                  then
+                     return;
+
+                  elsif
+                     Ekind (Ent) = E_Constant
+                       or else
+                     Ekind (Ent) = E_In_Parameter
+                  then
+                     --  This is the case where we must have Ent defined
+                     --  before U_Ent. Clearly if they are in different
+                     --  units this requirement is met since the unit
+                     --  containing Ent is already processed.
+
+                     if not In_Same_Source_Unit (Ent, U_Ent) then
+                        return;
+
+                     --  Otherwise location of Ent must be before the
+                     --  location of U_Ent, that's what prior defined means.
+
+                     elsif Loc_Ent < Loc_U_Ent then
+                        return;
+
+                     else
+                        Error_Msg_NE
+                          ("invalid address clause for initialized object &!",
+                           Nod, U_Ent);
+                        Error_Msg_Name_1 := Chars (Ent);
+                        Error_Msg_Name_2 := Chars (U_Ent);
+                        Error_Msg_N
+                          ("\% must be defined before % ('R'M 13.1(22))!",
+                           Nod);
+                     end if;
+
+                  elsif Nkind (Original_Node (Nod)) = N_Function_Call then
+                     Check_Expr_Constants (Original_Node (Nod));
+
+                  else
+                     Error_Msg_NE
+                       ("invalid address clause for initialized object &!",
+                        Nod, U_Ent);
+                     Error_Msg_Name_1 := Chars (Ent);
+                     Error_Msg_N
+                       ("\reference to variable% not allowed ('R'M 13.1(22))!",
+                        Nod);
+                  end if;
+               end;
+
+            when N_Integer_Literal   |
+                 N_Real_Literal      |
+                 N_String_Literal    |
+                 N_Character_Literal =>
+               return;
+
+            when N_Range =>
+               Check_Expr_Constants (Low_Bound (Nod));
+               Check_Expr_Constants (High_Bound (Nod));
+
+            when N_Explicit_Dereference =>
+               Check_Expr_Constants (Prefix (Nod));
+
+            when N_Indexed_Component =>
+               Check_Expr_Constants (Prefix (Nod));
+               Check_List_Constants (Expressions (Nod));
+
+            when N_Slice =>
+               Check_Expr_Constants (Prefix (Nod));
+               Check_Expr_Constants (Discrete_Range (Nod));
+
+            when N_Selected_Component =>
+               Check_Expr_Constants (Prefix (Nod));
+
+            when N_Attribute_Reference =>
+
+               if (Attribute_Name (Nod) = Name_Address
+                    or else
+                   Attribute_Name (Nod) = Name_Access
+                    or else
+                   Attribute_Name (Nod) = Name_Unchecked_Access
+                    or else
+                   Attribute_Name (Nod) = Name_Unrestricted_Access)
+               then
+                  Check_At_Constant_Address (Prefix (Nod));
+
+               else
+                  Check_Expr_Constants (Prefix (Nod));
+                  Check_List_Constants (Expressions (Nod));
+               end if;
+
+            when N_Aggregate =>
+               Check_List_Constants (Component_Associations (Nod));
+               Check_List_Constants (Expressions (Nod));
+
+            when N_Component_Association =>
+               Check_Expr_Constants (Expression (Nod));
+
+            when N_Extension_Aggregate =>
+               Check_Expr_Constants (Ancestor_Part (Nod));
+               Check_List_Constants (Component_Associations (Nod));
+               Check_List_Constants (Expressions (Nod));
+
+            when N_Null =>
+               return;
+
+            when N_Binary_Op | N_And_Then | N_Or_Else | N_In | N_Not_In =>
+               Check_Expr_Constants (Left_Opnd (Nod));
+               Check_Expr_Constants (Right_Opnd (Nod));
+
+            when N_Unary_Op =>
+               Check_Expr_Constants (Right_Opnd (Nod));
+
+            when N_Type_Conversion           |
+                 N_Qualified_Expression      |
+                 N_Allocator                 =>
+               Check_Expr_Constants (Expression (Nod));
+
+            when N_Unchecked_Type_Conversion =>
+               Check_Expr_Constants (Expression (Nod));
+
+               --  If this is a rewritten unchecked conversion, subtypes
+               --  in this node are those created within the instance.
+               --  To avoid order of elaboration issues, replace them
+               --  with their base types. Note that address clauses can
+               --  cause order of elaboration problems because they are
+               --  elaborated by the back-end at the point of definition,
+               --  and may mention entities declared in between (as long
+               --  as everything is static). It is user-friendly to allow
+               --  unchecked conversions in this context.
+
+               if Nkind (Original_Node (Nod)) = N_Function_Call then
+                  Set_Etype (Expression (Nod),
+                    Base_Type (Etype (Expression (Nod))));
+                  Set_Etype (Nod, Base_Type (Etype (Nod)));
+               end if;
+
+            when N_Function_Call =>
+               if not Is_Pure (Entity (Name (Nod))) then
+                  Error_Msg_NE
+                    ("invalid address clause for initialized object &!",
+                     Nod, U_Ent);
+
+                  Error_Msg_NE
+                    ("\function & is not pure ('R'M 13.1(22))!",
+                     Nod, Entity (Name (Nod)));
+
+               else
+                  Check_List_Constants (Parameter_Associations (Nod));
+               end if;
+
+            when N_Parameter_Association =>
+               Check_Expr_Constants (Explicit_Actual_Parameter (Nod));
+
+            when others =>
+               Error_Msg_NE
+                 ("invalid address clause for initialized object &!",
+                  Nod, U_Ent);
+               Error_Msg_NE
+                 ("\must be constant defined before& ('R'M 13.1(22))!",
+                  Nod, U_Ent);
+         end case;
+      end Check_Expr_Constants;
+
+      --------------------------
+      -- Check_List_Constants --
+      --------------------------
+
+      procedure Check_List_Constants (Lst : List_Id) is
+         Nod1 : Node_Id;
+
+      begin
+         if Present (Lst) then
+            Nod1 := First (Lst);
+            while Present (Nod1) loop
+               Check_Expr_Constants (Nod1);
+               Next (Nod1);
+            end loop;
+         end if;
+      end Check_List_Constants;
+
+   --  Start of processing for Check_Constant_Address_Clause
+
+   begin
+      Check_Expr_Constants (Expr);
+   end Check_Constant_Address_Clause;
+
+   ----------------
+   -- Check_Size --
+   ----------------
+
+   procedure Check_Size
+     (N      : Node_Id;
+      T      : Entity_Id;
+      Siz    : Uint;
+      Biased : out Boolean)
+   is
+      UT : constant Entity_Id := Underlying_Type (T);
+      M  : Uint;
+
+   begin
+      Biased := False;
+
+      --  Immediate return if size is same as standard size or if composite
+      --  item, or generic type, or type with previous errors.
+
+      if No (UT)
+        or else UT = Any_Type
+        or else Is_Generic_Type (UT)
+        or else Is_Generic_Type (Root_Type (UT))
+        or else Is_Composite_Type (UT)
+        or else (Known_Esize (UT) and then Siz = Esize (UT))
+      then
+         return;
+
+      --  For fixed-point types, don't check minimum if type is not frozen,
+      --  since type is not known till then
+      --  at freeze time.
+
+      elsif Is_Fixed_Point_Type (UT)
+        and then not Is_Frozen (UT)
+      then
+         null;
+
+      --  Cases for which a minimum check is required
+
+      else
+         M := UI_From_Int (Minimum_Size (UT));
+
+         if Siz < M then
+
+            --  Size is less than minimum size, but one possibility remains
+            --  that we can manage with the new size if we bias the type
+
+            M := UI_From_Int (Minimum_Size (UT, Biased => True));
+
+            if Siz < M then
+               Error_Msg_Uint_1 := M;
+               Error_Msg_NE
+                 ("size for& too small, minimum allowed is ^", N, T);
+            else
+               Biased := True;
+            end if;
+         end if;
+      end if;
+   end Check_Size;
+
+   -------------------------
+   -- Get_Alignment_Value --
+   -------------------------
+
+   function Get_Alignment_Value (Expr : Node_Id) return Uint is
+      Align : constant Uint := Static_Integer (Expr);
+
+   begin
+      if Align = No_Uint then
+         return No_Uint;
+
+      elsif Align <= 0 then
+         Error_Msg_N ("alignment value must be positive", Expr);
+         return No_Uint;
+
+      else
+         for J in Int range 0 .. 64 loop
+            declare
+               M : constant Uint := Uint_2 ** J;
+
+            begin
+               exit when M = Align;
+
+               if M > Align then
+                  Error_Msg_N
+                    ("alignment value must be power of 2", Expr);
+                  return No_Uint;
+               end if;
+            end;
+         end loop;
+
+         return Align;
+      end if;
+   end Get_Alignment_Value;
+
+   -------------------------------------
+   -- Get_Attribute_Definition_Clause --
+   -------------------------------------
+
+   function Get_Attribute_Definition_Clause
+     (E    : Entity_Id;
+      Id   : Attribute_Id)
+      return Node_Id
+   is
+      N : Node_Id;
+
+   begin
+      N := First_Rep_Item (E);
+      while Present (N) loop
+         if Nkind (N) = N_Attribute_Definition_Clause
+           and then Get_Attribute_Id (Chars (N)) = Id
+         then
+            return N;
+         else
+            Next_Rep_Item (N);
+         end if;
+      end loop;
+
+      return Empty;
+   end Get_Attribute_Definition_Clause;
+
+   --------------------
+   -- Get_Rep_Pragma --
+   --------------------
+
+   function Get_Rep_Pragma (E : Entity_Id; Nam : Name_Id) return Node_Id is
+      N   : Node_Id;
+      Typ : Entity_Id;
+
+   begin
+      N := First_Rep_Item (E);
+
+      while Present (N) loop
+         if Nkind (N) = N_Pragma and then Chars (N) = Nam then
+
+            if Nam = Name_Stream_Convert then
+
+               --  For tagged types this pragma is not inherited, so we
+               --  must verify that it is defined for the given type and
+               --  not an ancestor.
+
+               Typ := Entity (Expression
+                       (First (Pragma_Argument_Associations (N))));
+
+               if not Is_Tagged_Type (E)
+                 or else E = Typ
+                 or else (Is_Private_Type (Typ)
+                           and then E = Full_View (Typ))
+               then
+                  return N;
+               else
+                  Next_Rep_Item (N);
+               end if;
+
+            else
+               return N;
+            end if;
+         else
+            Next_Rep_Item (N);
+         end if;
+      end loop;
+
+      return Empty;
+   end Get_Rep_Pragma;
+
+   ----------------
+   -- Initialize --
+   ----------------
+
+   procedure Initialize is
+   begin
+      Unchecked_Conversions.Init;
+   end Initialize;
+
+   -------------------------
+   -- Is_Operational_Item --
+   -------------------------
+
+   function Is_Operational_Item (N : Node_Id) return Boolean is
+   begin
+      if Nkind (N) /= N_Attribute_Definition_Clause then
+         return False;
+      else
+         declare
+            Id    : constant Attribute_Id := Get_Attribute_Id (Chars (N));
+
+         begin
+            return Id = Attribute_Input
+              or else Id = Attribute_Output
+              or else Id = Attribute_Read
+              or else Id = Attribute_Write;
+         end;
+      end if;
+   end Is_Operational_Item;
+
+   ------------------
+   -- Minimum_Size --
+   ------------------
+
+   function Minimum_Size
+     (T      : Entity_Id;
+      Biased : Boolean := False)
+      return   Nat
+   is
+      Lo     : Uint    := No_Uint;
+      Hi     : Uint    := No_Uint;
+      LoR    : Ureal   := No_Ureal;
+      HiR    : Ureal   := No_Ureal;
+      LoSet  : Boolean := False;
+      HiSet  : Boolean := False;
+      B      : Uint;
+      S      : Nat;
+      Ancest : Entity_Id;
+
+   begin
+      --  If bad type, return 0
+
+      if T = Any_Type then
+         return 0;
+
+      --  For generic types, just return zero. There cannot be any legitimate
+      --  need to know such a size, but this routine may be called with a
+      --  generic type as part of normal processing.
+
+      elsif Is_Generic_Type (Root_Type (T)) then
+         return 0;
+
+      --  Access types
+
+      elsif Is_Access_Type (T) then
+         return System_Address_Size;
+
+      --  Floating-point types
+
+      elsif Is_Floating_Point_Type (T) then
+         return UI_To_Int (Esize (Root_Type (T)));
+
+      --  Discrete types
+
+      elsif Is_Discrete_Type (T) then
+
+         --  The following loop is looking for the nearest compile time
+         --  known bounds following the ancestor subtype chain. The idea
+         --  is to find the most restrictive known bounds information.
+
+         Ancest := T;
+         loop
+            if Ancest = Any_Type or else Etype (Ancest) = Any_Type then
+               return 0;
+            end if;
+
+            if not LoSet then
+               if Compile_Time_Known_Value (Type_Low_Bound (Ancest)) then
+                  Lo := Expr_Rep_Value (Type_Low_Bound (Ancest));
+                  LoSet := True;
+                  exit when HiSet;
+               end if;
+            end if;
+
+            if not HiSet then
+               if Compile_Time_Known_Value (Type_High_Bound (Ancest)) then
+                  Hi := Expr_Rep_Value (Type_High_Bound (Ancest));
+                  HiSet := True;
+                  exit when LoSet;
+               end if;
+            end if;
+
+            Ancest := Ancestor_Subtype (Ancest);
+
+            if No (Ancest) then
+               Ancest := Base_Type (T);
+
+               if Is_Generic_Type (Ancest) then
+                  return 0;
+               end if;
+            end if;
+         end loop;
+
+      --  Fixed-point types. We can't simply use Expr_Value to get the
+      --  Corresponding_Integer_Value values of the bounds, since these
+      --  do not get set till the type is frozen, and this routine can
+      --  be called before the type is frozen. Similarly the test for
+      --  bounds being static needs to include the case where we have
+      --  unanalyzed real literals for the same reason.
+
+      elsif Is_Fixed_Point_Type (T) then
+
+         --  The following loop is looking for the nearest compile time
+         --  known bounds following the ancestor subtype chain. The idea
+         --  is to find the most restrictive known bounds information.
+
+         Ancest := T;
+         loop
+            if Ancest = Any_Type or else Etype (Ancest) = Any_Type then
+               return 0;
+            end if;
+
+            if not LoSet then
+               if Nkind (Type_Low_Bound (Ancest)) = N_Real_Literal
+                 or else Compile_Time_Known_Value (Type_Low_Bound (Ancest))
+               then
+                  LoR := Expr_Value_R (Type_Low_Bound (Ancest));
+                  LoSet := True;
+                  exit when HiSet;
+               end if;
+            end if;
+
+            if not HiSet then
+               if Nkind (Type_High_Bound (Ancest)) = N_Real_Literal
+                 or else Compile_Time_Known_Value (Type_High_Bound (Ancest))
+               then
+                  HiR := Expr_Value_R (Type_High_Bound (Ancest));
+                  HiSet := True;
+                  exit when LoSet;
+               end if;
+            end if;
+
+            Ancest := Ancestor_Subtype (Ancest);
+
+            if No (Ancest) then
+               Ancest := Base_Type (T);
+
+               if Is_Generic_Type (Ancest) then
+                  return 0;
+               end if;
+            end if;
+         end loop;
+
+         Lo := UR_To_Uint (LoR / Small_Value (T));
+         Hi := UR_To_Uint (HiR / Small_Value (T));
+
+      --  No other types allowed
+
+      else
+         raise Program_Error;
+      end if;
+
+      --  Fall through with Hi and Lo set. Deal with biased case.
+
+      if (Biased and then not Is_Fixed_Point_Type (T))
+        or else Has_Biased_Representation (T)
+      then
+         Hi := Hi - Lo;
+         Lo := Uint_0;
+      end if;
+
+      --  Signed case. Note that we consider types like range 1 .. -1 to be
+      --  signed for the purpose of computing the size, since the bounds
+      --  have to be accomodated in the base type.
+
+      if Lo < 0 or else Hi < 0 then
+         S := 1;
+         B := Uint_1;
+
+         --  S = size, B = 2 ** (size - 1) (can accomodate -B .. +(B - 1))
+         --  Note that we accomodate the case where the bounds cross. This
+         --  can happen either because of the way the bounds are declared
+         --  or because of the algorithm in Freeze_Fixed_Point_Type.
+
+         while Lo < -B
+           or else Hi < -B
+           or else Lo >= B
+           or else Hi >= B
+         loop
+            B := Uint_2 ** S;
+            S := S + 1;
+         end loop;
+
+      --  Unsigned case
+
+      else
+         --  If both bounds are positive, make sure that both are represen-
+         --  table in the case where the bounds are crossed. This can happen
+         --  either because of the way the bounds are declared, or because of
+         --  the algorithm in Freeze_Fixed_Point_Type.
+
+         if Lo > Hi then
+            Hi := Lo;
+         end if;
+
+         --  S = size, (can accomodate 0 .. (2**size - 1))
+
+         S := 0;
+         while Hi >= Uint_2 ** S loop
+            S := S + 1;
+         end loop;
+      end if;
+
+      return S;
+   end Minimum_Size;
+
+   -------------------------
+   -- New_Stream_Function --
+   -------------------------
+
+   procedure New_Stream_Function
+     (N    : Node_Id;
+      Ent  : Entity_Id;
+      Subp : Entity_Id;
+      Nam  : Name_Id)
+   is
+      Loc       : constant Source_Ptr := Sloc (N);
+      Subp_Id   : Entity_Id := Make_Defining_Identifier (Loc, Nam);
+      Subp_Decl : Node_Id;
+      F         : Entity_Id;
+      Etyp      : Entity_Id;
+
+   begin
+      F        := First_Formal (Subp);
+      Etyp     := Etype (Subp);
+
+      Subp_Decl :=
+        Make_Subprogram_Renaming_Declaration (Loc,
+          Specification =>
+
+            Make_Function_Specification (Loc,
+              Defining_Unit_Name => Subp_Id,
+              Parameter_Specifications =>
+                New_List (
+                  Make_Parameter_Specification (Loc,
+                    Defining_Identifier =>
+                      Make_Defining_Identifier (Loc, Name_S),
+                    Parameter_Type =>
+                      Make_Access_Definition (Loc,
+                        Subtype_Mark =>
+                          New_Reference_To (
+                            Designated_Type (Etype (F)), Loc)))),
+
+              Subtype_Mark =>
+                New_Reference_To (Etyp, Loc)),
+
+        Name => New_Reference_To (Subp, Loc));
+
+      if Is_Tagged_Type (Ent) and then not Is_Limited_Type (Ent) then
+         Set_TSS (Base_Type (Ent), Subp_Id);
+      else
+         Insert_Action (N, Subp_Decl);
+         Copy_TSS (Subp_Id, Base_Type (Ent));
+      end if;
+
+   end New_Stream_Function;
+
+   --------------------------
+   -- New_Stream_Procedure --
+   --------------------------
+
+   procedure New_Stream_Procedure
+     (N     : Node_Id;
+      Ent   : Entity_Id;
+      Subp  : Entity_Id;
+      Nam   : Name_Id;
+      Out_P : Boolean := False)
+   is
+      Loc       : constant Source_Ptr := Sloc (N);
+      Subp_Id   : Entity_Id := Make_Defining_Identifier (Loc, Nam);
+      Subp_Decl : Node_Id;
+      F         : Entity_Id;
+      Etyp      : Entity_Id;
+
+   begin
+      F        := First_Formal (Subp);
+      Etyp     := Etype (Next_Formal (F));
+
+      Subp_Decl :=
+        Make_Subprogram_Renaming_Declaration (Loc,
+          Specification =>
+
+            Make_Procedure_Specification (Loc,
+              Defining_Unit_Name => Subp_Id,
+              Parameter_Specifications =>
+                New_List (
+                  Make_Parameter_Specification (Loc,
+                    Defining_Identifier =>
+                      Make_Defining_Identifier (Loc, Name_S),
+                    Parameter_Type =>
+                      Make_Access_Definition (Loc,
+                        Subtype_Mark =>
+                          New_Reference_To (
+                            Designated_Type (Etype (F)), Loc))),
+
+                  Make_Parameter_Specification (Loc,
+                    Defining_Identifier =>
+                      Make_Defining_Identifier (Loc, Name_V),
+                    Out_Present => Out_P,
+                    Parameter_Type =>
+                      New_Reference_To (Etyp, Loc)))),
+        Name => New_Reference_To (Subp, Loc));
+
+      if Is_Tagged_Type (Ent) and then not Is_Limited_Type (Ent) then
+         Set_TSS (Base_Type (Ent), Subp_Id);
+      else
+         Insert_Action (N, Subp_Decl);
+         Copy_TSS (Subp_Id, Base_Type (Ent));
+      end if;
+
+   end New_Stream_Procedure;
+
+   ---------------------
+   -- Record_Rep_Item --
+   ---------------------
+
+   procedure Record_Rep_Item (T : Entity_Id; N : Node_Id) is
+   begin
+      Set_Next_Rep_Item (N, First_Rep_Item (T));
+      Set_First_Rep_Item (T, N);
+   end Record_Rep_Item;
+
+   ------------------------
+   -- Rep_Item_Too_Early --
+   ------------------------
+
+   function Rep_Item_Too_Early
+     (T     : Entity_Id;
+      N     : Node_Id)
+      return  Boolean
+   is
+   begin
+      --  Cannot apply rep items to generic types
+
+      if Is_Type (T)
+        and then Is_Generic_Type (Root_Type (T))
+      then
+         Error_Msg_N
+           ("representation item not allowed for generic type", N);
+         return True;
+      end if;
+
+      --  Otherwise check for incompleted type
+
+      if Is_Incomplete_Or_Private_Type (T)
+        and then No (Underlying_Type (T))
+      then
+         Error_Msg_N
+           ("representation item must be after full type declaration", N);
+         return True;
+
+      --  If the type has incompleted components, a representation clause is
+      --  illegal but stream attributes and Convention pragmas are correct.
+
+      elsif Has_Private_Component (T) then
+         if (Nkind (N) = N_Pragma or else Is_Operational_Item (N)) then
+            return False;
+         else
+            Error_Msg_N
+              ("representation item must appear after type is fully defined",
+                N);
+            return True;
+         end if;
+      else
+         return False;
+      end if;
+   end Rep_Item_Too_Early;
+
+   -----------------------
+   -- Rep_Item_Too_Late --
+   -----------------------
+
+   function Rep_Item_Too_Late
+     (T     : Entity_Id;
+      N     : Node_Id;
+      FOnly : Boolean := False)
+      return  Boolean
+   is
+      S           : Entity_Id;
+      Parent_Type : Entity_Id;
+
+      procedure Too_Late;
+      --  Output the too late message
+
+      procedure Too_Late is
+      begin
+         Error_Msg_N ("representation item appears too late!", N);
+      end Too_Late;
+
+   --  Start of processing for Rep_Item_Too_Late
+
+   begin
+      --  First make sure entity is not frozen (RM 13.1(9)). Exclude imported
+      --  types, which may be frozen if they appear in a representation clause
+      --  for a local type.
+
+      if Is_Frozen (T)
+        and then not From_With_Type (T)
+      then
+         Too_Late;
+         S := First_Subtype (T);
+
+         if Present (Freeze_Node (S)) then
+            Error_Msg_NE
+              ("?no more representation items for }!", Freeze_Node (S), S);
+         end if;
+
+         return True;
+
+      --  Check for case of non-tagged derived type whose parent either has
+      --  primitive operations, or is a by reference type (RM 13.1(10)).
+
+      elsif Is_Type (T)
+        and then not FOnly
+        and then Is_Derived_Type (T)
+        and then not Is_Tagged_Type (T)
+      then
+         Parent_Type := Etype (Base_Type (T));
+
+         if Has_Primitive_Operations (Parent_Type) then
+            Too_Late;
+            Error_Msg_NE
+              ("primitive operations already defined for&!", N, Parent_Type);
+            return True;
+
+         elsif Is_By_Reference_Type (Parent_Type) then
+            Too_Late;
+            Error_Msg_NE
+              ("parent type & is a by reference type!", N, Parent_Type);
+            return True;
+         end if;
+      end if;
+
+      --  No error, link item into head of chain of rep items for the entity
+
+      Record_Rep_Item (T, N);
+      return False;
+   end Rep_Item_Too_Late;
+
+   -------------------------
+   -- Same_Representation --
+   -------------------------
+
+   function Same_Representation (Typ1, Typ2 : Entity_Id) return Boolean is
+      T1 : constant Entity_Id := Underlying_Type (Typ1);
+      T2 : constant Entity_Id := Underlying_Type (Typ2);
+
+   begin
+      --  A quick check, if base types are the same, then we definitely have
+      --  the same representation, because the subtype specific representation
+      --  attributes (Size and Alignment) do not affect representation from
+      --  the point of view of this test.
+
+      if Base_Type (T1) = Base_Type (T2) then
+         return True;
+
+      elsif Is_Private_Type (Base_Type (T2))
+        and then Base_Type (T1) = Full_View (Base_Type (T2))
+      then
+         return True;
+      end if;
+
+      --  Tagged types never have differing representations
+
+      if Is_Tagged_Type (T1) then
+         return True;
+      end if;
+
+      --  Representations are definitely different if conventions differ
+
+      if Convention (T1) /= Convention (T2) then
+         return False;
+      end if;
+
+      --  Representations are different if component alignments differ
+
+      if (Is_Record_Type (T1) or else Is_Array_Type (T1))
+        and then
+         (Is_Record_Type (T2) or else Is_Array_Type (T2))
+        and then Component_Alignment (T1) /= Component_Alignment (T2)
+      then
+         return False;
+      end if;
+
+      --  For arrays, the only real issue is component size. If we know the
+      --  component size for both arrays, and it is the same, then that's
+      --  good enough to know we don't have a change of representation.
+
+      if Is_Array_Type (T1) then
+         if Known_Component_Size (T1)
+           and then Known_Component_Size (T2)
+           and then Component_Size (T1) = Component_Size (T2)
+         then
+            return True;
+         end if;
+      end if;
+
+      --  Types definitely have same representation if neither has non-standard
+      --  representation since default representations are always consistent.
+      --  If only one has non-standard representation, and the other does not,
+      --  then we consider that they do not have the same representation. They
+      --  might, but there is no way of telling early enough.
+
+      if Has_Non_Standard_Rep (T1) then
+         if not Has_Non_Standard_Rep (T2) then
+            return False;
+         end if;
+      else
+         return not Has_Non_Standard_Rep (T2);
+      end if;
+
+      --  Here the two types both have non-standard representation, and we
+      --  need to determine if they have the same non-standard representation
+
+      --  For arrays, we simply need to test if the component sizes are the
+      --  same. Pragma Pack is reflected in modified component sizes, so this
+      --  check also deals with pragma Pack.
+
+      if Is_Array_Type (T1) then
+         return Component_Size (T1) = Component_Size (T2);
+
+      --  Tagged types always have the same representation, because it is not
+      --  possible to specify different representations for common fields.
+
+      elsif Is_Tagged_Type (T1) then
+         return True;
+
+      --  Case of record types
+
+      elsif Is_Record_Type (T1) then
+
+         --  Packed status must conform
+
+         if Is_Packed (T1) /= Is_Packed (T2) then
+            return False;
+
+         --  Otherwise we must check components. Typ2 maybe a constrained
+         --  subtype with fewer components, so we compare the components
+         --  of the base types.
+
+         else
+            Record_Case : declare
+               CD1, CD2 : Entity_Id;
+
+               function Same_Rep return Boolean;
+               --  CD1 and CD2 are either components or discriminants. This
+               --  function tests whether the two have the same representation
+
+               function Same_Rep return Boolean is
+               begin
+                  if No (Component_Clause (CD1)) then
+                     return No (Component_Clause (CD2));
+
+                  else
+                     return
+                        Present (Component_Clause (CD2))
+                          and then
+                        Component_Bit_Offset (CD1) = Component_Bit_Offset (CD2)
+                          and then
+                        Esize (CD1) = Esize (CD2);
+                  end if;
+               end Same_Rep;
+
+            --  Start processing for Record_Case
+
+            begin
+               if Has_Discriminants (T1) then
+                  CD1 := First_Discriminant (T1);
+                  CD2 := First_Discriminant (T2);
+
+                  while Present (CD1) loop
+                     if not Same_Rep then
+                        return False;
+                     else
+                        Next_Discriminant (CD1);
+                        Next_Discriminant (CD2);
+                     end if;
+                  end loop;
+               end if;
+
+               CD1 := First_Component (Underlying_Type (Base_Type (T1)));
+               CD2 := First_Component (Underlying_Type (Base_Type (T2)));
+
+               while Present (CD1) loop
+                  if not Same_Rep then
+                     return False;
+                  else
+                     Next_Component (CD1);
+                     Next_Component (CD2);
+                  end if;
+               end loop;
+
+               return True;
+            end Record_Case;
+         end if;
+
+      --  For enumeration types, we must check each literal to see if the
+      --  representation is the same. Note that we do not permit enumeration
+      --  reprsentation clauses for Character and Wide_Character, so these
+      --  cases were already dealt with.
+
+      elsif Is_Enumeration_Type (T1) then
+
+         Enumeration_Case : declare
+            L1, L2 : Entity_Id;
+
+         begin
+            L1 := First_Literal (T1);
+            L2 := First_Literal (T2);
+
+            while Present (L1) loop
+               if Enumeration_Rep (L1) /= Enumeration_Rep (L2) then
+                  return False;
+               else
+                  Next_Literal (L1);
+                  Next_Literal (L2);
+               end if;
+            end loop;
+
+            return True;
+
+         end Enumeration_Case;
+
+      --  Any other types have the same representation for these purposes
+
+      else
+         return True;
+      end if;
+
+   end Same_Representation;
+
+   --------------------
+   -- Set_Enum_Esize --
+   --------------------
+
+   procedure Set_Enum_Esize (T : Entity_Id) is
+      Lo : Uint;
+      Hi : Uint;
+      Sz : Nat;
+
+   begin
+      Init_Alignment (T);
+
+      --  Find the minimum standard size (8,16,32,64) that fits
+
+      Lo := Enumeration_Rep (Entity (Type_Low_Bound (T)));
+      Hi := Enumeration_Rep (Entity (Type_High_Bound (T)));
+
+      if Lo < 0 then
+         if Lo >= -Uint_2**07 and then Hi < Uint_2**07 then
+            Sz := 8;
+
+         elsif Lo >= -Uint_2**15 and then Hi < Uint_2**15 then
+            Sz := 16;
+
+         elsif Lo >= -Uint_2**31 and then Hi < Uint_2**31 then
+            Sz := 32;
+
+         else pragma Assert (Lo >= -Uint_2**63 and then Hi < Uint_2**63);
+            Sz := 64;
+         end if;
+
+      else
+         if Hi < Uint_2**08 then
+            Sz := 8;
+
+         elsif Hi < Uint_2**16 then
+            Sz := 16;
+
+         elsif Hi < Uint_2**32 then
+            Sz := 32;
+
+         else pragma Assert (Hi < Uint_2**63);
+            Sz := 64;
+         end if;
+      end if;
+
+      --  That minimum is the proper size unless we have a foreign convention
+      --  and the size required is 32 or less, in which case we bump the size
+      --  up to 32. This is required for C and C++ and seems reasonable for
+      --  all other foreign conventions.
+
+      if Has_Foreign_Convention (T)
+        and then Esize (T) < Standard_Integer_Size
+      then
+         Init_Esize (T, Standard_Integer_Size);
+
+      else
+         Init_Esize (T, Sz);
+      end if;
+
+   end Set_Enum_Esize;
+
+   -----------------------------------
+   -- Validate_Unchecked_Conversion --
+   -----------------------------------
+
+   procedure Validate_Unchecked_Conversion
+     (N        : Node_Id;
+      Act_Unit : Entity_Id)
+   is
+      Source : Entity_Id;
+      Target : Entity_Id;
+      Vnode  : Node_Id;
+
+   begin
+      --  Obtain source and target types. Note that we call Ancestor_Subtype
+      --  here because the processing for generic instantiation always makes
+      --  subtypes, and we want the original frozen actual types.
+
+      --  If we are dealing with private types, then do the check on their
+      --  fully declared counterparts if the full declarations have been
+      --  encountered (they don't have to be visible, but they must exist!)
+
+      Source := Ancestor_Subtype (Etype (First_Formal (Act_Unit)));
+
+      if Is_Private_Type (Source)
+        and then Present (Underlying_Type (Source))
+      then
+         Source := Underlying_Type (Source);
+      end if;
+
+      Target := Ancestor_Subtype (Etype (Act_Unit));
+
+      --  If either type is generic, the instantiation happens within a
+      --  generic unit, and there is nothing to check. The proper check
+      --  will happen when the enclosing generic is instantiated.
+
+      if Is_Generic_Type (Source) or else Is_Generic_Type (Target) then
+         return;
+      end if;
+
+      if Is_Private_Type (Target)
+        and then Present (Underlying_Type (Target))
+      then
+         Target := Underlying_Type (Target);
+      end if;
+
+      --  Source may be unconstrained array, but not target
+
+      if Is_Array_Type (Target)
+        and then not Is_Constrained (Target)
+      then
+         Error_Msg_N
+           ("unchecked conversion to unconstrained array not allowed", N);
+         return;
+      end if;
+
+      --  Make entry in unchecked conversion table for later processing
+      --  by Validate_Unchecked_Conversions, which will check sizes and
+      --  alignments (using values set by the back-end where possible).
+
+      Unchecked_Conversions.Append
+        (New_Val => UC_Entry'
+           (Enode  => N,
+            Source => Source,
+            Target => Target));
+
+      --  Generate N_Validate_Unchecked_Conversion node for back end if
+      --  the back end needs to perform special validation checks. At the
+      --  current time, only the JVM version requires such checks.
+
+      if Java_VM then
+         Vnode :=
+           Make_Validate_Unchecked_Conversion (Sloc (N));
+         Set_Source_Type (Vnode, Source);
+         Set_Target_Type (Vnode, Target);
+         Insert_After (N, Vnode);
+      end if;
+   end Validate_Unchecked_Conversion;
+
+   ------------------------------------
+   -- Validate_Unchecked_Conversions --
+   ------------------------------------
+
+   procedure Validate_Unchecked_Conversions is
+   begin
+      for N in Unchecked_Conversions.First .. Unchecked_Conversions.Last loop
+         declare
+            T : UC_Entry renames Unchecked_Conversions.Table (N);
+
+            Enode  : constant Node_Id   := T.Enode;
+            Source : constant Entity_Id := T.Source;
+            Target : constant Entity_Id := T.Target;
+
+            Source_Siz    : Uint;
+            Target_Siz    : Uint;
+
+         begin
+            --  This validation check, which warns if we have unequal sizes
+            --  for unchecked conversion, and thus potentially implementation
+            --  dependent semantics, is one of the few occasions on which we
+            --  use the official RM size instead of Esize. See description
+            --  in Einfo "Handling of Type'Size Values" for details.
+
+            if Errors_Detected = 0
+              and then Known_Static_RM_Size (Source)
+              and then Known_Static_RM_Size (Target)
+            then
+               Source_Siz := RM_Size (Source);
+               Target_Siz := RM_Size (Target);
+
+               if Source_Siz /= Target_Siz then
+                  Warn_On_Instance := True;
+                  Error_Msg_N
+                    ("types for unchecked conversion have different sizes?",
+                     Enode);
+
+                  if All_Errors_Mode then
+                     Error_Msg_Name_1 := Chars (Source);
+                     Error_Msg_Uint_1 := Source_Siz;
+                     Error_Msg_Name_2 := Chars (Target);
+                     Error_Msg_Uint_2 := Target_Siz;
+                     Error_Msg_N
+                       ("\size of % is ^, size of % is ^?", Enode);
+
+                     Error_Msg_Uint_1 := UI_Abs (Source_Siz - Target_Siz);
+
+                     if Is_Discrete_Type (Source)
+                       and then Is_Discrete_Type (Target)
+                     then
+                        if Source_Siz > Target_Siz then
+                           Error_Msg_N
+                             ("\^ high order bits of source will be ignored?",
+                              Enode);
+
+                        elsif Is_Modular_Integer_Type (Source) then
+                           Error_Msg_N
+                             ("\source will be extended with ^ high order " &
+                              "zero bits?", Enode);
+
+                        else
+                           Error_Msg_N
+                             ("\source will be extended with ^ high order " &
+                              "sign bits?",
+                              Enode);
+                        end if;
+
+                     elsif Source_Siz < Target_Siz then
+                        if Is_Discrete_Type (Target) then
+                           if Bytes_Big_Endian then
+                              Error_Msg_N
+                                ("\target value will include ^ undefined " &
+                                 "low order bits?",
+                                 Enode);
+                           else
+                              Error_Msg_N
+                                ("\target value will include ^ undefined " &
+                                 "high order bits?",
+                                 Enode);
+                           end if;
+
+                        else
+                           Error_Msg_N
+                             ("\^ trailing bits of target value will be " &
+                              "undefined?", Enode);
+                        end if;
+
+                     else pragma Assert (Source_Siz > Target_Siz);
+                        Error_Msg_N
+                          ("\^ trailing bits of source will be ignored?",
+                           Enode);
+                     end if;
+                  end if;
+
+                  Warn_On_Instance := False;
+               end if;
+            end if;
+
+            --  If both types are access types, we need to check the alignment.
+            --  If the alignment of both is specified, we can do it here.
+
+            if Errors_Detected = 0
+              and then Ekind (Source) in Access_Kind
+              and then Ekind (Target) in Access_Kind
+              and then Target_Strict_Alignment
+              and then Present (Designated_Type (Source))
+              and then Present (Designated_Type (Target))
+            then
+               declare
+                  D_Source : constant Entity_Id := Designated_Type (Source);
+                  D_Target : constant Entity_Id := Designated_Type (Target);
+
+               begin
+                  if Known_Alignment (D_Source)
+                    and then Known_Alignment (D_Target)
+                  then
+                     declare
+                        Source_Align : constant Uint := Alignment (D_Source);
+                        Target_Align : constant Uint := Alignment (D_Target);
+
+                     begin
+                        if Source_Align < Target_Align
+                          and then not Is_Tagged_Type (D_Source)
+                        then
+                           Warn_On_Instance := True;
+                           Error_Msg_Uint_1 := Target_Align;
+                           Error_Msg_Uint_2 := Source_Align;
+                           Error_Msg_Node_2 := D_Source;
+                           Error_Msg_NE
+                             ("alignment of & (^) is stricter than " &
+                              "alignment of & (^)?", Enode, D_Target);
+
+                           if All_Errors_Mode then
+                              Error_Msg_N
+                                ("\resulting access value may have invalid " &
+                                 "alignment?", Enode);
+                           end if;
+
+                           Warn_On_Instance := False;
+                        end if;
+                     end;
+                  end if;
+               end;
+            end if;
+         end;
+      end loop;
+   end Validate_Unchecked_Conversions;
+
+   ------------------
+   -- Warn_Overlay --
+   ------------------
+
+   procedure Warn_Overlay
+     (Expr : Node_Id;
+      Typ  : Entity_Id;
+      Nam  : Node_Id)
+   is
+      Old  : Entity_Id := Empty;
+      Decl : Node_Id;
+
+   begin
+      if not Address_Clause_Overlay_Warnings then
+         return;
+      end if;
+
+      if Present (Expr)
+        and then (Has_Non_Null_Base_Init_Proc (Typ)
+                    or else Is_Access_Type (Typ))
+        and then not Is_Imported (Entity (Nam))
+      then
+         if Nkind (Expr) = N_Attribute_Reference
+           and then Is_Entity_Name (Prefix (Expr))
+         then
+            Old := Entity (Prefix (Expr));
+
+         elsif Is_Entity_Name (Expr)
+           and then Ekind (Entity (Expr)) = E_Constant
+         then
+            Decl := Declaration_Node (Entity (Expr));
+
+            if Nkind (Decl) = N_Object_Declaration
+              and then Present (Expression (Decl))
+              and then Nkind (Expression (Decl)) = N_Attribute_Reference
+              and then Is_Entity_Name (Prefix (Expression (Decl)))
+            then
+               Old := Entity (Prefix (Expression (Decl)));
+
+            elsif Nkind (Expr) = N_Function_Call then
+               return;
+            end if;
+
+         --  A function call (most likely to To_Address) is probably not
+         --  an overlay, so skip warning. Ditto if the function call was
+         --  inlined and transformed into an entity.
+
+         elsif Nkind (Original_Node (Expr)) = N_Function_Call then
+            return;
+         end if;
+
+         Decl := Next (Parent (Expr));
+
+         --  If a pragma Import follows, we assume that it is for the current
+         --  target of the address clause, and skip the warning.
+
+         if Present (Decl)
+           and then Nkind (Decl) = N_Pragma
+           and then Chars (Decl) = Name_Import
+         then
+            return;
+         end if;
+
+         if Present (Old) then
+            Error_Msg_Node_2 := Old;
+            Error_Msg_N
+              ("default initialization of & may modify &?",
+               Nam);
+         else
+            Error_Msg_N
+              ("default initialization of & may modify overlaid storage?",
+               Nam);
+         end if;
+
+         --  Add friendly warning if initialization comes from a packed array
+         --  component.
+
+         if Is_Record_Type (Typ)  then
+            declare
+               Comp : Entity_Id;
+
+            begin
+               Comp := First_Component (Typ);
+
+               while Present (Comp) loop
+                  if Nkind (Parent (Comp)) = N_Component_Declaration
+                    and then Present (Expression (Parent (Comp)))
+                  then
+                     exit;
+                  elsif Is_Array_Type (Etype (Comp))
+                     and then Present (Packed_Array_Type (Etype (Comp)))
+                  then
+                     Error_Msg_NE
+                       ("packed array component& will be initialized to zero?",
+                          Nam, Comp);
+                     exit;
+                  else
+                     Next_Component (Comp);
+                  end if;
+               end loop;
+            end;
+         end if;
+
+         Error_Msg_N
+           ("use pragma Import for & to " &
+              "suppress initialization ('R'M B.1(24))?",
+             Nam);
+      end if;
+   end Warn_Overlay;
+
+end Sem_Ch13;
diff --git a/gcc/ada/sem_ch13.ads b/gcc/ada/sem_ch13.ads
new file mode 100644 (file)
index 0000000..5afe5ad
--- /dev/null
@@ -0,0 +1,171 @@
+------------------------------------------------------------------------------
+--                                                                          --
+--                         GNAT COMPILER COMPONENTS                         --
+--                                                                          --
+--                             S E M _ C H 1 3                              --
+--                                                                          --
+--                                 S p e c                                  --
+--                                                                          --
+--                            $Revision: 1.39 $
+--                                                                          --
+--          Copyright (C) 1992-2001 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- --
+-- ware  Foundation;  either version 2,  or (at your option) any later ver- --
+-- sion.  GNAT is distributed in the hope that it will be useful, but WITH- --
+-- OUT ANY WARRANTY;  without even the  implied warranty of MERCHANTABILITY --
+-- or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License --
+-- for  more details.  You should have  received  a copy of the GNU General --
+-- Public License  distributed with GNAT;  see file COPYING.  If not, write --
+-- to  the Free Software Foundation,  59 Temple Place - Suite 330,  Boston, --
+-- MA 02111-1307, USA.                                                      --
+--                                                                          --
+-- GNAT was originally developed  by the GNAT team at  New York University. --
+-- It is now maintained by Ada Core Technologies Inc (http://www.gnat.com). --
+--                                                                          --
+------------------------------------------------------------------------------
+
+with Snames; use Snames;
+with Types; use Types;
+with Uintp; use Uintp;
+
+package Sem_Ch13 is
+   procedure Analyze_At_Clause                          (N : Node_Id);
+   procedure Analyze_Attribute_Definition_Clause        (N : Node_Id);
+   procedure Analyze_Enumeration_Representation_Clause  (N : Node_Id);
+   procedure Analyze_Free_Statement                     (N : Node_Id);
+   procedure Analyze_Record_Representation_Clause       (N : Node_Id);
+   procedure Analyze_Code_Statement                     (N : Node_Id);
+
+   procedure Initialize;
+   --  Initialize internal tables for new compilation
+
+   procedure Set_Enum_Esize (T : Entity_Id);
+   --  This routine sets the Esize field for an enumeration type T, based
+   --  on the current representation information available for T. Note that
+   --  the setting of the RM_Size field is not affected. This routine also
+   --  initializes the alignment field to zero.
+
+   function Minimum_Size
+     (T      : Entity_Id;
+      Biased : Boolean := False)
+      return   Nat;
+   --  Given a primitive type, determines the minimum number of bits required
+   --  to represent all values of the type. This function may not be called
+   --  with any other types. If the flag Biased is set True, then the minimum
+   --  size calculation that biased representation is used in the case of a
+   --  discrete type, e.g. the range 7..8 gives a minimum size of 4 with
+   --  Biased set to False, and 1 with Biased set to True. Note that the
+   --  biased parameter only has an effect if the type is not biased, it
+   --  causes Minimum_Size to indicate the minimum size of an object with
+   --  the given type, of the size the type would have if it were biased. If
+   --  the type is already biased, then Minimum_Size returns the biased size,
+   --  regardless of the setting of Biased. Also, fixed-point types are never
+   --  biased in the current implementation.
+
+   procedure Check_Size
+     (N      : Node_Id;
+      T      : Entity_Id;
+      Siz    : Uint;
+      Biased : out Boolean);
+   --  Called when size Siz is specified for subtype T. This subprogram checks
+   --  that the size is appropriate, posting errors on node N as required.
+   --  For non-elementary types, a check is only made if an explicit size
+   --  has been given for the type (and the specified size must match). The
+   --  parameter Biased is set False if the size specified did not require
+   --  the use of biased representation, and True if biased representation
+   --  was required to meet the size requirement. Note that Biased is only
+   --  set if the type is not currently biased, but biasing it is the only
+   --  way to meet the requirement. If the type is currently biased, then
+   --  this biased size is used in the initial check, and Biased is False.
+
+   function Get_Rep_Pragma (E : Entity_Id; Nam : Name_Id) return Node_Id;
+   --  Searches the Rep_Item chain for the given entity E, for an instance
+   --  of a representation pragma with the given name Nam. If found then
+   --  the value returned is the N_Pragma node, otherwise Empty is returned.
+
+   function Get_Attribute_Definition_Clause
+     (E    : Entity_Id;
+      Id   : Attribute_Id)
+      return Node_Id;
+   --  Searches the Rep_Item chain for a given entity E, for an instance
+   --  of an attribute definition clause with the given attibute Id Id. If
+   --  found, the value returned is the N_Attribute_Definition_Clause node,
+   --  otherwise Empty is returned.
+
+   procedure Record_Rep_Item (T : Entity_Id; N : Node_Id);
+   --  N is the node for either a representation pragma or an attribute
+   --  definition clause that applies to type T. This procedure links
+   --  the node N onto the Rep_Item chain for the type T.
+
+   function Rep_Item_Too_Early
+     (T     : Entity_Id;
+      N     : Node_Id)
+      return  Boolean;
+   --  Called at the start of processing a representation clause or a
+   --  representation pragma. Used to check that the representation item
+   --  is not being applied to an incompleted type or to a generic formal
+   --  type or a type derived from a generic formal type. Returns False if
+   --  no such error occurs. If this error does occur, appropriate error
+   --  messages are posted on node N, and True is returned.
+
+   function Rep_Item_Too_Late
+     (T     : Entity_Id;
+      N     : Node_Id;
+      FOnly : Boolean := False)
+      return  Boolean;
+   --  Called at the start of processing a representation clause or a
+   --  representation pragma. Used to check that a representation item
+   --  for entity T does not appear too late (according to the rules in
+   --  RM 13.1(9) and RM 13.1(10)). N is the associated node, which in
+   --  the pragma case is the pragma or representation clause itself, used
+   --  for placing error messages if the item is too late.
+   --
+   --  Fonly is a flag that causes only the freezing rule (para 9) to be
+   --  applied, and the tests of para 10 are skipped. This is appropriate
+   --  for both subtype related attributes (Alignment and Size) and for
+   --  stream attributes, which, although certainly not subtype related
+   --  attributes, clearly should not be subject to the para 10 restrictions
+   --  (see AI95-00137). Similarly, we also skip the para 10 restrictions for
+   --  the Storage_Size case where they also clearly do not apply.
+   --
+   --  If the rep item is too late, an appropriate message is output and
+   --  True is returned, which is a signal that the caller should abandon
+   --  processing for the item. If the item is not too late, then False
+   --  is returned, and the caller can continue processing the item.
+   --
+   --  If no error is detected, this call also as a side effect links the
+   --  representation item onto the head of the representation item chain
+   --  (referenced by the First_Rep_Item field of the entity).
+   --
+   --  Note: Rep_Item_Too_Late must be called with the underlying type in
+   --  the case of a private or incomplete type. The protocol is to first
+   --  check for Rep_Item_Too_Early using the initial entity, then take the
+   --  underlying type, then call Rep_Item_Too_Late on the result.
+
+   function Same_Representation (Typ1, Typ2 : Entity_Id) return Boolean;
+   --  Given two types, where the two types are related by possible derivation,
+   --  determines if the two types have the same representation, or different
+   --  representations, requiring the special processing for representation
+   --  change. A False result is possible only for array, enumeration or
+   --  record types.
+
+   procedure Validate_Unchecked_Conversion
+     (N        : Node_Id;
+      Act_Unit : Entity_Id);
+   --  Validate a call to unchecked conversion. N is the node for the actual
+   --  instantiation, which is used only for error messages. Act_Unit is the
+   --  entity for the instantiation, from which the actual types etc for this
+   --  instantiation can be determined. This procedure makes an entry in a
+   --  table and/or generates an N_Validate_Unchecked_Conversion node. The
+   --  actual checking is done in Validate_Unchecked_Conversions or in the
+   --  back end as required.
+
+   procedure Validate_Unchecked_Conversions;
+   --  This routine is called after calling the backend to validate
+   --  unchecked conversions for size and alignment appropriateness.
+   --  The reason it is called that late is to take advantage of any
+   --  back-annotation of size and alignment performed by the backend.
+
+end Sem_Ch13;
diff --git a/gcc/ada/sem_ch2.adb b/gcc/ada/sem_ch2.adb
new file mode 100644 (file)
index 0000000..f8e85b3
--- /dev/null
@@ -0,0 +1,117 @@
+------------------------------------------------------------------------------
+--                                                                          --
+--                         GNAT COMPILER COMPONENTS                         --
+--                                                                          --
+--                              S E M _ C H 2                               --
+--                                                                          --
+--                                 B o d y                                  --
+--                                                                          --
+--                            $Revision: 1.8 $                              --
+--                                                                          --
+--          Copyright (C) 1992-1999, 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- --
+-- ware  Foundation;  either version 2,  or (at your option) any later ver- --
+-- sion.  GNAT is distributed in the hope that it will be useful, but WITH- --
+-- OUT ANY WARRANTY;  without even the  implied warranty of MERCHANTABILITY --
+-- or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License --
+-- for  more details.  You should have  received  a copy of the GNU General --
+-- Public License  distributed with GNAT;  see file COPYING.  If not, write --
+-- to  the Free Software Foundation,  59 Temple Place - Suite 330,  Boston, --
+-- MA 02111-1307, USA.                                                      --
+--                                                                          --
+-- GNAT was originally developed  by the GNAT team at  New York University. --
+-- It is now maintained by Ada Core Technologies Inc (http://www.gnat.com). --
+--                                                                          --
+------------------------------------------------------------------------------
+
+with Atree;    use Atree;
+with Opt;      use Opt;
+with Restrict; use Restrict;
+with Sem_Ch8;  use Sem_Ch8;
+with Sinfo;    use Sinfo;
+with Stand;    use Stand;
+
+package body Sem_Ch2 is
+
+   -------------------------------
+   -- Analyze_Character_Literal --
+   -------------------------------
+
+   procedure Analyze_Character_Literal (N : Node_Id) is
+   begin
+
+      --  The type is eventually inherited from the context. If expansion
+      --  has already established the proper type, do not modify it.
+
+      if No (Etype (N)) then
+         Set_Etype (N, Any_Character);
+      end if;
+
+      Set_Is_Static_Expression (N);
+
+      if Comes_From_Source (N)
+        and then not In_Character_Range (Char_Literal_Value (N))
+      then
+         Check_Restriction (No_Wide_Characters, N);
+      end if;
+   end Analyze_Character_Literal;
+
+   ------------------------
+   -- Analyze_Identifier --
+   ------------------------
+
+   procedure Analyze_Identifier (N : Node_Id) is
+   begin
+      Find_Direct_Name (N);
+   end Analyze_Identifier;
+
+   -----------------------------
+   -- Analyze_Integer_Literal --
+   -----------------------------
+
+   procedure Analyze_Integer_Literal (N : Node_Id) is
+   begin
+      Set_Etype (N, Universal_Integer);
+      Set_Is_Static_Expression (N);
+   end Analyze_Integer_Literal;
+
+   --------------------------
+   -- Analyze_Real_Literal --
+   --------------------------
+
+   procedure Analyze_Real_Literal (N : Node_Id) is
+   begin
+      Set_Etype (N, Universal_Real);
+      Set_Is_Static_Expression (N);
+   end Analyze_Real_Literal;
+
+   ----------------------------
+   -- Analyze_String_Literal --
+   ----------------------------
+
+   procedure Analyze_String_Literal (N : Node_Id) is
+   begin
+
+      --  The type is eventually inherited from the context. If expansion
+      --  has already established the proper type, do not modify it.
+
+      if No (Etype (N)) then
+         Set_Etype (N, Any_String);
+      end if;
+
+      --  String literals are static in Ada 95. Note that if the subtype
+      --  turns out to be non-static, then the Is_Static_Expression flag
+      --  will be reset in Eval_String_Literal.
+
+      if Ada_95 then
+         Set_Is_Static_Expression (N);
+      end if;
+
+      if Comes_From_Source (N) and then Has_Wide_Character (N) then
+         Check_Restriction (No_Wide_Characters, N);
+      end if;
+   end Analyze_String_Literal;
+
+end Sem_Ch2;
diff --git a/gcc/ada/sem_ch2.ads b/gcc/ada/sem_ch2.ads
new file mode 100644 (file)
index 0000000..d85de7f
--- /dev/null
@@ -0,0 +1,46 @@
+------------------------------------------------------------------------------
+--                                                                          --
+--                         GNAT COMPILER COMPONENTS                         --
+--                                                                          --
+--                              S E M _ C H 2                               --
+--                                                                          --
+--                                 S p e c                                  --
+--                                                                          --
+--                            $Revision: 1.3 $                              --
+--                                                                          --
+--          Copyright (C) 1992-1998, 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- --
+-- ware  Foundation;  either version 2,  or (at your option) any later ver- --
+-- sion.  GNAT is distributed in the hope that it will be useful, but WITH- --
+-- OUT ANY WARRANTY;  without even the  implied warranty of MERCHANTABILITY --
+-- or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License --
+-- for  more details.  You should have  received  a copy of the GNU General --
+-- Public License  distributed with GNAT;  see file COPYING.  If not, write --
+-- to  the Free Software Foundation,  59 Temple Place - Suite 330,  Boston, --
+-- MA 02111-1307, USA.                                                      --
+--                                                                          --
+-- GNAT was originally developed  by the GNAT team at  New York University. --
+-- It is now maintained by Ada Core Technologies Inc (http://www.gnat.com). --
+--                                                                          --
+------------------------------------------------------------------------------
+
+with Types; use Types;
+
+package Sem_Ch2 is
+
+   procedure Analyze_Character_Literal (N : Node_Id);
+   procedure Analyze_Identifier        (N : Node_Id);
+   procedure Analyze_Integer_Literal   (N : Node_Id);
+   procedure Analyze_Real_Literal      (N : Node_Id);
+   procedure Analyze_String_Literal    (N : Node_Id);
+
+private
+   pragma Inline (Analyze_Character_Literal);
+   pragma Inline (Analyze_Identifier);
+   pragma Inline (Analyze_Integer_Literal);
+   pragma Inline (Analyze_Real_Literal);
+   pragma Inline (Analyze_String_Literal);
+
+end Sem_Ch2;
diff --git a/gcc/ada/sem_ch3.adb b/gcc/ada/sem_ch3.adb
new file mode 100644 (file)
index 0000000..dd9b6b0
--- /dev/null
@@ -0,0 +1,12122 @@
+------------------------------------------------------------------------------
+--                                                                          --
+--                         GNAT COMPILER COMPONENTS                         --
+--                                                                          --
+--                              S E M _ C H 3                               --
+--                                                                          --
+--                                 B o d y                                  --
+--                                                                          --
+--                            $Revision: 1.1354 $
+--                                                                          --
+--          Copyright (C) 1992-2001, 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- --
+-- ware  Foundation;  either version 2,  or (at your option) any later ver- --
+-- sion.  GNAT is distributed in the hope that it will be useful, but WITH- --
+-- OUT ANY WARRANTY;  without even the  implied warranty of MERCHANTABILITY --
+-- or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License --
+-- for  more details.  You should have  received  a copy of the GNU General --
+-- Public License  distributed with GNAT;  see file COPYING.  If not, write --
+-- to  the Free Software Foundation,  59 Temple Place - Suite 330,  Boston, --
+-- MA 02111-1307, USA.                                                      --
+--                                                                          --
+-- GNAT was originally developed  by the GNAT team at  New York University. --
+-- It is now maintained by Ada Core Technologies Inc (http://www.gnat.com). --
+--                                                                          --
+------------------------------------------------------------------------------
+
+with Atree;    use Atree;
+with Checks;   use Checks;
+with Elists;   use Elists;
+with Einfo;    use Einfo;
+with Errout;   use Errout;
+with Eval_Fat; use Eval_Fat;
+with Exp_Ch3;  use Exp_Ch3;
+with Exp_Dist; use Exp_Dist;
+with Exp_Util; use Exp_Util;
+with Freeze;   use Freeze;
+with Itypes;   use Itypes;
+with Layout;   use Layout;
+with Lib;      use Lib;
+with Lib.Xref; use Lib.Xref;
+with Namet;    use Namet;
+with Nmake;    use Nmake;
+with Opt;      use Opt;
+with Restrict; use Restrict;
+with Rtsfind;  use Rtsfind;
+with Sem;      use Sem;
+with Sem_Case; use Sem_Case;
+with Sem_Cat;  use Sem_Cat;
+with Sem_Ch6;  use Sem_Ch6;
+with Sem_Ch7;  use Sem_Ch7;
+with Sem_Ch8;  use Sem_Ch8;
+with Sem_Ch13; use Sem_Ch13;
+with Sem_Disp; use Sem_Disp;
+with Sem_Dist; use Sem_Dist;
+with Sem_Elim; use Sem_Elim;
+with Sem_Eval; use Sem_Eval;
+with Sem_Mech; use Sem_Mech;
+with Sem_Res;  use Sem_Res;
+with Sem_Smem; use Sem_Smem;
+with Sem_Type; use Sem_Type;
+with Sem_Util; use Sem_Util;
+with Stand;    use Stand;
+with Sinfo;    use Sinfo;
+with Snames;   use Snames;
+with Tbuild;   use Tbuild;
+with Ttypes;   use Ttypes;
+with Uintp;    use Uintp;
+with Urealp;   use Urealp;
+
+package body Sem_Ch3 is
+
+   -----------------------
+   -- Local Subprograms --
+   -----------------------
+
+   procedure Build_Derived_Type
+     (N             : Node_Id;
+      Parent_Type   : Entity_Id;
+      Derived_Type  : Entity_Id;
+      Is_Completion : Boolean;
+      Derive_Subps  : Boolean := True);
+   --  Create and decorate a Derived_Type given the Parent_Type entity.
+   --  N is the N_Full_Type_Declaration node containing the derived type
+   --  definition. Parent_Type is the entity for the parent type in the derived
+   --  type definition and Derived_Type the actual derived type. Is_Completion
+   --  must be set to False if Derived_Type is the N_Defining_Identifier node
+   --  in N (ie Derived_Type = Defining_Identifier (N)). In this case N is not
+   --  the completion of a private type declaration. If Is_Completion is
+   --  set to True, N is the completion of a private type declaration and
+   --  Derived_Type is different from the defining identifier inside N (i.e.
+   --  Derived_Type /= Defining_Identifier (N)). Derive_Subps indicates whether
+   --  the parent subprograms should be derived. The only case where this
+   --  parameter is False is when Build_Derived_Type is recursively called to
+   --  process an implicit derived full type for a type derived from a private
+   --  type (in that case the subprograms must only be derived for the private
+   --  view of the type).
+   --  ??? These flags need a bit of re-examination and re-documentaion:
+   --  ???  are they both necessary (both seem related to the recursion)?
+
+   procedure Build_Derived_Access_Type
+     (N            : Node_Id;
+      Parent_Type  : Entity_Id;
+      Derived_Type : Entity_Id);
+   --  Subsidiary procedure to Build_Derived_Type. For a derived access type,
+   --  create an implicit base if the parent type is constrained or if the
+   --  subtype indication has a constraint.
+
+   procedure Build_Derived_Array_Type
+     (N            : Node_Id;
+      Parent_Type  : Entity_Id;
+      Derived_Type : Entity_Id);
+   --  Subsidiary procedure to Build_Derived_Type. For a derived array type,
+   --  create an implicit base if the parent type is constrained or if the
+   --  subtype indication has a constraint.
+
+   procedure Build_Derived_Concurrent_Type
+     (N            : Node_Id;
+      Parent_Type  : Entity_Id;
+      Derived_Type : Entity_Id);
+   --  Subsidiary procedure to Build_Derived_Type. For a derived task or pro-
+   --  tected type, inherit entries and protected subprograms, check legality
+   --  of discriminant constraints if any.
+
+   procedure Build_Derived_Enumeration_Type
+     (N            : Node_Id;
+      Parent_Type  : Entity_Id;
+      Derived_Type : Entity_Id);
+   --  Subsidiary procedure to Build_Derived_Type. For a derived enumeration
+   --  type, we must create a new list of literals. Types derived from
+   --  Character and Wide_Character are special-cased.
+
+   procedure Build_Derived_Numeric_Type
+     (N            : Node_Id;
+      Parent_Type  : Entity_Id;
+      Derived_Type : Entity_Id);
+   --  Subsidiary procedure to Build_Derived_Type. For numeric types, create
+   --  an anonymous base type, and propagate constraint to subtype if needed.
+
+   procedure Build_Derived_Private_Type
+     (N            : Node_Id;
+      Parent_Type  : Entity_Id;
+      Derived_Type : Entity_Id;
+      Is_Completion : Boolean;
+      Derive_Subps  : Boolean := True);
+   --  Substidiary procedure to Build_Derived_Type. This procedure is complex
+   --  because the parent may or may not have a completion, and the derivation
+   --  may itself be a completion.
+
+   procedure Build_Derived_Record_Type
+     (N            : Node_Id;
+      Parent_Type  : Entity_Id;
+      Derived_Type : Entity_Id;
+      Derive_Subps : Boolean := True);
+   --  Subsidiary procedure to Build_Derived_Type and
+   --  Analyze_Private_Extension_Declaration used for tagged and untagged
+   --  record types. All parameters are as in Build_Derived_Type except that
+   --  N, in addition to being an N_Full_Type_Declaration node, can also be an
+   --  N_Private_Extension_Declaration node. See the definition of this routine
+   --  for much more info. Derive_Subps indicates whether subprograms should
+   --  be derived from the parent type. The only case where Derive_Subps is
+   --  False is for an implicit derived full type for a type derived from a
+   --  private type (see Build_Derived_Type).
+
+   function Inherit_Components
+     (N             : Node_Id;
+      Parent_Base   : Entity_Id;
+      Derived_Base  : Entity_Id;
+      Is_Tagged     : Boolean;
+      Inherit_Discr : Boolean;
+      Discs         : Elist_Id)
+      return          Elist_Id;
+   --  Called from Build_Derived_Record_Type to inherit the components of
+   --  Parent_Base (a base type) into the Derived_Base (the derived base type).
+   --  For more information on derived types and component inheritance please
+   --  consult the comment above the body of Build_Derived_Record_Type.
+   --
+   --  N is the original derived type declaration.
+   --  Is_Tagged is set if we are dealing with tagged types.
+   --  If Inherit_Discr is set, Derived_Base inherits its discriminants from
+   --  Parent_Base, otherwise no discriminants are inherited.
+   --  Discs gives the list of constraints that apply to Parent_Base in the
+   --  derived type declaration. If Discs is set to No_Elist, then we have the
+   --  following situation:
+   --
+   --     type Parent (D1..Dn : ..) is [tagged] record ...;
+   --     type Derived is new Parent [with ...];
+   --
+   --  which gets treated as
+   --
+   --     type Derived (D1..Dn : ..) is new Parent (D1,..,Dn) [with ...];
+   --
+   --  For untagged types the returned value is an association list:
+   --  (Old_Component => New_Component), where Old_Component is the Entity_Id
+   --  of a component in Parent_Base and New_Component is the Entity_Id of the
+   --  corresponding component in Derived_Base. For untagged records, this
+   --  association list is needed when copying the record declaration for the
+   --  derived base. In the tagged case the value returned is irrelevant.
+
+   procedure Build_Discriminal (Discrim : Entity_Id);
+   --  Create the discriminal corresponding to discriminant Discrim, that is
+   --  the parameter corresponding to Discrim to be used in initialization
+   --  procedures for the type where Discrim is a discriminant. Discriminals
+   --  are not used during semantic analysis, and are not fully defined
+   --  entities until expansion. Thus they are not given a scope until
+   --  intialization procedures are built.
+
+   function Build_Discriminant_Constraints
+     (T           : Entity_Id;
+      Def         : Node_Id;
+      Derived_Def : Boolean := False)
+      return        Elist_Id;
+   --  Validate discriminant constraints, and return the list of the
+   --  constraints in order of discriminant declarations. T is the
+   --  discriminated unconstrained type. Def is the N_Subtype_Indication
+   --  node where the discriminants constraints for T are specified.
+   --  Derived_Def is True if we are building the discriminant constraints
+   --  in a derived type definition of the form "type D (...) is new T (xxx)".
+   --  In this case T is the parent type and Def is the constraint "(xxx)" on
+   --  T and this routine sets the Corresponding_Discriminant field of the
+   --  discriminants in the derived type D to point to the corresponding
+   --  discriminants in the parent type T.
+
+   procedure Build_Discriminated_Subtype
+     (T           : Entity_Id;
+      Def_Id      : Entity_Id;
+      Elist       : Elist_Id;
+      Related_Nod : Node_Id;
+      For_Access  : Boolean := False);
+   --  Subsidiary procedure to Constrain_Discriminated_Type and to
+   --  Process_Incomplete_Dependents. Given
+   --
+   --     T (a possibly discriminated base type)
+   --     Def_Id (a very partially built subtype for T),
+   --
+   --  the call completes Def_Id to be the appropriate E_*_Subtype.
+   --
+   --  The Elist is the list of discriminant constraints if any (it is set to
+   --  No_Elist if T is not a discriminated type, and to an empty list if
+   --  T has discriminants but there are no discriminant constraints). The
+   --  Related_Nod is the same as Decl_Node in Create_Constrained_Components.
+   --  The For_Access says whether or not this subtype is really constraining
+   --  an access type. That is its sole purpose is the designated type of an
+   --  access type -- in which case a Private_Subtype Is_For_Access_Subtype
+   --  is built to avoid freezing T when the access subtype is frozen.
+
+   function Build_Scalar_Bound
+     (Bound : Node_Id;
+      Par_T : Entity_Id;
+      Der_T : Entity_Id;
+      Loc   : Source_Ptr)
+      return  Node_Id;
+   --  The bounds of a derived scalar type are conversions of the bounds of
+   --  the parent type. Optimize the representation if the bounds are literals.
+   --  Needs a more complete spec--what are the parameters exactly, and what
+   --  exactly is the returned value, and how is Bound affected???
+
+   procedure Build_Underlying_Full_View
+     (N   : Node_Id;
+      Typ : Entity_Id;
+      Par : Entity_Id);
+   --  If the completion of a private type is itself derived from a private
+   --  type, or if the full view of a private subtype is itself private, the
+   --  back-end has no way to compute the actual size of this type. We build
+   --  an internal subtype declaration of the proper parent type to convey
+   --  this information. This extra mechanism is needed because a full
+   --  view cannot itself have a full view (it would get clobbered during
+   --  view exchanges).
+
+   procedure Check_Access_Discriminant_Requires_Limited
+     (D   : Node_Id;
+      Loc : Node_Id);
+   --  Check the restriction that the type to which an access discriminant
+   --  belongs must be a concurrent type or a descendant of a type with
+   --  the reserved word 'limited' in its declaration.
+
+   procedure Check_Delta_Expression (E : Node_Id);
+   --  Check that the expression represented by E is suitable for use as
+   --  a delta expression, i.e. it is of real type and is static.
+
+   procedure Check_Digits_Expression (E : Node_Id);
+   --  Check that the expression represented by E is suitable for use as
+   --  a digits expression, i.e. it is of integer type, positive and static.
+
+   procedure Check_Incomplete (T : Entity_Id);
+   --  Called to verify that an incomplete type is not used prematurely
+
+   procedure Check_Initialization (T : Entity_Id; Exp : Node_Id);
+   --  Validate the initialization of an object declaration. T is the
+   --  required type, and Exp is the initialization expression.
+
+   procedure Check_Or_Process_Discriminants (N : Node_Id; T : Entity_Id);
+   --  If T is the full declaration of an incomplete or private type, check
+   --  the conformance of the discriminants, otherwise process them.
+
+   procedure Check_Real_Bound (Bound : Node_Id);
+   --  Check given bound for being of real type and static. If not, post an
+   --  appropriate message, and rewrite the bound with the real literal zero.
+
+   procedure Constant_Redeclaration
+     (Id : Entity_Id;
+      N  : Node_Id;
+      T  : out Entity_Id);
+   --  Various checks on legality of full declaration of deferred constant.
+   --  Id is the entity for the redeclaration, N is the N_Object_Declaration,
+   --  node. The caller has not yet set any attributes of this entity.
+
+   procedure Convert_Scalar_Bounds
+     (N            : Node_Id;
+      Parent_Type  : Entity_Id;
+      Derived_Type : Entity_Id;
+      Loc          : Source_Ptr);
+   --  For derived scalar types, convert the bounds in the type definition
+   --  to the derived type, and complete their analysis.
+
+   procedure Copy_Array_Base_Type_Attributes (T1, T2 : Entity_Id);
+   --  Copies attributes from array base type T2 to array base type T1.
+   --  Copies only attributes that apply to base types, but not subtypes.
+
+   procedure Copy_Array_Subtype_Attributes (T1, T2 : Entity_Id);
+   --  Copies attributes from array subtype T2 to array subtype T1. Copies
+   --  attributes that apply to both subtypes and base types.
+
+   procedure Create_Constrained_Components
+     (Subt        : Entity_Id;
+      Decl_Node   : Node_Id;
+      Typ         : Entity_Id;
+      Constraints : Elist_Id);
+   --  Build the list of entities for a constrained discriminated record
+   --  subtype. If a component depends on a discriminant, replace its subtype
+   --  using the discriminant values in the discriminant constraint.
+   --  Subt is the defining identifier for the subtype whose list of
+   --  constrained entities we will create. Decl_Node is the type declaration
+   --  node where we will attach all the itypes created. Typ is the base
+   --  discriminated type for the subtype Subt. Constraints is the list of
+   --  discriminant constraints for Typ.
+
+   function Constrain_Component_Type
+     (Compon_Type     : Entity_Id;
+      Constrained_Typ : Entity_Id;
+      Related_Node    : Node_Id;
+      Typ             : Entity_Id;
+      Constraints     : Elist_Id)
+      return            Entity_Id;
+   --  Given a discriminated base type Typ, a list of discriminant constraint
+   --  Constraints for Typ and the type of a component of Typ, Compon_Type,
+   --  create and return the type corresponding to Compon_type where all
+   --  discriminant references are replaced with the corresponding
+   --  constraint. If no discriminant references occurr in Compon_Typ then
+   --  return it as is. Constrained_Typ is the final constrained subtype to
+   --  which the constrained Compon_Type belongs. Related_Node is the node
+   --  where we will attach all the itypes created.
+
+   procedure Constrain_Access
+     (Def_Id      : in out Entity_Id;
+      S           : Node_Id;
+      Related_Nod : Node_Id);
+   --  Apply a list of constraints to an access type. If Def_Id is empty,
+   --  it is an anonymous type created for a subtype indication. In that
+   --  case it is created in the procedure and attached to Related_Nod.
+
+   procedure Constrain_Array
+     (Def_Id      : in out Entity_Id;
+      SI          : Node_Id;
+      Related_Nod : Node_Id;
+      Related_Id  : Entity_Id;
+      Suffix      : Character);
+   --  Apply a list of index constraints to an unconstrained array type. The
+   --  first parameter is the entity for the resulting subtype. A value of
+   --  Empty for Def_Id indicates that an implicit type must be created, but
+   --  creation is delayed (and must be done by this procedure) because other
+   --  subsidiary implicit types must be created first (which is why Def_Id
+   --  is an in/out parameter). Related_Nod gives the place where this type has
+   --  to be inserted in the tree. The Related_Id and Suffix parameters are
+   --  used to build the associated Implicit type name.
+
+   procedure Constrain_Concurrent
+     (Def_Id      : in out Entity_Id;
+      SI          : Node_Id;
+      Related_Nod : Node_Id;
+      Related_Id  : Entity_Id;
+      Suffix      : Character);
+   --  Apply list of discriminant constraints to an unconstrained concurrent
+   --  type.
+   --
+   --    SI is the N_Subtype_Indication node containing the constraint and
+   --    the unconstrained type to constrain.
+   --
+   --    Def_Id is the entity for the resulting constrained subtype. A
+   --    value of Empty for Def_Id indicates that an implicit type must be
+   --    created, but creation is delayed (and must be done by this procedure)
+   --    because other subsidiary implicit types must be created first (which
+   --    is why Def_Id is an in/out parameter).
+   --
+   --    Related_Nod gives the place where this type has to be inserted
+   --    in the tree
+   --
+   --  The last two arguments are used to create its external name if needed.
+
+   function Constrain_Corresponding_Record
+     (Prot_Subt   : Entity_Id;
+      Corr_Rec    : Entity_Id;
+      Related_Nod : Node_Id;
+      Related_Id  : Entity_Id)
+      return Entity_Id;
+   --  When constraining a protected type or task type with discriminants,
+   --  constrain the corresponding record with the same discriminant values.
+
+   procedure Constrain_Decimal
+     (Def_Id      : Node_Id;
+      S           : Node_Id;
+      Related_Nod : Node_Id);
+   --  Constrain a decimal fixed point type with a digits constraint and/or a
+   --  range constraint, and build E_Decimal_Fixed_Point_Subtype entity.
+
+   procedure Constrain_Discriminated_Type
+     (Def_Id      : Entity_Id;
+      S           : Node_Id;
+      Related_Nod : Node_Id;
+      For_Access  : Boolean := False);
+   --  Process discriminant constraints of composite type. Verify that values
+   --  have been provided for all discriminants, that the original type is
+   --  unconstrained, and that the types of the supplied expressions match
+   --  the discriminant types. The first three parameters are like in routine
+   --  Constrain_Concurrent. See Build_Discrimated_Subtype for an explanation
+   --  of For_Access.
+
+   procedure Constrain_Enumeration
+     (Def_Id      : Node_Id;
+      S           : Node_Id;
+      Related_Nod : Node_Id);
+   --  Constrain an enumeration type with a range constraint. This is
+   --  identical to Constrain_Integer, but for the Ekind of the
+   --  resulting subtype.
+
+   procedure Constrain_Float
+     (Def_Id      : Node_Id;
+      S           : Node_Id;
+      Related_Nod : Node_Id);
+   --  Constrain a floating point type with either a digits constraint
+   --  and/or a range constraint, building a E_Floating_Point_Subtype.
+
+   procedure Constrain_Index
+     (Index        : Node_Id;
+      S            : Node_Id;
+      Related_Nod  : Node_Id;
+      Related_Id   : Entity_Id;
+      Suffix       : Character;
+      Suffix_Index : Nat);
+   --  Process an index constraint in a constrained array declaration.
+   --  The constraint can be a subtype name, or a range with or without
+   --  an explicit subtype mark. The index is the corresponding index of the
+   --  unconstrained array. The Related_Id and Suffix parameters are used to
+   --  build the associated Implicit type name.
+
+   procedure Constrain_Integer
+     (Def_Id      : Node_Id;
+      S           : Node_Id;
+      Related_Nod : Node_Id);
+   --  Build subtype of a signed or modular integer type.
+
+   procedure Constrain_Ordinary_Fixed
+     (Def_Id      : Node_Id;
+      S           : Node_Id;
+      Related_Nod : Node_Id);
+   --  Constrain an ordinary fixed point type with a range constraint, and
+   --  build an E_Ordinary_Fixed_Point_Subtype entity.
+
+   procedure Copy_And_Swap (Privat, Full : Entity_Id);
+   --  Copy the Privat entity into the entity of its full declaration
+   --  then swap the two entities in such a manner that the former private
+   --  type is now seen as a full type.
+
+   procedure Copy_Private_To_Full (Priv, Full : Entity_Id);
+   --  Initialize the full view declaration with the relevant fields
+   --  from the private view.
+
+   procedure Decimal_Fixed_Point_Type_Declaration
+     (T   : Entity_Id;
+      Def : Node_Id);
+   --  Create a new decimal fixed point type, and apply the constraint to
+   --  obtain a subtype of this new type.
+
+   procedure Complete_Private_Subtype
+     (Priv        : Entity_Id;
+      Full        : Entity_Id;
+      Full_Base   : Entity_Id;
+      Related_Nod : Node_Id);
+   --  Complete the implicit full view of a private subtype by setting
+   --  the appropriate semantic fields. If the full view of the parent is
+   --  a record type, build constrained components of subtype.
+
+   procedure Derived_Standard_Character
+     (N             : Node_Id;
+      Parent_Type   : Entity_Id;
+      Derived_Type  : Entity_Id);
+   --  Subsidiary procedure to Build_Derived_Enumeration_Type which handles
+   --  derivations from types Standard.Character and Standard.Wide_Character.
+
+   procedure Derived_Type_Declaration
+     (T             : Entity_Id;
+      N             : Node_Id;
+      Is_Completion : Boolean);
+   --  Process a derived type declaration. This routine will invoke
+   --  Build_Derived_Type to process the actual derived type definition.
+   --  Parameters N and Is_Completion have the same meaning as in
+   --  Build_Derived_Type. T is the N_Defining_Identifier for the entity
+   --  defined in the N_Full_Type_Declaration node N, that is T is the
+   --  derived type.
+
+   function Find_Type_Of_Subtype_Indic (S : Node_Id) return Entity_Id;
+   --  Given a subtype indication S (which is really an N_Subtype_Indication
+   --  node or a plain N_Identifier), find the type of the subtype mark.
+
+   procedure Enumeration_Type_Declaration (T : Entity_Id; Def : Node_Id);
+   --  Insert each literal in symbol table, as an overloadable identifier
+   --  Each enumeration type is mapped into a sequence of integers, and
+   --  each literal is defined as a constant with integer value. If any
+   --  of the literals are character literals, the type is a character
+   --  type, which means that strings are legal aggregates for arrays of
+   --  components of the type.
+
+   procedure Expand_Others_Choice
+     (Case_Table     : Choice_Table_Type;
+      Others_Choice  : Node_Id;
+      Choice_Type    : Entity_Id);
+   --  In the case of a variant part of a record type that has an OTHERS
+   --  choice, this procedure expands the OTHERS into the actual choices
+   --  that it represents. This new list of choice nodes is attached to
+   --  the OTHERS node via the Others_Discrete_Choices field. The Case_Table
+   --  contains all choices that have been given explicitly in the variant.
+
+   function Find_Type_Of_Object
+     (Obj_Def     : Node_Id;
+      Related_Nod : Node_Id)
+      return        Entity_Id;
+   --  Get type entity for object referenced by Obj_Def, attaching the
+   --  implicit types generated to Related_Nod
+
+   procedure Floating_Point_Type_Declaration (T : Entity_Id; Def : Node_Id);
+   --  Create a new float, and apply the constraint to obtain subtype of it
+
+   function Has_Range_Constraint (N : Node_Id) return Boolean;
+   --  Given an N_Subtype_Indication node N, return True if a range constraint
+   --  is present, either directly, or as part of a digits or delta constraint.
+   --  In addition, a digits constraint in the decimal case returns True, since
+   --  it establishes a default range if no explicit range is present.
+
+   function Is_Valid_Constraint_Kind
+     (T_Kind          : Type_Kind;
+      Constraint_Kind : Node_Kind)
+      return Boolean;
+   --  Returns True if it is legal to apply the given kind of constraint
+   --  to the given kind of type (index constraint to an array type,
+   --  for example).
+
+   procedure Modular_Type_Declaration (T : Entity_Id; Def : Node_Id);
+   --  Create new modular type. Verify that modulus is in  bounds and is
+   --  a power of two (implementation restriction).
+
+   procedure New_Binary_Operator (Op_Name : Name_Id; Typ : Entity_Id);
+   --  Create an abbreviated declaration for an operator in order to
+   --  materialize minimally operators on derived types.
+
+   procedure Ordinary_Fixed_Point_Type_Declaration
+     (T   : Entity_Id;
+      Def : Node_Id);
+   --  Create a new ordinary fixed point type, and apply the constraint
+   --  to obtain subtype of it.
+
+   procedure Prepare_Private_Subtype_Completion
+     (Id          : Entity_Id;
+      Related_Nod : Node_Id);
+   --  Id is a subtype of some private type. Creates the full declaration
+   --  associated with Id whenever possible, i.e. when the full declaration
+   --  of the base type is already known. Records each subtype into
+   --  Private_Dependents of the base type.
+
+   procedure Process_Incomplete_Dependents
+     (N      : Node_Id;
+      Full_T : Entity_Id;
+      Inc_T  : Entity_Id);
+   --  Process all entities that depend on an incomplete type. There include
+   --  subtypes, subprogram types that mention the incomplete type in their
+   --  profiles, and subprogram with access parameters that designate the
+   --  incomplete type.
+
+   --  Inc_T is the defining identifier of an incomplete type declaration, its
+   --  Ekind is E_Incomplete_Type.
+   --
+   --    N is the corresponding N_Full_Type_Declaration for Inc_T.
+   --
+   --    Full_T is N's defining identifier.
+   --
+   --  Subtypes of incomplete types with discriminants are completed when the
+   --  parent type is. This is simpler than private subtypes, because they can
+   --  only appear in the same scope, and there is no need to exchange views.
+   --  Similarly, access_to_subprogram types may have a parameter or a return
+   --  type that is an incomplete type, and that must be replaced with the
+   --  full type.
+
+   --  If the full type is tagged, subprogram with access parameters that
+   --  designated the incomplete may be primitive operations of the full type,
+   --  and have to be processed accordingly.
+
+   procedure Process_Real_Range_Specification (Def : Node_Id);
+   --  Given the type definition for a real type, this procedure processes
+   --  and checks the real range specification of this type definition if
+   --  one is present. If errors are found, error messages are posted, and
+   --  the Real_Range_Specification of Def is reset to Empty.
+
+   procedure Record_Type_Declaration (T : Entity_Id; N : Node_Id);
+   --  Process a record type declaration (for both untagged and tagged
+   --  records). Parameters T and N are exactly like in procedure
+   --  Derived_Type_Declaration, except that no flag Is_Completion is
+   --  needed for this routine.
+
+   procedure Record_Type_Definition (Def : Node_Id; T : Entity_Id);
+   --  This routine is used to process the actual record type definition
+   --  (both for untagged and tagged records). Def is a record type
+   --  definition node. This procedure analyzes the components in this
+   --  record type definition. T is the entity for the enclosing record
+   --  type. It is provided so that its Has_Task flag can be set if any of
+   --  the component have Has_Task set.
+
+   procedure Set_Fixed_Range
+     (E   : Entity_Id;
+      Loc : Source_Ptr;
+      Lo  : Ureal;
+      Hi  : Ureal);
+   --  Build a range node with the given bounds and set it as the Scalar_Range
+   --  of the given fixed-point type entity. Loc is the source location used
+   --  for the constructed range. See body for further details.
+
+   procedure Set_Scalar_Range_For_Subtype
+     (Def_Id      : Entity_Id;
+      R           : Node_Id;
+      Subt        : Entity_Id;
+      Related_Nod : Node_Id);
+   --  This routine is used to set the scalar range field for a subtype
+   --  given Def_Id, the entity for the subtype, and R, the range expression
+   --  for the scalar range. Subt provides the parent subtype to be used
+   --  to analyze, resolve, and check the given range.
+
+   procedure Signed_Integer_Type_Declaration (T : Entity_Id; Def : Node_Id);
+   --  Create a new signed integer entity, and apply the constraint to obtain
+   --  the required first named subtype of this type.
+
+   -----------------------
+   -- Access_Definition --
+   -----------------------
+
+   function Access_Definition
+     (Related_Nod : Node_Id;
+      N           : Node_Id)
+      return        Entity_Id
+   is
+      Anon_Type : constant Entity_Id :=
+        Create_Itype (E_Anonymous_Access_Type, Related_Nod,
+          Scope_Id => Scope (Current_Scope));
+      Desig_Type : Entity_Id;
+
+   begin
+      if Is_Entry (Current_Scope)
+        and then Is_Task_Type (Etype (Scope (Current_Scope)))
+      then
+         Error_Msg_N ("task entries cannot have access parameters", N);
+      end if;
+
+      Find_Type (Subtype_Mark (N));
+      Desig_Type := Entity (Subtype_Mark (N));
+
+      Set_Directly_Designated_Type
+                             (Anon_Type, Desig_Type);
+      Set_Etype              (Anon_Type, Anon_Type);
+      Init_Size_Align        (Anon_Type);
+      Set_Depends_On_Private (Anon_Type, Has_Private_Component (Anon_Type));
+
+      --  The anonymous access type is as public as the discriminated type or
+      --  subprogram that defines it. It is imported (for back-end purposes)
+      --  if the designated type is.
+
+      Set_Is_Public          (Anon_Type, Is_Public (Scope (Anon_Type)));
+      Set_From_With_Type     (Anon_Type, From_With_Type (Desig_Type));
+
+      --  The context is either a subprogram declaration or an access
+      --  discriminant, in a private or a full type declaration. In
+      --  the case of a subprogram, If the designated type is incomplete,
+      --  the operation will be a primitive operation of the full type, to
+      --  be updated subsequently.
+
+      if Ekind (Desig_Type) = E_Incomplete_Type
+        and then Is_Overloadable (Current_Scope)
+      then
+         Append_Elmt (Current_Scope, Private_Dependents (Desig_Type));
+         Set_Has_Delayed_Freeze (Current_Scope);
+      end if;
+
+      return Anon_Type;
+   end Access_Definition;
+
+   -----------------------------------
+   -- Access_Subprogram_Declaration --
+   -----------------------------------
+
+   procedure Access_Subprogram_Declaration
+     (T_Name : Entity_Id;
+      T_Def  : Node_Id)
+   is
+      Formals : constant List_Id   := Parameter_Specifications (T_Def);
+      Formal  : Entity_Id;
+      Desig_Type : constant Entity_Id :=
+                   Create_Itype (E_Subprogram_Type, Parent (T_Def));
+
+   begin
+      if Nkind (T_Def) = N_Access_Function_Definition then
+         Analyze (Subtype_Mark (T_Def));
+         Set_Etype (Desig_Type, Entity (Subtype_Mark (T_Def)));
+      else
+         Set_Etype (Desig_Type, Standard_Void_Type);
+      end if;
+
+      if Present (Formals) then
+         New_Scope (Desig_Type);
+         Process_Formals (Desig_Type, Formals, Parent (T_Def));
+
+         --  A bit of a kludge here, End_Scope requires that the parent
+         --  pointer be set to something reasonable, but Itypes don't
+         --  have parent pointers. So we set it and then unset it ???
+         --  If and when Itypes have proper parent pointers to their
+         --  declarations, this kludge can be removed.
+
+         Set_Parent (Desig_Type, T_Name);
+         End_Scope;
+         Set_Parent (Desig_Type, Empty);
+      end if;
+
+      --  The return type and/or any parameter type may be incomplete. Mark
+      --  the subprogram_type as depending on the incomplete type, so that
+      --  it can be updated when the full type declaration is seen.
+
+      if Present (Formals) then
+         Formal := First_Formal (Desig_Type);
+
+         while Present (Formal) loop
+
+            if Ekind (Formal) /= E_In_Parameter
+              and then Nkind (T_Def) = N_Access_Function_Definition
+            then
+               Error_Msg_N ("functions can only have IN parameters", Formal);
+            end if;
+
+            if Ekind (Etype (Formal)) = E_Incomplete_Type then
+               Append_Elmt (Desig_Type, Private_Dependents (Etype (Formal)));
+               Set_Has_Delayed_Freeze (Desig_Type);
+            end if;
+
+            Next_Formal (Formal);
+         end loop;
+      end if;
+
+      if Ekind (Etype (Desig_Type)) = E_Incomplete_Type
+        and then not Has_Delayed_Freeze (Desig_Type)
+      then
+         Append_Elmt (Desig_Type, Private_Dependents (Etype (Desig_Type)));
+         Set_Has_Delayed_Freeze (Desig_Type);
+      end if;
+
+      Check_Delayed_Subprogram (Desig_Type);
+
+      if Protected_Present (T_Def) then
+         Set_Ekind (T_Name, E_Access_Protected_Subprogram_Type);
+         Set_Convention (Desig_Type, Convention_Protected);
+      else
+         Set_Ekind (T_Name, E_Access_Subprogram_Type);
+      end if;
+
+      Set_Etype                    (T_Name, T_Name);
+      Init_Size_Align              (T_Name);
+      Set_Directly_Designated_Type (T_Name, Desig_Type);
+
+      Check_Restriction (No_Access_Subprograms, T_Def);
+   end Access_Subprogram_Declaration;
+
+   ----------------------------
+   -- Access_Type_Declaration --
+   ----------------------------
+
+   procedure Access_Type_Declaration (T : Entity_Id; Def : Node_Id) is
+      S : constant Node_Id := Subtype_Indication (Def);
+      P : constant Node_Id := Parent (Def);
+
+   begin
+      --  Check for permissible use of incomplete type
+
+      if Nkind (S) /= N_Subtype_Indication then
+         Analyze (S);
+
+         if Ekind (Root_Type (Entity (S))) = E_Incomplete_Type then
+            Set_Directly_Designated_Type (T, Entity (S));
+         else
+            Set_Directly_Designated_Type (T,
+              Process_Subtype (S, P, T, 'P'));
+         end if;
+
+      else
+         Set_Directly_Designated_Type (T,
+           Process_Subtype (S, P, T, 'P'));
+      end if;
+
+      if All_Present (Def) or Constant_Present (Def) then
+         Set_Ekind (T, E_General_Access_Type);
+      else
+         Set_Ekind (T, E_Access_Type);
+      end if;
+
+      if Base_Type (Designated_Type (T)) = T then
+         Error_Msg_N ("access type cannot designate itself", S);
+      end if;
+
+      Set_Etype              (T, T);
+
+      --  If the type has appeared already in a with_type clause, it is
+      --  frozen and the pointer size is already set. Else, initialize.
+
+      if not From_With_Type (T) then
+         Init_Size_Align (T);
+      end if;
+
+      Set_Is_Access_Constant (T, Constant_Present (Def));
+
+      --  If designated type is an imported tagged type, indicate that the
+      --  access type is also imported, and therefore restricted in its use.
+      --  The access type may already be imported, so keep setting otherwise.
+
+      if From_With_Type (Designated_Type (T)) then
+         Set_From_With_Type (T);
+      end if;
+
+      --  Note that Has_Task is always false, since the access type itself
+      --  is not a task type. See Einfo for more description on this point.
+      --  Exactly the same consideration applies to Has_Controlled_Component.
+
+      Set_Has_Task (T, False);
+      Set_Has_Controlled_Component (T, False);
+   end Access_Type_Declaration;
+
+   -----------------------------------
+   -- Analyze_Component_Declaration --
+   -----------------------------------
+
+   procedure Analyze_Component_Declaration (N : Node_Id) is
+      Id : constant Entity_Id := Defining_Identifier (N);
+      T  : Entity_Id;
+      P  : Entity_Id;
+
+   begin
+      Generate_Definition (Id);
+      Enter_Name (Id);
+      T := Find_Type_Of_Object (Subtype_Indication (N), N);
+
+      --  If the component declaration includes a default expression, then we
+      --  check that the component is not of a limited type (RM 3.7(5)),
+      --  and do the special preanalysis of the expression (see section on
+      --  "Handling of Default Expressions" in the spec of package Sem).
+
+      if Present (Expression (N)) then
+         Analyze_Default_Expression (Expression (N), T);
+         Check_Initialization (T, Expression (N));
+      end if;
+
+      --  The parent type may be a private view with unknown discriminants,
+      --  and thus unconstrained. Regular components must be constrained.
+
+      if Is_Indefinite_Subtype (T) and then Chars (Id) /= Name_uParent then
+         Error_Msg_N
+           ("unconstrained subtype in component declaration",
+            Subtype_Indication (N));
+
+      --  Components cannot be abstract, except for the special case of
+      --  the _Parent field (case of extending an abstract tagged type)
+
+      elsif Is_Abstract (T) and then Chars (Id) /= Name_uParent then
+         Error_Msg_N ("type of a component cannot be abstract", N);
+      end if;
+
+      Set_Etype (Id, T);
+      Set_Is_Aliased (Id, Aliased_Present (N));
+
+      --  If the this component is private (or depends on a private type),
+      --  flag the record type to indicate that some operations are not
+      --  available.
+
+      P := Private_Component (T);
+
+      if Present (P) then
+         --  Check for circular definitions.
+
+         if P = Any_Type then
+            Set_Etype (Id, Any_Type);
+
+         --  There is a gap in the visibility of operations only if the
+         --  component type is not defined in the scope of the record type.
+
+         elsif Scope (P) = Scope (Current_Scope) then
+            null;
+
+         elsif Is_Limited_Type (P) then
+            Set_Is_Limited_Composite (Current_Scope);
+
+         else
+            Set_Is_Private_Composite (Current_Scope);
+         end if;
+      end if;
+
+      if P /= Any_Type
+        and then Is_Limited_Type (T)
+        and then Chars (Id) /= Name_uParent
+        and then Is_Tagged_Type (Current_Scope)
+      then
+         if Is_Derived_Type (Current_Scope)
+           and then not Is_Limited_Record (Root_Type (Current_Scope))
+         then
+            Error_Msg_N
+              ("extension of nonlimited type cannot have limited components",
+               N);
+            Set_Etype (Id, Any_Type);
+            Set_Is_Limited_Composite (Current_Scope, False);
+
+         elsif not Is_Derived_Type (Current_Scope)
+           and then not Is_Limited_Record (Current_Scope)
+         then
+            Error_Msg_N ("nonlimited type cannot have limited components", N);
+            Set_Etype (Id, Any_Type);
+            Set_Is_Limited_Composite (Current_Scope, False);
+         end if;
+      end if;
+
+      Set_Original_Record_Component (Id, Id);
+   end Analyze_Component_Declaration;
+
+   --------------------------
+   -- Analyze_Declarations --
+   --------------------------
+
+   procedure Analyze_Declarations (L : List_Id) is
+      D           : Node_Id;
+      Next_Node   : Node_Id;
+      Freeze_From : Entity_Id := Empty;
+
+      procedure Adjust_D;
+      --  Adjust D not to include implicit label declarations, since these
+      --  have strange Sloc values that result in elaboration check problems.
+
+      procedure Adjust_D is
+      begin
+         while Present (Prev (D))
+           and then Nkind (D) = N_Implicit_Label_Declaration
+         loop
+            Prev (D);
+         end loop;
+      end Adjust_D;
+
+   --  Start of processing for Analyze_Declarations
+
+   begin
+      D := First (L);
+      while Present (D) loop
+
+         --  Complete analysis of declaration
+
+         Analyze (D);
+         Next_Node := Next (D);
+
+         if No (Freeze_From) then
+            Freeze_From := First_Entity (Current_Scope);
+         end if;
+
+         --  At the end of a declarative part, freeze remaining entities
+         --  declared in it. The end of the visible declarations of a
+         --  package specification is not the end of a declarative part
+         --  if private declarations are present. The end of a package
+         --  declaration is a freezing point only if it a library package.
+         --  A task definition or protected type definition is not a freeze
+         --  point either. Finally, we do not freeze entities in generic
+         --  scopes, because there is no code generated for them and freeze
+         --  nodes will be generated for the instance.
+
+         --  The end of a package instantiation is not a freeze point, but
+         --  for now we make it one, because the generic body is inserted
+         --  (currently) immediately after. Generic instantiations will not
+         --  be a freeze point once delayed freezing of bodies is implemented.
+         --  (This is needed in any case for early instantiations ???).
+
+         if No (Next_Node) then
+            if Nkind (Parent (L)) = N_Component_List
+              or else Nkind (Parent (L)) = N_Task_Definition
+              or else Nkind (Parent (L)) = N_Protected_Definition
+            then
+               null;
+
+            elsif Nkind (Parent (L)) /= N_Package_Specification then
+
+               if Nkind (Parent (L)) = N_Package_Body then
+                  Freeze_From := First_Entity (Current_Scope);
+               end if;
+
+               Adjust_D;
+               Freeze_All (Freeze_From, D);
+               Freeze_From := Last_Entity (Current_Scope);
+
+            elsif Scope (Current_Scope) /= Standard_Standard
+              and then not Is_Child_Unit (Current_Scope)
+              and then No (Generic_Parent (Parent (L)))
+            then
+               null;
+
+            elsif L /= Visible_Declarations (Parent (L))
+               or else No (Private_Declarations (Parent (L)))
+               or else Is_Empty_List (Private_Declarations (Parent (L)))
+            then
+               Adjust_D;
+               Freeze_All (Freeze_From, D);
+               Freeze_From := Last_Entity (Current_Scope);
+            end if;
+
+         --  If next node is a body then freeze all types before the body.
+         --  An exception occurs for expander generated bodies, which can
+         --  be recognized by their already being analyzed. The expander
+         --  ensures that all types needed by these bodies have been frozen
+         --  but it is not necessary to freeze all types (and would be wrong
+         --  since it would not correspond to an RM defined freeze point).
+
+         elsif not Analyzed (Next_Node)
+           and then (Nkind (Next_Node) = N_Subprogram_Body
+             or else Nkind (Next_Node) = N_Entry_Body
+             or else Nkind (Next_Node) = N_Package_Body
+             or else Nkind (Next_Node) = N_Protected_Body
+             or else Nkind (Next_Node) = N_Task_Body
+             or else Nkind (Next_Node) in N_Body_Stub)
+         then
+            Adjust_D;
+            Freeze_All (Freeze_From, D);
+            Freeze_From := Last_Entity (Current_Scope);
+         end if;
+
+         D := Next_Node;
+      end loop;
+
+   end Analyze_Declarations;
+
+   --------------------------------
+   -- Analyze_Default_Expression --
+   --------------------------------
+
+   procedure Analyze_Default_Expression (N : Node_Id; T : Entity_Id) is
+      Save_In_Default_Expression : constant Boolean := In_Default_Expression;
+
+   begin
+      In_Default_Expression := True;
+      Pre_Analyze_And_Resolve (N, T);
+      In_Default_Expression := Save_In_Default_Expression;
+   end Analyze_Default_Expression;
+
+   ----------------------------------
+   -- Analyze_Incomplete_Type_Decl --
+   ----------------------------------
+
+   procedure Analyze_Incomplete_Type_Decl (N : Node_Id) is
+      F : constant Boolean := Is_Pure (Current_Scope);
+      T : Entity_Id;
+
+   begin
+      Generate_Definition (Defining_Identifier (N));
+
+      --  Process an incomplete declaration. The identifier must not have been
+      --  declared already in the scope. However, an incomplete declaration may
+      --  appear in the private part of a package, for a private type that has
+      --  already been declared.
+
+      --  In this case, the discriminants (if any) must match.
+
+      T := Find_Type_Name (N);
+
+      Set_Ekind (T, E_Incomplete_Type);
+      Init_Size_Align (T);
+      Set_Is_First_Subtype (T, True);
+      Set_Etype (T, T);
+      New_Scope (T);
+
+      Set_Girder_Constraint (T, No_Elist);
+
+      if Present (Discriminant_Specifications (N)) then
+         Process_Discriminants (N);
+      end if;
+
+      End_Scope;
+
+      --  If the type has discriminants, non-trivial subtypes may be
+      --  be declared before the full view of the type. The full views
+      --  of those subtypes will be built after the full view of the type.
+
+      Set_Private_Dependents (T, New_Elmt_List);
+      Set_Is_Pure (T, F);
+   end Analyze_Incomplete_Type_Decl;
+
+   -----------------------------
+   -- Analyze_Itype_Reference --
+   -----------------------------
+
+   --  Nothing to do. This node is placed in the tree only for the benefit
+   --  of Gigi processing, and has no effect on the semantic processing.
+
+   procedure Analyze_Itype_Reference (N : Node_Id) is
+   begin
+      pragma Assert (Is_Itype (Itype (N)));
+      null;
+   end Analyze_Itype_Reference;
+
+   --------------------------------
+   -- Analyze_Number_Declaration --
+   --------------------------------
+
+   procedure Analyze_Number_Declaration (N : Node_Id) is
+      Id    : constant Entity_Id := Defining_Identifier (N);
+      E     : constant Node_Id   := Expression (N);
+      T     : Entity_Id;
+      Index : Interp_Index;
+      It    : Interp;
+
+   begin
+      Generate_Definition (Id);
+      Enter_Name (Id);
+
+      --  This is an optimization of a common case of an integer literal
+
+      if Nkind (E) = N_Integer_Literal then
+         Set_Is_Static_Expression (E, True);
+         Set_Etype                (E, Universal_Integer);
+
+         Set_Etype     (Id, Universal_Integer);
+         Set_Ekind     (Id, E_Named_Integer);
+         Set_Is_Frozen (Id, True);
+         return;
+      end if;
+
+      Set_Is_Pure (Id, Is_Pure (Current_Scope));
+
+      Analyze (E);
+
+      --  Verify that the expression is static and numeric. If
+      --  the expression is overloaded, we apply the preference
+      --  rule that favors root numeric types.
+
+      if not Is_Overloaded (E) then
+         T := Etype (E);
+
+      else
+         T := Any_Type;
+         Get_First_Interp (E, Index, It);
+
+         while Present (It.Typ) loop
+            if (Is_Integer_Type (It.Typ)
+                 or else Is_Real_Type (It.Typ))
+              and then (Scope (Base_Type (It.Typ))) = Standard_Standard
+            then
+               if T = Any_Type then
+                  T := It.Typ;
+
+               elsif It.Typ = Universal_Real
+                 or else It.Typ = Universal_Integer
+               then
+                  --  Choose universal interpretation over any other.
+
+                  T := It.Typ;
+                  exit;
+               end if;
+            end if;
+
+            Get_Next_Interp (Index, It);
+         end loop;
+      end if;
+
+      if Is_Integer_Type (T)  then
+         Resolve (E, T);
+         Set_Etype (Id, Universal_Integer);
+         Set_Ekind (Id, E_Named_Integer);
+
+      elsif Is_Real_Type (T) then
+
+         --  Because the real value is converted to universal_real, this
+         --  is a legal context for a universal fixed expression.
+
+         if T = Universal_Fixed then
+            declare
+               Loc  : constant Source_Ptr := Sloc (N);
+               Conv : constant Node_Id := Make_Type_Conversion (Loc,
+                        Subtype_Mark =>
+                          New_Occurrence_Of (Universal_Real, Loc),
+                        Expression => Relocate_Node (E));
+
+            begin
+               Rewrite (E, Conv);
+               Analyze (E);
+            end;
+
+         elsif T = Any_Fixed then
+            Error_Msg_N ("illegal context for mixed mode operation", E);
+
+            --  Expression is of the form : universal_fixed * integer.
+            --  Try to resolve as universal_real.
+
+            T := Universal_Real;
+            Set_Etype (E, T);
+         end if;
+
+         Resolve (E, T);
+         Set_Etype (Id, Universal_Real);
+         Set_Ekind (Id, E_Named_Real);
+
+      else
+         Wrong_Type (E, Any_Numeric);
+         Resolve (E, T);
+         Set_Etype               (Id, T);
+         Set_Ekind               (Id, E_Constant);
+         Set_Not_Source_Assigned (Id, True);
+         Set_Is_True_Constant    (Id, True);
+         return;
+      end if;
+
+      if Nkind (E) = N_Integer_Literal
+        or else Nkind (E) = N_Real_Literal
+      then
+         Set_Etype (E, Etype (Id));
+      end if;
+
+      if not Is_OK_Static_Expression (E) then
+         Error_Msg_N ("non-static expression used in number declaration", E);
+         Rewrite (E, Make_Integer_Literal (Sloc (N), 1));
+         Set_Etype (E, Any_Type);
+      end if;
+
+   end Analyze_Number_Declaration;
+
+   --------------------------------
+   -- Analyze_Object_Declaration --
+   --------------------------------
+
+   procedure Analyze_Object_Declaration (N : Node_Id) is
+      Loc   : constant Source_Ptr := Sloc (N);
+      Id    : constant Entity_Id  := Defining_Identifier (N);
+      T     : Entity_Id;
+      Act_T : Entity_Id;
+
+      E : Node_Id := Expression (N);
+      --  E is set to Expression (N) throughout this routine. When
+      --  Expression (N) is modified, E is changed accordingly.
+
+      Prev_Entity : Entity_Id := Empty;
+
+      function Build_Default_Subtype return Entity_Id;
+      --  If the object is limited or aliased, and if the type is unconstrained
+      --  and there is no expression, the discriminants cannot be modified and
+      --  the subtype of the object is constrained by the defaults, so it is
+      --  worthile building the corresponding subtype.
+
+      ---------------------------
+      -- Build_Default_Subtype --
+      ---------------------------
+
+      function Build_Default_Subtype return Entity_Id is
+         Act         : Entity_Id;
+         Constraints : List_Id := New_List;
+         Decl        : Node_Id;
+         Disc        : Entity_Id;
+
+      begin
+         Disc  := First_Discriminant (T);
+
+         if No (Discriminant_Default_Value (Disc)) then
+            return T;   --   previous error.
+         end if;
+
+         Act := Make_Defining_Identifier (Loc, New_Internal_Name ('S'));
+         while Present (Disc) loop
+            Append (
+              New_Copy_Tree (
+                Discriminant_Default_Value (Disc)), Constraints);
+            Next_Discriminant (Disc);
+         end loop;
+
+         Decl :=
+           Make_Subtype_Declaration (Loc,
+             Defining_Identifier => Act,
+             Subtype_Indication =>
+               Make_Subtype_Indication (Loc,
+                 Subtype_Mark => New_Occurrence_Of (T, Loc),
+                 Constraint =>
+                   Make_Index_Or_Discriminant_Constraint
+                     (Loc, Constraints)));
+
+         Insert_Before (N, Decl);
+         Analyze (Decl);
+         return Act;
+      end Build_Default_Subtype;
+
+   --  Start of processing for Analyze_Object_Declaration
+
+   begin
+      --  There are three kinds of implicit types generated by an
+      --  object declaration:
+
+      --   1. Those for generated by the original Object Definition
+
+      --   2. Those generated by the Expression
+
+      --   3. Those used to constrained the Object Definition with the
+      --       expression constraints when it is unconstrained
+
+      --  They must be generated in this order to avoid order of elaboration
+      --  issues. Thus the first step (after entering the name) is to analyze
+      --  the object definition.
+
+      if Constant_Present (N) then
+         Prev_Entity := Current_Entity_In_Scope (Id);
+
+         --  If homograph is an implicit subprogram, it is overridden by the
+         --  current declaration.
+
+         if Present (Prev_Entity)
+           and then Is_Overloadable (Prev_Entity)
+           and then Is_Inherited_Operation (Prev_Entity)
+         then
+            Prev_Entity := Empty;
+         end if;
+      end if;
+
+      if Present (Prev_Entity) then
+         Constant_Redeclaration (Id, N, T);
+
+         Generate_Reference (Prev_Entity, Id, 'c');
+
+         --  If in main unit, set as referenced, so we do not complain about
+         --  the full declaration being an unreferenced entity.
+
+         if In_Extended_Main_Source_Unit (Id) then
+            Set_Referenced (Id);
+         end if;
+
+         if Error_Posted (N) then
+            --  Type mismatch or illegal redeclaration, Do not analyze
+            --  expression to avoid cascaded errors.
+
+            T := Find_Type_Of_Object (Object_Definition (N), N);
+            Set_Etype (Id, T);
+            Set_Ekind (Id, E_Variable);
+            return;
+         end if;
+
+      --  In the normal case, enter identifier at the start to catch
+      --  premature usage in the initialization expression.
+
+      else
+         Generate_Definition (Id);
+         Enter_Name (Id);
+
+         T := Find_Type_Of_Object (Object_Definition (N), N);
+
+         if Error_Posted (Id) then
+            Set_Etype (Id, T);
+            Set_Ekind (Id, E_Variable);
+            return;
+         end if;
+      end if;
+
+      Set_Is_Pure (Id, Is_Pure (Current_Scope));
+
+      --  If deferred constant, make sure context is appropriate. We detect
+      --  a deferred constant as a constant declaration with no expression.
+
+      if Constant_Present (N)
+        and then No (E)
+      then
+         if not Is_Package (Current_Scope)
+           or else In_Private_Part (Current_Scope)
+         then
+            Error_Msg_N
+              ("invalid context for deferred constant declaration", N);
+            Set_Constant_Present (N, False);
+
+         --  In Ada 83, deferred constant must be of private type
+
+         elsif not Is_Private_Type (T) then
+            if Ada_83 and then Comes_From_Source (N) then
+               Error_Msg_N
+                 ("(Ada 83) deferred constant must be private type", N);
+            end if;
+         end if;
+
+      --  If not a deferred constant, then object declaration freezes its type
+
+      else
+         Check_Fully_Declared (T, N);
+         Freeze_Before (N, T);
+      end if;
+
+      --  If the object was created by a constrained array definition, then
+      --  set the link in both the anonymous base type and anonymous subtype
+      --  that are built to represent the array type to point to the object.
+
+      if Nkind (Object_Definition (Declaration_Node (Id))) =
+                        N_Constrained_Array_Definition
+      then
+         Set_Related_Array_Object (T, Id);
+         Set_Related_Array_Object (Base_Type (T), Id);
+      end if;
+
+      --  Special checks for protected objects not at library level
+
+      if Is_Protected_Type (T)
+        and then not Is_Library_Level_Entity (Id)
+      then
+         Check_Restriction (No_Local_Protected_Objects, Id);
+
+         --  Protected objects with interrupt handlers must be at library level
+
+         if Has_Interrupt_Handler (T) then
+            Error_Msg_N
+              ("interrupt object can only be declared at library level", Id);
+         end if;
+      end if;
+
+      --  The actual subtype of the object is the nominal subtype, unless
+      --  the nominal one is unconstrained and obtained from the expression.
+
+      Act_T := T;
+
+      --  Process initialization expression if present and not in error
+
+      if Present (E) and then E /= Error then
+         Analyze (E);
+
+         if not Assignment_OK (N) then
+            Check_Initialization (T, E);
+         end if;
+
+         Resolve (E, T);
+
+         --  Check for library level object that will require implicit
+         --  heap allocation.
+
+         if Is_Array_Type (T)
+           and then not Size_Known_At_Compile_Time (T)
+           and then Is_Library_Level_Entity (Id)
+         then
+            --  String literals are always allowed
+
+            if T = Standard_String
+              and then Nkind (E) = N_String_Literal
+            then
+               null;
+
+            --  Otherwise we do not allow this since it may cause an
+            --  implicit heap allocation.
+
+            else
+               Check_Restriction
+                 (No_Implicit_Heap_Allocations, Object_Definition (N));
+            end if;
+         end if;
+
+         --  Check incorrect use of dynamically tagged expressions. Note
+         --  the use of Is_Tagged_Type (T) which seems redundant but is in
+         --  fact important to avoid spurious errors due to expanded code
+         --  for dispatching functions over an anonymous access type
+
+         if (Is_Class_Wide_Type (Etype (E)) or else Is_Dynamically_Tagged (E))
+           and then Is_Tagged_Type (T)
+           and then not Is_Class_Wide_Type (T)
+         then
+            Error_Msg_N ("dynamically tagged expression not allowed!", E);
+         end if;
+
+         Apply_Scalar_Range_Check (E, T);
+         Apply_Static_Length_Check (E, T);
+      end if;
+
+      --  Abstract type is never permitted for a variable or constant.
+      --  Note: we inhibit this check for objects that do not come from
+      --  source because there is at least one case (the expansion of
+      --  x'class'input where x is abstract) where we legitimately
+      --  generate an abstract object.
+
+      if Is_Abstract (T) and then Comes_From_Source (N) then
+         Error_Msg_N ("type of object cannot be abstract",
+           Object_Definition (N));
+         if Is_CPP_Class (T) then
+            Error_Msg_NE ("\} may need a cpp_constructor",
+              Object_Definition (N), T);
+         end if;
+
+      --  Case of unconstrained type
+
+      elsif Is_Indefinite_Subtype (T) then
+
+         --  Nothing to do in deferred constant case
+
+         if Constant_Present (N) and then No (E) then
+            null;
+
+         --  Case of no initialization present
+
+         elsif No (E) then
+            if No_Initialization (N) then
+               null;
+
+            elsif Is_Class_Wide_Type (T) then
+               Error_Msg_N
+                 ("initialization required in class-wide declaration ", N);
+
+            else
+               Error_Msg_N
+                 ("unconstrained subtype not allowed (need initialization)",
+                  Object_Definition (N));
+            end if;
+
+         --  Case of initialization present but in error. Set initial
+         --  expression as absent (but do not make above complaints)
+
+         elsif E = Error then
+            Set_Expression (N, Empty);
+            E := Empty;
+
+         --  Case of initialization present
+
+         else
+            --  Not allowed in Ada 83
+
+            if not Constant_Present (N) then
+               if Ada_83
+                 and then Comes_From_Source (Object_Definition (N))
+               then
+                  Error_Msg_N
+                    ("(Ada 83) unconstrained variable not allowed",
+                     Object_Definition (N));
+               end if;
+            end if;
+
+            --  Now we constrain the variable from the initializing expression
+
+            --  If the expression is an aggregate, it has been expanded into
+            --  individual assignments. Retrieve the actual type from the
+            --  expanded construct.
+
+            if Is_Array_Type (T)
+              and then No_Initialization (N)
+              and then Nkind (Original_Node (E)) = N_Aggregate
+            then
+               Act_T := Etype (E);
+
+            else
+               Expand_Subtype_From_Expr (N, T, Object_Definition (N), E);
+               Act_T := Find_Type_Of_Object (Object_Definition (N), N);
+            end if;
+
+            Set_Is_Constr_Subt_For_U_Nominal (Act_T);
+
+            if Aliased_Present (N) then
+               Set_Is_Constr_Subt_For_UN_Aliased (Act_T);
+            end if;
+
+            Freeze_Before (N, Act_T);
+            Freeze_Before (N, T);
+         end if;
+
+      elsif Is_Array_Type (T)
+        and then No_Initialization (N)
+        and then Nkind (Original_Node (E)) = N_Aggregate
+      then
+         if not Is_Entity_Name (Object_Definition (N)) then
+            Act_T := Etype (E);
+
+            if Aliased_Present (N) then
+               Set_Is_Constr_Subt_For_UN_Aliased (Act_T);
+            end if;
+         end if;
+
+         --  When the given object definition and the aggregate are specified
+         --  independently, and their lengths might differ do a length check.
+         --  This cannot happen if the aggregate is of the form (others =>...)
+
+         if not Is_Constrained (T) then
+            null;
+
+         elsif T = Etype (E) then
+            null;
+
+         elsif Nkind (E) = N_Aggregate
+           and then Present (Component_Associations (E))
+           and then Present (Choices (First (Component_Associations (E))))
+           and then Nkind (First
+            (Choices (First (Component_Associations (E))))) = N_Others_Choice
+         then
+            null;
+
+         else
+            Apply_Length_Check (E, T);
+         end if;
+
+      elsif (Is_Limited_Record (T)
+               or else Is_Concurrent_Type (T))
+        and then not Is_Constrained (T)
+        and then Has_Discriminants (T)
+      then
+         Act_T := Build_Default_Subtype;
+         Rewrite (Object_Definition (N), New_Occurrence_Of (Act_T, Loc));
+
+      elsif not Is_Constrained (T)
+        and then Has_Discriminants (T)
+        and then Constant_Present (N)
+        and then Nkind (E) = N_Function_Call
+      then
+         --  The back-end has problems with constants of a discriminated type
+         --  with defaults, if the initial value is a function call. We
+         --  generate an intermediate temporary for the result of the call.
+         --  It is unclear why this should make it acceptable to gcc. ???
+
+         Remove_Side_Effects (E);
+      end if;
+
+      if T = Standard_Wide_Character
+        or else Root_Type (T) = Standard_Wide_String
+      then
+         Check_Restriction (No_Wide_Characters, Object_Definition (N));
+      end if;
+
+      --  Now establish the proper kind and type of the object
+
+      if Constant_Present (N) then
+         Set_Ekind               (Id, E_Constant);
+         Set_Not_Source_Assigned (Id, True);
+         Set_Is_True_Constant    (Id, True);
+
+      else
+         Set_Ekind (Id, E_Variable);
+
+         --  A variable is set as shared passive if it appears in a shared
+         --  passive package, and is at the outer level. This is not done
+         --  for entities generated during expansion, because those are
+         --  always manipulated locally.
+
+         if Is_Shared_Passive (Current_Scope)
+           and then Is_Library_Level_Entity (Id)
+           and then Comes_From_Source (Id)
+         then
+            Set_Is_Shared_Passive (Id);
+            Check_Shared_Var (Id, T, N);
+         end if;
+
+         --  If an initializing expression is present, then the variable
+         --  is potentially a true constant if no further assignments are
+         --  present. The code generator can use this for optimization.
+         --  The flag will be reset if there are any assignments. We only
+         --  set this flag for non library level entities, since for any
+         --  library level entities, assignments could exist in other units.
+
+         if Present (E) then
+            if not Is_Library_Level_Entity (Id) then
+
+               --  For now we omit this, because it seems to cause some
+               --  problems. In particular, if you uncomment this out, then
+               --  test case 4427-002 will fail for unclear reasons ???
+
+               if False then
+                  Set_Is_True_Constant (Id);
+               end if;
+            end if;
+
+         --  Case of no initializing expression present. If the type is not
+         --  fully initialized, then we set Not_Source_Assigned, since this
+         --  is a case of a potentially uninitialized object. Note that we
+         --  do not consider access variables to be fully initialized for
+         --  this purpose, since it still seems dubious if someone declares
+         --  an access variable and never assigns to it.
+
+         else
+            if Is_Access_Type (T)
+              or else not Is_Fully_Initialized_Type (T)
+            then
+               Set_Not_Source_Assigned (Id);
+            end if;
+         end if;
+      end if;
+
+      Init_Alignment (Id);
+      Init_Esize     (Id);
+
+      if Aliased_Present (N) then
+         Set_Is_Aliased (Id);
+
+         if No (E)
+           and then Is_Record_Type (T)
+           and then not Is_Constrained (T)
+           and then Has_Discriminants (T)
+         then
+            Set_Actual_Subtype (Id, Build_Default_Subtype);
+         end if;
+      end if;
+
+      Set_Etype (Id, Act_T);
+
+      if Has_Controlled_Component (Etype (Id))
+        or else Is_Controlled (Etype (Id))
+      then
+         if not Is_Library_Level_Entity (Id) then
+            Check_Restriction (No_Nested_Finalization, N);
+
+         else
+            Validate_Controlled_Object (Id);
+         end if;
+
+         --  Generate a warning when an initialization causes an obvious
+         --  ABE violation. If the init expression is a simple aggregate
+         --  there shouldn't be any initialize/adjust call generated. This
+         --  will be true as soon as aggregates are built in place when
+         --  possible. ??? at the moment we do not generate warnings for
+         --  temporaries created for those aggregates although a
+         --  Program_Error might be generated if compiled with -gnato
+
+         if Is_Controlled (Etype (Id))
+            and then Comes_From_Source (Id)
+         then
+            declare
+               BT            : constant Entity_Id := Base_Type (Etype (Id));
+               Implicit_Call : Entity_Id;
+
+               function Is_Aggr (N : Node_Id) return Boolean;
+               --  Check that N is an aggregate
+
+               function Is_Aggr (N : Node_Id) return Boolean is
+               begin
+                  case Nkind (Original_Node (N)) is
+                     when N_Aggregate | N_Extension_Aggregate =>
+                        return True;
+
+                     when N_Qualified_Expression |
+                          N_Type_Conversion      |
+                          N_Unchecked_Type_Conversion =>
+                        return Is_Aggr (Expression (Original_Node (N)));
+
+                     when others =>
+                        return False;
+                  end case;
+               end Is_Aggr;
+
+            begin
+               --  If no underlying type, we already are in an error situation
+               --  don't try to add a warning since we do not have access
+               --  prim-op list.
+
+               if No (Underlying_Type (BT)) then
+                  Implicit_Call := Empty;
+
+               --  A generic type does not have usable primitive operators.
+               --  Initialization calls are built for instances.
+
+               elsif Is_Generic_Type (BT) then
+                  Implicit_Call := Empty;
+
+               --  if the init expression is not an aggregate, an adjust
+               --  call will be generated
+
+               elsif Present (E) and then not Is_Aggr (E) then
+                  Implicit_Call := Find_Prim_Op (BT, Name_Adjust);
+
+               --  if no init expression and we are not in the deferred
+               --  constant case, an Initialize call will be generated
+
+               elsif No (E) and then not Constant_Present (N) then
+                  Implicit_Call := Find_Prim_Op (BT, Name_Initialize);
+
+               else
+                  Implicit_Call := Empty;
+               end if;
+            end;
+         end if;
+      end if;
+
+      if Has_Task (Etype (Id)) then
+         if not Is_Library_Level_Entity (Id) then
+            Check_Restriction (No_Task_Hierarchy, N);
+            Check_Potentially_Blocking_Operation (N);
+         end if;
+      end if;
+
+      --  Some simple constant-propagation: if the expression is a constant
+      --  string initialized with a literal, share the literal. This avoids
+      --  a run-time copy.
+
+      if Present (E)
+        and then Is_Entity_Name (E)
+        and then Ekind (Entity (E)) = E_Constant
+        and then Base_Type (Etype (E)) = Standard_String
+      then
+         declare
+            Val : constant Node_Id := Constant_Value (Entity (E));
+
+         begin
+            if Present (Val)
+              and then Nkind (Val) = N_String_Literal
+            then
+               Rewrite (E, New_Copy (Val));
+            end if;
+         end;
+      end if;
+
+      --  Another optimization: if the nominal subtype is unconstrained and
+      --  the expression is a function call that returns and unconstrained
+      --  type, rewrite the declararation as a renaming of the result of the
+      --  call. The exceptions below are cases where the copy is expected,
+      --  either by the back end (Aliased case) or by the semantics, as for
+      --  initializing controlled types or copying tags for classwide types.
+
+      if Present (E)
+        and then Nkind (E) = N_Explicit_Dereference
+        and then Nkind (Original_Node (E)) = N_Function_Call
+        and then not Is_Library_Level_Entity (Id)
+        and then not Is_Constrained (T)
+        and then not Is_Aliased (Id)
+        and then not Is_Class_Wide_Type (T)
+        and then not Is_Controlled (T)
+        and then not Has_Controlled_Component (Base_Type (T))
+        and then Expander_Active
+      then
+         Rewrite (N,
+           Make_Object_Renaming_Declaration (Loc,
+             Defining_Identifier => Id,
+             Subtype_Mark        => New_Occurrence_Of
+                                      (Base_Type (Etype (Id)), Loc),
+             Name                => E));
+
+         Set_Renamed_Object (Id, E);
+      end if;
+
+      if Present (Prev_Entity)
+        and then Is_Frozen (Prev_Entity)
+        and then not Error_Posted (Id)
+      then
+         Error_Msg_N ("full constant declaration appears too late", N);
+      end if;
+
+      Check_Eliminated (Id);
+   end Analyze_Object_Declaration;
+
+   ---------------------------
+   -- Analyze_Others_Choice --
+   ---------------------------
+
+   --  Nothing to do for the others choice node itself, the semantic analysis
+   --  of the others choice will occur as part of the processing of the parent
+
+   procedure Analyze_Others_Choice (N : Node_Id) is
+   begin
+      null;
+   end Analyze_Others_Choice;
+
+   -------------------------------------------
+   -- Analyze_Private_Extension_Declaration --
+   -------------------------------------------
+
+   procedure Analyze_Private_Extension_Declaration (N : Node_Id) is
+      T           : Entity_Id        := Defining_Identifier (N);
+      Indic       : constant Node_Id := Subtype_Indication (N);
+      Parent_Type : Entity_Id;
+      Parent_Base : Entity_Id;
+
+   begin
+      Generate_Definition (T);
+      Enter_Name (T);
+
+      Parent_Type := Find_Type_Of_Subtype_Indic (Indic);
+      Parent_Base := Base_Type (Parent_Type);
+
+      if Parent_Type = Any_Type
+        or else Etype (Parent_Type) = Any_Type
+      then
+         Set_Ekind (T, Ekind (Parent_Type));
+         Set_Etype (T, Any_Type);
+         return;
+
+      elsif not Is_Tagged_Type (Parent_Type) then
+         Error_Msg_N
+           ("parent of type extension must be a tagged type ", Indic);
+         return;
+
+      elsif Ekind (Parent_Type) = E_Void
+        or else Ekind (Parent_Type) = E_Incomplete_Type
+      then
+         Error_Msg_N ("premature derivation of incomplete type", Indic);
+         return;
+      end if;
+
+      --  Perhaps the parent type should be changed to the class-wide type's
+      --  specific type in this case to prevent cascading errors ???
+
+      if Is_Class_Wide_Type (Parent_Type) then
+         Error_Msg_N
+           ("parent of type extension must not be a class-wide type", Indic);
+         return;
+      end if;
+
+      if (not Is_Package (Current_Scope)
+           and then Nkind (Parent (N)) /= N_Generic_Subprogram_Declaration)
+        or else In_Private_Part (Current_Scope)
+
+      then
+         Error_Msg_N ("invalid context for private extension", N);
+      end if;
+
+      --  Set common attributes
+
+      Set_Is_Pure          (T, Is_Pure (Current_Scope));
+      Set_Scope            (T, Current_Scope);
+      Set_Ekind            (T, E_Record_Type_With_Private);
+      Init_Size_Align      (T);
+
+      Set_Etype            (T,            Parent_Base);
+      Set_Has_Task         (T, Has_Task  (Parent_Base));
+
+      Set_Convention       (T, Convention     (Parent_Type));
+      Set_First_Rep_Item   (T, First_Rep_Item (Parent_Type));
+      Set_Is_First_Subtype (T);
+      Make_Class_Wide_Type (T);
+
+      Build_Derived_Record_Type (N, Parent_Type, T);
+   end Analyze_Private_Extension_Declaration;
+
+   ---------------------------------
+   -- Analyze_Subtype_Declaration --
+   ---------------------------------
+
+   procedure Analyze_Subtype_Declaration (N : Node_Id) is
+      Id       : constant Entity_Id := Defining_Identifier (N);
+      T        : Entity_Id;
+      R_Checks : Check_Result;
+
+   begin
+      Generate_Definition (Id);
+      Set_Is_Pure (Id, Is_Pure (Current_Scope));
+      Init_Size_Align (Id);
+
+      --  The following guard condition on Enter_Name is to handle cases
+      --  where the defining identifier has already been entered into the
+      --  scope but the declaration as a whole needs to be analyzed.
+
+      --  This case in particular happens for derived enumeration types.
+      --  The derived enumeration type is processed as an inserted enumeration
+      --  type declaration followed by a rewritten subtype declaration. The
+      --  defining identifier, however, is entered into the name scope very
+      --  early in the processing of the original type declaration and
+      --  therefore needs to be avoided here, when the created subtype
+      --  declaration is analyzed. (See Build_Derived_Types)
+
+      --  This also happens when the full view of a private type is a
+      --  derived type with constraints. In this case the entity has been
+      --  introduced in the private declaration.
+
+      if Present (Etype (Id))
+        and then (Is_Private_Type (Etype (Id))
+                   or else Is_Task_Type (Etype (Id))
+                   or else Is_Rewrite_Substitution (N))
+      then
+         null;
+
+      else
+         Enter_Name (Id);
+      end if;
+
+      T := Process_Subtype (Subtype_Indication (N), N, Id, 'P');
+
+      --  Inherit common attributes
+
+      Set_Is_Generic_Type (Id, Is_Generic_Type (Base_Type (T)));
+      Set_Is_Volatile (Id, Is_Volatile (T));
+      Set_Is_Atomic   (Id, Is_Atomic   (T));
+
+      --  In the case where there is no constraint given in the subtype
+      --  indication, Process_Subtype just returns the Subtype_Mark,
+      --  so its semantic attributes must be established here.
+
+      if Nkind (Subtype_Indication (N)) /= N_Subtype_Indication then
+         Set_Etype (Id, Base_Type (T));
+
+         case Ekind (T) is
+            when Array_Kind =>
+               Set_Ekind                (Id, E_Array_Subtype);
+
+               --  Shouldn't we call Copy_Array_Subtype_Attributes here???
+
+               Set_First_Index          (Id, First_Index        (T));
+               Set_Is_Aliased           (Id, Is_Aliased         (T));
+               Set_Is_Constrained       (Id, Is_Constrained     (T));
+
+            when Decimal_Fixed_Point_Kind =>
+               Set_Ekind                (Id, E_Decimal_Fixed_Point_Subtype);
+               Set_Digits_Value         (Id, Digits_Value       (T));
+               Set_Delta_Value          (Id, Delta_Value        (T));
+               Set_Scale_Value          (Id, Scale_Value        (T));
+               Set_Small_Value          (Id, Small_Value        (T));
+               Set_Scalar_Range         (Id, Scalar_Range       (T));
+               Set_Machine_Radix_10     (Id, Machine_Radix_10   (T));
+               Set_Is_Constrained       (Id, Is_Constrained     (T));
+               Set_RM_Size              (Id, RM_Size            (T));
+
+            when Enumeration_Kind =>
+               Set_Ekind                (Id, E_Enumeration_Subtype);
+               Set_First_Literal        (Id, First_Literal (Base_Type (T)));
+               Set_Scalar_Range         (Id, Scalar_Range       (T));
+               Set_Is_Character_Type    (Id, Is_Character_Type  (T));
+               Set_Is_Constrained       (Id, Is_Constrained     (T));
+               Set_RM_Size              (Id, RM_Size            (T));
+
+            when Ordinary_Fixed_Point_Kind =>
+               Set_Ekind                (Id, E_Ordinary_Fixed_Point_Subtype);
+               Set_Scalar_Range         (Id, Scalar_Range       (T));
+               Set_Small_Value          (Id, Small_Value        (T));
+               Set_Delta_Value          (Id, Delta_Value        (T));
+               Set_Is_Constrained       (Id, Is_Constrained     (T));
+               Set_RM_Size              (Id, RM_Size            (T));
+
+            when Float_Kind =>
+               Set_Ekind                (Id, E_Floating_Point_Subtype);
+               Set_Scalar_Range         (Id, Scalar_Range       (T));
+               Set_Digits_Value         (Id, Digits_Value       (T));
+               Set_Is_Constrained       (Id, Is_Constrained     (T));
+
+            when Signed_Integer_Kind =>
+               Set_Ekind                (Id, E_Signed_Integer_Subtype);
+               Set_Scalar_Range         (Id, Scalar_Range       (T));
+               Set_Is_Constrained       (Id, Is_Constrained     (T));
+               Set_RM_Size              (Id, RM_Size            (T));
+
+            when Modular_Integer_Kind =>
+               Set_Ekind                (Id, E_Modular_Integer_Subtype);
+               Set_Scalar_Range         (Id, Scalar_Range       (T));
+               Set_Is_Constrained       (Id, Is_Constrained     (T));
+               Set_RM_Size              (Id, RM_Size            (T));
+
+            when Class_Wide_Kind =>
+               Set_Ekind                (Id, E_Class_Wide_Subtype);
+               Set_First_Entity         (Id, First_Entity       (T));
+               Set_Last_Entity          (Id, Last_Entity        (T));
+               Set_Class_Wide_Type      (Id, Class_Wide_Type    (T));
+               Set_Cloned_Subtype       (Id, T);
+               Set_Is_Tagged_Type       (Id, True);
+               Set_Has_Unknown_Discriminants
+                                        (Id, True);
+
+               if Ekind (T) = E_Class_Wide_Subtype then
+                  Set_Equivalent_Type   (Id, Equivalent_Type    (T));
+               end if;
+
+            when E_Record_Type | E_Record_Subtype =>
+               Set_Ekind                (Id, E_Record_Subtype);
+
+               if Ekind (T) = E_Record_Subtype
+                 and then Present (Cloned_Subtype (T))
+               then
+                  Set_Cloned_Subtype    (Id, Cloned_Subtype (T));
+               else
+                  Set_Cloned_Subtype    (Id, T);
+               end if;
+
+               Set_First_Entity         (Id, First_Entity       (T));
+               Set_Last_Entity          (Id, Last_Entity        (T));
+               Set_Has_Discriminants    (Id, Has_Discriminants  (T));
+               Set_Is_Constrained       (Id, Is_Constrained     (T));
+               Set_Is_Limited_Record    (Id, Is_Limited_Record  (T));
+               Set_Has_Unknown_Discriminants
+                                        (Id, Has_Unknown_Discriminants (T));
+
+               if Has_Discriminants (T) then
+                  Set_Discriminant_Constraint
+                                        (Id, Discriminant_Constraint (T));
+                  Set_Girder_Constraint_From_Discriminant_Constraint (Id);
+
+               elsif Has_Unknown_Discriminants (Id) then
+                  Set_Discriminant_Constraint (Id, No_Elist);
+               end if;
+
+               if Is_Tagged_Type (T) then
+                  Set_Is_Tagged_Type    (Id);
+                  Set_Is_Abstract       (Id, Is_Abstract (T));
+                  Set_Primitive_Operations
+                                        (Id, Primitive_Operations (T));
+                  Set_Class_Wide_Type   (Id, Class_Wide_Type (T));
+               end if;
+
+            when Private_Kind =>
+               Set_Ekind              (Id, Subtype_Kind (Ekind   (T)));
+               Set_Has_Discriminants  (Id, Has_Discriminants     (T));
+               Set_Is_Constrained     (Id, Is_Constrained        (T));
+               Set_First_Entity       (Id, First_Entity          (T));
+               Set_Last_Entity        (Id, Last_Entity           (T));
+               Set_Private_Dependents (Id, New_Elmt_List);
+               Set_Is_Limited_Record  (Id, Is_Limited_Record     (T));
+               Set_Has_Unknown_Discriminants
+                                      (Id, Has_Unknown_Discriminants (T));
+
+               if Is_Tagged_Type (T) then
+                  Set_Is_Tagged_Type  (Id);
+                  Set_Is_Abstract     (Id, Is_Abstract (T));
+                  Set_Class_Wide_Type (Id, Class_Wide_Type (T));
+               end if;
+
+               --  In general the attributes of the subtype of a private
+               --  type are the attributes of the partial view of parent.
+               --  However, the full view may be a discriminated type,
+               --  and the subtype must share the discriminant constraint
+               --  to generate correct calls to initialization procedures.
+
+               if Has_Discriminants (T) then
+                  Set_Discriminant_Constraint
+                                     (Id, Discriminant_Constraint (T));
+                  Set_Girder_Constraint_From_Discriminant_Constraint (Id);
+
+               elsif Present (Full_View (T))
+                 and then Has_Discriminants (Full_View (T))
+               then
+                  Set_Discriminant_Constraint
+                               (Id, Discriminant_Constraint (Full_View (T)));
+                  Set_Girder_Constraint_From_Discriminant_Constraint (Id);
+
+                  --  This would seem semantically correct, but apparently
+                  --  confuses the back-end (4412-009). To be explained ???
+
+                  --  Set_Has_Discriminants (Id);
+               end if;
+
+               Prepare_Private_Subtype_Completion (Id, N);
+
+            when Access_Kind =>
+               Set_Ekind             (Id, E_Access_Subtype);
+               Set_Is_Constrained    (Id, Is_Constrained        (T));
+               Set_Is_Access_Constant
+                                     (Id, Is_Access_Constant    (T));
+               Set_Directly_Designated_Type
+                                     (Id, Designated_Type       (T));
+
+               --  A Pure library_item must not contain the declaration of a
+               --  named access type, except within a subprogram, generic
+               --  subprogram, task unit, or protected unit (RM 10.2.1(16)).
+
+               if Comes_From_Source (Id)
+                 and then In_Pure_Unit
+                 and then not In_Subprogram_Task_Protected_Unit
+               then
+                  Error_Msg_N
+                    ("named access types not allowed in pure unit", N);
+               end if;
+
+            when Concurrent_Kind =>
+
+               Set_Ekind                (Id, Subtype_Kind (Ekind   (T)));
+               Set_Corresponding_Record_Type (Id,
+                                         Corresponding_Record_Type (T));
+               Set_First_Entity         (Id, First_Entity          (T));
+               Set_First_Private_Entity (Id, First_Private_Entity  (T));
+               Set_Has_Discriminants    (Id, Has_Discriminants     (T));
+               Set_Is_Constrained       (Id, Is_Constrained        (T));
+               Set_Last_Entity          (Id, Last_Entity           (T));
+
+               if Has_Discriminants (T) then
+                  Set_Discriminant_Constraint (Id,
+                                           Discriminant_Constraint (T));
+                  Set_Girder_Constraint_From_Discriminant_Constraint (Id);
+               end if;
+
+            --  If the subtype name denotes an incomplete type
+            --  an error was already reported by Process_Subtype.
+
+            when E_Incomplete_Type =>
+               Set_Etype (Id, Any_Type);
+
+            when others =>
+               raise Program_Error;
+         end case;
+      end if;
+
+      if Etype (Id) = Any_Type then
+         return;
+      end if;
+
+      --  Some common processing on all types
+
+      Set_Size_Info      (Id,                 T);
+      Set_First_Rep_Item (Id, First_Rep_Item (T));
+
+      T := Etype (Id);
+
+      Set_Is_Immediately_Visible (Id, True);
+      Set_Depends_On_Private     (Id, Has_Private_Component (T));
+
+      if Present (Generic_Parent_Type (N))
+        and then
+          (Nkind
+             (Parent (Generic_Parent_Type (N))) /= N_Formal_Type_Declaration
+            or else Nkind
+              (Formal_Type_Definition (Parent (Generic_Parent_Type (N))))
+                /=  N_Formal_Private_Type_Definition)
+      then
+         if Is_Tagged_Type (Id) then
+            if Is_Class_Wide_Type (Id) then
+               Derive_Subprograms (Generic_Parent_Type (N), Id, Etype (T));
+            else
+               Derive_Subprograms (Generic_Parent_Type (N), Id, T);
+            end if;
+
+         elsif Scope (Etype (Id)) /= Standard_Standard then
+            Derive_Subprograms (Generic_Parent_Type (N), Id);
+         end if;
+      end if;
+
+      if Is_Private_Type (T)
+        and then Present (Full_View (T))
+      then
+         Conditional_Delay (Id, Full_View (T));
+
+      --  The subtypes of components or subcomponents of protected types
+      --  do not need freeze nodes, which would otherwise appear in the
+      --  wrong scope (before the freeze node for the protected type). The
+      --  proper subtypes are those of the subcomponents of the corresponding
+      --  record.
+
+      elsif Ekind (Scope (Id)) /= E_Protected_Type
+        and then Present (Scope (Scope (Id))) -- error defense!
+        and then Ekind (Scope (Scope (Id))) /= E_Protected_Type
+      then
+         Conditional_Delay (Id, T);
+      end if;
+
+      --  Check that constraint_error is raised for a scalar subtype
+      --  indication when the lower or upper bound of a non-null range
+      --  lies outside the range of the type mark.
+
+      if Nkind (Subtype_Indication (N)) = N_Subtype_Indication then
+         if Is_Scalar_Type (Etype (Id))
+            and then Scalar_Range (Id) /=
+                     Scalar_Range (Etype (Subtype_Mark
+                                           (Subtype_Indication (N))))
+         then
+            Apply_Range_Check
+              (Scalar_Range (Id),
+               Etype (Subtype_Mark (Subtype_Indication (N))));
+
+         elsif Is_Array_Type (Etype (Id))
+           and then Present (First_Index (Id))
+         then
+            --  This really should be a subprogram that finds the indications
+            --  to check???
+
+            if ((Nkind (First_Index (Id)) = N_Identifier
+                   and then Ekind (Entity (First_Index (Id))) in Scalar_Kind)
+                 or else Nkind (First_Index (Id)) = N_Subtype_Indication)
+              and then
+                Nkind (Scalar_Range (Etype (First_Index (Id)))) = N_Range
+            then
+               declare
+                  Target_Typ : Entity_Id :=
+                    Etype
+                      (First_Index
+                        (Etype (Subtype_Mark (Subtype_Indication (N)))));
+               begin
+                  R_Checks :=
+                    Range_Check
+                      (Scalar_Range (Etype (First_Index (Id))),
+                       Target_Typ,
+                       Etype (First_Index (Id)),
+                       Defining_Identifier (N));
+
+                  Insert_Range_Checks
+                    (R_Checks,
+                     N,
+                     Target_Typ,
+                     Sloc (Defining_Identifier (N)));
+               end;
+            end if;
+         end if;
+      end if;
+
+      Check_Eliminated (Id);
+   end Analyze_Subtype_Declaration;
+
+   --------------------------------
+   -- Analyze_Subtype_Indication --
+   --------------------------------
+
+   procedure Analyze_Subtype_Indication (N : Node_Id) is
+      T : constant Entity_Id := Subtype_Mark (N);
+      R : constant Node_Id   := Range_Expression (Constraint (N));
+
+   begin
+      Analyze (T);
+      Analyze (R);
+      Set_Etype (N, Etype (R));
+   end Analyze_Subtype_Indication;
+
+   ------------------------------
+   -- Analyze_Type_Declaration --
+   ------------------------------
+
+   procedure Analyze_Type_Declaration (N : Node_Id) is
+      Def    : constant Node_Id   := Type_Definition (N);
+      Def_Id : constant Entity_Id := Defining_Identifier (N);
+      T      : Entity_Id;
+      Prev   : Entity_Id;
+
+   begin
+      Prev := Find_Type_Name (N);
+
+      if Ekind (Prev) = E_Incomplete_Type then
+         T := Full_View (Prev);
+      else
+         T := Prev;
+      end if;
+
+      Set_Is_Pure (T, Is_Pure (Current_Scope));
+
+      --  We set the flag Is_First_Subtype here. It is needed to set the
+      --  corresponding flag for the Implicit class-wide-type created
+      --  during tagged types processing.
+
+      Set_Is_First_Subtype (T, True);
+
+      --  Only composite types other than array types are allowed to have
+      --  discriminants.
+
+      case Nkind (Def) is
+
+         --  For derived types, the rule will be checked once we've figured
+         --  out the parent type.
+
+         when N_Derived_Type_Definition =>
+            null;
+
+         --  For record types, discriminants are allowed.
+
+         when N_Record_Definition =>
+            null;
+
+         when others =>
+            if Present (Discriminant_Specifications (N)) then
+               Error_Msg_N
+                 ("elementary or array type cannot have discriminants",
+                  Defining_Identifier
+                  (First (Discriminant_Specifications (N))));
+            end if;
+      end case;
+
+      --  Elaborate the type definition according to kind, and generate
+      --  susbsidiary (implicit) subtypes where needed. We skip this if
+      --  it was already done (this happens during the reanalysis that
+      --  follows a call to the high level optimizer).
+
+      if not Analyzed (T) then
+         Set_Analyzed (T);
+
+         case Nkind (Def) is
+
+            when N_Access_To_Subprogram_Definition =>
+               Access_Subprogram_Declaration (T, Def);
+
+               --  If this is a remote access to subprogram, we must create
+               --  the equivalent fat pointer type, and related subprograms.
+
+               if Is_Remote_Types (Current_Scope)
+                 or else Is_Remote_Call_Interface (Current_Scope)
+               then
+                  Validate_Remote_Access_To_Subprogram_Type (N);
+                  Process_Remote_AST_Declaration (N);
+               end if;
+
+               --  Validate categorization rule against access type declaration
+               --  usually a violation in Pure unit, Shared_Passive unit.
+
+               Validate_Access_Type_Declaration (T, N);
+
+            when N_Access_To_Object_Definition =>
+               Access_Type_Declaration (T, Def);
+
+               --  Validate categorization rule against access type declaration
+               --  usually a violation in Pure unit, Shared_Passive unit.
+
+               Validate_Access_Type_Declaration (T, N);
+
+               --  If we are in a Remote_Call_Interface package and define
+               --  a RACW, Read and Write attribute must be added.
+
+               if (Is_Remote_Call_Interface (Current_Scope)
+                     or else Is_Remote_Types (Current_Scope))
+                 and then Is_Remote_Access_To_Class_Wide_Type (Def_Id)
+               then
+                  Add_RACW_Features (Def_Id);
+               end if;
+
+            when N_Array_Type_Definition =>
+               Array_Type_Declaration (T, Def);
+
+            when N_Derived_Type_Definition =>
+               Derived_Type_Declaration (T, N, T /= Def_Id);
+
+            when N_Enumeration_Type_Definition =>
+               Enumeration_Type_Declaration (T, Def);
+
+            when N_Floating_Point_Definition =>
+               Floating_Point_Type_Declaration (T, Def);
+
+            when N_Decimal_Fixed_Point_Definition =>
+               Decimal_Fixed_Point_Type_Declaration (T, Def);
+
+            when N_Ordinary_Fixed_Point_Definition =>
+               Ordinary_Fixed_Point_Type_Declaration (T, Def);
+
+            when N_Signed_Integer_Type_Definition =>
+               Signed_Integer_Type_Declaration (T, Def);
+
+            when N_Modular_Type_Definition =>
+               Modular_Type_Declaration (T, Def);
+
+            when N_Record_Definition =>
+               Record_Type_Declaration (T, N);
+
+            when others =>
+               raise Program_Error;
+
+         end case;
+      end if;
+
+      if Etype (T) = Any_Type then
+         return;
+      end if;
+
+      --  Some common processing for all types
+
+      Set_Depends_On_Private (T, Has_Private_Component (T));
+
+      --  Both the declared entity, and its anonymous base type if one
+      --  was created, need freeze nodes allocated.
+
+      declare
+         B : constant Entity_Id := Base_Type (T);
+
+      begin
+         --  In the case where the base type is different from the first
+         --  subtype, we pre-allocate a freeze node, and set the proper
+         --  link to the first subtype. Freeze_Entity will use this
+         --  preallocated freeze node when it freezes the entity.
+
+         if B /= T then
+            Ensure_Freeze_Node (B);
+            Set_First_Subtype_Link (Freeze_Node (B), T);
+         end if;
+
+         if not From_With_Type (T) then
+            Set_Has_Delayed_Freeze (T);
+         end if;
+      end;
+
+      --  Case of T is the full declaration of some private type which has
+      --  been swapped in Defining_Identifier (N).
+
+      if T /= Def_Id and then Is_Private_Type (Def_Id) then
+         Process_Full_View (N, T, Def_Id);
+
+         --  Record the reference. The form of this is a little strange,
+         --  since the full declaration has been swapped in. So the first
+         --  parameter here represents the entity to which a reference is
+         --  made which is the "real" entity, i.e. the one swapped in,
+         --  and the second parameter provides the reference location.
+
+         Generate_Reference (T, T, 'c');
+
+         --  If in main unit, set as referenced, so we do not complain about
+         --  the full declaration being an unreferenced entity.
+
+         if In_Extended_Main_Source_Unit (Def_Id) then
+            Set_Referenced (Def_Id);
+         end if;
+
+      --  For completion of incomplete type, process incomplete dependents
+      --  and always mark the full type as referenced (it is the incomplete
+      --  type that we get for any real reference).
+
+      elsif Ekind (Prev) = E_Incomplete_Type then
+         Process_Incomplete_Dependents (N, T, Prev);
+         Generate_Reference (Prev, Def_Id, 'c');
+
+         --  If in main unit, set as referenced, so we do not complain about
+         --  the full declaration being an unreferenced entity.
+
+         if In_Extended_Main_Source_Unit (Def_Id) then
+            Set_Referenced (Def_Id);
+         end if;
+
+      --  If not private type or incomplete type completion, this is a real
+      --  definition of a new entity, so record it.
+
+      else
+         Generate_Definition (Def_Id);
+      end if;
+
+      Check_Eliminated (Def_Id);
+   end Analyze_Type_Declaration;
+
+   --------------------------
+   -- Analyze_Variant_Part --
+   --------------------------
+
+   procedure Analyze_Variant_Part (N : Node_Id) is
+
+      procedure Non_Static_Choice_Error (Choice : Node_Id);
+      --  Error routine invoked by the generic instantiation below when
+      --  the variant part has a non static choice.
+
+      procedure Process_Declarations (Variant : Node_Id);
+      --  Analyzes all the declarations associated with a Variant.
+      --  Needed by the generic instantiation below.
+
+      package Variant_Choices_Processing is new
+        Generic_Choices_Processing
+          (Get_Alternatives          => Variants,
+           Get_Choices               => Discrete_Choices,
+           Process_Empty_Choice      => No_OP,
+           Process_Non_Static_Choice => Non_Static_Choice_Error,
+           Process_Associated_Node   => Process_Declarations);
+      use Variant_Choices_Processing;
+      --  Instantiation of the generic choice processing package.
+
+      -----------------------------
+      -- Non_Static_Choice_Error --
+      -----------------------------
+
+      procedure Non_Static_Choice_Error (Choice : Node_Id) is
+      begin
+         Error_Msg_N ("choice given in variant part is not static", Choice);
+      end Non_Static_Choice_Error;
+
+      --------------------------
+      -- Process_Declarations --
+      --------------------------
+
+      procedure Process_Declarations (Variant : Node_Id) is
+      begin
+         if not Null_Present (Component_List (Variant)) then
+            Analyze_Declarations (Component_Items (Component_List (Variant)));
+
+            if Present (Variant_Part (Component_List (Variant))) then
+               Analyze (Variant_Part (Component_List (Variant)));
+            end if;
+         end if;
+      end Process_Declarations;
+
+      --  Variables local to Analyze_Case_Statement.
+
+      Others_Choice : Node_Id;
+
+      Discr_Name : Node_Id;
+      Discr_Type : Entity_Id;
+
+      Case_Table     : Choice_Table_Type (1 .. Number_Of_Choices (N));
+      Last_Choice    : Nat;
+      Dont_Care      : Boolean;
+      Others_Present : Boolean := False;
+
+   --  Start of processing for Analyze_Variant_Part
+
+   begin
+      Discr_Name := Name (N);
+      Analyze (Discr_Name);
+
+      if Ekind (Entity (Discr_Name)) /= E_Discriminant then
+         Error_Msg_N ("invalid discriminant name in variant part", Discr_Name);
+      end if;
+
+      Discr_Type := Etype (Entity (Discr_Name));
+
+      --  Call the instantiated Analyze_Choices which does the rest of the work
+
+      Analyze_Choices
+        (N, Discr_Type, Case_Table, Last_Choice, Dont_Care, Others_Present);
+
+      if Others_Present then
+         --  Fill in Others_Discrete_Choices field of the OTHERS choice
+
+         Others_Choice := First (Discrete_Choices (Last (Variants (N))));
+         Expand_Others_Choice
+           (Case_Table (1 .. Last_Choice), Others_Choice, Discr_Type);
+      end if;
+
+   end Analyze_Variant_Part;
+
+   ----------------------------
+   -- Array_Type_Declaration --
+   ----------------------------
+
+   procedure Array_Type_Declaration (T : in out Entity_Id; Def : Node_Id) is
+      Component_Def : constant Node_Id := Subtype_Indication (Def);
+      Element_Type  : Entity_Id;
+      Implicit_Base : Entity_Id;
+      Index         : Node_Id;
+      Related_Id    : Entity_Id := Empty;
+      Nb_Index      : Nat;
+      P             : constant Node_Id := Parent (Def);
+      Priv          : Entity_Id;
+
+   begin
+      if Nkind (Def) = N_Constrained_Array_Definition then
+
+         Index := First (Discrete_Subtype_Definitions (Def));
+
+         --  Find proper names for the implicit types which may be public.
+         --  in case of anonymous arrays we use the name of the first object
+         --  of that type as prefix.
+
+         if No (T) then
+            Related_Id :=  Defining_Identifier (P);
+         else
+            Related_Id := T;
+         end if;
+
+      else
+         Index := First (Subtype_Marks (Def));
+      end if;
+
+      Nb_Index := 1;
+
+      while Present (Index) loop
+         Analyze (Index);
+         Make_Index (Index, P, Related_Id, Nb_Index);
+         Next_Index (Index);
+         Nb_Index := Nb_Index + 1;
+      end loop;
+
+      Element_Type := Process_Subtype (Component_Def, P, Related_Id, 'C');
+
+      --  Constrained array case
+
+      if No (T) then
+         T := Create_Itype (E_Void, P, Related_Id, 'T');
+      end if;
+
+      if Nkind (Def) = N_Constrained_Array_Definition then
+
+         --  Establish Implicit_Base as unconstrained base type
+
+         Implicit_Base := Create_Itype (E_Array_Type, P, Related_Id, 'B');
+
+         Init_Size_Align        (Implicit_Base);
+         Set_Etype              (Implicit_Base, Implicit_Base);
+         Set_Scope              (Implicit_Base, Current_Scope);
+         Set_Has_Delayed_Freeze (Implicit_Base);
+
+         --  The constrained array type is a subtype of the unconstrained one
+
+         Set_Ekind          (T, E_Array_Subtype);
+         Init_Size_Align    (T);
+         Set_Etype          (T, Implicit_Base);
+         Set_Scope          (T, Current_Scope);
+         Set_Is_Constrained (T, True);
+         Set_First_Index    (T, First (Discrete_Subtype_Definitions (Def)));
+         Set_Has_Delayed_Freeze (T);
+
+         --  Complete setup of implicit base type
+
+         Set_First_Index    (Implicit_Base, First_Index (T));
+         Set_Component_Type (Implicit_Base, Element_Type);
+         Set_Has_Task       (Implicit_Base, Has_Task (Element_Type));
+         Set_Component_Size (Implicit_Base, Uint_0);
+         Set_Has_Controlled_Component (Implicit_Base,
+           Has_Controlled_Component (Element_Type)
+             or else Is_Controlled (Element_Type));
+         Set_Finalize_Storage_Only (Implicit_Base,
+           Finalize_Storage_Only (Element_Type));
+
+      --  Unconstrained array case
+
+      else
+         Set_Ekind                    (T, E_Array_Type);
+         Init_Size_Align              (T);
+         Set_Etype                    (T, T);
+         Set_Scope                    (T, Current_Scope);
+         Set_Component_Size           (T, Uint_0);
+         Set_Is_Constrained           (T, False);
+         Set_First_Index              (T, First (Subtype_Marks (Def)));
+         Set_Has_Delayed_Freeze       (T, True);
+         Set_Has_Task                 (T, Has_Task (Element_Type));
+         Set_Has_Controlled_Component (T,
+           Has_Controlled_Component (Element_Type)
+             or else Is_Controlled (Element_Type));
+         Set_Finalize_Storage_Only (T,
+           Finalize_Storage_Only (Element_Type));
+      end if;
+
+      Set_Component_Type (T, Element_Type);
+
+      if Aliased_Present (Def) then
+         Set_Has_Aliased_Components (Etype (T));
+      end if;
+
+      Priv := Private_Component (Element_Type);
+
+      if Present (Priv) then
+         --  Check for circular definitions.
+
+         if Priv = Any_Type then
+            Set_Component_Type (T, Any_Type);
+            Set_Component_Type (Etype (T), Any_Type);
+
+         --  There is a gap in the visiblity of operations on the composite
+         --  type only if the component type is defined in a different scope.
+
+         elsif Scope (Priv) = Current_Scope then
+            null;
+
+         elsif Is_Limited_Type (Priv) then
+            Set_Is_Limited_Composite (Etype (T));
+            Set_Is_Limited_Composite (T);
+         else
+            Set_Is_Private_Composite (Etype (T));
+            Set_Is_Private_Composite (T);
+         end if;
+      end if;
+
+      --  Create a concatenation operator for the new type. Internal
+      --  array types created for packed entities do not need such, they
+      --  are compatible with the user-defined type.
+
+      if Number_Dimensions (T) = 1
+         and then not Is_Packed_Array_Type (T)
+      then
+         New_Binary_Operator (Name_Op_Concat, T);
+      end if;
+
+      --  In the case of an unconstrained array the parser has already
+      --  verified that all the indices are unconstrained but we still
+      --  need to make sure that the element type is constrained.
+
+      if Is_Indefinite_Subtype (Element_Type) then
+         Error_Msg_N
+           ("unconstrained element type in array declaration ",
+            Component_Def);
+
+      elsif Is_Abstract (Element_Type) then
+         Error_Msg_N ("The type of a component cannot be abstract ",
+              Component_Def);
+      end if;
+
+   end Array_Type_Declaration;
+
+   -------------------------------
+   -- Build_Derived_Access_Type --
+   -------------------------------
+
+   procedure Build_Derived_Access_Type
+     (N            : Node_Id;
+      Parent_Type  : Entity_Id;
+      Derived_Type : Entity_Id)
+   is
+      S : constant Node_Id := Subtype_Indication (Type_Definition (N));
+
+      Desig_Type      : Entity_Id;
+      Discr           : Entity_Id;
+      Discr_Con_Elist : Elist_Id;
+      Discr_Con_El    : Elmt_Id;
+
+      Subt            : Entity_Id;
+
+   begin
+      --  Set the designated type so it is available in case this is
+      --  an access to a self-referential type, e.g. a standard list
+      --  type with a next pointer. Will be reset after subtype is built.
+
+      Set_Directly_Designated_Type (Derived_Type,
+        Designated_Type (Parent_Type));
+
+      Subt := Process_Subtype (S, N);
+
+      if Nkind (S) /= N_Subtype_Indication
+        and then Subt /= Base_Type (Subt)
+      then
+         Set_Ekind (Derived_Type, E_Access_Subtype);
+      end if;
+
+      if Ekind (Derived_Type) = E_Access_Subtype then
+         declare
+            Pbase      : constant Entity_Id := Base_Type (Parent_Type);
+            Ibase      : constant Entity_Id :=
+                           Create_Itype (Ekind (Pbase), N, Derived_Type, 'B');
+            Svg_Chars  : constant Name_Id   := Chars (Ibase);
+            Svg_Next_E : constant Entity_Id := Next_Entity (Ibase);
+
+         begin
+            Copy_Node (Pbase, Ibase);
+
+            Set_Chars       (Ibase, Svg_Chars);
+            Set_Next_Entity (Ibase, Svg_Next_E);
+            Set_Sloc        (Ibase, Sloc (Derived_Type));
+            Set_Scope       (Ibase, Scope (Derived_Type));
+            Set_Freeze_Node (Ibase, Empty);
+            Set_Is_Frozen   (Ibase, False);
+
+            Set_Etype (Ibase, Pbase);
+            Set_Etype (Derived_Type, Ibase);
+         end;
+      end if;
+
+      Set_Directly_Designated_Type
+        (Derived_Type, Designated_Type (Subt));
+
+      Set_Is_Constrained     (Derived_Type, Is_Constrained (Subt));
+      Set_Is_Access_Constant (Derived_Type, Is_Access_Constant (Parent_Type));
+      Set_Size_Info          (Derived_Type,                     Parent_Type);
+      Set_RM_Size            (Derived_Type, RM_Size            (Parent_Type));
+      Set_Depends_On_Private (Derived_Type,
+                              Has_Private_Component (Derived_Type));
+      Conditional_Delay      (Derived_Type, Subt);
+
+      --  Note: we do not copy the Storage_Size_Variable, since
+      --  we always go to the root type for this information.
+
+      --  Apply range checks to discriminants for derived record case
+      --  ??? THIS CODE SHOULD NOT BE HERE REALLY.
+
+      Desig_Type := Designated_Type (Derived_Type);
+      if Is_Composite_Type (Desig_Type)
+        and then (not Is_Array_Type (Desig_Type))
+        and then Has_Discriminants (Desig_Type)
+        and then Base_Type (Desig_Type) /= Desig_Type
+      then
+         Discr_Con_Elist := Discriminant_Constraint (Desig_Type);
+         Discr_Con_El := First_Elmt (Discr_Con_Elist);
+
+         Discr := First_Discriminant (Base_Type (Desig_Type));
+         while Present (Discr_Con_El) loop
+            Apply_Range_Check (Node (Discr_Con_El), Etype (Discr));
+            Next_Elmt (Discr_Con_El);
+            Next_Discriminant (Discr);
+         end loop;
+      end if;
+   end Build_Derived_Access_Type;
+
+   ------------------------------
+   -- Build_Derived_Array_Type --
+   ------------------------------
+
+   procedure Build_Derived_Array_Type
+     (N            : Node_Id;
+      Parent_Type  : Entity_Id;
+      Derived_Type : Entity_Id)
+   is
+      Loc           : constant Source_Ptr := Sloc (N);
+      Tdef          : constant Node_Id    := Type_Definition (N);
+      Indic         : constant Node_Id    := Subtype_Indication (Tdef);
+      Parent_Base   : constant Entity_Id  := Base_Type (Parent_Type);
+      Implicit_Base : Entity_Id;
+      New_Indic     : Node_Id;
+
+      procedure Make_Implicit_Base;
+      --  If the parent subtype is constrained, the derived type is a
+      --  subtype of an implicit base type derived from the parent base.
+
+      ------------------------
+      -- Make_Implicit_Base --
+      ------------------------
+
+      procedure Make_Implicit_Base is
+      begin
+         Implicit_Base :=
+           Create_Itype (Ekind (Parent_Base), N, Derived_Type, 'B');
+
+         Set_Ekind (Implicit_Base, Ekind (Parent_Base));
+         Set_Etype (Implicit_Base, Parent_Base);
+
+         Copy_Array_Subtype_Attributes   (Implicit_Base, Parent_Base);
+         Copy_Array_Base_Type_Attributes (Implicit_Base, Parent_Base);
+
+         Set_Has_Delayed_Freeze (Implicit_Base, True);
+      end Make_Implicit_Base;
+
+   --  Start of processing for Build_Derived_Array_Type
+
+   begin
+      if not Is_Constrained (Parent_Type) then
+         if Nkind (Indic) /= N_Subtype_Indication then
+            Set_Ekind (Derived_Type, E_Array_Type);
+
+            Copy_Array_Subtype_Attributes   (Derived_Type, Parent_Type);
+            Copy_Array_Base_Type_Attributes (Derived_Type, Parent_Type);
+
+            Set_Has_Delayed_Freeze (Derived_Type, True);
+
+         else
+            Make_Implicit_Base;
+            Set_Etype (Derived_Type, Implicit_Base);
+
+            New_Indic :=
+              Make_Subtype_Declaration (Loc,
+                Defining_Identifier => Derived_Type,
+                Subtype_Indication  =>
+                  Make_Subtype_Indication (Loc,
+                    Subtype_Mark => New_Reference_To (Implicit_Base, Loc),
+                    Constraint => Constraint (Indic)));
+
+            Rewrite (N, New_Indic);
+            Analyze (N);
+         end if;
+
+      else
+         if Nkind (Indic) /= N_Subtype_Indication then
+            Make_Implicit_Base;
+
+            Set_Ekind             (Derived_Type, Ekind (Parent_Type));
+            Set_Etype             (Derived_Type, Implicit_Base);
+            Copy_Array_Subtype_Attributes (Derived_Type, Parent_Type);
+
+         else
+            Error_Msg_N ("illegal constraint on constrained type", Indic);
+         end if;
+      end if;
+
+      --  If the parent type is not a derived type itself, and is
+      --  declared in a closed scope (e.g., a subprogram), then we
+      --  need to explicitly introduce the new type's concatenation
+      --  operator since Derive_Subprograms will not inherit the
+      --  parent's operator.
+
+      if Number_Dimensions (Parent_Type) = 1
+        and then not Is_Limited_Type (Parent_Type)
+        and then not Is_Derived_Type (Parent_Type)
+        and then not Is_Package (Scope (Base_Type (Parent_Type)))
+      then
+         New_Binary_Operator (Name_Op_Concat, Derived_Type);
+      end if;
+   end Build_Derived_Array_Type;
+
+   -----------------------------------
+   -- Build_Derived_Concurrent_Type --
+   -----------------------------------
+
+   procedure Build_Derived_Concurrent_Type
+     (N            : Node_Id;
+      Parent_Type  : Entity_Id;
+      Derived_Type : Entity_Id)
+   is
+      D_Constraint : Node_Id;
+      Disc_Spec    : Node_Id;
+      Old_Disc     : Entity_Id;
+      New_Disc     : Entity_Id;
+      Constraint_Present : constant Boolean :=
+         Nkind (Subtype_Indication (Type_Definition (N))) =
+           N_Subtype_Indication;
+
+   begin
+      Set_Girder_Constraint (Derived_Type, No_Elist);
+
+      if Is_Task_Type (Parent_Type) then
+         Set_Storage_Size_Variable (Derived_Type,
+           Storage_Size_Variable (Parent_Type));
+      end if;
+
+      if Present (Discriminant_Specifications (N)) then
+         New_Scope (Derived_Type);
+         Check_Or_Process_Discriminants (N, Derived_Type);
+         End_Scope;
+      end if;
+
+      --  All attributes are inherited from parent. In particular,
+      --  entries and the corresponding record type are the same.
+      --  Discriminants may be renamed, and must be treated separately.
+
+      Set_Has_Discriminants
+                       (Derived_Type, Has_Discriminants (Parent_Type));
+      Set_Corresponding_Record_Type
+                       (Derived_Type, Corresponding_Record_Type
+                                                        (Parent_Type));
+
+      if Constraint_Present then
+
+         if not Has_Discriminants (Parent_Type) then
+            Error_Msg_N ("untagged parent must have discriminants", N);
+
+         elsif Present (Discriminant_Specifications (N)) then
+
+            --  Verify that new discriminants are used to constrain
+            --  the old ones.
+
+            Old_Disc   := First_Discriminant (Parent_Type);
+            New_Disc   := First_Discriminant (Derived_Type);
+            Disc_Spec  := First (Discriminant_Specifications (N));
+            D_Constraint :=
+              First (Constraints (
+                Constraint (Subtype_Indication (Type_Definition (N)))));
+
+            while Present (Old_Disc) and then Present (Disc_Spec) loop
+
+               if Nkind (Discriminant_Type (Disc_Spec)) /=
+                 N_Access_Definition
+               then
+                  Analyze (Discriminant_Type (Disc_Spec));
+                  if not Subtypes_Statically_Compatible (
+                             Etype (Discriminant_Type (Disc_Spec)),
+                               Etype (Old_Disc))
+                  then
+                     Error_Msg_N
+                       ("not statically compatible with parent discriminant",
+                        Discriminant_Type (Disc_Spec));
+                  end if;
+               end if;
+
+               if Nkind (D_Constraint) = N_Identifier
+                 and then Chars (D_Constraint) /=
+                   Chars (Defining_Identifier (Disc_Spec))
+               then
+                  Error_Msg_N ("new discriminants must constrain old ones",
+                    D_Constraint);
+               else
+                  Set_Corresponding_Discriminant (New_Disc, Old_Disc);
+               end if;
+
+               Next_Discriminant (Old_Disc);
+               Next_Discriminant (New_Disc);
+               Next (Disc_Spec);
+            end loop;
+
+            if Present (Old_Disc) or else Present (Disc_Spec) then
+               Error_Msg_N ("discriminant mismatch in derivation", N);
+            end if;
+
+         end if;
+
+      elsif Present (Discriminant_Specifications (N)) then
+         Error_Msg_N
+           ("missing discriminant constraint in untagged derivation",
+            N);
+      end if;
+
+      if Present (Discriminant_Specifications (N)) then
+
+         Old_Disc := First_Discriminant (Parent_Type);
+
+         while Present (Old_Disc) loop
+
+            if No (Next_Entity (Old_Disc))
+              or else Ekind (Next_Entity (Old_Disc)) /= E_Discriminant
+            then
+               Set_Next_Entity (Last_Entity (Derived_Type),
+                                         Next_Entity (Old_Disc));
+               exit;
+            end if;
+
+            Next_Discriminant (Old_Disc);
+         end loop;
+
+      else
+         Set_First_Entity (Derived_Type, First_Entity (Parent_Type));
+      end if;
+
+      Set_Last_Entity  (Derived_Type, Last_Entity  (Parent_Type));
+
+      Set_Has_Completion (Derived_Type);
+   end Build_Derived_Concurrent_Type;
+
+   ------------------------------------
+   -- Build_Derived_Enumeration_Type --
+   ------------------------------------
+
+   procedure Build_Derived_Enumeration_Type
+     (N            : Node_Id;
+      Parent_Type  : Entity_Id;
+      Derived_Type : Entity_Id)
+   is
+      Loc           : constant Source_Ptr := Sloc (N);
+      Def           : constant Node_Id    := Type_Definition (N);
+      Indic         : constant Node_Id    := Subtype_Indication (Def);
+      Implicit_Base : Entity_Id;
+      Literal       : Entity_Id;
+      New_Lit       : Entity_Id;
+      Literals_List : List_Id;
+      Type_Decl     : Node_Id;
+      Hi, Lo        : Node_Id;
+      Rang_Expr     : Node_Id;
+
+   begin
+      --  Since types Standard.Character and Standard.Wide_Character do
+      --  not have explicit literals lists we need to process types derived
+      --  from them specially. This is handled by Derived_Standard_Character.
+      --  If the parent type is a generic type, there are no literals either,
+      --  and we construct the same skeletal representation as for the generic
+      --  parent type.
+
+      if Root_Type (Parent_Type) = Standard_Character
+        or else Root_Type (Parent_Type) = Standard_Wide_Character
+      then
+         Derived_Standard_Character (N, Parent_Type, Derived_Type);
+
+      elsif Is_Generic_Type (Root_Type (Parent_Type)) then
+         declare
+            Lo : Node_Id;
+            Hi : Node_Id;
+
+         begin
+            Lo :=
+               Make_Attribute_Reference (Loc,
+                 Attribute_Name => Name_First,
+                 Prefix => New_Reference_To (Derived_Type, Loc));
+            Set_Etype (Lo, Derived_Type);
+
+            Hi :=
+               Make_Attribute_Reference (Loc,
+                 Attribute_Name => Name_Last,
+                 Prefix => New_Reference_To (Derived_Type, Loc));
+            Set_Etype (Hi, Derived_Type);
+
+            Set_Scalar_Range (Derived_Type,
+               Make_Range (Loc,
+                 Low_Bound => Lo,
+                 High_Bound => Hi));
+         end;
+
+      else
+         --  If a constraint is present, analyze the bounds to catch
+         --  premature usage of the derived literals.
+
+         if Nkind (Indic) = N_Subtype_Indication
+           and then Nkind (Range_Expression (Constraint (Indic))) = N_Range
+         then
+            Analyze (Low_Bound  (Range_Expression (Constraint (Indic))));
+            Analyze (High_Bound (Range_Expression (Constraint (Indic))));
+         end if;
+
+         --  Introduce an implicit base type for the derived type even
+         --  if there is no constraint attached to it, since this seems
+         --  closer to the Ada semantics. Build a full type declaration
+         --  tree for the derived type using the implicit base type as
+         --  the defining identifier. The build a subtype declaration
+         --  tree which applies the constraint (if any) have it replace
+         --  the derived type declaration.
+
+         Literal := First_Literal (Parent_Type);
+         Literals_List := New_List;
+
+         while Present (Literal)
+           and then Ekind (Literal) = E_Enumeration_Literal
+         loop
+            --  Literals of the derived type have the same representation as
+            --  those of the parent type, but this representation can be
+            --  overridden by an explicit representation clause. Indicate
+            --  that there is no explicit representation given yet. These
+            --  derived literals are implicit operations of the new type,
+            --  and can be overriden by explicit ones.
+
+            if Nkind (Literal) = N_Defining_Character_Literal then
+               New_Lit :=
+                 Make_Defining_Character_Literal (Loc, Chars (Literal));
+            else
+               New_Lit := Make_Defining_Identifier (Loc, Chars (Literal));
+            end if;
+
+            Set_Ekind                (New_Lit, E_Enumeration_Literal);
+            Set_Enumeration_Pos      (New_Lit, Enumeration_Pos (Literal));
+            Set_Enumeration_Rep      (New_Lit, Enumeration_Rep (Literal));
+            Set_Enumeration_Rep_Expr (New_Lit, Empty);
+            Set_Alias                (New_Lit, Literal);
+            Set_Is_Known_Valid       (New_Lit, True);
+
+            Append (New_Lit, Literals_List);
+            Next_Literal (Literal);
+         end loop;
+
+         Implicit_Base :=
+           Make_Defining_Identifier (Sloc (Derived_Type),
+             New_External_Name (Chars (Derived_Type), 'B'));
+
+         --  Indicate the proper nature of the derived type. This must
+         --  be done before analysis of the literals, to recognize cases
+         --  when a literal may be hidden by a previous explicit function
+         --  definition (cf. c83031a).
+
+         Set_Ekind (Derived_Type, E_Enumeration_Subtype);
+         Set_Etype (Derived_Type, Implicit_Base);
+
+         Type_Decl :=
+           Make_Full_Type_Declaration (Loc,
+             Defining_Identifier => Implicit_Base,
+             Discriminant_Specifications => No_List,
+             Type_Definition =>
+               Make_Enumeration_Type_Definition (Loc, Literals_List));
+
+         Mark_Rewrite_Insertion (Type_Decl);
+         Insert_Before (N, Type_Decl);
+         Analyze (Type_Decl);
+
+         --  After the implicit base is analyzed its Etype needs to be
+         --  changed to reflect the fact that it is derived from the
+         --  parent type which was ignored during analysis. We also set
+         --  the size at this point.
+
+         Set_Etype (Implicit_Base, Parent_Type);
+
+         Set_Size_Info      (Implicit_Base,                 Parent_Type);
+         Set_RM_Size        (Implicit_Base, RM_Size        (Parent_Type));
+         Set_First_Rep_Item (Implicit_Base, First_Rep_Item (Parent_Type));
+
+         Set_Has_Non_Standard_Rep
+                            (Implicit_Base, Has_Non_Standard_Rep
+                                                           (Parent_Type));
+         Set_Has_Delayed_Freeze (Implicit_Base);
+
+         --  Process the subtype indication including a validation check
+         --  on the constraint, if any. If a constraint is given, its bounds
+         --  must be implicitly converted to the new type.
+
+         if Nkind (Indic) = N_Subtype_Indication then
+
+            declare
+               R   : constant Node_Id :=
+                       Range_Expression (Constraint (Indic));
+
+            begin
+               if Nkind (R) = N_Range then
+                  Hi := Build_Scalar_Bound
+                          (High_Bound (R), Parent_Type, Implicit_Base, Loc);
+                  Lo := Build_Scalar_Bound
+                          (Low_Bound  (R), Parent_Type, Implicit_Base, Loc);
+
+               else
+                  --  Constraint is a Range attribute. Replace with the
+                  --  explicit mention of the bounds of the prefix, which
+                  --  must be a subtype.
+
+                  Analyze (Prefix (R));
+                  Hi :=
+                    Convert_To (Implicit_Base,
+                      Make_Attribute_Reference (Loc,
+                        Attribute_Name => Name_Last,
+                        Prefix =>
+                          New_Occurrence_Of (Entity (Prefix (R)), Loc)));
+
+                  Lo :=
+                    Convert_To (Implicit_Base,
+                      Make_Attribute_Reference (Loc,
+                        Attribute_Name => Name_First,
+                        Prefix =>
+                          New_Occurrence_Of (Entity (Prefix (R)), Loc)));
+               end if;
+
+            end;
+
+         else
+            Hi :=
+              Build_Scalar_Bound
+                (Type_High_Bound (Parent_Type),
+                 Parent_Type, Implicit_Base, Loc);
+            Lo :=
+               Build_Scalar_Bound
+                 (Type_Low_Bound (Parent_Type),
+                  Parent_Type, Implicit_Base, Loc);
+         end if;
+
+         Rang_Expr :=
+           Make_Range (Loc,
+             Low_Bound  => Lo,
+             High_Bound => Hi);
+
+         --  If we constructed a default range for the case where no range
+         --  was given, then the expressions in the range must not freeze
+         --  since they do not correspond to expressions in the source.
+
+         if Nkind (Indic) /= N_Subtype_Indication then
+            Set_Must_Not_Freeze (Lo);
+            Set_Must_Not_Freeze (Hi);
+            Set_Must_Not_Freeze (Rang_Expr);
+         end if;
+
+         Rewrite (N,
+           Make_Subtype_Declaration (Loc,
+             Defining_Identifier => Derived_Type,
+             Subtype_Indication =>
+               Make_Subtype_Indication (Loc,
+                 Subtype_Mark => New_Occurrence_Of (Implicit_Base, Loc),
+                 Constraint =>
+                   Make_Range_Constraint (Loc,
+                     Range_Expression => Rang_Expr))));
+
+         Analyze (N);
+
+         --  If pragma Discard_Names applies on the first subtype
+         --  of the parent type, then it must be applied on this
+         --  subtype as well.
+
+         if Einfo.Discard_Names (First_Subtype (Parent_Type)) then
+            Set_Discard_Names (Derived_Type);
+         end if;
+
+         --  Apply a range check. Since this range expression doesn't
+         --  have an Etype, we have to specifically pass the Source_Typ
+         --  parameter. Is this right???
+
+         if Nkind (Indic) = N_Subtype_Indication then
+            Apply_Range_Check (Range_Expression (Constraint (Indic)),
+                               Parent_Type,
+                               Source_Typ => Entity (Subtype_Mark (Indic)));
+         end if;
+      end if;
+
+   end Build_Derived_Enumeration_Type;
+
+   --------------------------------
+   -- Build_Derived_Numeric_Type --
+   --------------------------------
+
+   procedure Build_Derived_Numeric_Type
+     (N            : Node_Id;
+      Parent_Type  : Entity_Id;
+      Derived_Type : Entity_Id)
+   is
+      Loc           : constant Source_Ptr := Sloc (N);
+      Tdef          : constant Node_Id    := Type_Definition (N);
+      Indic         : constant Node_Id    := Subtype_Indication (Tdef);
+      Parent_Base   : constant Entity_Id  := Base_Type (Parent_Type);
+      No_Constraint : constant Boolean    := Nkind (Indic) /=
+                                                  N_Subtype_Indication;
+      Implicit_Base    : Entity_Id;
+
+      Lo : Node_Id;
+      Hi : Node_Id;
+      T  : Entity_Id;
+
+   begin
+      --  Process the subtype indication including a validation check on
+      --  the constraint if any.
+
+      T := Process_Subtype (Indic, N);
+
+      --  Introduce an implicit base type for the derived type even if
+      --  there is no constraint attached to it, since this seems closer
+      --  to the Ada semantics.
+
+      Implicit_Base :=
+        Create_Itype (Ekind (Parent_Base), N, Derived_Type, 'B');
+
+      Set_Etype          (Implicit_Base, Parent_Base);
+      Set_Ekind          (Implicit_Base, Ekind          (Parent_Base));
+      Set_Size_Info      (Implicit_Base,                 Parent_Base);
+      Set_RM_Size        (Implicit_Base, RM_Size        (Parent_Base));
+      Set_First_Rep_Item (Implicit_Base, First_Rep_Item (Parent_Base));
+      Set_Parent         (Implicit_Base, Parent (Derived_Type));
+
+      if Is_Discrete_Or_Fixed_Point_Type (Parent_Base) then
+         Set_RM_Size (Implicit_Base, RM_Size (Parent_Base));
+      end if;
+
+      Set_Has_Delayed_Freeze (Implicit_Base);
+
+      Lo := New_Copy_Tree (Type_Low_Bound  (Parent_Base));
+      Hi := New_Copy_Tree (Type_High_Bound (Parent_Base));
+
+      Set_Scalar_Range (Implicit_Base,
+        Make_Range (Loc,
+          Low_Bound  => Lo,
+          High_Bound => Hi));
+
+      if Has_Infinities (Parent_Base) then
+         Set_Includes_Infinities (Scalar_Range (Implicit_Base));
+      end if;
+
+      --  The Derived_Type, which is the entity of the declaration, is
+      --  a subtype of the implicit base. Its Ekind is a subtype, even
+      --  in the absence of an explicit constraint.
+
+      Set_Etype (Derived_Type, Implicit_Base);
+
+      --  If we did not have a constraint, then the Ekind is set from the
+      --  parent type (otherwise Process_Subtype has set the bounds)
+
+      if No_Constraint then
+         Set_Ekind (Derived_Type, Subtype_Kind (Ekind (Parent_Type)));
+      end if;
+
+      --  If we did not have a range constraint, then set the range
+      --  from the parent type. Otherwise, the call to Process_Subtype
+      --  has set the bounds.
+
+      if No_Constraint
+        or else not Has_Range_Constraint (Indic)
+      then
+         Set_Scalar_Range (Derived_Type,
+           Make_Range (Loc,
+             Low_Bound  => New_Copy_Tree (Type_Low_Bound  (Parent_Type)),
+             High_Bound => New_Copy_Tree (Type_High_Bound (Parent_Type))));
+         Set_Is_Constrained (Derived_Type, Is_Constrained (Parent_Type));
+
+         if Has_Infinities (Parent_Type) then
+            Set_Includes_Infinities (Scalar_Range (Derived_Type));
+         end if;
+      end if;
+
+      --  Set remaining type-specific fields, depending on numeric type
+
+      if Is_Modular_Integer_Type (Parent_Type) then
+         Set_Modulus (Implicit_Base, Modulus (Parent_Base));
+
+         Set_Non_Binary_Modulus
+           (Implicit_Base, Non_Binary_Modulus (Parent_Base));
+
+      elsif Is_Floating_Point_Type (Parent_Type) then
+
+         --  Digits of base type is always copied from the digits value of
+         --  the parent base type, but the digits of the derived type will
+         --  already have been set if there was a constraint present.
+
+         Set_Digits_Value (Implicit_Base, Digits_Value (Parent_Base));
+         Set_Vax_Float    (Implicit_Base, Vax_Float    (Parent_Base));
+
+         if No_Constraint then
+            Set_Digits_Value (Derived_Type, Digits_Value (Parent_Type));
+         end if;
+
+      elsif Is_Fixed_Point_Type (Parent_Type) then
+
+         --  Small of base type and derived type are always copied from
+         --  the parent base type, since smalls never change. The delta
+         --  of the base type is also copied from the parent base type.
+         --  However the delta of the derived type will have been set
+         --  already if a constraint was present.
+
+         Set_Small_Value (Derived_Type,  Small_Value (Parent_Base));
+         Set_Small_Value (Implicit_Base, Small_Value (Parent_Base));
+         Set_Delta_Value (Implicit_Base, Delta_Value (Parent_Base));
+
+         if No_Constraint then
+            Set_Delta_Value (Derived_Type,  Delta_Value (Parent_Type));
+         end if;
+
+         --  The scale and machine radix in the decimal case are always
+         --  copied from the parent base type.
+
+         if Is_Decimal_Fixed_Point_Type (Parent_Type) then
+            Set_Scale_Value (Derived_Type,  Scale_Value (Parent_Base));
+            Set_Scale_Value (Implicit_Base, Scale_Value (Parent_Base));
+
+            Set_Machine_Radix_10
+              (Derived_Type,  Machine_Radix_10 (Parent_Base));
+            Set_Machine_Radix_10
+              (Implicit_Base, Machine_Radix_10 (Parent_Base));
+
+            Set_Digits_Value (Implicit_Base, Digits_Value (Parent_Base));
+
+            if No_Constraint then
+               Set_Digits_Value (Derived_Type, Digits_Value (Parent_Base));
+
+            else
+               --  the analysis of the subtype_indication sets the
+               --  digits value of the derived type.
+
+               null;
+            end if;
+         end if;
+      end if;
+
+      --  The type of the bounds is that of the parent type, and they
+      --  must be converted to the derived type.
+
+      Convert_Scalar_Bounds (N, Parent_Type, Derived_Type, Loc);
+
+      --  The implicit_base should be frozen when the derived type is frozen,
+      --  but note that it is used in the conversions of the bounds. For
+      --  fixed types we delay the determination of the bounds until the proper
+      --  freezing point. For other numeric types this is rejected by GCC, for
+      --  reasons that are currently unclear (???), so we choose to freeze the
+      --  implicit base now. In the case of integers and floating point types
+      --  this is harmless because subsequent representation clauses cannot
+      --  affect anything, but it is still baffling that we cannot use the
+      --  same mechanism for all derived numeric types.
+
+      if Is_Fixed_Point_Type (Parent_Type) then
+         Conditional_Delay (Implicit_Base, Parent_Type);
+      else
+         Freeze_Before (N, Implicit_Base);
+      end if;
+
+   end Build_Derived_Numeric_Type;
+
+   --------------------------------
+   -- Build_Derived_Private_Type --
+   --------------------------------
+
+   procedure Build_Derived_Private_Type
+     (N            : Node_Id;
+      Parent_Type  : Entity_Id;
+      Derived_Type : Entity_Id;
+      Is_Completion : Boolean;
+      Derive_Subps  : Boolean := True)
+   is
+      Der_Base    : Entity_Id;
+      Discr       : Entity_Id;
+      Full_Decl   : Node_Id := Empty;
+      Full_Der    : Entity_Id;
+      Full_P      : Entity_Id;
+      Last_Discr  : Entity_Id;
+      Par_Scope   : constant Entity_Id := Scope (Base_Type (Parent_Type));
+      Swapped     : Boolean := False;
+
+      procedure Copy_And_Build;
+      --  Copy derived type declaration, replace parent with its full view,
+      --  and analyze new declaration.
+
+      procedure Copy_And_Build is
+         Full_N  : Node_Id;
+
+      begin
+         if Ekind (Parent_Type) in Record_Kind
+           or else (Ekind (Parent_Type) in Enumeration_Kind
+             and then Root_Type (Parent_Type) /= Standard_Character
+             and then Root_Type (Parent_Type) /= Standard_Wide_Character
+             and then not Is_Generic_Type (Root_Type (Parent_Type)))
+         then
+            Full_N := New_Copy_Tree (N);
+            Insert_After (N, Full_N);
+            Build_Derived_Type (
+              Full_N, Parent_Type, Full_Der, True, Derive_Subps => False);
+
+         else
+            Build_Derived_Type (
+              N, Parent_Type, Full_Der, True, Derive_Subps => False);
+         end if;
+      end Copy_And_Build;
+
+   --  Start of processing for Build_Derived_Private_Type
+
+   begin
+      if Is_Tagged_Type (Parent_Type) then
+         Build_Derived_Record_Type
+           (N, Parent_Type, Derived_Type, Derive_Subps);
+         return;
+
+      elsif Has_Discriminants (Parent_Type) then
+
+         if Present (Full_View (Parent_Type)) then
+            if not Is_Completion then
+
+               --  Copy declaration for subsequent analysis.
+
+               Full_Decl := New_Copy_Tree (N);
+               Full_Der  := New_Copy (Derived_Type);
+               Insert_After (N, Full_Decl);
+
+            else
+               --  If this is a completion, the full view being built is
+               --  itself private. We build a subtype of the parent with
+               --  the same constraints as this full view, to convey to the
+               --  back end the constrained components and the size of this
+               --  subtype. If the parent is constrained, its full view can
+               --  serve as the underlying full view of the derived type.
+
+               if No (Discriminant_Specifications (N)) then
+
+                  if Nkind (Subtype_Indication (Type_Definition (N)))
+                    = N_Subtype_Indication
+                  then
+                     Build_Underlying_Full_View (N, Derived_Type, Parent_Type);
+
+                  elsif Is_Constrained (Full_View (Parent_Type)) then
+                     Set_Underlying_Full_View (Derived_Type,
+                       Full_View (Parent_Type));
+                  end if;
+
+               else
+                  --  If there are new discriminants, the parent subtype is
+                  --  constrained by them, but it is not clear how to build
+                  --  the underlying_full_view in this case ???
+
+                  null;
+               end if;
+            end if;
+         end if;
+
+         Build_Derived_Record_Type
+           (N, Parent_Type, Derived_Type, Derive_Subps);
+
+         if Present (Full_View (Parent_Type))
+           and then not Is_Completion
+         then
+            if not In_Open_Scopes (Par_Scope)
+              or else not In_Same_Source_Unit (N, Parent_Type)
+            then
+               --  Swap partial and full views temporarily
+
+               Install_Private_Declarations (Par_Scope);
+               Install_Visible_Declarations (Par_Scope);
+               Swapped := True;
+            end if;
+
+            --  Subprograms have been derived on the private view,
+            --  the completion does not derive them anew.
+
+            Build_Derived_Record_Type
+              (Full_Decl, Parent_Type, Full_Der, False);
+
+            if Swapped then
+               Uninstall_Declarations (Par_Scope);
+
+               if In_Open_Scopes (Par_Scope) then
+                  Install_Visible_Declarations (Par_Scope);
+               end if;
+            end if;
+
+            Der_Base := Base_Type (Derived_Type);
+            Set_Full_View (Derived_Type, Full_Der);
+            Set_Full_View (Der_Base, Base_Type (Full_Der));
+
+            --  Copy the discriminant list from full view to
+            --  the partial views (base type and its subtype).
+            --  Gigi requires that the partial and full views
+            --  have the same discriminants.
+            --  ??? Note that since the partial view is pointing
+            --  to discriminants in the full view, their scope
+            --  will be that of the full view. This might
+            --  cause some front end problems and need
+            --  adustment?
+
+            Discr := First_Discriminant (Base_Type (Full_Der));
+            Set_First_Entity (Der_Base, Discr);
+
+            loop
+               Last_Discr := Discr;
+               Next_Discriminant (Discr);
+               exit when No (Discr);
+            end loop;
+
+            Set_Last_Entity (Der_Base, Last_Discr);
+
+            Set_First_Entity (Derived_Type, First_Entity (Der_Base));
+            Set_Last_Entity  (Derived_Type, Last_Entity  (Der_Base));
+
+         else
+            --  If this is a completion, the derived type stays private
+            --  and there is no need to create a further full view, except
+            --  in the unusual case when the derivation is nested within a
+            --  child unit, see below.
+
+            null;
+         end if;
+
+      elsif Present (Full_View (Parent_Type))
+        and then  Has_Discriminants (Full_View (Parent_Type))
+      then
+         if Has_Unknown_Discriminants (Parent_Type)
+           and then Nkind (Subtype_Indication (Type_Definition (N)))
+             = N_Subtype_Indication
+         then
+            Error_Msg_N
+              ("cannot constrain type with unknown discriminants",
+               Subtype_Indication (Type_Definition (N)));
+            return;
+         end if;
+
+         --  Inherit the discriminants of the full view, but
+         --  keep the proper parent type.
+
+         --  ??? this looks wrong, we are replacing (and thus,
+         --  erasing) the partial view!
+
+         --  In any case, the primitive operations are inherited from
+         --  the parent type, not from the internal full view.
+
+         Build_Derived_Record_Type
+           (N, Full_View (Parent_Type), Derived_Type,
+             Derive_Subps => False);
+         Set_Etype (Base_Type (Derived_Type), Base_Type (Parent_Type));
+
+         if Derive_Subps then
+            Derive_Subprograms (Parent_Type, Derived_Type);
+         end if;
+
+      else
+
+         --  Untagged type, No discriminants on either view.
+
+         if Nkind (Subtype_Indication (Type_Definition (N)))
+           = N_Subtype_Indication
+         then
+            Error_Msg_N
+              ("illegal constraint on type without discriminants", N);
+         end if;
+
+         if Present (Discriminant_Specifications (N))
+           and then Present (Full_View (Parent_Type))
+           and then not Is_Tagged_Type (Full_View (Parent_Type))
+         then
+            Error_Msg_N
+              ("cannot add discriminants to untagged type", N);
+         end if;
+
+         Set_Girder_Constraint (Derived_Type, No_Elist);
+         Set_Is_Constrained (Derived_Type, Is_Constrained (Parent_Type));
+         Set_Is_Controlled  (Derived_Type, Is_Controlled  (Parent_Type));
+         Set_Has_Controlled_Component (Derived_Type,
+           Has_Controlled_Component (Parent_Type));
+
+         --  Direct controlled types do not inherit the Finalize_Storage_Only
+         --  flag.
+
+         if not Is_Controlled  (Parent_Type) then
+            Set_Finalize_Storage_Only (Derived_Type,
+              Finalize_Storage_Only (Parent_Type));
+         end if;
+
+         --  Construct the implicit full view by deriving from full
+         --  view of the parent type. In order to get proper visiblity,
+         --  we install the parent scope and its declarations.
+
+         --  ??? if the parent is untagged private and its
+         --  completion is tagged, this mechanism will not
+         --  work because we cannot derive from the tagged
+         --  full view unless we have an extension
+
+         if Present (Full_View (Parent_Type))
+           and then not Is_Tagged_Type (Full_View (Parent_Type))
+           and then not Is_Completion
+         then
+            Full_Der := Make_Defining_Identifier (Sloc (Derived_Type),
+                                              Chars (Derived_Type));
+            Set_Is_Itype (Full_Der);
+            Set_Has_Private_Declaration (Full_Der);
+            Set_Has_Private_Declaration (Derived_Type);
+            Set_Associated_Node_For_Itype (Full_Der, N);
+            Set_Parent (Full_Der, Parent (Derived_Type));
+            Set_Full_View (Derived_Type, Full_Der);
+
+            if not In_Open_Scopes (Par_Scope) then
+               Install_Private_Declarations (Par_Scope);
+               Install_Visible_Declarations (Par_Scope);
+               Copy_And_Build;
+               Uninstall_Declarations (Par_Scope);
+
+            --  If parent scope is open and in another unit, and
+            --  parent has a completion, then the derivation is taking
+            --  place in the visible part of a child unit. In that
+            --  case retrieve the full view of the parent momentarily.
+
+            elsif not In_Same_Source_Unit (N, Parent_Type) then
+               Full_P := Full_View (Parent_Type);
+               Exchange_Declarations (Parent_Type);
+               Copy_And_Build;
+               Exchange_Declarations (Full_P);
+
+            --  Otherwise it is a local derivation.
+
+            else
+               Copy_And_Build;
+            end if;
+
+            Set_Scope                (Full_Der, Current_Scope);
+            Set_Is_First_Subtype     (Full_Der,
+                                       Is_First_Subtype (Derived_Type));
+            Set_Has_Size_Clause      (Full_Der, False);
+            Set_Has_Alignment_Clause (Full_Der, False);
+            Set_Next_Entity          (Full_Der, Empty);
+            Set_Has_Delayed_Freeze   (Full_Der);
+            Set_Is_Frozen            (Full_Der, False);
+            Set_Freeze_Node          (Full_Der, Empty);
+            Set_Depends_On_Private   (Full_Der,
+                                        Has_Private_Component    (Full_Der));
+         end if;
+      end if;
+
+      Set_Has_Unknown_Discriminants (Derived_Type,
+        Has_Unknown_Discriminants (Parent_Type));
+
+      if Is_Private_Type (Derived_Type) then
+         Set_Private_Dependents (Derived_Type, New_Elmt_List);
+      end if;
+
+      if Is_Private_Type (Parent_Type)
+        and then Base_Type (Parent_Type) = Parent_Type
+        and then In_Open_Scopes (Scope (Parent_Type))
+      then
+         Append_Elmt (Derived_Type, Private_Dependents (Parent_Type));
+
+         if Is_Child_Unit (Scope (Current_Scope))
+           and then Is_Completion
+           and then In_Private_Part (Current_Scope)
+         then
+            --  This is the unusual case where a type completed by a private
+            --  derivation occurs within a package nested in a child unit,
+            --  and the parent is declared in an ancestor. In this case, the
+            --  full view of the parent type will become visible in the body
+            --  of the enclosing child, and only then will the current type
+            --  be possibly non-private. We build a underlying full view that
+            --  will be installed when the enclosing child body is compiled.
+
+            declare
+               IR : constant Node_Id := Make_Itype_Reference (Sloc (N));
+
+            begin
+               Full_Der :=
+                 Make_Defining_Identifier (Sloc (Derived_Type),
+                   Chars (Derived_Type));
+               Set_Is_Itype (Full_Der);
+               Set_Itype (IR, Full_Der);
+               Insert_After (N, IR);
+
+               --  The full view will be used to swap entities on entry/exit
+               --  to the body, and must appear in the entity list for the
+               --  package.
+
+               Append_Entity (Full_Der, Scope (Derived_Type));
+               Set_Has_Private_Declaration (Full_Der);
+               Set_Has_Private_Declaration (Derived_Type);
+               Set_Associated_Node_For_Itype (Full_Der, N);
+               Set_Parent (Full_Der, Parent (Derived_Type));
+               Full_P := Full_View (Parent_Type);
+               Exchange_Declarations (Parent_Type);
+               Copy_And_Build;
+               Exchange_Declarations (Full_P);
+               Set_Underlying_Full_View (Derived_Type, Full_Der);
+            end;
+         end if;
+      end if;
+   end Build_Derived_Private_Type;
+
+   -------------------------------
+   -- Build_Derived_Record_Type --
+   -------------------------------
+
+   --  1. INTRODUCTION.
+
+   --  Ideally we would like to use the same model of type derivation for
+   --  tagged and untagged record types. Unfortunately this is not quite
+   --  possible because the semantics of representation clauses is different
+   --  for tagged and untagged records under inheritance. Consider the
+   --  following:
+
+   --     type R (...) is [tagged] record ... end record;
+   --     type T (...) is new R (...) [with ...];
+
+   --  The representation clauses of T can specify a completely different
+   --  record layout from R's. Hence a same component can be placed in two very
+   --  different positions in objects of type T and R. If R and T are tagged
+   --  types, representation clauses for T can only specify the layout of non
+   --  inherited components, thus components that are common in R and T have
+   --  the same position in objects of type R or T.
+
+   --  This has two implications. The first is that the entire tree for R's
+   --  declaration needs to be copied for T in the untagged case, so that
+   --  T can be viewd as a record type of its own with its own derivation
+   --  clauses. The second implication is the way we handle discriminants.
+   --  Specifically, in the untagged case we need a way to communicate to Gigi
+   --  what are the real discriminants in the record, while for the semantics
+   --  we need to consider those introduced by the user to rename the
+   --  discriminants in the parent type. This is handled by introducing the
+   --  notion of girder discriminants. See below for more.
+
+   --  Fortunately the way regular components are inherited can be handled in
+   --  the same way in tagged and untagged types.
+
+   --  To complicate things a bit more the private view of a private extension
+   --  cannot be handled in the same way as the full view (for one thing the
+   --  semantic rules are somewhat different). We will explain what differs
+   --  below.
+
+   --  2. DISCRIMINANTS UNDER INHERITANCE.
+
+   --  The semantic rules governing the discriminants of derived types are
+   --  quite subtle.
+
+   --   type Derived_Type_Name [KNOWN_DISCRIMINANT_PART] is new
+   --      [abstract]  Parent_Type_Name [CONSTRAINT] [RECORD_EXTENSION_PART]
+
+   --  If parent type has discriminants, then the discriminants that are
+   --  declared in the derived type are [3.4 (11)]:
+
+   --  o The discriminants specified by a new KNOWN_DISCRIMINANT_PART, if
+   --    there is one;
+
+   --  o Otherwise, each discriminant of the parent type (implicitely
+   --    declared in the same order with the same specifications). In this
+   --    case, the discriminants are said to be "inherited", or if unknown in
+   --    the parent are also unknown in the derived type.
+
+   --  Furthermore if a KNOWN_DISCRIMINANT_PART is provided, then [3.7(13-18)]:
+
+   --  o The parent subtype shall be constrained;
+
+   --  o If the parent type is not a tagged type, then each discriminant of
+   --    the derived type shall be used in the constraint defining a parent
+   --    subtype [Implementation note: this ensures that the new discriminant
+   --    can share storage with an existing discriminant.].
+
+   --  For the derived type each discriminant of the parent type is either
+   --  inherited, constrained to equal some new discriminant of the derived
+   --  type, or constrained to the value of an expression.
+
+   --  When inherited or constrained to equal some new discriminant, the
+   --  parent discriminant and the discriminant of the derived type are said
+   --  to "correspond".
+
+   --  If a discriminant of the parent type is constrained to a specific value
+   --  in the derived type definition, then the discriminant is said to be
+   --  "specified" by that derived type definition.
+
+   --  3. DISCRIMINANTS IN DERIVED UNTAGGED RECORD TYPES.
+
+   --  We have spoken about girder discriminants in the point 1 (introduction)
+   --  above. There are two sort of girder discriminants: implicit and
+   --  explicit. As long as the derived type inherits the same discriminants as
+   --  the root record type, girder discriminants are the same as regular
+   --  discriminants, and are said to be implicit. However, if any discriminant
+   --  in the root type was renamed in the derived type, then the derived
+   --  type will contain explicit girder discriminants. Explicit girder
+   --  discriminants are discriminants in addition to the semantically visible
+   --  discriminants defined for the derived type. Girder discriminants are
+   --  used by Gigi to figure out what are the physical discriminants in
+   --  objects of the derived type (see precise definition in einfo.ads).
+   --  As an example, consider the following:
+
+   --           type R  (D1, D2, D3 : Int) is record ... end record;
+   --           type T1 is new R;
+   --           type T2 (X1, X2: Int) is new T1 (X2, 88, X1);
+   --           type T3 is new T2;
+   --           type T4 (Y : Int) is new T3 (Y, 99);
+
+   --  The following table summarizes the discriminants and girder
+   --  discriminants in R and T1 through T4.
+
+   --   Type      Discrim     Girder Discrim  Comment
+   --    R      (D1, D2, D3)   (D1, D2, D3)   Gider discrims are implicit in R
+   --    T1     (D1, D2, D3)   (D1, D2, D3)   Gider discrims are implicit in T1
+   --    T2     (X1, X2)       (D1, D2, D3)   Gider discrims are EXPLICIT in T2
+   --    T3     (X1, X2)       (D1, D2, D3)   Gider discrims are EXPLICIT in T3
+   --    T4     (Y)            (D1, D2, D3)   Gider discrims are EXPLICIT in T4
+
+   --  Field Corresponding_Discriminant (abbreviated CD below) allows to find
+   --  the corresponding discriminant in the parent type, while
+   --  Original_Record_Component (abbreviated ORC below), the actual physical
+   --  component that is renamed. Finally the field Is_Completely_Hidden
+   --  (abbreaviated ICH below) is set for all explicit girder discriminants
+   --  (see einfo.ads for more info). For the above example this gives:
+
+   --                 Discrim     CD        ORC     ICH
+   --                 ^^^^^^^     ^^        ^^^     ^^^
+   --                 D1 in R    empty     itself    no
+   --                 D2 in R    empty     itself    no
+   --                 D3 in R    empty     itself    no
+
+   --                 D1 in T1  D1 in R    itself    no
+   --                 D2 in T1  D2 in R    itself    no
+   --                 D3 in T1  D3 in R    itself    no
+
+   --                 X1 in T2  D3 in T1  D3 in T2   no
+   --                 X2 in T2  D1 in T1  D1 in T2   no
+   --                 D1 in T2   empty    itself    yes
+   --                 D2 in T2   empty    itself    yes
+   --                 D3 in T2   empty    itself    yes
+
+   --                 X1 in T3  X1 in T2  D3 in T3   no
+   --                 X2 in T3  X2 in T2  D1 in T3   no
+   --                 D1 in T3   empty    itself    yes
+   --                 D2 in T3   empty    itself    yes
+   --                 D3 in T3   empty    itself    yes
+
+   --                 Y  in T4  X1 in T3  D3 in T3   no
+   --                 D1 in T3   empty    itself    yes
+   --                 D2 in T3   empty    itself    yes
+   --                 D3 in T3   empty    itself    yes
+
+   --  4. DISCRIMINANTS IN DERIVED TAGGED RECORD TYPES.
+
+   --  Type derivation for tagged types is fairly straightforward. if no
+   --  discriminants are specified by the derived type, these are inherited
+   --  from the parent. No explicit girder discriminants are ever necessary.
+   --  The only manipulation that is done to the tree is that of adding a
+   --  _parent field with parent type and constrained to the same constraint
+   --  specified for the parent in the derived type definition. For instance:
+
+   --           type R  (D1, D2, D3 : Int) is tagged record ... end record;
+   --           type T1 is new R with null record;
+   --           type T2 (X1, X2: Int) is new T1 (X2, 88, X1) with null record;
+
+   --  are changed into :
+
+   --           type T1 (D1, D2, D3 : Int) is new R (D1, D2, D3) with record
+   --              _parent : R (D1, D2, D3);
+   --           end record;
+
+   --           type T2 (X1, X2: Int) is new T1 (X2, 88, X1) with record
+   --              _parent : T1 (X2, 88, X1);
+   --           end record;
+
+   --  The discriminants actually present in R, T1 and T2 as well as their CD,
+   --  ORC and ICH fields are:
+
+   --                 Discrim     CD        ORC     ICH
+   --                 ^^^^^^^     ^^        ^^^     ^^^
+   --                 D1 in R    empty     itself    no
+   --                 D2 in R    empty     itself    no
+   --                 D3 in R    empty     itself    no
+
+   --                 D1 in T1  D1 in R    D1 in R   no
+   --                 D2 in T1  D2 in R    D2 in R   no
+   --                 D3 in T1  D3 in R    D3 in R   no
+
+   --                 X1 in T2  D3 in T1   D3 in R   no
+   --                 X2 in T2  D1 in T1   D1 in R   no
+
+   --  5. FIRST TRANSFORMATION FOR DERIVED RECORDS.
+   --
+   --  Regardless of whether we dealing with a tagged or untagged type
+   --  we will transform all derived type declarations of the form
+   --
+   --               type T is new R (...) [with ...];
+   --  or
+   --               subtype S is R (...);
+   --               type T is new S [with ...];
+   --  into
+   --               type BT is new R [with ...];
+   --               subtype T is BT (...);
+   --
+   --  That is, the base derived type is constrained only if it has no
+   --  discriminants. The reason for doing this is that GNAT's semantic model
+   --  assumes that a base type with discriminants is unconstrained.
+   --
+   --  Note that, strictly speaking, the above transformation is not always
+   --  correct. Consider for instance the following exercpt from ACVC b34011a:
+   --
+   --       procedure B34011A is
+   --          type REC (D : integer := 0) is record
+   --             I : Integer;
+   --          end record;
+
+   --          package P is
+   --             type T6 is new Rec;
+   --             function F return T6;
+   --          end P;
+
+   --          use P;
+   --          package Q6 is
+   --             type U is new T6 (Q6.F.I);                   -- ERROR: Q6.F.
+   --          end Q6;
+   --
+   --  The definition of Q6.U is illegal. However transforming Q6.U into
+
+   --             type BaseU is new T6;
+   --             subtype U is BaseU (Q6.F.I)
+
+   --  turns U into a legal subtype, which is incorrect. To avoid this problem
+   --  we always analyze the constraint (in this case (Q6.F.I)) before applying
+   --  the transformation described above.
+
+   --  There is another instance where the above transformation is incorrect.
+   --  Consider:
+
+   --          package Pack is
+   --             type Base (D : Integer) is tagged null record;
+   --             procedure P (X : Base);
+
+   --             type Der is new Base (2) with null record;
+   --             procedure P (X : Der);
+   --          end Pack;
+
+   --  Then the above transformation turns this into
+
+   --             type Der_Base is new Base with null record;
+   --             --  procedure P (X : Base) is implicitely inherited here
+   --             --  as procedure P (X : Der_Base).
+
+   --             subtype Der is Der_Base (2);
+   --             procedure P (X : Der);
+   --             --  The overriding of P (X : Der_Base) is illegal since we
+   --             --  have a parameter conformance problem.
+
+   --  To get around this problem, after having semantically processed Der_Base
+   --  and the rewritten subtype declaration for Der, we copy Der_Base field
+   --  Discriminant_Constraint from Der so that when parameter conformance is
+   --  checked when P is overridden, no sematic errors are flagged.
+
+   --  6. SECOND TRANSFORMATION FOR DERIVED RECORDS.
+
+   --  Regardless of the fact that we dealing with a tagged or untagged type
+   --  we will transform all derived type declarations of the form
+
+   --               type R (D1, .., Dn : ...) is [tagged] record ...;
+   --               type T is new R [with ...];
+   --  into
+   --               type T (D1, .., Dn : ...) is new R (D1, .., Dn) [with ...];
+
+   --  The reason for such transformation is that it allows us to implement a
+   --  very clean form of component inheritance as explained below.
+
+   --  Note that this transformation is not achieved by direct tree rewriting
+   --  and manipulation, but rather by redoing the semantic actions that the
+   --  above transformation will entail. This is done directly in routine
+   --  Inherit_Components.
+
+   --  7. TYPE DERIVATION AND COMPONENT INHERITANCE.
+
+   --  In both tagged and untagged derived types, regular non discriminant
+   --  components are inherited in the derived type from the parent type. In
+   --  the absence of discriminants component, inheritance is straightforward
+   --  as components can simply be copied from the parent.
+   --  If the parent has discriminants, inheriting components constrained with
+   --  these discriminants requires caution. Consider the following example:
+
+   --      type R  (D1, D2 : Positive) is [tagged] record
+   --         S : String (D1 .. D2);
+   --      end record;
+
+   --      type T1                is new R        [with null record];
+   --      type T2 (X : positive) is new R (1, X) [with null record];
+
+   --  As explained in 6. above, T1 is rewritten as
+
+   --      type T1 (D1, D2 : Positive) is new R (D1, D2) [with null record];
+
+   --  which makes the treatment for T1 and T2 identical.
+
+   --  What we want when inheriting S, is that references to D1 and D2 in R are
+   --  replaced with references to their correct constraints, ie D1 and D2 in
+   --  T1 and 1 and X in T2. So all R's discriminant references are replaced
+   --  with either discriminant references in the derived type or expressions.
+   --  This replacement is acheived as follows: before inheriting R's
+   --  components, a subtype R (D1, D2) for T1 (resp. R (1, X) for T2) is
+   --  created in the scope of T1 (resp. scope of T2) so that discriminants D1
+   --  and D2 of T1 are visible (resp. discriminant X of T2 is visible).
+   --  For T2, for instance, this has the effect of replacing String (D1 .. D2)
+   --  by String (1 .. X).
+
+   --  8. TYPE DERIVATION IN PRIVATE TYPE EXTENSIONS.
+
+   --  We explain here the rules governing private type extensions relevant to
+   --  type derivation. These rules are explained on the following example:
+
+   --      type D [(...)] is new A [(...)] with private;      <-- partial view
+   --      type D [(...)] is new P [(...)] with null record;  <-- full view
+
+   --  Type A is called the ancestor subtype of the private extension.
+   --  Type P is the parent type of the full view of the private extension. It
+   --  must be A or a type derived from A.
+
+   --  The rules concerning the discriminants of private type extensions are
+   --  [7.3(10-13)]:
+
+   --  o If a private extension inherits known discriminants from the ancestor
+   --    subtype, then the full view shall also inherit its discriminants from
+   --    the ancestor subtype and the parent subtype of the full view shall be
+   --    constrained if and only if the ancestor subtype is constrained.
+
+   --  o If a partial view has unknown discriminants, then the full view may
+   --    define a definite or an indefinite subtype, with or without
+   --    discriminants.
+
+   --  o If a partial view has neither known nor unknown discriminants, then
+   --    the full view shall define a definite subtype.
+
+   --  o If the ancestor subtype of a private extension has constrained
+   --    discrimiants, then the parent subtype of the full view shall impose a
+   --    statically matching constraint on those discriminants.
+
+   --  This means that only the following forms of private extensions are
+   --  allowed:
+
+   --      type D is new A with private;      <-- partial view
+   --      type D is new P with null record;  <-- full view
+
+   --  If A has no discriminants than P has no discriminants, otherwise P must
+   --  inherit A's discriminants.
+
+   --      type D is new A (...) with private;      <-- partial view
+   --      type D is new P (:::) with null record;  <-- full view
+
+   --  P must inherit A's discriminants and (...) and (:::) must statically
+   --  match.
+
+   --      subtype A is R (...);
+   --      type D is new A with private;      <-- partial view
+   --      type D is new P with null record;  <-- full view
+
+   --  P must have inherited R's discriminants and must be derived from A or
+   --  any of its subtypes.
+
+   --      type D (..) is new A with private;              <-- partial view
+   --      type D (..) is new P [(:::)] with null record;  <-- full view
+
+   --  No specific constraints on P's discriminants or constraint (:::).
+   --  Note that A can be unconstrained, but the parent subtype P must either
+   --  be constrained or (:::) must be present.
+
+   --      type D (..) is new A [(...)] with private;      <-- partial view
+   --      type D (..) is new P [(:::)] with null record;  <-- full view
+
+   --  P's constraints on A's discriminants must statically match those
+   --  imposed by (...).
+
+   --  9. IMPLEMENTATION OF TYPE DERIVATION FOR PRIVATE EXTENSIONS.
+
+   --  The full view of a private extension is handled exactly as described
+   --  above. The model chose for the private view of a private extension
+   --  is the same for what concerns discriminants (ie they receive the same
+   --  treatment as in the tagged case). However, the private view of the
+   --  private extension always inherits the components of the parent base,
+   --  without replacing any discriminant reference. Strictly speacking this
+   --  is incorrect. However, Gigi never uses this view to generate code so
+   --  this is a purely semantic issue. In theory, a set of transformations
+   --  similar to those given in 5. and 6. above could be applied to private
+   --  views of private extensions to have the same model of component
+   --  inheritance as for non private extensions. However, this is not done
+   --  because it would further complicate private type processing.
+   --  Semantically speaking, this leaves us in an uncomfortable
+   --  situation. As an example consider:
+
+   --          package Pack is
+   --             type R (D : integer) is tagged record
+   --                S : String (1 .. D);
+   --             end record;
+   --             procedure P (X : R);
+   --             type T is new R (1) with private;
+   --          private
+   --             type T is new R (1) with null record;
+   --          end;
+
+   --  This is transformed into:
+
+   --          package Pack is
+   --             type R (D : integer) is tagged record
+   --                S : String (1 .. D);
+   --             end record;
+   --             procedure P (X : R);
+   --             type T is new R (1) with private;
+   --          private
+   --             type BaseT is new R with null record;
+   --             subtype  T is BaseT (1);
+   --          end;
+
+   --  (strictly speaking the above is incorrect Ada).
+
+   --  From the semantic standpoint the private view of private extension T
+   --  should be flagged as constrained since one can clearly have
+   --
+   --             Obj : T;
+   --
+   --  in a unit withing Pack. However, when deriving subprograms for the
+   --  private view of private extension T, T must be seen as unconstrained
+   --  since T has discriminants (this is a constraint of the current
+   --  subprogram derivation model). Thus, when processing the private view of
+   --  a private extension such as T, we first mark T as unconstrained, we
+   --  process it, we perform program derivation and just before returning from
+   --  Build_Derived_Record_Type we mark T as constrained.
+   --  ??? Are there are other unconfortable cases that we will have to
+   --      deal with.
+
+   --  10. RECORD_TYPE_WITH_PRIVATE complications.
+
+   --  Types that are derived from a visible record type and have a private
+   --  extension present other peculiarities. They behave mostly like private
+   --  types, but if they have primitive operations defined, these will not
+   --  have the proper signatures for further inheritance, because other
+   --  primitive operations will use the implicit base that we define for
+   --  private derivations below. This affect subprogram inheritance (see
+   --  Derive_Subprograms for details). We also derive the implicit base from
+   --  the base type of the full view, so that the implicit base is a record
+   --  type and not another private type, This avoids infinite loops.
+
+   procedure Build_Derived_Record_Type
+     (N            : Node_Id;
+      Parent_Type  : Entity_Id;
+      Derived_Type : Entity_Id;
+      Derive_Subps : Boolean := True)
+   is
+      Loc          : constant Source_Ptr := Sloc (N);
+      Parent_Base  : Entity_Id;
+
+      Type_Def     : Node_Id;
+      Indic        : Node_Id;
+
+      Discrim      : Entity_Id;
+      Last_Discrim : Entity_Id;
+      Constrs      : Elist_Id;
+      Discs        : Elist_Id := New_Elmt_List;
+      --  An empty Discs list means that there were no constraints in the
+      --  subtype indication or that there was an error processing it.
+
+      Assoc_List   : Elist_Id;
+      New_Discrs   : Elist_Id;
+
+      New_Base     : Entity_Id;
+      New_Decl     : Node_Id;
+      New_Indic    : Node_Id;
+
+      Is_Tagged          : constant Boolean := Is_Tagged_Type (Parent_Type);
+      Discriminant_Specs : constant Boolean
+        := Present (Discriminant_Specifications (N));
+      Private_Extension  : constant Boolean
+        := (Nkind (N) = N_Private_Extension_Declaration);
+
+      Constraint_Present : Boolean;
+      Inherit_Discrims   : Boolean := False;
+
+      Save_Etype         : Entity_Id;
+      Save_Discr_Constr  : Elist_Id;
+      Save_Next_Entity   : Entity_Id;
+
+   begin
+      if Ekind (Parent_Type) = E_Record_Type_With_Private
+        and then Present (Full_View (Parent_Type))
+        and then Has_Discriminants (Parent_Type)
+      then
+         Parent_Base := Base_Type (Full_View (Parent_Type));
+      else
+         Parent_Base := Base_Type (Parent_Type);
+      end if;
+
+      --  Before we start the previously documented transformations, here is
+      --  a little fix for size and alignment of tagged types. Normally when
+      --  we derive type D from type P, we copy the size and alignment of P
+      --  as the default for D, and in the absence of explicit representation
+      --  clauses for D, the size and alignment are indeed the same as the
+      --  parent.
+
+      --  But this is wrong for tagged types, since fields may be added,
+      --  and the default size may need to be larger, and the default
+      --  alignment may need to be larger.
+
+      --  We therefore reset the size and alignment fields in the tagged
+      --  case. Note that the size and alignment will in any case be at
+      --  least as large as the parent type (since the derived type has
+      --  a copy of the parent type in the _parent field)
+
+      if Is_Tagged then
+         Init_Size_Align (Derived_Type);
+      end if;
+
+      --  STEP 0a: figure out what kind of derived type declaration we have.
+
+      if Private_Extension then
+         Type_Def := N;
+         Set_Ekind (Derived_Type, E_Record_Type_With_Private);
+
+      else
+         Type_Def := Type_Definition (N);
+
+         --  Ekind (Parent_Base) in not necessarily E_Record_Type since
+         --  Parent_Base can be a private type or private extension. However,
+         --  for tagged types with an extension the newly added fields are
+         --  visible and hence the Derived_Type is always an E_Record_Type.
+         --  (except that the parent may have its own private fields).
+         --  For untagged types we preserve the Ekind of the Parent_Base.
+
+         if Present (Record_Extension_Part (Type_Def)) then
+            Set_Ekind (Derived_Type, E_Record_Type);
+         else
+            Set_Ekind (Derived_Type, Ekind (Parent_Base));
+         end if;
+      end if;
+
+      --  Indic can either be an N_Identifier if the subtype indication
+      --  contains no constraint or an N_Subtype_Indication if the subtype
+      --  indication has a constraint.
+
+      Indic := Subtype_Indication (Type_Def);
+      Constraint_Present := (Nkind (Indic) = N_Subtype_Indication);
+
+      if Constraint_Present then
+         if not Has_Discriminants (Parent_Base) then
+            Error_Msg_N
+              ("invalid constraint: type has no discriminant",
+                 Constraint (Indic));
+
+            Constraint_Present := False;
+            Rewrite (Indic, New_Copy_Tree (Subtype_Mark (Indic)));
+
+         elsif Is_Constrained (Parent_Type) then
+            Error_Msg_N
+               ("invalid constraint: parent type is already constrained",
+                  Constraint (Indic));
+
+            Constraint_Present := False;
+            Rewrite (Indic, New_Copy_Tree (Subtype_Mark (Indic)));
+         end if;
+      end if;
+
+      --  STEP 0b: If needed, apply transformation given in point 5. above.
+
+      if not Private_Extension
+        and then Has_Discriminants (Parent_Type)
+        and then not Discriminant_Specs
+        and then (Is_Constrained (Parent_Type) or else Constraint_Present)
+      then
+         --  First, we must analyze the constraint (see comment in point 5.).
+
+         if Constraint_Present then
+            New_Discrs := Build_Discriminant_Constraints (Parent_Type, Indic);
+
+            if Has_Discriminants (Derived_Type)
+              and then Has_Private_Declaration (Derived_Type)
+              and then Present (Discriminant_Constraint (Derived_Type))
+            then
+               --  Verify that constraints of the full view conform to those
+               --  given in partial view.
+
+               declare
+                  C1, C2 : Elmt_Id;
+
+               begin
+                  C1 := First_Elmt (New_Discrs);
+                  C2 := First_Elmt (Discriminant_Constraint (Derived_Type));
+
+                  while Present (C1) and then Present (C2) loop
+                     if not
+                       Fully_Conformant_Expressions (Node (C1), Node (C2))
+                     then
+                        Error_Msg_N (
+                          "constraint not conformant to previous declaration",
+                             Node (C1));
+                     end if;
+                     Next_Elmt (C1);
+                     Next_Elmt (C2);
+                  end loop;
+               end;
+            end if;
+         end if;
+
+         --  Insert and analyze the declaration for the unconstrained base type
+
+         New_Base := Create_Itype (Ekind (Derived_Type), N, Derived_Type, 'B');
+
+         New_Decl :=
+           Make_Full_Type_Declaration (Loc,
+              Defining_Identifier => New_Base,
+              Type_Definition     =>
+                Make_Derived_Type_Definition (Loc,
+                  Abstract_Present      => Abstract_Present (Type_Def),
+                  Subtype_Indication    =>
+                    New_Occurrence_Of (Parent_Base, Loc),
+                  Record_Extension_Part =>
+                    Relocate_Node (Record_Extension_Part (Type_Def))));
+
+         Set_Parent (New_Decl, Parent (N));
+         Mark_Rewrite_Insertion (New_Decl);
+         Insert_Before (N, New_Decl);
+
+         --  Note that this call passes False for the Derive_Subps
+         --  parameter because subprogram derivation is deferred until
+         --  after creating the subtype (see below).
+
+         Build_Derived_Type
+           (New_Decl, Parent_Base, New_Base,
+            Is_Completion => True, Derive_Subps => False);
+
+         --  ??? This needs re-examination to determine whether the
+         --  above call can simply be replaced by a call to Analyze.
+
+         Set_Analyzed (New_Decl);
+
+         --  Insert and analyze the declaration for the constrained subtype
+
+         if Constraint_Present then
+            New_Indic :=
+              Make_Subtype_Indication (Loc,
+                Subtype_Mark => New_Occurrence_Of (New_Base, Loc),
+                Constraint   => Relocate_Node (Constraint (Indic)));
+
+         else
+            declare
+               Expr        : Node_Id;
+               Constr_List : List_Id := New_List;
+               C           : Elmt_Id;
+
+            begin
+               C := First_Elmt (Discriminant_Constraint (Parent_Type));
+               while Present (C) loop
+                  Expr := Node (C);
+
+                  --  It is safe here to call New_Copy_Tree since
+                  --  Force_Evaluation was called on each constraint in
+                  --  Build_Discriminant_Constraints.
+
+                  Append (New_Copy_Tree (Expr), To => Constr_List);
+
+                  Next_Elmt (C);
+               end loop;
+
+               New_Indic :=
+                 Make_Subtype_Indication (Loc,
+                   Subtype_Mark => New_Occurrence_Of (New_Base, Loc),
+                   Constraint   =>
+                     Make_Index_Or_Discriminant_Constraint (Loc, Constr_List));
+            end;
+         end if;
+
+         Rewrite (N,
+           Make_Subtype_Declaration (Loc,
+             Defining_Identifier => Derived_Type,
+             Subtype_Indication  => New_Indic));
+
+         Analyze (N);
+
+         --  Derivation of subprograms must be delayed until the
+         --  full subtype has been established to ensure proper
+         --  overriding of subprograms inherited by full types.
+         --  If the derivations occurred as part of the call to
+         --  Build_Derived_Type above, then the check for type
+         --  conformance would fail because earlier primitive
+         --  subprograms could still refer to the full type prior
+         --  the change to the new subtype and hence wouldn't
+         --  match the new base type created here.
+
+         Derive_Subprograms (Parent_Type, Derived_Type);
+
+         --  For tagged types the Discriminant_Constraint of the new base itype
+         --  is inherited from the first subtype so that no subtype conformance
+         --  problem arise when the first subtype overrides primitive
+         --  operations inherited by the implicit base type.
+
+         if Is_Tagged then
+            Set_Discriminant_Constraint
+              (New_Base, Discriminant_Constraint (Derived_Type));
+         end if;
+
+         return;
+      end if;
+
+      --  If we get here Derived_Type will have no discriminants or it will be
+      --  a discriminated unconstrained base type.
+
+      --  STEP 1a: perform preliminary actions/checks for derived tagged types
+
+      if Is_Tagged then
+         --  The parent type is frozen for non-private extensions (RM 13.14(7))
+
+         if not Private_Extension then
+            Freeze_Before (N, Parent_Type);
+         end if;
+
+         if Type_Access_Level (Derived_Type) /= Type_Access_Level (Parent_Type)
+           and then not Is_Generic_Type (Derived_Type)
+         then
+            if Is_Controlled (Parent_Type) then
+               Error_Msg_N
+                 ("controlled type must be declared at the library level",
+                  Indic);
+            else
+               Error_Msg_N
+                 ("type extension at deeper accessibility level than parent",
+                  Indic);
+            end if;
+
+         else
+            declare
+               GB : constant Node_Id := Enclosing_Generic_Body (Derived_Type);
+
+            begin
+               if Present (GB)
+                 and then GB /= Enclosing_Generic_Body (Parent_Base)
+               then
+                  Error_Msg_N
+                    ("parent type must not be outside generic body",
+                     Indic);
+               end if;
+            end;
+         end if;
+      end if;
+
+      --  STEP 1b : preliminary cleanup of the full view of private types
+
+      --  If the type is already marked as having discriminants, then it's the
+      --  completion of a private type or private extension and we need to
+      --  retain the discriminants from the partial view if the current
+      --  declaration has Discriminant_Specifications so that we can verify
+      --  conformance. However, we must remove any existing components that
+      --  were inherited from the parent (and attached in Copy_Private_To_Full)
+      --  because the full type inherits all appropriate components anyway, and
+      --  we don't want the partial view's components interfering.
+
+      if Has_Discriminants (Derived_Type) and then Discriminant_Specs then
+         Discrim := First_Discriminant (Derived_Type);
+         loop
+            Last_Discrim := Discrim;
+            Next_Discriminant (Discrim);
+            exit when No (Discrim);
+         end loop;
+
+         Set_Last_Entity (Derived_Type, Last_Discrim);
+
+      --  In all other cases wipe out the list of inherited components (even
+      --  inherited discriminants), it will be properly rebuilt here.
+
+      else
+         Set_First_Entity (Derived_Type, Empty);
+         Set_Last_Entity  (Derived_Type, Empty);
+      end if;
+
+      --  STEP 1c: Initialize some flags for the Derived_Type
+
+      --  The following flags must be initialized here so that
+      --  Process_Discriminants can check that discriminants of tagged types
+      --  do not have a default initial value and that access discriminants
+      --  are only specified for limited records. For completeness, these
+      --  flags are also initialized along with all the other flags below.
+
+      Set_Is_Tagged_Type    (Derived_Type, Is_Tagged);
+      Set_Is_Limited_Record (Derived_Type, Is_Limited_Record (Parent_Type));
+
+      --  STEP 2a: process discriminants of derived type if any.
+
+      New_Scope (Derived_Type);
+
+      if Discriminant_Specs then
+         Set_Has_Unknown_Discriminants (Derived_Type, False);
+
+         --  The following call initializes fields Has_Discriminants and
+         --  Discriminant_Constraint, unless we are processing the completion
+         --  of a private type declaration.
+
+         Check_Or_Process_Discriminants (N, Derived_Type);
+
+         --  For non-tagged types the constraint on the Parent_Type must be
+         --  present and is used to rename the discriminants.
+
+         if not Is_Tagged and then not Has_Discriminants (Parent_Type) then
+            Error_Msg_N ("untagged parent must have discriminants", Indic);
+
+         elsif not Is_Tagged and then not Constraint_Present then
+            Error_Msg_N
+              ("discriminant constraint needed for derived untagged records",
+               Indic);
+
+         --  Otherwise the parent subtype must be constrained unless we have a
+         --  private extension.
+
+         elsif not Constraint_Present
+           and then not Private_Extension
+           and then not Is_Constrained (Parent_Type)
+         then
+            Error_Msg_N
+              ("unconstrained type not allowed in this context", Indic);
+
+         elsif Constraint_Present then
+            --  The following call sets the field Corresponding_Discriminant
+            --  for the discriminants in the Derived_Type.
+
+            Discs := Build_Discriminant_Constraints (Parent_Type, Indic, True);
+
+            --  For untagged types all new discriminants must rename
+            --  discriminants in the parent. For private extensions new
+            --  discriminants cannot rename old ones (implied by [7.3(13)]).
+
+            Discrim := First_Discriminant (Derived_Type);
+
+            while Present (Discrim) loop
+               if not Is_Tagged
+                 and then not Present (Corresponding_Discriminant (Discrim))
+               then
+                  Error_Msg_N
+                    ("new discriminants must constrain old ones", Discrim);
+
+               elsif Private_Extension
+                 and then Present (Corresponding_Discriminant (Discrim))
+               then
+                  Error_Msg_N
+                    ("Only static constraints allowed for parent"
+                     & " discriminants in the partial view", Indic);
+
+                  exit;
+               end if;
+
+               --  If a new discriminant is used in the constraint,
+               --  then its subtype must be statically compatible
+               --  with the parent discriminant's subtype (3.7(15)).
+
+               if Present (Corresponding_Discriminant (Discrim))
+                 and then
+                   not Subtypes_Statically_Compatible
+                         (Etype (Discrim),
+                          Etype (Corresponding_Discriminant (Discrim)))
+               then
+                  Error_Msg_N
+                    ("subtype must be compatible with parent discriminant",
+                     Discrim);
+               end if;
+
+               Next_Discriminant (Discrim);
+            end loop;
+         end if;
+
+      --  STEP 2b: No new discriminants, inherit discriminants if any
+
+      else
+         if Private_Extension then
+            Set_Has_Unknown_Discriminants
+              (Derived_Type, Has_Unknown_Discriminants (Parent_Type)
+                             or else Unknown_Discriminants_Present (N));
+         else
+            Set_Has_Unknown_Discriminants
+              (Derived_Type, Has_Unknown_Discriminants (Parent_Type));
+         end if;
+
+         if not Has_Unknown_Discriminants (Derived_Type)
+           and then Has_Discriminants (Parent_Type)
+         then
+            Inherit_Discrims := True;
+            Set_Has_Discriminants
+              (Derived_Type, True);
+            Set_Discriminant_Constraint
+              (Derived_Type, Discriminant_Constraint (Parent_Base));
+         end if;
+
+         --  The following test is true for private types (remember
+         --  transformation 5. is not applied to those) and in an error
+         --  situation.
+
+         if Constraint_Present then
+            Discs := Build_Discriminant_Constraints (Parent_Type, Indic);
+         end if;
+
+         --  For now mark a new derived type as cosntrained only if it has no
+         --  discriminants. At the end of Build_Derived_Record_Type we properly
+         --  set this flag in the case of private extensions. See comments in
+         --  point 9. just before body of Build_Derived_Record_Type.
+
+         Set_Is_Constrained
+           (Derived_Type,
+            not (Inherit_Discrims
+                 or else Has_Unknown_Discriminants (Derived_Type)));
+      end if;
+
+      --  STEP 3: initialize fields of derived type.
+
+      Set_Is_Tagged_Type    (Derived_Type, Is_Tagged);
+      Set_Girder_Constraint (Derived_Type, No_Elist);
+
+      --  Fields inherited from the Parent_Type
+
+      Set_Discard_Names
+        (Derived_Type, Einfo.Discard_Names      (Parent_Type));
+      Set_Has_Specified_Layout
+        (Derived_Type, Has_Specified_Layout     (Parent_Type));
+      Set_Is_Limited_Composite
+        (Derived_Type, Is_Limited_Composite     (Parent_Type));
+      Set_Is_Limited_Record
+        (Derived_Type, Is_Limited_Record        (Parent_Type));
+      Set_Is_Private_Composite
+        (Derived_Type, Is_Private_Composite     (Parent_Type));
+
+      --  Fields inherited from the Parent_Base
+
+      Set_Has_Controlled_Component
+        (Derived_Type, Has_Controlled_Component (Parent_Base));
+      Set_Has_Non_Standard_Rep
+        (Derived_Type, Has_Non_Standard_Rep     (Parent_Base));
+      Set_Has_Primitive_Operations
+        (Derived_Type, Has_Primitive_Operations (Parent_Base));
+
+      --  Direct controlled types do not inherit the Finalize_Storage_Only
+      --  flag.
+
+      if not Is_Controlled  (Parent_Type) then
+         Set_Finalize_Storage_Only (Derived_Type,
+           Finalize_Storage_Only (Parent_Type));
+      end if;
+
+      --  Set fields for private derived types.
+
+      if Is_Private_Type (Derived_Type) then
+         Set_Depends_On_Private (Derived_Type, True);
+         Set_Private_Dependents (Derived_Type, New_Elmt_List);
+
+      --  Inherit fields from non private record types. If this is the
+      --  completion of a derivation from a private type, the parent itself
+      --  is private, and the attributes come from its full view, which must
+      --  be present.
+
+      else
+         if Is_Private_Type (Parent_Base)
+           and then not Is_Record_Type (Parent_Base)
+         then
+            Set_Component_Alignment
+              (Derived_Type, Component_Alignment (Full_View (Parent_Base)));
+            Set_C_Pass_By_Copy
+              (Derived_Type, C_Pass_By_Copy      (Full_View (Parent_Base)));
+         else
+            Set_Component_Alignment
+              (Derived_Type, Component_Alignment (Parent_Base));
+
+            Set_C_Pass_By_Copy
+              (Derived_Type, C_Pass_By_Copy      (Parent_Base));
+         end if;
+      end if;
+
+      --  Set fields for tagged types.
+
+      if Is_Tagged then
+         Set_Primitive_Operations (Derived_Type, New_Elmt_List);
+
+         --  All tagged types defined in Ada.Finalization are controlled
+
+         if Chars (Scope (Derived_Type)) = Name_Finalization
+           and then Chars (Scope (Scope (Derived_Type))) = Name_Ada
+           and then Scope (Scope (Scope (Derived_Type))) = Standard_Standard
+         then
+            Set_Is_Controlled (Derived_Type);
+         else
+            Set_Is_Controlled (Derived_Type, Is_Controlled (Parent_Base));
+         end if;
+
+         Make_Class_Wide_Type (Derived_Type);
+         Set_Is_Abstract      (Derived_Type, Abstract_Present (Type_Def));
+
+         if Has_Discriminants (Derived_Type)
+           and then Constraint_Present
+         then
+            Set_Girder_Constraint
+              (Derived_Type, Expand_To_Girder_Constraint (Parent_Base, Discs));
+         end if;
+
+      else
+         Set_Is_Packed (Derived_Type, Is_Packed (Parent_Base));
+         Set_Has_Non_Standard_Rep
+                       (Derived_Type, Has_Non_Standard_Rep (Parent_Base));
+      end if;
+
+      --  STEP 4: Inherit components from the parent base and constrain them.
+      --          Apply the second transformation described in point 6. above.
+
+      if (not Is_Empty_Elmt_List (Discs) or else Inherit_Discrims)
+        or else not Has_Discriminants (Parent_Type)
+        or else not Is_Constrained (Parent_Type)
+      then
+         Constrs := Discs;
+      else
+         Constrs := Discriminant_Constraint (Parent_Type);
+      end if;
+
+      Assoc_List := Inherit_Components (N,
+        Parent_Base, Derived_Type, Is_Tagged, Inherit_Discrims, Constrs);
+
+      --  STEP 5a: Copy the parent record declaration for untagged types
+
+      if not Is_Tagged then
+
+         --  Discriminant_Constraint (Derived_Type) has been properly
+         --  constructed. Save it and temporarily set it to Empty because we do
+         --  not want the call to New_Copy_Tree below to mess this list.
+
+         if Has_Discriminants (Derived_Type) then
+            Save_Discr_Constr := Discriminant_Constraint (Derived_Type);
+            Set_Discriminant_Constraint (Derived_Type, No_Elist);
+         else
+            Save_Discr_Constr := No_Elist;
+         end if;
+
+         --  Save the Etype field of Derived_Type. It is correctly set now, but
+         --  the call to New_Copy tree may remap it to point to itself, which
+         --  is not what we want. Ditto for the Next_Entity field.
+
+         Save_Etype       := Etype (Derived_Type);
+         Save_Next_Entity := Next_Entity (Derived_Type);
+
+         --  Assoc_List maps all girder discriminants in the Parent_Base to
+         --  girder discriminants in the Derived_Type. It is fundamental that
+         --  no types or itypes with discriminants other than the girder
+         --  discriminants appear in the entities declared inside
+         --  Derived_Type. Gigi won't like it.
+
+         New_Decl :=
+           New_Copy_Tree
+             (Parent (Parent_Base), Map => Assoc_List, New_Sloc => Loc);
+
+         --  Restore the fields saved prior to the New_Copy_Tree call
+         --  and compute the girder constraint.
+
+         Set_Etype       (Derived_Type, Save_Etype);
+         Set_Next_Entity (Derived_Type, Save_Next_Entity);
+
+         if Has_Discriminants (Derived_Type) then
+            Set_Discriminant_Constraint
+              (Derived_Type, Save_Discr_Constr);
+            Set_Girder_Constraint
+              (Derived_Type, Expand_To_Girder_Constraint (Parent_Base, Discs));
+         end if;
+
+         --  Insert the new derived type declaration
+
+         Rewrite (N, New_Decl);
+
+      --  STEP 5b: Complete the processing for record extensions in generics
+
+      --  There is no completion for record extensions declared in the
+      --  parameter part of a generic, so we need to complete processing for
+      --  these generic record extensions here. The call to
+      --  Record_Type_Definition will change the Ekind of the components
+      --  from E_Void to E_Component.
+
+      elsif Private_Extension and then Is_Generic_Type (Derived_Type) then
+         Record_Type_Definition (Empty, Derived_Type);
+
+      --  STEP 5c: Process the record extension for non private tagged types.
+
+      elsif not Private_Extension then
+         --  Add the _parent field in the derived type.
+
+         Expand_Derived_Record (Derived_Type, Type_Def);
+
+         --  Analyze the record extension
+
+         Record_Type_Definition
+           (Record_Extension_Part (Type_Def), Derived_Type);
+      end if;
+
+      End_Scope;
+
+      if Etype (Derived_Type) = Any_Type then
+         return;
+      end if;
+
+      --  Set delayed freeze and then derive subprograms, we need to do
+      --  this in this order so that derived subprograms inherit the
+      --  derived freeze if necessary.
+
+      Set_Has_Delayed_Freeze (Derived_Type);
+      if Derive_Subps then
+         Derive_Subprograms (Parent_Type, Derived_Type);
+      end if;
+
+      --  If we have a private extension which defines a constrained derived
+      --  type mark as constrained here after we have derived subprograms. See
+      --  comment on point 9. just above the body of Build_Derived_Record_Type.
+
+      if Private_Extension and then Inherit_Discrims then
+         if Constraint_Present and then not Is_Empty_Elmt_List (Discs) then
+            Set_Is_Constrained          (Derived_Type, True);
+            Set_Discriminant_Constraint (Derived_Type, Discs);
+
+         elsif Is_Constrained (Parent_Type) then
+            Set_Is_Constrained
+              (Derived_Type, True);
+            Set_Discriminant_Constraint
+              (Derived_Type, Discriminant_Constraint (Parent_Type));
+         end if;
+      end if;
+
+   end Build_Derived_Record_Type;
+
+   ------------------------
+   -- Build_Derived_Type --
+   ------------------------
+
+   procedure Build_Derived_Type
+     (N             : Node_Id;
+      Parent_Type   : Entity_Id;
+      Derived_Type  : Entity_Id;
+      Is_Completion : Boolean;
+      Derive_Subps  : Boolean := True)
+   is
+      Parent_Base : constant Entity_Id := Base_Type (Parent_Type);
+
+   begin
+      --  Set common attributes
+
+      Set_Scope          (Derived_Type, Current_Scope);
+
+      Set_Ekind          (Derived_Type, Ekind     (Parent_Base));
+      Set_Etype          (Derived_Type,            Parent_Base);
+      Set_Has_Task       (Derived_Type, Has_Task  (Parent_Base));
+
+      Set_Size_Info      (Derived_Type,                 Parent_Type);
+      Set_RM_Size        (Derived_Type, RM_Size        (Parent_Type));
+      Set_Convention     (Derived_Type, Convention     (Parent_Type));
+      Set_First_Rep_Item (Derived_Type, First_Rep_Item (Parent_Type));
+
+      case Ekind (Parent_Type) is
+         when Numeric_Kind =>
+            Build_Derived_Numeric_Type (N, Parent_Type, Derived_Type);
+
+         when Array_Kind =>
+            Build_Derived_Array_Type (N, Parent_Type,  Derived_Type);
+
+         when E_Record_Type
+            | E_Record_Subtype
+            | Class_Wide_Kind  =>
+            Build_Derived_Record_Type
+              (N, Parent_Type, Derived_Type, Derive_Subps);
+            return;
+
+         when Enumeration_Kind =>
+            Build_Derived_Enumeration_Type (N, Parent_Type, Derived_Type);
+
+         when Access_Kind =>
+            Build_Derived_Access_Type (N, Parent_Type, Derived_Type);
+
+         when Incomplete_Or_Private_Kind =>
+            Build_Derived_Private_Type
+              (N, Parent_Type, Derived_Type, Is_Completion, Derive_Subps);
+
+            --  For discriminated types, the derivation includes deriving
+            --  primitive operations. For others it is done below.
+
+            if Is_Tagged_Type (Parent_Type)
+              or else Has_Discriminants (Parent_Type)
+              or else (Present (Full_View (Parent_Type))
+                        and then Has_Discriminants (Full_View (Parent_Type)))
+            then
+               return;
+            end if;
+
+         when Concurrent_Kind =>
+            Build_Derived_Concurrent_Type (N, Parent_Type, Derived_Type);
+
+         when others =>
+            raise Program_Error;
+      end case;
+
+      if Etype (Derived_Type) = Any_Type then
+         return;
+      end if;
+
+      --  Set delayed freeze and then derive subprograms, we need to do
+      --  this in this order so that derived subprograms inherit the
+      --  derived freeze if necessary.
+
+      Set_Has_Delayed_Freeze (Derived_Type);
+      if Derive_Subps then
+         Derive_Subprograms (Parent_Type, Derived_Type);
+      end if;
+
+      Set_Has_Primitive_Operations
+        (Base_Type (Derived_Type), Has_Primitive_Operations (Parent_Type));
+   end Build_Derived_Type;
+
+   -----------------------
+   -- Build_Discriminal --
+   -----------------------
+
+   procedure Build_Discriminal (Discrim : Entity_Id) is
+      D_Minal : Entity_Id;
+      CR_Disc : Entity_Id;
+
+   begin
+      --  A discriminal has the same names as the discriminant.
+
+      D_Minal := Make_Defining_Identifier (Sloc (Discrim), Chars (Discrim));
+
+      Set_Ekind     (D_Minal, E_In_Parameter);
+      Set_Mechanism (D_Minal, Default_Mechanism);
+      Set_Etype     (D_Minal, Etype (Discrim));
+
+      Set_Discriminal (Discrim, D_Minal);
+      Set_Discriminal_Link (D_Minal, Discrim);
+
+      --  For task types, build at once the discriminants of the corresponding
+      --  record, which are needed if discriminants are used in entry defaults
+      --  and in family bounds.
+
+      if Is_Concurrent_Type (Current_Scope)
+        or else Is_Limited_Type (Current_Scope)
+      then
+         CR_Disc := Make_Defining_Identifier (Sloc (Discrim), Chars (Discrim));
+
+         Set_Ekind     (CR_Disc, E_In_Parameter);
+         Set_Mechanism (CR_Disc, Default_Mechanism);
+         Set_Etype     (CR_Disc, Etype (Discrim));
+         Set_CR_Discriminant (Discrim, CR_Disc);
+      end if;
+   end Build_Discriminal;
+
+   ------------------------------------
+   -- Build_Discriminant_Constraints --
+   ------------------------------------
+
+   function Build_Discriminant_Constraints
+     (T           : Entity_Id;
+      Def         : Node_Id;
+      Derived_Def : Boolean := False)
+      return        Elist_Id
+   is
+      C          : constant Node_Id := Constraint (Def);
+      Nb_Discr   : constant Nat     := Number_Discriminants (T);
+      Discr_Expr : array (1 .. Nb_Discr) of Node_Id := (others => Empty);
+      --  Saves the expression corresponding to a given discriminant in T.
+
+      function Pos_Of_Discr (T : Entity_Id; D : Entity_Id) return Nat;
+      --  Return the Position number within array Discr_Expr of a discriminant
+      --  D within the discriminant list of the discriminated type T.
+
+      ------------------
+      -- Pos_Of_Discr --
+      ------------------
+
+      function Pos_Of_Discr (T : Entity_Id; D : Entity_Id) return Nat is
+         Disc : Entity_Id;
+
+      begin
+         Disc := First_Discriminant (T);
+         for J in Discr_Expr'Range loop
+            if Disc = D then
+               return J;
+            end if;
+
+            Next_Discriminant (Disc);
+         end loop;
+
+         --  Note: Since this function is called on discriminants that are
+         --  known to belong to the discriminated type, falling through the
+         --  loop with no match signals an internal compiler error.
+
+         raise Program_Error;
+      end Pos_Of_Discr;
+
+      --  Variables local to Build_Discriminant_Constraints
+
+      Discr : Entity_Id;
+      E     : Entity_Id;
+      Elist : Elist_Id := New_Elmt_List;
+
+      Constr    : Node_Id;
+      Expr      : Node_Id;
+      Id        : Node_Id;
+      Position  : Nat;
+      Found     : Boolean;
+
+      Discrim_Present : Boolean := False;
+
+   --  Start of processing for Build_Discriminant_Constraints
+
+   begin
+      --  The following loop will process positional associations only.
+      --  For a positional association, the (single) discriminant is
+      --  implicitly specified by position, in textual order (RM 3.7.2).
+
+      Discr  := First_Discriminant (T);
+      Constr := First (Constraints (C));
+
+      for D in Discr_Expr'Range loop
+         exit when Nkind (Constr) = N_Discriminant_Association;
+
+         if No (Constr) then
+            Error_Msg_N ("too few discriminants given in constraint", C);
+            return New_Elmt_List;
+
+         elsif Nkind (Constr) = N_Range
+           or else (Nkind (Constr) = N_Attribute_Reference
+                     and then
+                    Attribute_Name (Constr) = Name_Range)
+         then
+            Error_Msg_N
+              ("a range is not a valid discriminant constraint", Constr);
+            Discr_Expr (D) := Error;
+
+         else
+            Analyze_And_Resolve (Constr, Base_Type (Etype (Discr)));
+            Discr_Expr (D) := Constr;
+         end if;
+
+         Next_Discriminant (Discr);
+         Next (Constr);
+      end loop;
+
+      if No (Discr) and then Present (Constr) then
+         Error_Msg_N ("too many discriminants given in constraint", Constr);
+         return New_Elmt_List;
+      end if;
+
+      --  Named associations can be given in any order, but if both positional
+      --  and named associations are used in the same discriminant constraint,
+      --  then positional associations must occur first, at their normal
+      --  position. Hence once a named association is used, the rest of the
+      --  discriminant constraint must use only named associations.
+
+      while Present (Constr) loop
+
+         --  Positional association forbidden after a named association.
+
+         if Nkind (Constr) /= N_Discriminant_Association then
+            Error_Msg_N ("positional association follows named one", Constr);
+            return New_Elmt_List;
+
+         --  Otherwise it is a named association
+
+         else
+            --  E records the type of the discriminants in the named
+            --  association. All the discriminants specified in the same name
+            --  association must have the same type.
+
+            E := Empty;
+
+            --  Search the list of discriminants in T to see if the simple name
+            --  given in the constraint matches any of them.
+
+            Id := First (Selector_Names (Constr));
+            while Present (Id) loop
+               Found := False;
+
+               --  If Original_Discriminant is present, we are processing a
+               --  generic instantiation and this is an instance node. We need
+               --  to find the name of the corresponding discriminant in the
+               --  actual record type T and not the name of the discriminant in
+               --  the generic formal. Example:
+               --
+               --    generic
+               --       type G (D : int) is private;
+               --    package P is
+               --       subtype W is G (D => 1);
+               --    end package;
+               --    type Rec (X : int) is record ... end record;
+               --    package Q is new P (G => Rec);
+               --
+               --  At the point of the instantiation, formal type G is Rec
+               --  and therefore when reanalyzing "subtype W is G (D => 1);"
+               --  which really looks like "subtype W is Rec (D => 1);" at
+               --  the point of instantiation, we want to find the discriminant
+               --  that corresponds to D in Rec, ie X.
+
+               if Present (Original_Discriminant (Id)) then
+                  Discr := Find_Corresponding_Discriminant (Id, T);
+                  Found := True;
+
+               else
+                  Discr := First_Discriminant (T);
+                  while Present (Discr) loop
+                     if Chars (Discr) = Chars (Id) then
+                        Found := True;
+                        exit;
+                     end if;
+
+                     Next_Discriminant (Discr);
+                  end loop;
+
+                  if not Found then
+                     Error_Msg_N ("& does not match any discriminant", Id);
+                     return New_Elmt_List;
+
+                  --  The following is only useful for the benefit of generic
+                  --  instances but it does not interfere with other
+                  --  processsing for the non-generic case so we do it in all
+                  --  cases (for generics this statement is executed when
+                  --  processing the generic definition, see comment at the
+                  --  begining of this if statement).
+
+                  else
+                     Set_Original_Discriminant (Id, Discr);
+                  end if;
+               end if;
+
+               Position := Pos_Of_Discr (T, Discr);
+
+               if Present (Discr_Expr (Position)) then
+                  Error_Msg_N ("duplicate constraint for discriminant&", Id);
+
+               else
+                  --  Each discriminant specified in the same named association
+                  --  must be associated with a separate copy of the
+                  --  corresponding expression.
+
+                  if Present (Next (Id)) then
+                     Expr := New_Copy_Tree (Expression (Constr));
+                     Set_Parent (Expr, Parent (Expression (Constr)));
+                  else
+                     Expr := Expression (Constr);
+                  end if;
+
+                  Discr_Expr (Position) := Expr;
+                  Analyze_And_Resolve (Expr, Base_Type (Etype (Discr)));
+               end if;
+
+               --  A discriminant association with more than one discriminant
+               --  name is only allowed if the named discriminants are all of
+               --  the same type (RM 3.7.1(8)).
+
+               if E = Empty then
+                  E := Base_Type (Etype (Discr));
+
+               elsif Base_Type (Etype (Discr)) /= E then
+                  Error_Msg_N
+                    ("all discriminants in an association " &
+                     "must have the same type", Id);
+               end if;
+
+               Next (Id);
+            end loop;
+         end if;
+
+         Next (Constr);
+      end loop;
+
+      --  A discriminant constraint must provide exactly one value for each
+      --  discriminant of the type (RM 3.7.1(8)).
+
+      for J in Discr_Expr'Range loop
+         if No (Discr_Expr (J)) then
+            Error_Msg_N ("too few discriminants given in constraint", C);
+            return New_Elmt_List;
+         end if;
+      end loop;
+
+      --  Determine if there are discriminant expressions in the constraint.
+
+      for J in Discr_Expr'Range loop
+         if Denotes_Discriminant (Discr_Expr (J)) then
+            Discrim_Present := True;
+         end if;
+      end loop;
+
+      --  Build an element list consisting of the expressions given in the
+      --  discriminant constraint and apply the appropriate range
+      --  checks. The list is constructed after resolving any named
+      --  discriminant associations and therefore the expressions appear in
+      --  the textual order of the discriminants.
+
+      Discr := First_Discriminant (T);
+      for J in Discr_Expr'Range loop
+         if Discr_Expr (J) /= Error then
+
+            Append_Elmt (Discr_Expr (J), Elist);
+
+            --  If any of the discriminant constraints is given by a
+            --  discriminant and we are in a derived type declaration we
+            --  have a discriminant renaming. Establish link between new
+            --  and old discriminant.
+
+            if Denotes_Discriminant (Discr_Expr (J)) then
+               if Derived_Def then
+                  Set_Corresponding_Discriminant
+                    (Entity (Discr_Expr (J)), Discr);
+               end if;
+
+            --  Force the evaluation of non-discriminant expressions.
+            --  If we have found a discriminant in the constraint 3.4(26)
+            --  and 3.8(18) demand that no range checks are performed are
+            --  after evaluation. In all other cases perform a range check.
+
+            else
+               if not Discrim_Present then
+                  Apply_Range_Check (Discr_Expr (J), Etype (Discr));
+               end if;
+
+               Force_Evaluation (Discr_Expr (J));
+            end if;
+
+         --  Check that the designated type of an access discriminant's
+         --  expression is not a class-wide type unless the discriminant's
+         --  designated type is also class-wide.
+
+            if Ekind (Etype (Discr)) = E_Anonymous_Access_Type
+              and then not Is_Class_Wide_Type
+                         (Designated_Type (Etype (Discr)))
+              and then Etype (Discr_Expr (J)) /= Any_Type
+              and then Is_Class_Wide_Type
+                         (Designated_Type (Etype (Discr_Expr (J))))
+            then
+               Wrong_Type (Discr_Expr (J), Etype (Discr));
+            end if;
+         end if;
+
+         Next_Discriminant (Discr);
+      end loop;
+
+      return Elist;
+   end Build_Discriminant_Constraints;
+
+   ---------------------------------
+   -- Build_Discriminated_Subtype --
+   ---------------------------------
+
+   procedure Build_Discriminated_Subtype
+     (T           : Entity_Id;
+      Def_Id      : Entity_Id;
+      Elist       : Elist_Id;
+      Related_Nod : Node_Id;
+      For_Access  : Boolean := False)
+   is
+      Has_Discrs  : constant Boolean := Has_Discriminants (T);
+      Constrained : constant Boolean
+                      := (Has_Discrs and then not Is_Empty_Elmt_List (Elist))
+                           or else Is_Constrained (T);
+
+   begin
+      if Ekind (T) = E_Record_Type then
+         if For_Access then
+            Set_Ekind (Def_Id, E_Private_Subtype);
+            Set_Is_For_Access_Subtype (Def_Id, True);
+         else
+            Set_Ekind (Def_Id, E_Record_Subtype);
+         end if;
+
+      elsif Ekind (T) = E_Task_Type then
+         Set_Ekind (Def_Id, E_Task_Subtype);
+
+      elsif Ekind (T) = E_Protected_Type then
+         Set_Ekind (Def_Id, E_Protected_Subtype);
+
+      elsif Is_Private_Type (T) then
+         Set_Ekind (Def_Id, Subtype_Kind (Ekind (T)));
+
+      elsif Is_Class_Wide_Type (T) then
+         Set_Ekind (Def_Id, E_Class_Wide_Subtype);
+
+      else
+         --  Incomplete type. Attach subtype to list of dependents, to be
+         --  completed with full view of parent type.
+
+         Set_Ekind (Def_Id, Ekind (T));
+         Append_Elmt (Def_Id, Private_Dependents (T));
+      end if;
+
+      Set_Etype             (Def_Id, T);
+      Init_Size_Align       (Def_Id);
+      Set_Has_Discriminants (Def_Id, Has_Discrs);
+      Set_Is_Constrained    (Def_Id, Constrained);
+
+      Set_First_Entity      (Def_Id, First_Entity   (T));
+      Set_Last_Entity       (Def_Id, Last_Entity    (T));
+      Set_First_Rep_Item    (Def_Id, First_Rep_Item (T));
+
+      if Is_Tagged_Type (T) then
+         Set_Is_Tagged_Type  (Def_Id);
+         Make_Class_Wide_Type (Def_Id);
+      end if;
+
+      Set_Girder_Constraint (Def_Id, No_Elist);
+
+      if Has_Discrs then
+         Set_Discriminant_Constraint (Def_Id, Elist);
+         Set_Girder_Constraint_From_Discriminant_Constraint (Def_Id);
+      end if;
+
+      if Is_Tagged_Type (T) then
+         Set_Primitive_Operations (Def_Id, Primitive_Operations (T));
+         Set_Is_Abstract (Def_Id, Is_Abstract (T));
+      end if;
+
+      --  Subtypes introduced by component declarations do not need to be
+      --  marked as delayed, and do not get freeze nodes, because the semantics
+      --  verifies that the parents of the subtypes are frozen before the
+      --  enclosing record is frozen.
+
+      if not Is_Type (Scope (Def_Id)) then
+         Set_Depends_On_Private (Def_Id, Depends_On_Private (T));
+
+         if Is_Private_Type (T)
+           and then Present (Full_View (T))
+         then
+            Conditional_Delay (Def_Id, Full_View (T));
+         else
+            Conditional_Delay (Def_Id, T);
+         end if;
+      end if;
+
+      if Is_Record_Type (T) then
+         Set_Is_Limited_Record (Def_Id, Is_Limited_Record (T));
+
+         if Has_Discrs
+            and then not Is_Empty_Elmt_List (Elist)
+            and then not For_Access
+         then
+            Create_Constrained_Components (Def_Id, Related_Nod, T, Elist);
+         elsif not For_Access then
+            Set_Cloned_Subtype (Def_Id, T);
+         end if;
+      end if;
+
+   end Build_Discriminated_Subtype;
+
+   ------------------------
+   -- Build_Scalar_Bound --
+   ------------------------
+
+   function Build_Scalar_Bound
+     (Bound : Node_Id;
+      Par_T : Entity_Id;
+      Der_T : Entity_Id;
+      Loc   : Source_Ptr)
+      return Node_Id
+   is
+      New_Bound : Entity_Id;
+
+   begin
+      --  Note: not clear why this is needed, how can the original bound
+      --  be unanalyzed at this point? and if it is, what business do we
+      --  have messing around with it? and why is the base type of the
+      --  parent type the right type for the resolution. It probably is
+      --  not! It is OK for the new bound we are creating, but not for
+      --  the old one??? Still if it never happens, no problem!
+
+      Analyze_And_Resolve (Bound, Base_Type (Par_T));
+
+      if Nkind (Bound) = N_Integer_Literal
+        or else Nkind (Bound) = N_Real_Literal
+      then
+         New_Bound := New_Copy (Bound);
+         Set_Etype (New_Bound, Der_T);
+         Set_Analyzed (New_Bound);
+
+      elsif Is_Entity_Name (Bound) then
+         New_Bound := OK_Convert_To (Der_T, New_Copy (Bound));
+
+      --  The following is almost certainly wrong. What business do we have
+      --  relocating a node (Bound) that is presumably still attached to
+      --  the tree elsewhere???
+
+      else
+         New_Bound := OK_Convert_To (Der_T, Relocate_Node (Bound));
+      end if;
+
+      Set_Etype (New_Bound, Der_T);
+      return New_Bound;
+   end Build_Scalar_Bound;
+
+   --------------------------------
+   -- Build_Underlying_Full_View --
+   --------------------------------
+
+   procedure Build_Underlying_Full_View
+     (N   : Node_Id;
+      Typ : Entity_Id;
+      Par : Entity_Id)
+   is
+      Loc  : constant Source_Ptr := Sloc (N);
+      Subt : constant Entity_Id :=
+               Make_Defining_Identifier
+                 (Loc, New_External_Name (Chars (Typ), 'S'));
+
+      Constr : Node_Id;
+      Indic  : Node_Id;
+      C      : Node_Id;
+      Id     : Node_Id;
+
+   begin
+      if Nkind (N) = N_Full_Type_Declaration then
+         Constr := Constraint (Subtype_Indication (Type_Definition (N)));
+
+      --  ??? ??? is this assert right, I assume so otherwise Constr
+      --  would not be defined below (this used to be an elsif)
+
+      else pragma Assert (Nkind (N) = N_Subtype_Declaration);
+         Constr := New_Copy_Tree (Constraint (Subtype_Indication (N)));
+      end if;
+
+      --  If the constraint has discriminant associations, the discriminant
+      --  entity is already set, but it denotes a discriminant of the new
+      --  type, not the original parent, so it must be found anew.
+
+      C := First (Constraints (Constr));
+
+      while Present (C) loop
+
+         if Nkind (C) = N_Discriminant_Association then
+            Id := First (Selector_Names (C));
+
+            while Present (Id) loop
+               Set_Original_Discriminant (Id, Empty);
+               Next (Id);
+            end loop;
+         end if;
+
+         Next (C);
+      end loop;
+
+      Indic := Make_Subtype_Declaration (Loc,
+         Defining_Identifier => Subt,
+         Subtype_Indication  =>
+           Make_Subtype_Indication (Loc,
+             Subtype_Mark => New_Reference_To (Par, Loc),
+             Constraint   => New_Copy_Tree (Constr)));
+
+      Insert_Before (N, Indic);
+      Analyze (Indic);
+      Set_Underlying_Full_View (Typ, Full_View (Subt));
+   end Build_Underlying_Full_View;
+
+   -------------------------------
+   -- Check_Abstract_Overriding --
+   -------------------------------
+
+   procedure Check_Abstract_Overriding (T : Entity_Id) is
+      Op_List  : Elist_Id;
+      Elmt     : Elmt_Id;
+      Subp     : Entity_Id;
+      Type_Def : Node_Id;
+
+   begin
+      Op_List := Primitive_Operations (T);
+
+      --  Loop to check primitive operations
+
+      Elmt := First_Elmt (Op_List);
+      while Present (Elmt) loop
+         Subp := Node (Elmt);
+
+         --  Special exception, do not complain about failure to
+         --  override _Input and _Output, since we always provide
+         --  automatic overridings for these subprograms.
+
+         if Is_Abstract (Subp)
+           and then Chars (Subp) /= Name_uInput
+           and then Chars (Subp) /= Name_uOutput
+           and then not Is_Abstract (T)
+         then
+            if Present (Alias (Subp)) then
+               --  Only perform the check for a derived subprogram when
+               --  the type has an explicit record extension. This avoids
+               --  incorrectly flagging abstract subprograms for the case
+               --  of a type without an extension derived from a formal type
+               --  with a tagged actual (can occur within a private part).
+
+               Type_Def := Type_Definition (Parent (T));
+               if Nkind (Type_Def) = N_Derived_Type_Definition
+                 and then Present (Record_Extension_Part (Type_Def))
+               then
+                  Error_Msg_NE
+                    ("type must be declared abstract or & overridden",
+                     T, Subp);
+               end if;
+            else
+               Error_Msg_NE
+                 ("abstract subprogram not allowed for type&",
+                  Subp, T);
+               Error_Msg_NE
+                 ("nonabstract type has abstract subprogram&",
+                  T, Subp);
+            end if;
+         end if;
+
+         Next_Elmt (Elmt);
+      end loop;
+   end Check_Abstract_Overriding;
+
+   ------------------------------------------------
+   -- Check_Access_Discriminant_Requires_Limited --
+   ------------------------------------------------
+
+   procedure Check_Access_Discriminant_Requires_Limited
+     (D   : Node_Id;
+      Loc : Node_Id)
+   is
+   begin
+      --  A discriminant_specification for an access discriminant
+      --  shall appear only in the declaration for a task or protected
+      --  type, or for a type with the reserved word 'limited' in
+      --  its definition or in one of its ancestors. (RM 3.7(10))
+
+      if Nkind (Discriminant_Type (D)) = N_Access_Definition
+        and then not Is_Concurrent_Type (Current_Scope)
+        and then not Is_Concurrent_Record_Type (Current_Scope)
+        and then not Is_Limited_Record (Current_Scope)
+        and then Ekind (Current_Scope) /= E_Limited_Private_Type
+      then
+         Error_Msg_N
+           ("access discriminants allowed only for limited types", Loc);
+      end if;
+   end Check_Access_Discriminant_Requires_Limited;
+
+   -----------------------------------
+   -- Check_Aliased_Component_Types --
+   -----------------------------------
+
+   procedure Check_Aliased_Component_Types (T : Entity_Id) is
+      C : Entity_Id;
+
+   begin
+      --  ??? Also need to check components of record extensions,
+      --  but not components of protected types (which are always
+      --  limited).
+
+      if not Is_Limited_Type (T) then
+         if Ekind (T) = E_Record_Type then
+            C := First_Component (T);
+            while Present (C) loop
+               if Is_Aliased (C)
+                 and then Has_Discriminants (Etype (C))
+                 and then not Is_Constrained (Etype (C))
+                 and then not In_Instance
+               then
+                  Error_Msg_N
+                    ("aliased component must be constrained ('R'M 3.6(11))",
+                      C);
+               end if;
+
+               Next_Component (C);
+            end loop;
+
+         elsif Ekind (T) = E_Array_Type then
+            if Has_Aliased_Components (T)
+              and then Has_Discriminants (Component_Type (T))
+              and then not Is_Constrained (Component_Type (T))
+              and then not In_Instance
+            then
+               Error_Msg_N
+                 ("aliased component type must be constrained ('R'M 3.6(11))",
+                    T);
+            end if;
+         end if;
+      end if;
+   end Check_Aliased_Component_Types;
+
+   ----------------------
+   -- Check_Completion --
+   ----------------------
+
+   procedure Check_Completion (Body_Id : Node_Id := Empty) is
+      E : Entity_Id;
+
+      procedure Post_Error;
+      --  Post error message for lack of completion for entity E
+
+      procedure Post_Error is
+      begin
+         if not Comes_From_Source (E) then
+
+            if (Ekind (E) = E_Task_Type
+              or else Ekind (E) = E_Protected_Type)
+            then
+               --  It may be an anonymous protected type created for a
+               --  single variable. Post error on variable, if present.
+
+               declare
+                  Var : Entity_Id;
+
+               begin
+                  Var := First_Entity (Current_Scope);
+
+                  while Present (Var) loop
+                     exit when Etype (Var) = E
+                       and then Comes_From_Source (Var);
+
+                     Next_Entity (Var);
+                  end loop;
+
+                  if Present (Var) then
+                     E := Var;
+                  end if;
+               end;
+            end if;
+         end if;
+
+         --  If a generated entity has no completion, then either previous
+         --  semantic errors have disabled the expansion phase, or else
+         --  we had missing subunits, or else we are compiling without expan-
+         --  sion, or else something is very wrong.
+
+         if not Comes_From_Source (E) then
+            pragma Assert
+              (Errors_Detected > 0
+                or else Subunits_Missing
+                or else not Expander_Active);
+            return;
+
+         --  Here for source entity
+
+         else
+            --  Here if no body to post the error message, so we post the error
+            --  on the declaration that has no completion. This is not really
+            --  the right place to post it, think about this later ???
+
+            if No (Body_Id) then
+               if Is_Type (E) then
+                  Error_Msg_NE
+                    ("missing full declaration for }", Parent (E), E);
+               else
+                  Error_Msg_NE
+                    ("missing body for &", Parent (E), E);
+               end if;
+
+            --  Package body has no completion for a declaration that appears
+            --  in the corresponding spec. Post error on the body, with a
+            --  reference to the non-completed declaration.
+
+            else
+               Error_Msg_Sloc := Sloc (E);
+
+               if Is_Type (E) then
+                  Error_Msg_NE
+                    ("missing full declaration for }!", Body_Id, E);
+
+               elsif Is_Overloadable (E)
+                 and then Current_Entity_In_Scope (E) /= E
+               then
+                  --  It may be that the completion is mistyped and appears
+                  --  as a  distinct overloading of the entity.
+
+                  declare
+                     Candidate : Entity_Id := Current_Entity_In_Scope (E);
+                     Decl      : Node_Id := Unit_Declaration_Node (Candidate);
+
+                  begin
+                     if Is_Overloadable (Candidate)
+                       and then Ekind (Candidate) = Ekind (E)
+                       and then Nkind (Decl) = N_Subprogram_Body
+                       and then Acts_As_Spec (Decl)
+                     then
+                        Check_Type_Conformant (Candidate, E);
+
+                     else
+                        Error_Msg_NE ("missing body for & declared#!",
+                           Body_Id, E);
+                     end if;
+                  end;
+               else
+                  Error_Msg_NE ("missing body for & declared#!",
+                     Body_Id, E);
+               end if;
+            end if;
+         end if;
+      end Post_Error;
+
+   --  Start processing for Check_Completion
+
+   begin
+      E := First_Entity (Current_Scope);
+      while Present (E) loop
+         if Is_Intrinsic_Subprogram (E) then
+            null;
+
+         --  The following situation requires special handling: a child
+         --  unit that appears in the context clause of the body of its
+         --  parent:
+
+         --    procedure Parent.Child (...);
+         --
+         --    with Parent.Child;
+         --    package body Parent is
+
+         --  Here Parent.Child appears as a local entity, but should not
+         --  be flagged as requiring completion, because it is a
+         --  compilation unit.
+
+         elsif     Ekind (E) = E_Function
+           or else Ekind (E) = E_Procedure
+           or else Ekind (E) = E_Generic_Function
+           or else Ekind (E) = E_Generic_Procedure
+         then
+            if not Has_Completion (E)
+              and then not Is_Abstract (E)
+              and then Nkind (Parent (Unit_Declaration_Node (E))) /=
+                                                       N_Compilation_Unit
+              and then Chars (E) /= Name_uSize
+            then
+               Post_Error;
+            end if;
+
+         elsif Is_Entry (E) then
+            if not Has_Completion (E) and then
+              (Ekind (Scope (E)) = E_Protected_Object
+                or else Ekind (Scope (E)) = E_Protected_Type)
+            then
+               Post_Error;
+            end if;
+
+         elsif Is_Package (E) then
+            if Unit_Requires_Body (E) then
+               if not Has_Completion (E)
+                 and then Nkind (Parent (Unit_Declaration_Node (E))) /=
+                                                       N_Compilation_Unit
+               then
+                  Post_Error;
+               end if;
+
+            elsif not Is_Child_Unit (E) then
+               May_Need_Implicit_Body (E);
+            end if;
+
+         elsif Ekind (E) = E_Incomplete_Type
+           and then No (Underlying_Type (E))
+         then
+            Post_Error;
+
+         elsif (Ekind (E) = E_Task_Type or else
+                Ekind (E) = E_Protected_Type)
+           and then not Has_Completion (E)
+         then
+            Post_Error;
+
+         elsif Ekind (E) = E_Constant
+           and then Ekind (Etype (E)) = E_Task_Type
+           and then not Has_Completion (Etype (E))
+         then
+            Post_Error;
+
+         elsif Ekind (E) = E_Protected_Object
+           and then not Has_Completion (Etype (E))
+         then
+            Post_Error;
+
+         elsif Ekind (E) = E_Record_Type then
+            if Is_Tagged_Type (E) then
+               Check_Abstract_Overriding (E);
+            end if;
+
+            Check_Aliased_Component_Types (E);
+
+         elsif Ekind (E) = E_Array_Type then
+            Check_Aliased_Component_Types (E);
+
+         end if;
+
+         Next_Entity (E);
+      end loop;
+   end Check_Completion;
+
+   ----------------------------
+   -- Check_Delta_Expression --
+   ----------------------------
+
+   procedure Check_Delta_Expression (E : Node_Id) is
+   begin
+      if not (Is_Real_Type (Etype (E))) then
+         Wrong_Type (E, Any_Real);
+
+      elsif not Is_OK_Static_Expression (E) then
+         Error_Msg_N ("non-static expression used for delta value", E);
+
+      elsif not UR_Is_Positive (Expr_Value_R (E)) then
+         Error_Msg_N ("delta expression must be positive", E);
+
+      else
+         return;
+      end if;
+
+      --  If any of above errors occurred, then replace the incorrect
+      --  expression by the real 0.1, which should prevent further errors.
+
+      Rewrite (E,
+        Make_Real_Literal (Sloc (E), Ureal_Tenth));
+      Analyze_And_Resolve (E, Standard_Float);
+
+   end Check_Delta_Expression;
+
+   -----------------------------
+   -- Check_Digits_Expression --
+   -----------------------------
+
+   procedure Check_Digits_Expression (E : Node_Id) is
+   begin
+      if not (Is_Integer_Type (Etype (E))) then
+         Wrong_Type (E, Any_Integer);
+
+      elsif not Is_OK_Static_Expression (E) then
+         Error_Msg_N ("non-static expression used for digits value", E);
+
+      elsif Expr_Value (E) <= 0 then
+         Error_Msg_N ("digits value must be greater than zero", E);
+
+      else
+         return;
+      end if;
+
+      --  If any of above errors occurred, then replace the incorrect
+      --  expression by the integer 1, which should prevent further errors.
+
+      Rewrite (E, Make_Integer_Literal (Sloc (E), 1));
+      Analyze_And_Resolve (E, Standard_Integer);
+
+   end Check_Digits_Expression;
+
+   ----------------------
+   -- Check_Incomplete --
+   ----------------------
+
+   procedure Check_Incomplete (T : Entity_Id) is
+   begin
+      if Ekind (Root_Type (Entity (T))) = E_Incomplete_Type then
+         Error_Msg_N ("invalid use of type before its full declaration", T);
+      end if;
+   end Check_Incomplete;
+
+   --------------------------
+   -- Check_Initialization --
+   --------------------------
+
+   procedure Check_Initialization (T : Entity_Id; Exp : Node_Id) is
+   begin
+      if (Is_Limited_Type (T)
+           or else Is_Limited_Composite (T))
+        and then not In_Instance
+      then
+         Error_Msg_N
+           ("cannot initialize entities of limited type", Exp);
+      end if;
+   end Check_Initialization;
+
+   ------------------------------------
+   -- Check_Or_Process_Discriminants --
+   ------------------------------------
+
+   --  If an incomplete or private type declaration was already given for
+   --  the type, the discriminants may have already been processed if they
+   --  were present on the incomplete declaration. In this case a full
+   --  conformance check is performed otherwise just process them.
+
+   procedure Check_Or_Process_Discriminants (N : Node_Id; T : Entity_Id) is
+   begin
+      if Has_Discriminants (T) then
+
+         --  Make the discriminants visible to component declarations.
+
+         declare
+            D    : Entity_Id := First_Discriminant (T);
+            Prev : Entity_Id;
+
+         begin
+            while Present (D) loop
+               Prev := Current_Entity (D);
+               Set_Current_Entity (D);
+               Set_Is_Immediately_Visible (D);
+               Set_Homonym (D, Prev);
+
+               --  This restriction gets applied to the full type here; it
+               --  has already been applied earlier to the partial view
+
+               Check_Access_Discriminant_Requires_Limited (Parent (D), N);
+
+               Next_Discriminant (D);
+            end loop;
+         end;
+
+      elsif Present (Discriminant_Specifications (N)) then
+         Process_Discriminants (N);
+      end if;
+   end Check_Or_Process_Discriminants;
+
+   ----------------------
+   -- Check_Real_Bound --
+   ----------------------
+
+   procedure Check_Real_Bound (Bound : Node_Id) is
+   begin
+      if not Is_Real_Type (Etype (Bound)) then
+         Error_Msg_N
+           ("bound in real type definition must be of real type", Bound);
+
+      elsif not Is_OK_Static_Expression (Bound) then
+         Error_Msg_N
+           ("non-static expression used for real type bound", Bound);
+
+      else
+         return;
+      end if;
+
+      Rewrite
+        (Bound, Make_Real_Literal (Sloc (Bound), Ureal_0));
+      Analyze (Bound);
+      Resolve (Bound, Standard_Float);
+   end Check_Real_Bound;
+
+   ------------------------------
+   -- Complete_Private_Subtype --
+   ------------------------------
+
+   procedure Complete_Private_Subtype
+     (Priv        : Entity_Id;
+      Full        : Entity_Id;
+      Full_Base   : Entity_Id;
+      Related_Nod : Node_Id)
+   is
+      Save_Next_Entity : Entity_Id;
+      Save_Homonym     : Entity_Id;
+
+   begin
+      --  Set semantic attributes for (implicit) private subtype completion.
+      --  If the full type has no discriminants, then it is a copy of the full
+      --  view of the base. Otherwise, it is a subtype of the base with a
+      --  possible discriminant constraint. Save and restore the original
+      --  Next_Entity field of full to ensure that the calls to Copy_Node
+      --  do not corrupt the entity chain.
+
+      --  Note that the type of the full view is the same entity as the
+      --  type of the partial view. In this fashion, the subtype has
+      --  access to the correct view of the parent.
+
+      Save_Next_Entity := Next_Entity (Full);
+      Save_Homonym     := Homonym (Priv);
+
+      case Ekind (Full_Base) is
+
+         when E_Record_Type    |
+              E_Record_Subtype |
+              Class_Wide_Kind  |
+              Private_Kind     |
+              Task_Kind        |
+              Protected_Kind   =>
+            Copy_Node (Priv, Full);
+
+            Set_Has_Discriminants  (Full, Has_Discriminants (Full_Base));
+            Set_First_Entity       (Full, First_Entity (Full_Base));
+            Set_Last_Entity        (Full, Last_Entity (Full_Base));
+
+         when others =>
+            Copy_Node (Full_Base, Full);
+            Set_Chars          (Full, Chars (Priv));
+            Conditional_Delay  (Full, Priv);
+            Set_Sloc           (Full, Sloc (Priv));
+
+      end case;
+
+      Set_Next_Entity (Full, Save_Next_Entity);
+      Set_Homonym     (Full, Save_Homonym);
+      Set_Associated_Node_For_Itype (Full, Related_Nod);
+
+      --  Set common attributes for all subtypes.
+
+      Set_Ekind (Full, Subtype_Kind (Ekind (Full_Base)));
+
+      --  The Etype of the full view is inconsistent. Gigi needs to see the
+      --  structural full view,  which is what the current scheme gives:
+      --  the Etype of the full view is the etype of the full base. However,
+      --  if the full base is a derived type, the full view then looks like
+      --  a subtype of the parent, not a subtype of the full base. If instead
+      --  we write:
+
+      --       Set_Etype (Full, Full_Base);
+
+      --  then we get inconsistencies in the front-end (confusion between
+      --  views). Several outstanding bugs are related to this.
+
+      Set_Is_First_Subtype (Full, False);
+      Set_Scope            (Full, Scope (Priv));
+      Set_Size_Info        (Full, Full_Base);
+      Set_RM_Size          (Full, RM_Size (Full_Base));
+      Set_Is_Itype         (Full);
+
+      --  A subtype of a private-type-without-discriminants, whose full-view
+      --  has discriminants with default expressions, is not constrained!
+
+      if not Has_Discriminants (Priv) then
+         Set_Is_Constrained (Full, Is_Constrained (Full_Base));
+      end if;
+
+      Set_First_Rep_Item     (Full, First_Rep_Item (Full_Base));
+      Set_Depends_On_Private (Full, Has_Private_Component (Full));
+
+      --  Freeze the private subtype entity if its parent is delayed,
+      --  and not already frozen. We skip this processing if the type
+      --  is an anonymous subtype of a record component, or is the
+      --  corresponding record of a protected type, since ???
+
+      if not Is_Type (Scope (Full)) then
+         Set_Has_Delayed_Freeze (Full,
+           Has_Delayed_Freeze (Full_Base)
+               and then (not Is_Frozen (Full_Base)));
+      end if;
+
+      Set_Freeze_Node (Full, Empty);
+      Set_Is_Frozen (Full, False);
+      Set_Full_View (Priv, Full);
+
+      if Has_Discriminants (Full) then
+         Set_Girder_Constraint_From_Discriminant_Constraint (Full);
+         Set_Girder_Constraint (Priv, Girder_Constraint (Full));
+         if Has_Unknown_Discriminants (Full) then
+            Set_Discriminant_Constraint (Full, No_Elist);
+         end if;
+      end if;
+
+      if Ekind (Full_Base) = E_Record_Type
+        and then Has_Discriminants (Full_Base)
+        and then Has_Discriminants (Priv) -- might not, if errors
+        and then not Is_Empty_Elmt_List (Discriminant_Constraint (Priv))
+      then
+         Create_Constrained_Components
+           (Full, Related_Nod, Full_Base, Discriminant_Constraint (Priv));
+
+      --  If the full base is itself derived from private, build a congruent
+      --  subtype of its underlying type, for use by the back end.
+
+      elsif Ekind (Full_Base) in Private_Kind
+        and then Is_Derived_Type (Full_Base)
+        and then Has_Discriminants (Full_Base)
+        and then
+          Nkind (Subtype_Indication (Parent (Priv))) = N_Subtype_Indication
+      then
+         Build_Underlying_Full_View (Parent (Priv), Full, Etype (Full_Base));
+
+      elsif Is_Record_Type (Full_Base) then
+
+         --  Show Full is simply a renaming of Full_Base.
+
+         Set_Cloned_Subtype (Full, Full_Base);
+      end if;
+
+      --  It is usafe to share to bounds of a scalar type, because the
+      --  Itype is elaborated on demand, and if a bound is non-static
+      --  then different orders of elaboration in different units will
+      --  lead to different external symbols.
+
+      if Is_Scalar_Type (Full_Base) then
+         Set_Scalar_Range (Full,
+           Make_Range (Sloc (Related_Nod),
+             Low_Bound  => Duplicate_Subexpr (Type_Low_Bound  (Full_Base)),
+             High_Bound => Duplicate_Subexpr (Type_High_Bound (Full_Base))));
+      end if;
+
+      --  ??? It seems that a lot of fields are missing that should be
+      --  copied from  Full_Base to Full. Here are some that are introduced
+      --  in a non-disruptive way but a cleanup is necessary.
+
+      if Is_Tagged_Type (Full_Base) then
+         Set_Is_Tagged_Type (Full);
+         Set_Primitive_Operations (Full, Primitive_Operations (Full_Base));
+
+      elsif Is_Concurrent_Type (Full_Base) then
+
+         if Has_Discriminants (Full)
+           and then Present (Corresponding_Record_Type (Full_Base))
+         then
+            Set_Corresponding_Record_Type (Full,
+              Constrain_Corresponding_Record
+                (Full, Corresponding_Record_Type (Full_Base),
+                  Related_Nod, Full_Base));
+
+         else
+            Set_Corresponding_Record_Type (Full,
+              Corresponding_Record_Type (Full_Base));
+         end if;
+      end if;
+
+   end Complete_Private_Subtype;
+
+   ----------------------------
+   -- Constant_Redeclaration --
+   ----------------------------
+
+   procedure Constant_Redeclaration
+     (Id : Entity_Id;
+      N  : Node_Id;
+      T  : out Entity_Id)
+   is
+      Prev    : constant Entity_Id := Current_Entity_In_Scope (Id);
+      Obj_Def : constant Node_Id := Object_Definition (N);
+      New_T   : Entity_Id;
+
+   begin
+      if Nkind (Parent (Prev)) = N_Object_Declaration then
+         if Nkind (Object_Definition
+                     (Parent (Prev))) = N_Subtype_Indication
+         then
+            --  Find type of new declaration. The constraints of the two
+            --  views must match statically, but there is no point in
+            --  creating an itype for the full view.
+
+            if Nkind (Obj_Def) = N_Subtype_Indication then
+               Find_Type (Subtype_Mark (Obj_Def));
+               New_T := Entity (Subtype_Mark (Obj_Def));
+
+            else
+               Find_Type (Obj_Def);
+               New_T := Entity (Obj_Def);
+            end if;
+
+            T := Etype (Prev);
+
+         else
+            --  The full view may impose a constraint, even if the partial
+            --  view does not, so construct the subtype.
+
+            New_T := Find_Type_Of_Object (Obj_Def, N);
+            T     := New_T;
+         end if;
+
+      else
+         --  Current declaration is illegal, diagnosed below in Enter_Name.
+
+         T := Empty;
+         New_T := Any_Type;
+      end if;
+
+      --  If previous full declaration exists, or if a homograph is present,
+      --  let Enter_Name handle it, either with an error, or with the removal
+      --  of an overridden implicit subprogram.
+
+      if Ekind (Prev) /= E_Constant
+        or else Present (Expression (Parent (Prev)))
+      then
+         Enter_Name (Id);
+
+      --  Verify that types of both declarations match.
+
+      elsif Base_Type (Etype (Prev)) /= Base_Type (New_T) then
+         Error_Msg_Sloc := Sloc (Prev);
+         Error_Msg_N ("type does not match declaration#", N);
+         Set_Full_View (Prev, Id);
+         Set_Etype (Id, Any_Type);
+
+      --  If so, process the full constant declaration
+
+      else
+         Set_Full_View (Prev, Id);
+         Set_Is_Public (Id, Is_Public (Prev));
+         Set_Is_Internal (Id);
+         Append_Entity (Id, Current_Scope);
+
+         --  Check ALIASED present if present before (RM 7.4(7))
+
+         if Is_Aliased (Prev)
+           and then not Aliased_Present (N)
+         then
+            Error_Msg_Sloc := Sloc (Prev);
+            Error_Msg_N ("ALIASED required (see declaration#)", N);
+         end if;
+
+         --  Check that placement is in private part
+
+         if Ekind (Current_Scope) = E_Package
+           and then not In_Private_Part (Current_Scope)
+         then
+            Error_Msg_Sloc := Sloc (Prev);
+            Error_Msg_N ("full constant for declaration#"
+                         & " must be in private part", N);
+         end if;
+      end if;
+   end Constant_Redeclaration;
+
+   ----------------------
+   -- Constrain_Access --
+   ----------------------
+
+   procedure Constrain_Access
+     (Def_Id      : in out Entity_Id;
+      S           : Node_Id;
+      Related_Nod : Node_Id)
+   is
+      T             : constant Entity_Id := Entity (Subtype_Mark (S));
+      Desig_Type    : constant Entity_Id := Designated_Type (T);
+      Desig_Subtype : Entity_Id := Create_Itype (E_Void, Related_Nod);
+      Constraint_OK : Boolean := True;
+
+   begin
+      if Is_Array_Type (Desig_Type) then
+         Constrain_Array (Desig_Subtype, S, Related_Nod, Def_Id, 'P');
+
+      elsif (Is_Record_Type (Desig_Type)
+              or else Is_Incomplete_Or_Private_Type (Desig_Type))
+        and then not Is_Constrained (Desig_Type)
+      then
+         --  ??? The following code is a temporary kludge to ignore
+         --  discriminant constraint on access type if
+         --  it is constraining the current record. Avoid creating the
+         --  implicit subtype of the record we are currently compiling
+         --  since right now, we cannot handle these.
+         --  For now, just return the access type itself.
+
+         if Desig_Type = Current_Scope
+           and then No (Def_Id)
+         then
+            Set_Ekind (Desig_Subtype, E_Record_Subtype);
+            Def_Id := Entity (Subtype_Mark (S));
+
+            --  This call added to ensure that the constraint is
+            --  analyzed (needed for a B test). Note that we
+            --  still return early from this procedure to avoid
+            --  recursive processing. ???
+
+            Constrain_Discriminated_Type
+              (Desig_Subtype, S, Related_Nod, For_Access => True);
+
+            return;
+         end if;
+
+         Constrain_Discriminated_Type (Desig_Subtype, S, Related_Nod,
+           For_Access => True);
+
+      elsif (Is_Task_Type (Desig_Type)
+              or else Is_Protected_Type (Desig_Type))
+        and then not Is_Constrained (Desig_Type)
+      then
+         Constrain_Concurrent
+           (Desig_Subtype, S, Related_Nod, Desig_Type, ' ');
+
+      else
+         Error_Msg_N ("invalid constraint on access type", S);
+         Desig_Subtype := Desig_Type; -- Ignore invalid constraint.
+         Constraint_OK := False;
+      end if;
+
+      if No (Def_Id) then
+         Def_Id := Create_Itype (E_Access_Subtype, Related_Nod);
+      else
+         Set_Ekind (Def_Id, E_Access_Subtype);
+      end if;
+
+      if Constraint_OK then
+         Set_Etype (Def_Id, Base_Type (T));
+
+         if Is_Private_Type (Desig_Type) then
+            Prepare_Private_Subtype_Completion (Desig_Subtype, Related_Nod);
+         end if;
+      else
+         Set_Etype (Def_Id, Any_Type);
+      end if;
+
+      Set_Size_Info                (Def_Id, T);
+      Set_Is_Constrained           (Def_Id, Constraint_OK);
+      Set_Directly_Designated_Type (Def_Id, Desig_Subtype);
+      Set_Depends_On_Private       (Def_Id, Has_Private_Component (Def_Id));
+      Set_Is_Access_Constant       (Def_Id, Is_Access_Constant (T));
+
+      --  Itypes created for constrained record components do not receive
+      --  a freeze node, they are elaborated when first seen.
+
+      if not Is_Record_Type (Current_Scope) then
+         Conditional_Delay (Def_Id, T);
+      end if;
+   end Constrain_Access;
+
+   ---------------------
+   -- Constrain_Array --
+   ---------------------
+
+   procedure Constrain_Array
+     (Def_Id      : in out Entity_Id;
+      SI          : Node_Id;
+      Related_Nod : Node_Id;
+      Related_Id  : Entity_Id;
+      Suffix      : Character)
+   is
+      C                     : constant Node_Id := Constraint (SI);
+      Number_Of_Constraints : Nat := 0;
+      Index                 : Node_Id;
+      S, T                  : Entity_Id;
+      Constraint_OK         : Boolean := True;
+
+   begin
+      T := Entity (Subtype_Mark (SI));
+
+      if Ekind (T) in Access_Kind then
+         T := Designated_Type (T);
+      end if;
+
+      --  If an index constraint follows a subtype mark in a subtype indication
+      --  then the type or subtype denoted by the subtype mark must not already
+      --  impose an index constraint. The subtype mark must denote either an
+      --  unconstrained array type or an access type whose designated type
+      --  is such an array type... (RM 3.6.1)
+
+      if Is_Constrained (T) then
+         Error_Msg_N
+           ("array type is already constrained", Subtype_Mark (SI));
+         Constraint_OK := False;
+
+      else
+         S := First (Constraints (C));
+
+         while Present (S) loop
+            Number_Of_Constraints := Number_Of_Constraints + 1;
+            Next (S);
+         end loop;
+
+         --  In either case, the index constraint must provide a discrete
+         --  range for each index of the array type and the type of each
+         --  discrete range must be the same as that of the corresponding
+         --  index. (RM 3.6.1)
+
+         if Number_Of_Constraints /= Number_Dimensions (T) then
+            Error_Msg_NE ("incorrect number of index constraints for }", C, T);
+            Constraint_OK := False;
+
+         else
+            S := First (Constraints (C));
+            Index := First_Index (T);
+            Analyze (Index);
+
+            --  Apply constraints to each index type
+
+            for J in 1 .. Number_Of_Constraints loop
+               Constrain_Index (Index, S, Related_Nod, Related_Id, Suffix, J);
+               Next (Index);
+               Next (S);
+            end loop;
+
+         end if;
+      end if;
+
+      if No (Def_Id) then
+         Def_Id :=
+           Create_Itype (E_Array_Subtype, Related_Nod, Related_Id, Suffix);
+      else
+         Set_Ekind (Def_Id, E_Array_Subtype);
+      end if;
+
+      Set_Size_Info      (Def_Id,                (T));
+      Set_First_Rep_Item (Def_Id, First_Rep_Item (T));
+      Set_Etype          (Def_Id, Base_Type      (T));
+
+      if Constraint_OK then
+         Set_First_Index (Def_Id, First (Constraints (C)));
+      end if;
+
+      Set_Component_Type     (Def_Id, Component_Type (T));
+      Set_Is_Constrained     (Def_Id, True);
+      Set_Is_Aliased         (Def_Id, Is_Aliased (T));
+      Set_Depends_On_Private (Def_Id, Has_Private_Component (Def_Id));
+
+      Set_Is_Private_Composite (Def_Id, Is_Private_Composite (T));
+      Set_Is_Limited_Composite (Def_Id, Is_Limited_Composite (T));
+
+      --  If the subtype is not that of a record component, build a freeze
+      --  node if parent still needs one.
+
+      --  If the subtype is not that of a record component, make sure
+      --  that the Depends_On_Private status is set (explanation ???)
+      --  and also that a conditional delay is set.
+
+      if not Is_Type (Scope (Def_Id)) then
+         Set_Depends_On_Private (Def_Id, Depends_On_Private (T));
+         Conditional_Delay (Def_Id, T);
+      end if;
+
+   end Constrain_Array;
+
+   ------------------------------
+   -- Constrain_Component_Type --
+   ------------------------------
+
+   function Constrain_Component_Type
+     (Compon_Type     : Entity_Id;
+      Constrained_Typ : Entity_Id;
+      Related_Node    : Node_Id;
+      Typ             : Entity_Id;
+      Constraints     : Elist_Id)
+      return            Entity_Id
+   is
+      Loc : constant Source_Ptr := Sloc (Constrained_Typ);
+
+      function Build_Constrained_Array_Type
+        (Old_Type : Entity_Id)
+         return     Entity_Id;
+      --  If Old_Type is an array type, one of whose indices is
+      --  constrained by a discriminant, build an Itype whose constraint
+      --  replaces the discriminant with its value in the constraint.
+
+      function Build_Constrained_Discriminated_Type
+        (Old_Type : Entity_Id)
+         return     Entity_Id;
+      --  Ditto for record components.
+
+      function Build_Constrained_Access_Type
+        (Old_Type : Entity_Id)
+         return     Entity_Id;
+      --  Ditto for access types. Makes use of previous two functions, to
+      --  constrain designated type.
+
+      function Build_Subtype (T : Entity_Id; C : List_Id) return Entity_Id;
+      --  T is an array or discriminated type, C is a list of constraints
+      --  that apply to T. This routine builds the constrained subtype.
+
+      function Is_Discriminant (Expr : Node_Id) return Boolean;
+      --  Returns True if Expr is a discriminant.
+
+      function Get_Value (Discrim : Entity_Id) return Node_Id;
+      --  Find the value of discriminant Discrim in Constraint.
+
+      -----------------------------------
+      -- Build_Constrained_Access_Type --
+      -----------------------------------
+
+      function Build_Constrained_Access_Type
+        (Old_Type : Entity_Id)
+        return      Entity_Id
+      is
+         Desig_Type    : constant Entity_Id := Designated_Type (Old_Type);
+         Itype         : Entity_Id;
+         Desig_Subtype : Entity_Id;
+         Scop          : Entity_Id;
+
+      begin
+         --  if the original access type was not embedded in the enclosing
+         --  type definition, there is no need to produce a new access
+         --  subtype. In fact every access type with an explicit constraint
+         --  generates an itype whose scope is the enclosing record.
+
+         if not Is_Type (Scope (Old_Type)) then
+            return Old_Type;
+
+         elsif Is_Array_Type (Desig_Type) then
+            Desig_Subtype := Build_Constrained_Array_Type (Desig_Type);
+
+         elsif Has_Discriminants (Desig_Type) then
+
+            --  This may be an access type to an enclosing record type for
+            --  which we are constructing the constrained components. Return
+            --  the enclosing record subtype. This is not always correct,
+            --  but avoids infinite recursion. ???
+
+            Desig_Subtype := Any_Type;
+
+            for J in reverse 0 .. Scope_Stack.Last loop
+               Scop := Scope_Stack.Table (J).Entity;
+
+               if Is_Type (Scop)
+                 and then Base_Type (Scop) = Base_Type (Desig_Type)
+               then
+                  Desig_Subtype := Scop;
+               end if;
+
+               exit when not Is_Type (Scop);
+            end loop;
+
+            if Desig_Subtype = Any_Type then
+               Desig_Subtype :=
+                 Build_Constrained_Discriminated_Type (Desig_Type);
+            end if;
+
+         else
+            return Old_Type;
+         end if;
+
+         if Desig_Subtype /= Desig_Type then
+            --  The Related_Node better be here or else we won't be able
+            --  to attach new itypes to a node in the tree.
+
+            pragma Assert (Present (Related_Node));
+
+            Itype := Create_Itype (E_Access_Subtype, Related_Node);
+
+            Set_Etype                    (Itype, Base_Type      (Old_Type));
+            Set_Size_Info                (Itype,                (Old_Type));
+            Set_Directly_Designated_Type (Itype, Desig_Subtype);
+            Set_Depends_On_Private       (Itype, Has_Private_Component
+                                                                (Old_Type));
+            Set_Is_Access_Constant       (Itype, Is_Access_Constant
+                                                                (Old_Type));
+
+            --  The new itype needs freezing when it depends on a not frozen
+            --  type and the enclosing subtype needs freezing.
+
+            if Has_Delayed_Freeze (Constrained_Typ)
+              and then not Is_Frozen (Constrained_Typ)
+            then
+               Conditional_Delay (Itype, Base_Type (Old_Type));
+            end if;
+
+            return Itype;
+
+         else
+            return Old_Type;
+         end if;
+      end Build_Constrained_Access_Type;
+
+      ----------------------------------
+      -- Build_Constrained_Array_Type --
+      ----------------------------------
+
+      function Build_Constrained_Array_Type
+        (Old_Type : Entity_Id)
+         return     Entity_Id
+      is
+         Lo_Expr     : Node_Id;
+         Hi_Expr     : Node_Id;
+         Old_Index   : Node_Id;
+         Range_Node  : Node_Id;
+         Constr_List : List_Id;
+
+         Need_To_Create_Itype : Boolean := False;
+
+      begin
+         Old_Index := First_Index (Old_Type);
+         while Present (Old_Index) loop
+            Get_Index_Bounds (Old_Index, Lo_Expr, Hi_Expr);
+
+            if Is_Discriminant (Lo_Expr)
+              or else Is_Discriminant (Hi_Expr)
+            then
+               Need_To_Create_Itype := True;
+            end if;
+
+            Next_Index (Old_Index);
+         end loop;
+
+         if Need_To_Create_Itype then
+            Constr_List := New_List;
+
+            Old_Index := First_Index (Old_Type);
+            while Present (Old_Index) loop
+               Get_Index_Bounds (Old_Index, Lo_Expr, Hi_Expr);
+
+               if Is_Discriminant (Lo_Expr) then
+                  Lo_Expr := Get_Value (Lo_Expr);
+               end if;
+
+               if Is_Discriminant (Hi_Expr) then
+                  Hi_Expr := Get_Value (Hi_Expr);
+               end if;
+
+               Range_Node :=
+                 Make_Range
+                   (Loc, New_Copy_Tree (Lo_Expr), New_Copy_Tree (Hi_Expr));
+
+               Append (Range_Node, To => Constr_List);
+
+               Next_Index (Old_Index);
+            end loop;
+
+            return Build_Subtype (Old_Type, Constr_List);
+
+         else
+            return Old_Type;
+         end if;
+      end Build_Constrained_Array_Type;
+
+      ------------------------------------------
+      -- Build_Constrained_Discriminated_Type --
+      ------------------------------------------
+
+      function Build_Constrained_Discriminated_Type
+        (Old_Type : Entity_Id)
+         return     Entity_Id
+      is
+         Expr           : Node_Id;
+         Constr_List    : List_Id;
+         Old_Constraint : Elmt_Id;
+
+         Need_To_Create_Itype : Boolean := False;
+
+      begin
+         Old_Constraint := First_Elmt (Discriminant_Constraint (Old_Type));
+         while Present (Old_Constraint) loop
+            Expr := Node (Old_Constraint);
+
+            if Is_Discriminant (Expr) then
+               Need_To_Create_Itype := True;
+            end if;
+
+            Next_Elmt (Old_Constraint);
+         end loop;
+
+         if Need_To_Create_Itype then
+            Constr_List := New_List;
+
+            Old_Constraint := First_Elmt (Discriminant_Constraint (Old_Type));
+            while Present (Old_Constraint) loop
+               Expr := Node (Old_Constraint);
+
+               if Is_Discriminant (Expr) then
+                  Expr := Get_Value (Expr);
+               end if;
+
+               Append (New_Copy_Tree (Expr), To => Constr_List);
+
+               Next_Elmt (Old_Constraint);
+            end loop;
+
+            return Build_Subtype (Old_Type, Constr_List);
+
+         else
+            return Old_Type;
+         end if;
+      end Build_Constrained_Discriminated_Type;
+
+      -------------------
+      -- Build_Subtype --
+      -------------------
+
+      function Build_Subtype (T : Entity_Id; C : List_Id) return Entity_Id is
+         Indic       : Node_Id;
+         Subtyp_Decl : Node_Id;
+         Def_Id      : Entity_Id;
+         Btyp        : Entity_Id := Base_Type (T);
+
+      begin
+         --  The Related_Node better be here or else we won't be able
+         --  to attach new itypes to a node in the tree.
+
+         pragma Assert (Present (Related_Node));
+
+         --  If the view of the component's type is incomplete or private
+         --  with unknown discriminants, then the constraint must be applied
+         --  to the full type.
+
+         if Has_Unknown_Discriminants (Btyp)
+           and then Present (Underlying_Type (Btyp))
+         then
+            Btyp := Underlying_Type (Btyp);
+         end if;
+
+         Indic :=
+           Make_Subtype_Indication (Loc,
+             Subtype_Mark => New_Occurrence_Of (Btyp, Loc),
+             Constraint   => Make_Index_Or_Discriminant_Constraint (Loc, C));
+
+         Def_Id := Create_Itype (Ekind (T), Related_Node);
+
+         Subtyp_Decl :=
+           Make_Subtype_Declaration (Loc,
+             Defining_Identifier => Def_Id,
+             Subtype_Indication  => Indic);
+         Set_Parent (Subtyp_Decl, Parent (Related_Node));
+
+         --  Itypes must be analyzed with checks off (see itypes.ads).
+
+         Analyze (Subtyp_Decl, Suppress => All_Checks);
+
+         return Def_Id;
+      end Build_Subtype;
+
+      ---------------
+      -- Get_Value --
+      ---------------
+
+      function Get_Value (Discrim : Entity_Id) return Node_Id is
+         D : Entity_Id := First_Discriminant (Typ);
+         E : Elmt_Id   := First_Elmt (Constraints);
+
+      begin
+         while Present (D) loop
+
+            --  If we are constraining the subtype of a derived tagged type,
+            --  recover the discriminant of the parent, which appears in
+            --  the constraint of an inherited component.
+
+            if D = Entity (Discrim)
+              or else Corresponding_Discriminant (D) = Entity (Discrim)
+            then
+               return Node (E);
+            end if;
+
+            Next_Discriminant (D);
+            Next_Elmt (E);
+         end loop;
+
+         --  Something is wrong if we did not find the value
+
+         raise Program_Error;
+      end Get_Value;
+
+      ---------------------
+      -- Is_Discriminant --
+      ---------------------
+
+      function Is_Discriminant (Expr : Node_Id) return Boolean is
+         Discrim_Scope : Entity_Id;
+
+      begin
+         if Denotes_Discriminant (Expr) then
+            Discrim_Scope := Scope (Entity (Expr));
+
+            --  Either we have a reference to one of Typ's discriminants,
+
+            pragma Assert (Discrim_Scope = Typ
+
+               --  or to the discriminants of the parent type, in the case
+               --  of a derivation of a tagged type with variants.
+
+               or else Discrim_Scope = Etype (Typ)
+               or else Full_View (Discrim_Scope) = Etype (Typ)
+
+               --  or same as above for the case where the discriminants
+               --  were declared in Typ's private view.
+
+               or else (Is_Private_Type (Discrim_Scope)
+                        and then Chars (Discrim_Scope) = Chars (Typ))
+
+               --  or else we are deriving from the full view and the
+               --  discriminant is declared in the private entity.
+
+               or else (Is_Private_Type (Typ)
+                        and then Chars (Discrim_Scope) = Chars (Typ))
+
+               --  or we have a class-wide type, in which case make sure the
+               --  discriminant found belongs to the root type.
+
+               or else (Is_Class_Wide_Type (Typ)
+                        and then Etype (Typ) = Discrim_Scope));
+
+            return True;
+         end if;
+
+         --  In all other cases we have something wrong.
+
+         return False;
+      end Is_Discriminant;
+
+   --  Start of processing for Constrain_Component_Type
+
+   begin
+      if Is_Array_Type (Compon_Type) then
+         return Build_Constrained_Array_Type (Compon_Type);
+
+      elsif Has_Discriminants (Compon_Type) then
+         return Build_Constrained_Discriminated_Type (Compon_Type);
+
+      elsif Is_Access_Type (Compon_Type) then
+         return Build_Constrained_Access_Type (Compon_Type);
+      end if;
+
+      return Compon_Type;
+   end Constrain_Component_Type;
+
+   --------------------------
+   -- Constrain_Concurrent --
+   --------------------------
+
+   --  For concurrent types, the associated record value type carries the same
+   --  discriminants, so when we constrain a concurrent type, we must constrain
+   --  the value type as well.
+
+   procedure Constrain_Concurrent
+     (Def_Id      : in out Entity_Id;
+      SI          : Node_Id;
+      Related_Nod : Node_Id;
+      Related_Id  : Entity_Id;
+      Suffix      : Character)
+   is
+      T_Ent : Entity_Id := Entity (Subtype_Mark (SI));
+      T_Val : Entity_Id;
+
+   begin
+      if Ekind (T_Ent) in Access_Kind then
+         T_Ent := Designated_Type (T_Ent);
+      end if;
+
+      T_Val := Corresponding_Record_Type (T_Ent);
+
+      if Present (T_Val) then
+
+         if No (Def_Id) then
+            Def_Id := Create_Itype (E_Void, Related_Nod, Related_Id, Suffix);
+         end if;
+
+         Constrain_Discriminated_Type (Def_Id, SI, Related_Nod);
+
+         Set_Depends_On_Private (Def_Id, Has_Private_Component (Def_Id));
+         Set_Corresponding_Record_Type (Def_Id,
+           Constrain_Corresponding_Record
+             (Def_Id, T_Val, Related_Nod, Related_Id));
+
+      else
+         --  If there is no associated record, expansion is disabled and this
+         --  is a generic context. Create a subtype in any case, so that
+         --  semantic analysis can proceed.
+
+         if No (Def_Id) then
+            Def_Id := Create_Itype (E_Void, Related_Nod, Related_Id, Suffix);
+         end if;
+
+         Constrain_Discriminated_Type (Def_Id, SI, Related_Nod);
+      end if;
+   end Constrain_Concurrent;
+
+   ------------------------------------
+   -- Constrain_Corresponding_Record --
+   ------------------------------------
+
+   function Constrain_Corresponding_Record
+     (Prot_Subt   : Entity_Id;
+      Corr_Rec    : Entity_Id;
+      Related_Nod : Node_Id;
+      Related_Id  : Entity_Id)
+      return Entity_Id
+   is
+      T_Sub : constant Entity_Id
+        := Create_Itype (E_Record_Subtype, Related_Nod, Related_Id, 'V');
+
+   begin
+      Set_Etype                   (T_Sub, Corr_Rec);
+      Init_Size_Align             (T_Sub);
+      Set_Has_Discriminants       (T_Sub, Has_Discriminants (Prot_Subt));
+      Set_Is_Constrained          (T_Sub, True);
+      Set_First_Entity            (T_Sub, First_Entity (Corr_Rec));
+      Set_Last_Entity             (T_Sub, Last_Entity  (Corr_Rec));
+
+      Conditional_Delay (T_Sub, Corr_Rec);
+
+      if Has_Discriminants (Prot_Subt) then -- False only if errors.
+         Set_Discriminant_Constraint (T_Sub,
+                                      Discriminant_Constraint (Prot_Subt));
+         Set_Girder_Constraint_From_Discriminant_Constraint (T_Sub);
+         Create_Constrained_Components (T_Sub, Related_Nod, Corr_Rec,
+                                        Discriminant_Constraint (T_Sub));
+      end if;
+
+      Set_Depends_On_Private      (T_Sub, Has_Private_Component (T_Sub));
+
+      return T_Sub;
+   end Constrain_Corresponding_Record;
+
+   -----------------------
+   -- Constrain_Decimal --
+   -----------------------
+
+   procedure Constrain_Decimal
+     (Def_Id      : Node_Id;
+      S           : Node_Id;
+      Related_Nod : Node_Id)
+   is
+      T           : constant Entity_Id  := Entity (Subtype_Mark (S));
+      C           : constant Node_Id    := Constraint (S);
+      Loc         : constant Source_Ptr := Sloc (C);
+      Range_Expr  : Node_Id;
+      Digits_Expr : Node_Id;
+      Digits_Val  : Uint;
+      Bound_Val   : Ureal;
+
+   begin
+      Set_Ekind (Def_Id, E_Decimal_Fixed_Point_Subtype);
+
+      if Nkind (C) = N_Range_Constraint then
+         Range_Expr := Range_Expression (C);
+         Digits_Val := Digits_Value (T);
+
+      else
+         pragma Assert (Nkind (C) = N_Digits_Constraint);
+         Digits_Expr := Digits_Expression (C);
+         Analyze_And_Resolve (Digits_Expr, Any_Integer);
+
+         Check_Digits_Expression (Digits_Expr);
+         Digits_Val := Expr_Value (Digits_Expr);
+
+         if Digits_Val > Digits_Value (T) then
+            Error_Msg_N
+               ("digits expression is incompatible with subtype", C);
+            Digits_Val := Digits_Value (T);
+         end if;
+
+         if Present (Range_Constraint (C)) then
+            Range_Expr := Range_Expression (Range_Constraint (C));
+         else
+            Range_Expr := Empty;
+         end if;
+      end if;
+
+      Set_Etype            (Def_Id, Base_Type        (T));
+      Set_Size_Info        (Def_Id,                  (T));
+      Set_First_Rep_Item   (Def_Id, First_Rep_Item   (T));
+      Set_Delta_Value      (Def_Id, Delta_Value      (T));
+      Set_Scale_Value      (Def_Id, Scale_Value      (T));
+      Set_Small_Value      (Def_Id, Small_Value      (T));
+      Set_Machine_Radix_10 (Def_Id, Machine_Radix_10 (T));
+      Set_Digits_Value     (Def_Id, Digits_Val);
+
+      --  Manufacture range from given digits value if no range present
+
+      if No (Range_Expr) then
+         Bound_Val := (Ureal_10 ** Digits_Val - Ureal_1) * Small_Value (T);
+         Range_Expr :=
+            Make_Range (Loc,
+               Low_Bound =>
+                 Convert_To (T, Make_Real_Literal (Loc, (-Bound_Val))),
+               High_Bound =>
+                 Convert_To (T, Make_Real_Literal (Loc, Bound_Val)));
+
+      end if;
+
+      Set_Scalar_Range_For_Subtype (Def_Id, Range_Expr, T, Related_Nod);
+      Set_Discrete_RM_Size (Def_Id);
+
+      --  Unconditionally delay the freeze, since we cannot set size
+      --  information in all cases correctly until the freeze point.
+
+      Set_Has_Delayed_Freeze (Def_Id);
+   end Constrain_Decimal;
+
+   ----------------------------------
+   -- Constrain_Discriminated_Type --
+   ----------------------------------
+
+   procedure Constrain_Discriminated_Type
+     (Def_Id      : Entity_Id;
+      S           : Node_Id;
+      Related_Nod : Node_Id;
+      For_Access  : Boolean := False)
+   is
+      T     : Entity_Id;
+      C     : Node_Id;
+      Elist : Elist_Id := New_Elmt_List;
+
+      procedure Fixup_Bad_Constraint;
+      --  This is called after finding a bad constraint, and after having
+      --  posted an appropriate error message. The mission is to leave the
+      --  entity T in as reasonable state as possible!
+
+      procedure Fixup_Bad_Constraint is
+      begin
+         --  Set a reasonable Ekind for the entity. For an incomplete type,
+         --  we can't do much, but for other types, we can set the proper
+         --  corresponding subtype kind.
+
+         if Ekind (T) = E_Incomplete_Type then
+            Set_Ekind (Def_Id, Ekind (T));
+         else
+            Set_Ekind (Def_Id, Subtype_Kind (Ekind (T)));
+         end if;
+
+         Set_Etype (Def_Id, Any_Type);
+         Set_Error_Posted (Def_Id);
+      end Fixup_Bad_Constraint;
+
+   --  Start of processing for Constrain_Discriminated_Type
+
+   begin
+      C := Constraint (S);
+
+      --  A discriminant constraint is only allowed in a subtype indication,
+      --  after a subtype mark. This subtype mark must denote either a type
+      --  with discriminants, or an access type whose designated type is a
+      --  type with discriminants. A discriminant constraint specifies the
+      --  values of these discriminants (RM 3.7.2(5)).
+
+      T := Base_Type (Entity (Subtype_Mark (S)));
+
+      if Ekind (T) in Access_Kind then
+         T := Designated_Type (T);
+      end if;
+
+      if not Has_Discriminants (T) then
+         Error_Msg_N ("invalid constraint: type has no discriminant", C);
+         Fixup_Bad_Constraint;
+         return;
+
+      elsif Is_Constrained (Entity (Subtype_Mark (S))) then
+         Error_Msg_N ("type is already constrained", Subtype_Mark (S));
+         Fixup_Bad_Constraint;
+         return;
+      end if;
+
+      --  T may be an unconstrained subtype (e.g. a generic actual).
+      --  Constraint applies to the base type.
+
+      T := Base_Type (T);
+
+      Elist := Build_Discriminant_Constraints (T, S);
+
+      --  If the list returned was empty we had an error in building the
+      --  discriminant constraint. We have also already signalled an error
+      --  in the incomplete type case
+
+      if Is_Empty_Elmt_List (Elist) then
+         Fixup_Bad_Constraint;
+         return;
+      end if;
+
+      Build_Discriminated_Subtype (T, Def_Id, Elist, Related_Nod, For_Access);
+   end Constrain_Discriminated_Type;
+
+   ---------------------------
+   -- Constrain_Enumeration --
+   ---------------------------
+
+   procedure Constrain_Enumeration
+     (Def_Id      : Node_Id;
+      S           : Node_Id;
+      Related_Nod : Node_Id)
+   is
+      T : constant Entity_Id := Entity (Subtype_Mark (S));
+      C : constant Node_Id   := Constraint (S);
+
+   begin
+      Set_Ekind (Def_Id, E_Enumeration_Subtype);
+
+      Set_First_Literal     (Def_Id, First_Literal (Base_Type (T)));
+
+      Set_Etype             (Def_Id, Base_Type         (T));
+      Set_Size_Info         (Def_Id,                   (T));
+      Set_First_Rep_Item    (Def_Id, First_Rep_Item    (T));
+      Set_Is_Character_Type (Def_Id, Is_Character_Type (T));
+
+      Set_Scalar_Range_For_Subtype
+        (Def_Id, Range_Expression (C), T, Related_Nod);
+
+      Set_Discrete_RM_Size (Def_Id);
+
+   end Constrain_Enumeration;
+
+   ----------------------
+   -- Constrain_Float --
+   ----------------------
+
+   procedure Constrain_Float
+     (Def_Id      : Node_Id;
+      S           : Node_Id;
+      Related_Nod : Node_Id)
+   is
+      T    : constant Entity_Id := Entity (Subtype_Mark (S));
+      C    : Node_Id;
+      D    : Node_Id;
+      Rais : Node_Id;
+
+   begin
+      Set_Ekind (Def_Id, E_Floating_Point_Subtype);
+
+      Set_Etype          (Def_Id, Base_Type      (T));
+      Set_Size_Info      (Def_Id,                (T));
+      Set_First_Rep_Item (Def_Id, First_Rep_Item (T));
+
+      --  Process the constraint
+
+      C := Constraint (S);
+
+      --  Digits constraint present
+
+      if Nkind (C) = N_Digits_Constraint then
+         D := Digits_Expression (C);
+         Analyze_And_Resolve (D, Any_Integer);
+         Check_Digits_Expression (D);
+         Set_Digits_Value (Def_Id, Expr_Value (D));
+
+         --  Check that digits value is in range. Obviously we can do this
+         --  at compile time, but it is strictly a runtime check, and of
+         --  course there is an ACVC test that checks this!
+
+         if Digits_Value (Def_Id) > Digits_Value (T) then
+            Error_Msg_Uint_1 := Digits_Value (T);
+            Error_Msg_N ("?digits value is too large, maximum is ^", D);
+            Rais := Make_Raise_Constraint_Error (Sloc (D));
+            Insert_Action (Declaration_Node (Def_Id), Rais);
+         end if;
+
+         C := Range_Constraint (C);
+
+      --  No digits constraint present
+
+      else
+         Set_Digits_Value (Def_Id, Digits_Value (T));
+      end if;
+
+      --  Range constraint present
+
+      if Nkind (C) = N_Range_Constraint then
+         Set_Scalar_Range_For_Subtype
+           (Def_Id, Range_Expression (C), T, Related_Nod);
+
+      --  No range constraint present
+
+      else
+         pragma Assert (No (C));
+         Set_Scalar_Range (Def_Id, Scalar_Range (T));
+      end if;
+
+      Set_Is_Constrained (Def_Id);
+   end Constrain_Float;
+
+   ---------------------
+   -- Constrain_Index --
+   ---------------------
+
+   procedure Constrain_Index
+     (Index        : Node_Id;
+      S            : Node_Id;
+      Related_Nod  : Node_Id;
+      Related_Id   : Entity_Id;
+      Suffix       : Character;
+      Suffix_Index : Nat)
+   is
+      Def_Id     : Entity_Id;
+      R          : Node_Id;
+      Checks_Off : Boolean := False;
+      T          : constant Entity_Id := Etype (Index);
+
+   begin
+      if Nkind (S) = N_Range
+        or else Nkind (S) = N_Attribute_Reference
+      then
+         --  A Range attribute will transformed into N_Range by Resolve.
+
+         Analyze (S);
+         Set_Etype (S, T);
+         R := S;
+
+         --  ??? Why on earth do we turn checks of in this very specific case ?
+
+         --  From the revision history: (Constrain_Index): Call
+         --  Process_Range_Expr_In_Decl with range checking off for range
+         --  bounds that are attributes. This avoids some horrible
+         --  constraint error checks.
+
+         if Nkind (R) = N_Range
+           and then Nkind (Low_Bound (R)) = N_Attribute_Reference
+           and then Nkind (High_Bound (R)) = N_Attribute_Reference
+         then
+            Checks_Off := True;
+         end if;
+
+         Process_Range_Expr_In_Decl
+           (R, T, Related_Nod, Empty_List, Checks_Off);
+
+         if not Error_Posted (S)
+           and then
+             (Nkind (S) /= N_Range
+               or else Base_Type (T) /= Base_Type (Etype (Low_Bound (S)))
+               or else Base_Type (T) /= Base_Type (Etype (High_Bound (S))))
+         then
+            if Base_Type (T) /= Any_Type
+              and then Etype (Low_Bound (S)) /= Any_Type
+              and then Etype (High_Bound (S)) /= Any_Type
+            then
+               Error_Msg_N ("range expected", S);
+            end if;
+         end if;
+
+      elsif Nkind (S) = N_Subtype_Indication then
+         --  the parser has verified that this is a discrete indication.
+
+         Resolve_Discrete_Subtype_Indication (S, T);
+         R := Range_Expression (Constraint (S));
+
+      elsif Nkind (S) = N_Discriminant_Association then
+
+         --  syntactically valid in subtype indication.
+
+         Error_Msg_N ("invalid index constraint", S);
+         Rewrite (S, New_Occurrence_Of (T, Sloc (S)));
+         return;
+
+      --  Subtype_Mark case, no anonymous subtypes to construct
+
+      else
+         Analyze (S);
+
+         if Is_Entity_Name (S) then
+
+            if not Is_Type (Entity (S)) then
+               Error_Msg_N ("expect subtype mark for index constraint", S);
+
+            elsif Base_Type (Entity (S)) /= Base_Type (T) then
+               Wrong_Type (S, Base_Type (T));
+            end if;
+
+            return;
+
+         else
+            Error_Msg_N ("invalid index constraint", S);
+            Rewrite (S, New_Occurrence_Of (T, Sloc (S)));
+            return;
+         end if;
+      end if;
+
+      Def_Id :=
+        Create_Itype (E_Void, Related_Nod, Related_Id, Suffix, Suffix_Index);
+
+      Set_Etype (Def_Id, Base_Type (T));
+
+      if Is_Modular_Integer_Type (T) then
+         Set_Ekind (Def_Id, E_Modular_Integer_Subtype);
+
+      elsif Is_Integer_Type (T) then
+         Set_Ekind (Def_Id, E_Signed_Integer_Subtype);
+
+      else
+         Set_Ekind (Def_Id, E_Enumeration_Subtype);
+         Set_Is_Character_Type (Def_Id, Is_Character_Type (T));
+      end if;
+
+      Set_Size_Info      (Def_Id,                (T));
+      Set_RM_Size        (Def_Id, RM_Size        (T));
+      Set_First_Rep_Item (Def_Id, First_Rep_Item (T));
+
+      --  ??? ??? is R always initialized, not at all obvious why?
+
+      Set_Scalar_Range   (Def_Id, R);
+
+      Set_Etype (S, Def_Id);
+      Set_Discrete_RM_Size (Def_Id);
+   end Constrain_Index;
+
+   -----------------------
+   -- Constrain_Integer --
+   -----------------------
+
+   procedure Constrain_Integer
+     (Def_Id      : Node_Id;
+      S           : Node_Id;
+      Related_Nod : Node_Id)
+   is
+      T : constant Entity_Id := Entity (Subtype_Mark (S));
+      C : constant Node_Id   := Constraint (S);
+
+   begin
+      Set_Scalar_Range_For_Subtype
+        (Def_Id, Range_Expression (C), T, Related_Nod);
+
+      if Is_Modular_Integer_Type (T) then
+         Set_Ekind (Def_Id, E_Modular_Integer_Subtype);
+      else
+         Set_Ekind (Def_Id, E_Signed_Integer_Subtype);
+      end if;
+
+      Set_Etype            (Def_Id, Base_Type        (T));
+      Set_Size_Info        (Def_Id,                  (T));
+      Set_First_Rep_Item   (Def_Id, First_Rep_Item   (T));
+      Set_Discrete_RM_Size (Def_Id);
+
+   end Constrain_Integer;
+
+   ------------------------------
+   -- Constrain_Ordinary_Fixed --
+   ------------------------------
+
+   procedure Constrain_Ordinary_Fixed
+     (Def_Id      : Node_Id;
+      S           : Node_Id;
+      Related_Nod : Node_Id)
+   is
+      T    : constant Entity_Id := Entity (Subtype_Mark (S));
+      C    : Node_Id;
+      D    : Node_Id;
+      Rais : Node_Id;
+
+   begin
+      Set_Ekind          (Def_Id, E_Ordinary_Fixed_Point_Subtype);
+      Set_Etype          (Def_Id, Base_Type        (T));
+      Set_Size_Info      (Def_Id,                  (T));
+      Set_First_Rep_Item (Def_Id, First_Rep_Item   (T));
+      Set_Small_Value    (Def_Id, Small_Value      (T));
+
+      --  Process the constraint
+
+      C := Constraint (S);
+
+      --  Delta constraint present
+
+      if Nkind (C) = N_Delta_Constraint then
+         D := Delta_Expression (C);
+         Analyze_And_Resolve (D, Any_Real);
+         Check_Delta_Expression (D);
+         Set_Delta_Value (Def_Id, Expr_Value_R (D));
+
+         --  Check that delta value is in range. Obviously we can do this
+         --  at compile time, but it is strictly a runtime check, and of
+         --  course there is an ACVC test that checks this!
+
+         if Delta_Value (Def_Id) < Delta_Value (T) then
+            Error_Msg_N ("?delta value is too small", D);
+            Rais := Make_Raise_Constraint_Error (Sloc (D));
+            Insert_Action (Declaration_Node (Def_Id), Rais);
+         end if;
+
+         C := Range_Constraint (C);
+
+      --  No delta constraint present
+
+      else
+         Set_Delta_Value (Def_Id, Delta_Value (T));
+      end if;
+
+      --  Range constraint present
+
+      if Nkind (C) = N_Range_Constraint then
+         Set_Scalar_Range_For_Subtype
+           (Def_Id, Range_Expression (C), T, Related_Nod);
+
+      --  No range constraint present
+
+      else
+         pragma Assert (No (C));
+         Set_Scalar_Range (Def_Id, Scalar_Range (T));
+
+      end if;
+
+      Set_Discrete_RM_Size (Def_Id);
+
+      --  Unconditionally delay the freeze, since we cannot set size
+      --  information in all cases correctly until the freeze point.
+
+      Set_Has_Delayed_Freeze (Def_Id);
+   end Constrain_Ordinary_Fixed;
+
+   ---------------------------
+   -- Convert_Scalar_Bounds --
+   ---------------------------
+
+   procedure Convert_Scalar_Bounds
+     (N            : Node_Id;
+      Parent_Type  : Entity_Id;
+      Derived_Type : Entity_Id;
+      Loc          : Source_Ptr)
+   is
+      Implicit_Base : constant Entity_Id := Base_Type (Derived_Type);
+
+      Lo  : Node_Id;
+      Hi  : Node_Id;
+      Rng : Node_Id;
+
+   begin
+      Lo := Build_Scalar_Bound
+              (Type_Low_Bound (Derived_Type),
+               Parent_Type, Implicit_Base, Loc);
+
+      Hi := Build_Scalar_Bound
+              (Type_High_Bound (Derived_Type),
+               Parent_Type, Implicit_Base, Loc);
+
+      Rng :=
+        Make_Range (Loc,
+          Low_Bound  => Lo,
+          High_Bound => Hi);
+
+      Set_Includes_Infinities (Rng, Has_Infinities (Derived_Type));
+
+      Set_Parent (Rng, N);
+      Set_Scalar_Range (Derived_Type, Rng);
+
+      --  Analyze the bounds
+
+      Analyze_And_Resolve (Lo, Implicit_Base);
+      Analyze_And_Resolve (Hi, Implicit_Base);
+
+      --  Analyze the range itself, except that we do not analyze it if
+      --  the bounds are real literals, and we have a fixed-point type.
+      --  The reason for this is that we delay setting the bounds in this
+      --  case till we know the final Small and Size values (see circuit
+      --  in Freeze.Freeze_Fixed_Point_Type for further details).
+
+      if Is_Fixed_Point_Type (Parent_Type)
+        and then Nkind (Lo) = N_Real_Literal
+        and then Nkind (Hi) = N_Real_Literal
+      then
+         return;
+
+      --  Here we do the analysis of the range.
+
+      --  Note: we do this manually, since if we do a normal Analyze and
+      --  Resolve call, there are problems with the conversions used for
+      --  the derived type range.
+
+      else
+         Set_Etype    (Rng, Implicit_Base);
+         Set_Analyzed (Rng, True);
+      end if;
+   end Convert_Scalar_Bounds;
+
+   -------------------
+   -- Copy_And_Swap --
+   -------------------
+
+   procedure Copy_And_Swap (Privat, Full : Entity_Id) is
+   begin
+      --  Initialize new full declaration entity by copying the pertinent
+      --  fields of the corresponding private declaration entity.
+
+      Copy_Private_To_Full (Privat, Full);
+
+      --  Swap the two entities. Now Privat is the full type entity and
+      --  Full is the private one. They will be swapped back at the end
+      --  of the private part. This swapping ensures that the entity that
+      --  is visible in the private part is the full declaration.
+
+      Exchange_Entities (Privat, Full);
+      Append_Entity (Full, Scope (Full));
+   end Copy_And_Swap;
+
+   -------------------------------------
+   -- Copy_Array_Base_Type_Attributes --
+   -------------------------------------
+
+   procedure Copy_Array_Base_Type_Attributes (T1, T2 : Entity_Id) is
+   begin
+      Set_Component_Alignment      (T1, Component_Alignment      (T2));
+      Set_Component_Type           (T1, Component_Type           (T2));
+      Set_Component_Size           (T1, Component_Size           (T2));
+      Set_Has_Controlled_Component (T1, Has_Controlled_Component (T2));
+      Set_Finalize_Storage_Only    (T1, Finalize_Storage_Only    (T2));
+      Set_Has_Non_Standard_Rep     (T1, Has_Non_Standard_Rep     (T2));
+      Set_Has_Task                 (T1, Has_Task                 (T2));
+      Set_Is_Packed                (T1, Is_Packed                (T2));
+      Set_Has_Aliased_Components   (T1, Has_Aliased_Components   (T2));
+      Set_Has_Atomic_Components    (T1, Has_Atomic_Components    (T2));
+      Set_Has_Volatile_Components  (T1, Has_Volatile_Components  (T2));
+   end Copy_Array_Base_Type_Attributes;
+
+   -----------------------------------
+   -- Copy_Array_Subtype_Attributes --
+   -----------------------------------
+
+   procedure Copy_Array_Subtype_Attributes (T1, T2 : Entity_Id) is
+   begin
+      Set_Size_Info (T1, T2);
+
+      Set_First_Index          (T1, First_Index           (T2));
+      Set_Is_Aliased           (T1, Is_Aliased            (T2));
+      Set_Is_Atomic            (T1, Is_Atomic             (T2));
+      Set_Is_Volatile          (T1, Is_Volatile           (T2));
+      Set_Is_Constrained       (T1, Is_Constrained        (T2));
+      Set_Depends_On_Private   (T1, Has_Private_Component (T2));
+      Set_First_Rep_Item       (T1, First_Rep_Item        (T2));
+      Set_Convention           (T1, Convention            (T2));
+      Set_Is_Limited_Composite (T1, Is_Limited_Composite  (T2));
+      Set_Is_Private_Composite (T1, Is_Private_Composite  (T2));
+   end Copy_Array_Subtype_Attributes;
+
+   --------------------------
+   -- Copy_Private_To_Full --
+   --------------------------
+
+   procedure Copy_Private_To_Full (Priv, Full : Entity_Id) is
+   begin
+      --  We temporarily set Ekind to a value appropriate for a type to
+      --  avoid assert failures in Einfo from checking for setting type
+      --  attributes on something that is not a type. Ekind (Priv) is an
+      --  appropriate choice, since it allowed the attributes to be set
+      --  in the first place. This Ekind value will be modified later.
+
+      Set_Ekind (Full, Ekind (Priv));
+
+      --  Also set Etype temporarily to Any_Type, again, in the absence
+      --  of errors, it will be properly reset, and if there are errors,
+      --  then we want a value of Any_Type to remain.
+
+      Set_Etype (Full, Any_Type);
+
+      --  Now start copying attributes
+
+      Set_Has_Discriminants          (Full, Has_Discriminants       (Priv));
+
+      if Has_Discriminants (Full) then
+         Set_Discriminant_Constraint (Full, Discriminant_Constraint (Priv));
+         Set_Girder_Constraint       (Full, Girder_Constraint       (Priv));
+      end if;
+
+      Set_Homonym                    (Full, Homonym                 (Priv));
+      Set_Is_Immediately_Visible     (Full, Is_Immediately_Visible  (Priv));
+      Set_Is_Public                  (Full, Is_Public               (Priv));
+      Set_Is_Pure                    (Full, Is_Pure                 (Priv));
+      Set_Is_Tagged_Type             (Full, Is_Tagged_Type          (Priv));
+
+      Conditional_Delay              (Full,                          Priv);
+
+      if Is_Tagged_Type (Full) then
+         Set_Primitive_Operations    (Full, Primitive_Operations    (Priv));
+
+         if Priv = Base_Type (Priv) then
+            Set_Class_Wide_Type      (Full, Class_Wide_Type         (Priv));
+         end if;
+      end if;
+
+      Set_Is_Volatile                (Full, Is_Volatile             (Priv));
+      Set_Scope                      (Full, Scope                   (Priv));
+      Set_Next_Entity                (Full, Next_Entity             (Priv));
+      Set_First_Entity               (Full, First_Entity            (Priv));
+      Set_Last_Entity                (Full, Last_Entity             (Priv));
+
+      --  If access types have been recorded for later handling, keep them
+      --  in the full view so that they get handled when the full view freeze
+      --  node is expanded.
+
+      if Present (Freeze_Node (Priv))
+        and then Present (Access_Types_To_Process (Freeze_Node (Priv)))
+      then
+         Ensure_Freeze_Node (Full);
+         Set_Access_Types_To_Process (Freeze_Node (Full),
+           Access_Types_To_Process (Freeze_Node (Priv)));
+      end if;
+   end Copy_Private_To_Full;
+
+   -----------------------------------
+   -- Create_Constrained_Components --
+   -----------------------------------
+
+   procedure Create_Constrained_Components
+     (Subt        : Entity_Id;
+      Decl_Node   : Node_Id;
+      Typ         : Entity_Id;
+      Constraints : Elist_Id)
+   is
+      Loc         : constant Source_Ptr := Sloc (Subt);
+      Assoc_List  : List_Id  := New_List;
+      Comp_List   : Elist_Id := New_Elmt_List;
+      Discr_Val   : Elmt_Id;
+      Errors      : Boolean;
+      New_C       : Entity_Id;
+      Old_C       : Entity_Id;
+      Is_Static   : Boolean := True;
+      Parent_Type : constant Entity_Id := Etype (Typ);
+
+      procedure Collect_Fixed_Components (Typ : Entity_Id);
+      --  Collect components of parent type that do not appear in a variant
+      --  part.
+
+      procedure Create_All_Components;
+      --  Iterate over Comp_List to create the components of the subtype.
+
+      function Create_Component (Old_Compon : Entity_Id) return Entity_Id;
+      --  Creates a new component from Old_Compon, coppying all the fields from
+      --  it, including its Etype, inserts the new component in the Subt entity
+      --  chain and returns the new component.
+
+      function Is_Variant_Record (T : Entity_Id) return Boolean;
+      --  If true, and discriminants are static, collect only components from
+      --  variants selected by discriminant values.
+
+      ------------------------------
+      -- Collect_Fixed_Components --
+      ------------------------------
+
+      procedure Collect_Fixed_Components (Typ : Entity_Id) is
+      begin
+      --   Build association list for discriminants, and find components of
+      --  the variant part selected by the values of the discriminants.
+
+         Old_C := First_Discriminant (Typ);
+         Discr_Val := First_Elmt (Constraints);
+
+         while Present (Old_C) loop
+            Append_To (Assoc_List,
+              Make_Component_Association (Loc,
+                 Choices    => New_List (New_Occurrence_Of (Old_C, Loc)),
+                 Expression => New_Copy (Node (Discr_Val))));
+
+            Next_Elmt (Discr_Val);
+            Next_Discriminant (Old_C);
+         end loop;
+
+         --  The tag, and the possible parent and controller components
+         --  are unconditionally in the subtype.
+
+         if Is_Tagged_Type (Typ)
+           or else Has_Controlled_Component (Typ)
+         then
+            Old_C := First_Component (Typ);
+
+            while Present (Old_C) loop
+               if Chars ((Old_C)) = Name_uTag
+                 or else Chars ((Old_C)) = Name_uParent
+                 or else Chars ((Old_C)) = Name_uController
+               then
+                  Append_Elmt (Old_C, Comp_List);
+               end if;
+
+               Next_Component (Old_C);
+            end loop;
+         end if;
+      end Collect_Fixed_Components;
+
+      ---------------------------
+      -- Create_All_Components --
+      ---------------------------
+
+      procedure Create_All_Components is
+         Comp : Elmt_Id;
+
+      begin
+         Comp := First_Elmt (Comp_List);
+
+         while Present (Comp) loop
+            Old_C := Node (Comp);
+            New_C := Create_Component (Old_C);
+
+            Set_Etype
+              (New_C,
+               Constrain_Component_Type
+                 (Etype (Old_C), Subt, Decl_Node, Typ, Constraints));
+            Set_Is_Public (New_C, Is_Public (Subt));
+
+            Next_Elmt (Comp);
+         end loop;
+      end Create_All_Components;
+
+      ----------------------
+      -- Create_Component --
+      ----------------------
+
+      function Create_Component (Old_Compon : Entity_Id) return Entity_Id is
+         New_Compon : Entity_Id := New_Copy (Old_Compon);
+
+      begin
+         --  Set the parent so we have a proper link for freezing etc. This
+         --  is not a real parent pointer, since of course our parent does
+         --  not own up to us and reference us, we are an illegitimate
+         --  child of the original parent!
+
+         Set_Parent (New_Compon, Parent (Old_Compon));
+
+         --  We do not want this node marked as Comes_From_Source, since
+         --  otherwise it would get first class status and a separate
+         --  cross-reference line would be generated. Illegitimate
+         --  children do not rate such recognition.
+
+         Set_Comes_From_Source (New_Compon, False);
+
+         --  But it is a real entity, and a birth certificate must be
+         --  properly registered by entering it into the entity list.
+
+         Enter_Name (New_Compon);
+         return New_Compon;
+      end Create_Component;
+
+      -----------------------
+      -- Is_Variant_Record --
+      -----------------------
+
+      function Is_Variant_Record (T : Entity_Id) return Boolean is
+      begin
+         return Nkind (Parent (T)) = N_Full_Type_Declaration
+           and then Nkind (Type_Definition (Parent (T))) = N_Record_Definition
+           and then Present (Component_List (Type_Definition (Parent (T))))
+           and then Present (
+             Variant_Part (Component_List (Type_Definition (Parent (T)))));
+      end Is_Variant_Record;
+
+   --  Start of processing for Create_Constrained_Components
+
+   begin
+      pragma Assert (Subt /= Base_Type (Subt));
+      pragma Assert (Typ = Base_Type (Typ));
+
+      Set_First_Entity (Subt, Empty);
+      Set_Last_Entity  (Subt, Empty);
+
+      --  Check whether constraint is fully static, in which case we can
+      --  optimize the list of components.
+
+      Discr_Val := First_Elmt (Constraints);
+
+      while Present (Discr_Val) loop
+
+         if not Is_OK_Static_Expression (Node (Discr_Val)) then
+            Is_Static := False;
+            exit;
+         end if;
+
+         Next_Elmt (Discr_Val);
+      end loop;
+
+      New_Scope (Subt);
+
+      --  Inherit the discriminants of the parent type.
+
+      Old_C := First_Discriminant (Typ);
+
+      while Present (Old_C) loop
+         New_C := Create_Component (Old_C);
+         Set_Is_Public (New_C, Is_Public (Subt));
+         Next_Discriminant (Old_C);
+      end loop;
+
+      if Is_Static
+        and then Is_Variant_Record (Typ)
+      then
+         Collect_Fixed_Components (Typ);
+
+         Gather_Components (
+           Typ,
+           Component_List (Type_Definition (Parent (Typ))),
+           Governed_By   => Assoc_List,
+           Into          => Comp_List,
+           Report_Errors => Errors);
+         pragma Assert (not Errors);
+
+         Create_All_Components;
+
+      --  If the subtype declaration is created for a tagged type derivation
+      --  with constraints, we retrieve the record definition of the parent
+      --  type to select the components of the proper variant.
+
+      elsif Is_Static
+        and then Is_Tagged_Type (Typ)
+        and then Nkind (Parent (Typ)) = N_Full_Type_Declaration
+        and then
+          Nkind (Type_Definition (Parent (Typ))) = N_Derived_Type_Definition
+        and then Is_Variant_Record (Parent_Type)
+      then
+         Collect_Fixed_Components (Typ);
+
+         Gather_Components (
+           Typ,
+           Component_List (Type_Definition (Parent (Parent_Type))),
+           Governed_By   => Assoc_List,
+           Into          => Comp_List,
+           Report_Errors => Errors);
+         pragma Assert (not Errors);
+
+         --  If the tagged derivation has a type extension, collect all the
+         --  new components therein.
+
+         if Present (
+           Record_Extension_Part (Type_Definition (Parent (Typ))))
+         then
+            Old_C := First_Component (Typ);
+
+            while Present (Old_C) loop
+               if Original_Record_Component (Old_C) = Old_C
+                and then Chars (Old_C) /= Name_uTag
+                and then Chars (Old_C) /= Name_uParent
+                and then Chars (Old_C) /= Name_uController
+               then
+                  Append_Elmt (Old_C, Comp_List);
+               end if;
+
+               Next_Component (Old_C);
+            end loop;
+         end if;
+
+         Create_All_Components;
+
+      else
+         --  If the discriminants are not static, or if this is a multi-level
+         --  type extension, we have to include all the components of the
+         --  parent type.
+
+         Old_C := First_Component (Typ);
+
+         while Present (Old_C) loop
+            New_C := Create_Component (Old_C);
+
+            Set_Etype
+              (New_C,
+               Constrain_Component_Type
+                 (Etype (Old_C), Subt, Decl_Node, Typ, Constraints));
+            Set_Is_Public (New_C, Is_Public (Subt));
+
+            Next_Component (Old_C);
+         end loop;
+      end if;
+
+      End_Scope;
+   end Create_Constrained_Components;
+
+   ------------------------------------------
+   -- Decimal_Fixed_Point_Type_Declaration --
+   ------------------------------------------
+
+   procedure Decimal_Fixed_Point_Type_Declaration
+     (T   : Entity_Id;
+      Def : Node_Id)
+   is
+      Loc           : constant Source_Ptr := Sloc (Def);
+      Digs_Expr     : constant Node_Id    := Digits_Expression (Def);
+      Delta_Expr    : constant Node_Id    := Delta_Expression (Def);
+      Implicit_Base : Entity_Id;
+      Digs_Val      : Uint;
+      Delta_Val     : Ureal;
+      Scale_Val     : Uint;
+      Bound_Val     : Ureal;
+
+   --  Start of processing for Decimal_Fixed_Point_Type_Declaration
+
+   begin
+      Check_Restriction (No_Fixed_Point, Def);
+
+      --  Create implicit base type
+
+      Implicit_Base :=
+        Create_Itype (E_Decimal_Fixed_Point_Type, Parent (Def), T, 'B');
+      Set_Etype (Implicit_Base, Implicit_Base);
+
+      --  Analyze and process delta expression
+
+      Analyze_And_Resolve (Delta_Expr, Universal_Real);
+
+      Check_Delta_Expression (Delta_Expr);
+      Delta_Val := Expr_Value_R (Delta_Expr);
+
+      --  Check delta is power of 10, and determine scale value from it
+
+      declare
+         Val : Ureal := Delta_Val;
+
+      begin
+         Scale_Val := Uint_0;
+
+         if Val < Ureal_1 then
+            while Val < Ureal_1 loop
+               Val := Val * Ureal_10;
+               Scale_Val := Scale_Val + 1;
+            end loop;
+
+            if Scale_Val > 18 then
+               Error_Msg_N ("scale exceeds maximum value of 18", Def);
+               Scale_Val := UI_From_Int (+18);
+            end if;
+
+         else
+            while Val > Ureal_1 loop
+               Val := Val / Ureal_10;
+               Scale_Val := Scale_Val - 1;
+            end loop;
+
+            if Scale_Val < -18 then
+               Error_Msg_N ("scale is less than minimum value of -18", Def);
+               Scale_Val := UI_From_Int (-18);
+            end if;
+         end if;
+
+         if Val /= Ureal_1 then
+            Error_Msg_N ("delta expression must be a power of 10", Def);
+            Delta_Val := Ureal_10 ** (-Scale_Val);
+         end if;
+      end;
+
+      --  Set delta, scale and small (small = delta for decimal type)
+
+      Set_Delta_Value (Implicit_Base, Delta_Val);
+      Set_Scale_Value (Implicit_Base, Scale_Val);
+      Set_Small_Value (Implicit_Base, Delta_Val);
+
+      --  Analyze and process digits expression
+
+      Analyze_And_Resolve (Digs_Expr, Any_Integer);
+      Check_Digits_Expression (Digs_Expr);
+      Digs_Val := Expr_Value (Digs_Expr);
+
+      if Digs_Val > 18 then
+         Digs_Val := UI_From_Int (+18);
+         Error_Msg_N ("digits value out of range, maximum is 18", Digs_Expr);
+      end if;
+
+      Set_Digits_Value (Implicit_Base, Digs_Val);
+      Bound_Val := UR_From_Uint (10 ** Digs_Val - 1) * Delta_Val;
+
+      --  Set range of base type from digits value for now. This will be
+      --  expanded to represent the true underlying base range by Freeze.
+
+      Set_Fixed_Range (Implicit_Base, Loc, -Bound_Val, Bound_Val);
+
+      --  Set size to zero for now, size will be set at freeze time. We have
+      --  to do this for ordinary fixed-point, because the size depends on
+      --  the specified small, and we might as well do the same for decimal
+      --  fixed-point.
+
+      Init_Size_Align (Implicit_Base);
+
+      --  Complete entity for first subtype
+
+      Set_Ekind          (T, E_Decimal_Fixed_Point_Subtype);
+      Set_Etype          (T, Implicit_Base);
+      Set_Size_Info      (T, Implicit_Base);
+      Set_First_Rep_Item (T, First_Rep_Item (Implicit_Base));
+      Set_Digits_Value   (T, Digs_Val);
+      Set_Delta_Value    (T, Delta_Val);
+      Set_Small_Value    (T, Delta_Val);
+      Set_Scale_Value    (T, Scale_Val);
+      Set_Is_Constrained (T);
+
+      --  If there are bounds given in the declaration use them as the
+      --  bounds of the first named subtype.
+
+      if Present (Real_Range_Specification (Def)) then
+         declare
+            RRS      : constant Node_Id := Real_Range_Specification (Def);
+            Low      : constant Node_Id := Low_Bound (RRS);
+            High     : constant Node_Id := High_Bound (RRS);
+            Low_Val  : Ureal;
+            High_Val : Ureal;
+
+         begin
+            Analyze_And_Resolve (Low, Any_Real);
+            Analyze_And_Resolve (High, Any_Real);
+            Check_Real_Bound (Low);
+            Check_Real_Bound (High);
+            Low_Val := Expr_Value_R (Low);
+            High_Val := Expr_Value_R (High);
+
+            if Low_Val < (-Bound_Val) then
+               Error_Msg_N
+                 ("range low bound too small for digits value", Low);
+               Low_Val := -Bound_Val;
+            end if;
+
+            if High_Val > Bound_Val then
+               Error_Msg_N
+                 ("range high bound too large for digits value", High);
+               High_Val := Bound_Val;
+            end if;
+
+            Set_Fixed_Range (T, Loc, Low_Val, High_Val);
+         end;
+
+      --  If no explicit range, use range that corresponds to given
+      --  digits value. This will end up as the final range for the
+      --  first subtype.
+
+      else
+         Set_Fixed_Range (T, Loc, -Bound_Val, Bound_Val);
+      end if;
+
+   end Decimal_Fixed_Point_Type_Declaration;
+
+   -----------------------
+   -- Derive_Subprogram --
+   -----------------------
+
+   procedure Derive_Subprogram
+     (New_Subp     : in out Entity_Id;
+      Parent_Subp  : Entity_Id;
+      Derived_Type : Entity_Id;
+      Parent_Type  : Entity_Id;
+      Actual_Subp  : Entity_Id := Empty)
+   is
+      Formal     : Entity_Id;
+      New_Formal : Entity_Id;
+      Same_Subt  : constant Boolean :=
+        Is_Scalar_Type (Parent_Type)
+          and then Subtypes_Statically_Compatible (Parent_Type, Derived_Type);
+
+      function Is_Private_Overriding return Boolean;
+      --  If Subp is a private overriding of a visible operation, the in-
+      --  herited operation derives from the overridden op (even though
+      --  its body is the overriding one) and the inherited operation is
+      --  visible now. See sem_disp to see the details of the handling of
+      --  the overridden subprogram, which is removed from the list of
+      --  primitive operations of the type.
+
+      procedure Replace_Type (Id, New_Id : Entity_Id);
+      --  When the type is an anonymous access type, create a new access type
+      --  designating the derived type.
+
+      ---------------------------
+      -- Is_Private_Overriding --
+      ---------------------------
+
+      function Is_Private_Overriding return Boolean is
+         Prev : Entity_Id;
+
+      begin
+         Prev := Homonym (Parent_Subp);
+
+         --  The visible operation that is overriden is a homonym of
+         --  the parent subprogram. We scan the homonym chain to find
+         --  the one whose alias is the subprogram we are deriving.
+
+         while Present (Prev) loop
+            if Is_Dispatching_Operation (Parent_Subp)
+              and then Present (Prev)
+              and then Ekind (Prev) = Ekind (Parent_Subp)
+              and then Alias (Prev) = Parent_Subp
+              and then Scope (Parent_Subp) = Scope (Prev)
+              and then not Is_Hidden (Prev)
+            then
+               return True;
+            end if;
+
+            Prev := Homonym (Prev);
+         end loop;
+
+         return False;
+      end Is_Private_Overriding;
+
+      ------------------
+      -- Replace_Type --
+      ------------------
+
+      procedure Replace_Type (Id, New_Id : Entity_Id) is
+         Acc_Type : Entity_Id;
+         IR       : Node_Id;
+
+      begin
+         --  When the type is an anonymous access type, create a new access
+         --  type designating the derived type. This itype must be elaborated
+         --  at the point of the derivation, not on subsequent calls that may
+         --  be out of the proper scope for Gigi, so we insert a reference to
+         --  it after the derivation.
+
+         if Ekind (Etype (Id)) = E_Anonymous_Access_Type then
+            declare
+               Desig_Typ : Entity_Id := Designated_Type (Etype (Id));
+
+            begin
+               if Ekind (Desig_Typ) = E_Record_Type_With_Private
+                 and then Present (Full_View (Desig_Typ))
+                 and then not Is_Private_Type (Parent_Type)
+               then
+                  Desig_Typ := Full_View (Desig_Typ);
+               end if;
+
+               if Base_Type (Desig_Typ) = Base_Type (Parent_Type) then
+                  Acc_Type := New_Copy (Etype (Id));
+                  Set_Etype (Acc_Type, Acc_Type);
+                  Set_Scope (Acc_Type, New_Subp);
+
+                  --  Compute size of anonymous access type.
+
+                  if Is_Array_Type (Desig_Typ)
+                    and then not Is_Constrained (Desig_Typ)
+                  then
+                     Init_Size (Acc_Type, 2 * System_Address_Size);
+                  else
+                     Init_Size (Acc_Type, System_Address_Size);
+                  end if;
+
+                  Init_Alignment (Acc_Type);
+
+                  Set_Directly_Designated_Type (Acc_Type, Derived_Type);
+
+                  Set_Etype (New_Id, Acc_Type);
+                  Set_Scope (New_Id, New_Subp);
+
+                  --  Create a reference to it.
+
+                  IR := Make_Itype_Reference (Sloc (Parent (Derived_Type)));
+                  Set_Itype (IR, Acc_Type);
+                  Insert_After (Parent (Derived_Type), IR);
+
+               else
+                  Set_Etype (New_Id, Etype (Id));
+               end if;
+            end;
+         elsif Base_Type (Etype (Id)) = Base_Type (Parent_Type)
+           or else
+             (Ekind (Etype (Id)) = E_Record_Type_With_Private
+               and then Present (Full_View (Etype (Id)))
+               and then Base_Type (Full_View (Etype (Id))) =
+                 Base_Type (Parent_Type))
+         then
+
+            --  Constraint checks on formals are generated during expansion,
+            --  based on the signature of the original subprogram. The bounds
+            --  of the derived type are not relevant, and thus we can use
+            --  the base type for the formals. However, the return type may be
+            --  used in a context that requires that the proper static bounds
+            --  be used (a case statement, for example)  and for those cases
+            --  we must use the derived type (first subtype), not its base.
+
+            if Etype (Id) = Parent_Type
+              and then Same_Subt
+            then
+               Set_Etype (New_Id, Derived_Type);
+            else
+               Set_Etype (New_Id, Base_Type (Derived_Type));
+            end if;
+
+         else
+            Set_Etype (New_Id, Etype (Id));
+         end if;
+      end Replace_Type;
+
+   --  Start of processing for Derive_Subprogram
+
+   begin
+      New_Subp :=
+         New_Entity (Nkind (Parent_Subp), Sloc (Derived_Type));
+      Set_Ekind (New_Subp, Ekind (Parent_Subp));
+
+      --  Check whether the inherited subprogram is a private operation that
+      --  should be inherited but not yet made visible. Such subprograms can
+      --  become visible at a later point (e.g., the private part of a public
+      --  child unit) via Declare_Inherited_Private_Subprograms. If the
+      --  following predicate is true, then this is not such a private
+      --  operation and the subprogram simply inherits the name of the parent
+      --  subprogram. Note the special check for the names of controlled
+      --  operations, which are currently exempted from being inherited with
+      --  a hidden name because they must be findable for generation of
+      --  implicit run-time calls.
+
+      if not Is_Hidden (Parent_Subp)
+        or else Is_Internal (Parent_Subp)
+        or else Is_Private_Overriding
+        or else Is_Internal_Name (Chars (Parent_Subp))
+        or else Chars (Parent_Subp) = Name_Initialize
+        or else Chars (Parent_Subp) = Name_Adjust
+        or else Chars (Parent_Subp) = Name_Finalize
+      then
+         Set_Chars (New_Subp, Chars (Parent_Subp));
+
+      --  If parent is hidden, this can be a regular derivation if the
+      --  parent is immediately visible in a non-instantiating context,
+      --  or if we are in the private part of an instance. This test
+      --  should still be refined ???
+
+      --  The test for In_Instance_Not_Visible avoids inheriting the
+      --  derived operation as a non-visible operation in cases where
+      --  the parent subprogram might not be visible now, but was
+      --  visible within the original generic, so it would be wrong
+      --  to make the inherited subprogram non-visible now. (Not
+      --  clear if this test is fully correct; are there any cases
+      --  where we should declare the inherited operation as not
+      --  visible to avoid it being overridden, e.g., when the
+      --  parent type is a generic actual with private primitives ???)
+
+      --  (they should be treated the same as other private inherited
+      --  subprograms, but it's not clear how to do this cleanly). ???
+
+      elsif (In_Open_Scopes (Scope (Base_Type (Parent_Type)))
+              and then Is_Immediately_Visible (Parent_Subp)
+              and then not In_Instance)
+        or else In_Instance_Not_Visible
+      then
+         Set_Chars (New_Subp, Chars (Parent_Subp));
+
+      --  The type is inheriting a private operation, so enter
+      --  it with a special name so it can't be overridden.
+
+      else
+         Set_Chars (New_Subp, New_External_Name (Chars (Parent_Subp), 'P'));
+      end if;
+
+      Set_Parent (New_Subp, Parent (Derived_Type));
+      Replace_Type (Parent_Subp, New_Subp);
+      Conditional_Delay (New_Subp, Parent_Subp);
+
+      Formal := First_Formal (Parent_Subp);
+      while Present (Formal) loop
+         New_Formal := New_Copy (Formal);
+
+         --  Normally we do not go copying parents, but in the case of
+         --  formals, we need to link up to the declaration (which is
+         --  the parameter specification), and it is fine to link up to
+         --  the original formal's parameter specification in this case.
+
+         Set_Parent (New_Formal, Parent (Formal));
+
+         Append_Entity (New_Formal, New_Subp);
+
+         Replace_Type (Formal, New_Formal);
+         Next_Formal (Formal);
+      end loop;
+
+      --  If this derivation corresponds to a tagged generic actual, then
+      --  primitive operations rename those of the actual. Otherwise the
+      --  primitive operations rename those of the parent type.
+
+      if No (Actual_Subp) then
+         Set_Alias (New_Subp, Parent_Subp);
+         Set_Is_Intrinsic_Subprogram (New_Subp,
+           Is_Intrinsic_Subprogram (Parent_Subp));
+
+      else
+         Set_Alias (New_Subp, Actual_Subp);
+      end if;
+
+      --  Derived subprograms of a tagged type must inherit the convention
+      --  of the parent subprogram (a requirement of AI-117). Derived
+      --  subprograms of untagged types simply get convention Ada by default.
+
+      if Is_Tagged_Type (Derived_Type) then
+         Set_Convention  (New_Subp, Convention  (Parent_Subp));
+      end if;
+
+      Set_Is_Imported (New_Subp, Is_Imported (Parent_Subp));
+      Set_Is_Exported (New_Subp, Is_Exported (Parent_Subp));
+
+      if Ekind (Parent_Subp) = E_Procedure then
+         Set_Is_Valued_Procedure
+           (New_Subp, Is_Valued_Procedure (Parent_Subp));
+      end if;
+
+      New_Overloaded_Entity (New_Subp, Derived_Type);
+
+      --  Check for case of a derived subprogram for the instantiation
+      --  of a formal derived tagged type, so mark the subprogram as
+      --  dispatching and inherit the dispatching attributes of the
+      --  parent subprogram. The derived subprogram is effectively a
+      --  renaming of the actual subprogram, so it needs to have the
+      --  same attributes as the actual.
+
+      if Present (Actual_Subp)
+        and then Is_Dispatching_Operation (Parent_Subp)
+      then
+         Set_Is_Dispatching_Operation (New_Subp);
+         if Present (DTC_Entity (Parent_Subp)) then
+            Set_DTC_Entity (New_Subp, DTC_Entity (Parent_Subp));
+            Set_DT_Position (New_Subp, DT_Position (Parent_Subp));
+         end if;
+      end if;
+
+      --  Indicate that a derived subprogram does not require a body
+      --  and that it does not require processing of default expressions.
+
+      Set_Has_Completion (New_Subp);
+      Set_Default_Expressions_Processed (New_Subp);
+
+      --  A derived function with a controlling result is abstract.
+      --  If the Derived_Type is a nonabstract formal generic derived
+      --  type, then inherited operations are not abstract: check is
+      --  done at instantiation time. If the derivation is for a generic
+      --  actual, the function is not abstract unless the actual is.
+
+      if Is_Generic_Type (Derived_Type)
+        and then not Is_Abstract (Derived_Type)
+      then
+         null;
+
+      elsif Is_Abstract (Alias (New_Subp))
+        or else (Is_Tagged_Type (Derived_Type)
+                   and then Etype (New_Subp) = Derived_Type
+                   and then No (Actual_Subp))
+      then
+         Set_Is_Abstract (New_Subp);
+      end if;
+
+      if Ekind (New_Subp) = E_Function then
+         Set_Mechanism (New_Subp, Mechanism (Parent_Subp));
+      end if;
+   end Derive_Subprogram;
+
+   ------------------------
+   -- Derive_Subprograms --
+   ------------------------
+
+   procedure Derive_Subprograms
+     (Parent_Type    : Entity_Id;
+      Derived_Type   : Entity_Id;
+      Generic_Actual : Entity_Id := Empty)
+   is
+      Op_List     : Elist_Id := Collect_Primitive_Operations (Parent_Type);
+      Act_List    : Elist_Id;
+      Act_Elmt    : Elmt_Id;
+      Elmt        : Elmt_Id;
+      Subp        : Entity_Id;
+      New_Subp    : Entity_Id := Empty;
+      Parent_Base : Entity_Id;
+
+   begin
+      if Ekind (Parent_Type) = E_Record_Type_With_Private
+        and then Has_Discriminants (Parent_Type)
+        and then Present (Full_View (Parent_Type))
+      then
+         Parent_Base := Full_View (Parent_Type);
+      else
+         Parent_Base := Parent_Type;
+      end if;
+
+      Elmt := First_Elmt (Op_List);
+
+      if Present (Generic_Actual) then
+         Act_List := Collect_Primitive_Operations (Generic_Actual);
+         Act_Elmt := First_Elmt (Act_List);
+      else
+         Act_Elmt := No_Elmt;
+      end if;
+
+      --  Literals are derived earlier in the process of building the
+      --  derived type, and are skipped here.
+
+      while Present (Elmt) loop
+         Subp := Node (Elmt);
+
+         if Ekind (Subp) /= E_Enumeration_Literal then
+            if No (Generic_Actual) then
+               Derive_Subprogram
+                 (New_Subp, Subp, Derived_Type, Parent_Base);
+
+            else
+               Derive_Subprogram (New_Subp, Subp,
+                 Derived_Type, Parent_Base, Node (Act_Elmt));
+               Next_Elmt (Act_Elmt);
+            end if;
+         end if;
+
+         Next_Elmt (Elmt);
+      end loop;
+   end Derive_Subprograms;
+
+   --------------------------------
+   -- Derived_Standard_Character --
+   --------------------------------
+
+   procedure Derived_Standard_Character
+     (N             : Node_Id;
+      Parent_Type   : Entity_Id;
+      Derived_Type  : Entity_Id)
+   is
+      Loc           : constant Source_Ptr := Sloc (N);
+      Def           : constant Node_Id    := Type_Definition (N);
+      Indic         : constant Node_Id    := Subtype_Indication (Def);
+      Parent_Base   : constant Entity_Id  := Base_Type (Parent_Type);
+      Implicit_Base : constant Entity_Id  :=
+                        Create_Itype
+                          (E_Enumeration_Type, N, Derived_Type, 'B');
+
+      Lo : Node_Id;
+      Hi : Node_Id;
+      T  : Entity_Id;
+
+   begin
+      T := Process_Subtype (Indic, N);
+
+      Set_Etype     (Implicit_Base, Parent_Base);
+      Set_Size_Info (Implicit_Base, Root_Type (Parent_Type));
+      Set_RM_Size   (Implicit_Base, RM_Size (Root_Type (Parent_Type)));
+
+      Set_Is_Character_Type  (Implicit_Base, True);
+      Set_Has_Delayed_Freeze (Implicit_Base);
+
+      Lo := New_Copy_Tree (Type_Low_Bound  (Parent_Type));
+      Hi := New_Copy_Tree (Type_High_Bound (Parent_Type));
+
+      Set_Scalar_Range (Implicit_Base,
+        Make_Range (Loc,
+          Low_Bound  => Lo,
+          High_Bound => Hi));
+
+      Conditional_Delay (Derived_Type, Parent_Type);
+
+      Set_Ekind (Derived_Type, E_Enumeration_Subtype);
+      Set_Etype (Derived_Type, Implicit_Base);
+      Set_Size_Info         (Derived_Type, Parent_Type);
+
+      if Unknown_RM_Size (Derived_Type) then
+         Set_RM_Size (Derived_Type, RM_Size (Parent_Type));
+      end if;
+
+      Set_Is_Character_Type (Derived_Type, True);
+
+      if Nkind (Indic) /= N_Subtype_Indication then
+         Set_Scalar_Range (Derived_Type, Scalar_Range (Implicit_Base));
+      end if;
+
+      Convert_Scalar_Bounds (N, Parent_Type, Derived_Type, Loc);
+
+      --  Because the implicit base is used in the conversion of the bounds,
+      --  we have to freeze it now. This is similar to what is done for
+      --  numeric types, and it equally suspicious, but otherwise a non-
+      --  static bound will have a reference to an unfrozen type, which is
+      --  rejected by Gigi (???).
+
+      Freeze_Before (N, Implicit_Base);
+
+   end Derived_Standard_Character;
+
+   ------------------------------
+   -- Derived_Type_Declaration --
+   ------------------------------
+
+   procedure Derived_Type_Declaration
+     (T             : Entity_Id;
+      N             : Node_Id;
+      Is_Completion : Boolean)
+   is
+      Def          : constant Node_Id := Type_Definition (N);
+      Indic        : constant Node_Id := Subtype_Indication (Def);
+      Extension    : constant Node_Id := Record_Extension_Part (Def);
+      Parent_Type  : Entity_Id;
+      Parent_Scope : Entity_Id;
+      Taggd        : Boolean;
+
+   begin
+      Parent_Type := Find_Type_Of_Subtype_Indic (Indic);
+
+      if Parent_Type = Any_Type
+        or else Etype (Parent_Type) = Any_Type
+        or else (Is_Class_Wide_Type (Parent_Type)
+                  and then Etype (Parent_Type) = T)
+      then
+         --  If Parent_Type is undefined or illegal, make new type into
+         --  a subtype of Any_Type, and set a few attributes to prevent
+         --  cascaded errors. If this is a self-definition, emit error now.
+
+         if T = Parent_Type
+           or else T = Etype (Parent_Type)
+         then
+            Error_Msg_N ("type cannot be used in its own definition", Indic);
+         end if;
+
+         Set_Ekind        (T, Ekind (Parent_Type));
+         Set_Etype        (T, Any_Type);
+         Set_Scalar_Range (T, Scalar_Range (Any_Type));
+
+         if Is_Tagged_Type (T) then
+            Set_Primitive_Operations (T, New_Elmt_List);
+         end if;
+         return;
+
+      elsif Is_Unchecked_Union (Parent_Type) then
+         Error_Msg_N ("cannot derive from Unchecked_Union type", N);
+      end if;
+
+      --  Only composite types other than array types are allowed to have
+      --  discriminants.
+
+      if Present (Discriminant_Specifications (N))
+        and then (Is_Elementary_Type (Parent_Type)
+                  or else Is_Array_Type (Parent_Type))
+        and then not Error_Posted (N)
+      then
+         Error_Msg_N
+           ("elementary or array type cannot have discriminants",
+            Defining_Identifier (First (Discriminant_Specifications (N))));
+         Set_Has_Discriminants (T, False);
+      end if;
+
+      --  In Ada 83, a derived type defined in a package specification cannot
+      --  be used for further derivation until the end of its visible part.
+      --  Note that derivation in the private part of the package is allowed.
+
+      if Ada_83
+        and then Is_Derived_Type (Parent_Type)
+        and then In_Visible_Part (Scope (Parent_Type))
+      then
+         if Ada_83 and then Comes_From_Source (Indic) then
+            Error_Msg_N
+              ("(Ada 83): premature use of type for derivation", Indic);
+         end if;
+      end if;
+
+      --  Check for early use of incomplete or private type
+
+      if Ekind (Parent_Type) = E_Void
+        or else Ekind (Parent_Type) = E_Incomplete_Type
+      then
+         Error_Msg_N ("premature derivation of incomplete type", Indic);
+         return;
+
+      elsif (Is_Incomplete_Or_Private_Type (Parent_Type)
+              and then not Is_Generic_Type (Parent_Type)
+              and then not Is_Generic_Type (Root_Type (Parent_Type))
+              and then not Is_Generic_Actual_Type (Parent_Type))
+        or else Has_Private_Component (Parent_Type)
+      then
+         --  The ancestor type of a formal type can be incomplete, in which
+         --  case only the operations of the partial view are available in
+         --  the generic. Subsequent checks may be required when the full
+         --  view is analyzed, to verify that derivation from a tagged type
+         --  has an extension.
+
+         if Nkind (Original_Node (N)) = N_Formal_Type_Declaration then
+            null;
+
+         elsif No (Underlying_Type (Parent_Type))
+           or else Has_Private_Component (Parent_Type)
+         then
+            Error_Msg_N
+              ("premature derivation of derived or private type", Indic);
+
+            --  Flag the type itself as being in error, this prevents some
+            --  nasty problems with people looking at the malformed type.
+
+            Set_Error_Posted (T);
+
+         --  Check that within the immediate scope of an untagged partial
+         --  view it's illegal to derive from the partial view if the
+         --  full view is tagged. (7.3(7))
+
+         --  We verify that the Parent_Type is a partial view by checking
+         --  that it is not a Full_Type_Declaration (i.e. a private type or
+         --  private extension declaration), to distinguish a partial view
+         --  from  a derivation from a private type which also appears as
+         --  E_Private_Type.
+
+         elsif Present (Full_View (Parent_Type))
+           and then Nkind (Parent (Parent_Type)) /= N_Full_Type_Declaration
+           and then not Is_Tagged_Type (Parent_Type)
+           and then Is_Tagged_Type (Full_View (Parent_Type))
+         then
+            Parent_Scope := Scope (T);
+            while Present (Parent_Scope)
+              and then Parent_Scope /= Standard_Standard
+            loop
+               if Parent_Scope = Scope (Parent_Type) then
+                  Error_Msg_N
+                    ("premature derivation from type with tagged full view",
+                     Indic);
+               end if;
+
+               Parent_Scope := Scope (Parent_Scope);
+            end loop;
+         end if;
+      end if;
+
+      --  Check that form of derivation is appropriate
+
+      Taggd := Is_Tagged_Type (Parent_Type);
+
+      --  Perhaps the parent type should be changed to the class-wide type's
+      --  specific type in this case to prevent cascading errors ???
+
+      if Present (Extension) and then Is_Class_Wide_Type (Parent_Type) then
+         Error_Msg_N ("parent type must not be a class-wide type", Indic);
+         return;
+      end if;
+
+      if Present (Extension) and then not Taggd then
+         Error_Msg_N
+           ("type derived from untagged type cannot have extension", Indic);
+
+      elsif No (Extension) and then Taggd then
+         --  If this is within a private part (or body) of a generic
+         --  instantiation then the derivation is allowed (the parent
+         --  type can only appear tagged in this case if it's a generic
+         --  actual type, since it would otherwise have been rejected
+         --  in the analysis of the generic template).
+
+         if not Is_Generic_Actual_Type (Parent_Type)
+           or else In_Visible_Part (Scope (Parent_Type))
+         then
+            Error_Msg_N
+              ("type derived from tagged type must have extension", Indic);
+         end if;
+      end if;
+
+      Build_Derived_Type (N, Parent_Type, T, Is_Completion);
+   end Derived_Type_Declaration;
+
+   ----------------------------------
+   -- Enumeration_Type_Declaration --
+   ----------------------------------
+
+   procedure Enumeration_Type_Declaration (T : Entity_Id; Def : Node_Id) is
+      Ev     : Uint;
+      L      : Node_Id;
+      R_Node : Node_Id;
+      B_Node : Node_Id;
+
+   begin
+      --  Create identifier node representing lower bound
+
+      B_Node := New_Node (N_Identifier, Sloc (Def));
+      L := First (Literals (Def));
+      Set_Chars (B_Node, Chars (L));
+      Set_Entity (B_Node,  L);
+      Set_Etype (B_Node, T);
+      Set_Is_Static_Expression (B_Node, True);
+
+      R_Node := New_Node (N_Range, Sloc (Def));
+      Set_Low_Bound  (R_Node, B_Node);
+
+      Set_Ekind (T, E_Enumeration_Type);
+      Set_First_Literal (T, L);
+      Set_Etype (T, T);
+      Set_Is_Constrained (T);
+
+      Ev := Uint_0;
+
+      --  Loop through literals of enumeration type setting pos and rep values
+      --  except that if the Ekind is already set, then it means that the
+      --  literal was already constructed (case of a derived type declaration
+      --  and we should not disturb the Pos and Rep values.
+
+      while Present (L) loop
+         if Ekind (L) /= E_Enumeration_Literal then
+            Set_Ekind (L, E_Enumeration_Literal);
+            Set_Enumeration_Pos (L, Ev);
+            Set_Enumeration_Rep (L, Ev);
+            Set_Is_Known_Valid  (L, True);
+         end if;
+
+         Set_Etype (L, T);
+         New_Overloaded_Entity (L);
+         Generate_Definition (L);
+         Set_Convention (L, Convention_Intrinsic);
+
+         if Nkind (L) = N_Defining_Character_Literal then
+            Set_Is_Character_Type (T, True);
+         end if;
+
+         Ev := Ev + 1;
+         Next (L);
+      end loop;
+
+      --  Now create a node representing upper bound
+
+      B_Node := New_Node (N_Identifier, Sloc (Def));
+      Set_Chars (B_Node, Chars (Last (Literals (Def))));
+      Set_Entity (B_Node,  Last (Literals (Def)));
+      Set_Etype (B_Node, T);
+      Set_Is_Static_Expression (B_Node, True);
+
+      Set_High_Bound (R_Node, B_Node);
+      Set_Scalar_Range (T, R_Node);
+      Set_RM_Size (T, UI_From_Int (Minimum_Size (T)));
+      Set_Enum_Esize (T);
+
+      --  Set Discard_Names if configuration pragma setg, or if there is
+      --  a parameterless pragma in the current declarative region
+
+      if Global_Discard_Names
+        or else Discard_Names (Scope (T))
+      then
+         Set_Discard_Names (T);
+      end if;
+   end Enumeration_Type_Declaration;
+
+   --------------------------
+   -- Expand_Others_Choice --
+   --------------------------
+
+   procedure Expand_Others_Choice
+     (Case_Table    : Choice_Table_Type;
+      Others_Choice : Node_Id;
+      Choice_Type   : Entity_Id)
+   is
+      Choice      : Node_Id;
+      Choice_List : List_Id := New_List;
+      Exp_Lo      : Node_Id;
+      Exp_Hi      : Node_Id;
+      Hi          : Uint;
+      Lo          : Uint;
+      Loc         : Source_Ptr := Sloc (Others_Choice);
+      Previous_Hi : Uint;
+
+      function Build_Choice (Value1, Value2 : Uint) return Node_Id;
+      --  Builds a node representing the missing choices given by the
+      --  Value1 and Value2. A N_Range node is built if there is more than
+      --  one literal value missing. Otherwise a single N_Integer_Literal,
+      --  N_Identifier or N_Character_Literal is built depending on what
+      --  Choice_Type is.
+
+      function Lit_Of (Value : Uint) return Node_Id;
+      --  Returns the Node_Id for the enumeration literal corresponding to the
+      --  position given by Value within the enumeration type Choice_Type.
+
+      ------------------
+      -- Build_Choice --
+      ------------------
+
+      function Build_Choice (Value1, Value2 : Uint) return Node_Id is
+         Lit_Node : Node_Id;
+         Lo, Hi   : Node_Id;
+
+      begin
+         --  If there is only one choice value missing between Value1 and
+         --  Value2, build an integer or enumeration literal to represent it.
+
+         if (Value2 - Value1) = 0 then
+            if Is_Integer_Type (Choice_Type) then
+               Lit_Node := Make_Integer_Literal (Loc, Value1);
+               Set_Etype (Lit_Node, Choice_Type);
+            else
+               Lit_Node := Lit_Of (Value1);
+            end if;
+
+         --  Otherwise is more that one choice value that is missing between
+         --  Value1 and Value2, therefore build a N_Range node of either
+         --  integer or enumeration literals.
+
+         else
+            if Is_Integer_Type (Choice_Type) then
+               Lo := Make_Integer_Literal (Loc, Value1);
+               Set_Etype (Lo, Choice_Type);
+               Hi := Make_Integer_Literal (Loc, Value2);
+               Set_Etype (Hi, Choice_Type);
+               Lit_Node :=
+                 Make_Range (Loc,
+                   Low_Bound  => Lo,
+                   High_Bound => Hi);
+
+            else
+               Lit_Node :=
+                 Make_Range (Loc,
+                   Low_Bound  => Lit_Of (Value1),
+                   High_Bound => Lit_Of (Value2));
+            end if;
+         end if;
+
+         return Lit_Node;
+      end Build_Choice;
+
+      ------------
+      -- Lit_Of --
+      ------------
+
+      function Lit_Of (Value : Uint) return Node_Id is
+         Lit : Entity_Id;
+
+      begin
+         --  In the case where the literal is of type Character, there needs
+         --  to be some special handling since there is no explicit chain
+         --  of literals to search. Instead, a N_Character_Literal node
+         --  is created with the appropriate Char_Code and Chars fields.
+
+         if Root_Type (Choice_Type) = Standard_Character then
+            Set_Character_Literal_Name (Char_Code (UI_To_Int (Value)));
+            Lit := New_Node (N_Character_Literal, Loc);
+            Set_Chars (Lit, Name_Find);
+            Set_Char_Literal_Value (Lit, Char_Code (UI_To_Int (Value)));
+            Set_Etype (Lit, Choice_Type);
+            Set_Is_Static_Expression (Lit, True);
+            return Lit;
+
+         --  Otherwise, iterate through the literals list of Choice_Type
+         --  "Value" number of times until the desired literal is reached
+         --  and then return an occurrence of it.
+
+         else
+            Lit := First_Literal (Choice_Type);
+            for J in 1 .. UI_To_Int (Value) loop
+               Next_Literal (Lit);
+            end loop;
+
+            return New_Occurrence_Of (Lit, Loc);
+         end if;
+      end Lit_Of;
+
+   --  Start of processing for Expand_Others_Choice
+
+   begin
+      if Case_Table'Length = 0 then
+
+         --  Pathological case: only an others case is present.
+         --  The others case covers the full range of the type.
+
+         if Is_Static_Subtype (Choice_Type) then
+            Choice := New_Occurrence_Of (Choice_Type, Loc);
+         else
+            Choice := New_Occurrence_Of (Base_Type (Choice_Type), Loc);
+         end if;
+
+         Set_Others_Discrete_Choices (Others_Choice, New_List (Choice));
+         return;
+      end if;
+
+      --  Establish the bound values for the variant depending upon whether
+      --  the type of the discriminant name is static or not.
+
+      if Is_OK_Static_Subtype (Choice_Type) then
+         Exp_Lo := Type_Low_Bound (Choice_Type);
+         Exp_Hi := Type_High_Bound (Choice_Type);
+      else
+         Exp_Lo := Type_Low_Bound (Base_Type (Choice_Type));
+         Exp_Hi := Type_High_Bound (Base_Type (Choice_Type));
+      end if;
+
+      Lo := Expr_Value (Case_Table (Case_Table'First).Lo);
+      Hi := Expr_Value (Case_Table (Case_Table'First).Hi);
+      Previous_Hi := Expr_Value (Case_Table (Case_Table'First).Hi);
+
+      --  Build the node for any missing choices that are smaller than any
+      --  explicit choices given in the variant.
+
+      if Expr_Value (Exp_Lo) < Lo then
+         Append (Build_Choice (Expr_Value (Exp_Lo), Lo - 1), Choice_List);
+      end if;
+
+      --  Build the nodes representing any missing choices that lie between
+      --  the explicit ones given in the variant.
+
+      for J in Case_Table'First + 1 .. Case_Table'Last loop
+         Lo := Expr_Value (Case_Table (J).Lo);
+         Hi := Expr_Value (Case_Table (J).Hi);
+
+         if Lo /= (Previous_Hi + 1) then
+            Append_To (Choice_List, Build_Choice (Previous_Hi + 1, Lo - 1));
+         end if;
+
+         Previous_Hi := Hi;
+      end loop;
+
+      --  Build the node for any missing choices that are greater than any
+      --  explicit choices given in the variant.
+
+      if Expr_Value (Exp_Hi) > Hi then
+         Append (Build_Choice (Hi + 1, Expr_Value (Exp_Hi)), Choice_List);
+      end if;
+
+      Set_Others_Discrete_Choices (Others_Choice, Choice_List);
+   end Expand_Others_Choice;
+
+   ---------------------------------
+   -- Expand_To_Girder_Constraint --
+   ---------------------------------
+
+   function Expand_To_Girder_Constraint
+     (Typ        : Entity_Id;
+      Constraint : Elist_Id)
+      return       Elist_Id
+   is
+      Explicitly_Discriminated_Type : Entity_Id;
+      Expansion    : Elist_Id;
+      Discriminant : Entity_Id;
+
+      function Type_With_Explicit_Discrims (Id : Entity_Id) return Entity_Id;
+      --  Find the nearest type that actually specifies discriminants.
+
+      ---------------------------------
+      -- Type_With_Explicit_Discrims --
+      ---------------------------------
+
+      function Type_With_Explicit_Discrims (Id : Entity_Id) return Entity_Id is
+         Typ : constant E := Base_Type (Id);
+
+      begin
+         if Ekind (Typ) in Incomplete_Or_Private_Kind then
+            if Present (Full_View (Typ)) then
+               return Type_With_Explicit_Discrims (Full_View (Typ));
+            end if;
+
+         else
+            if Has_Discriminants (Typ) then
+               return Typ;
+            end if;
+         end if;
+
+         if Etype (Typ) = Typ then
+            return Empty;
+         elsif Has_Discriminants (Typ) then
+            return Typ;
+         else
+            return Type_With_Explicit_Discrims (Etype (Typ));
+         end if;
+
+      end Type_With_Explicit_Discrims;
+
+   --  Start of processing for Expand_To_Girder_Constraint
+
+   begin
+      if No (Constraint)
+        or else Is_Empty_Elmt_List (Constraint)
+      then
+         return No_Elist;
+      end if;
+
+      Explicitly_Discriminated_Type := Type_With_Explicit_Discrims (Typ);
+
+      if No (Explicitly_Discriminated_Type) then
+         return No_Elist;
+      end if;
+
+      Expansion := New_Elmt_List;
+
+      Discriminant :=
+         First_Girder_Discriminant (Explicitly_Discriminated_Type);
+
+      while Present (Discriminant) loop
+
+         Append_Elmt (
+           Get_Discriminant_Value (
+             Discriminant, Explicitly_Discriminated_Type, Constraint),
+           Expansion);
+
+         Next_Girder_Discriminant (Discriminant);
+      end loop;
+
+      return Expansion;
+   end Expand_To_Girder_Constraint;
+
+   --------------------
+   -- Find_Type_Name --
+   --------------------
+
+   function Find_Type_Name (N : Node_Id) return Entity_Id is
+      Id       : constant Entity_Id := Defining_Identifier (N);
+      Prev     : Entity_Id;
+      New_Id   : Entity_Id;
+      Prev_Par : Node_Id;
+
+   begin
+      --  Find incomplete declaration, if some was given.
+
+      Prev := Current_Entity_In_Scope (Id);
+
+      if Present (Prev) then
+
+         --  Previous declaration exists. Error if not incomplete/private case
+         --  except if previous declaration is implicit, etc. Enter_Name will
+         --  emit error if appropriate.
+
+         Prev_Par := Parent (Prev);
+
+         if not Is_Incomplete_Or_Private_Type (Prev) then
+            Enter_Name (Id);
+            New_Id := Id;
+
+         elsif Nkind (N) /= N_Full_Type_Declaration
+           and then Nkind (N) /= N_Task_Type_Declaration
+           and then Nkind (N) /= N_Protected_Type_Declaration
+         then
+            --  Completion must be a full type declarations (RM 7.3(4))
+
+            Error_Msg_Sloc := Sloc (Prev);
+            Error_Msg_NE ("invalid completion of }", Id, Prev);
+
+            --  Set scope of Id to avoid cascaded errors. Entity is never
+            --  examined again, except when saving globals in generics.
+
+            Set_Scope (Id, Current_Scope);
+            New_Id := Id;
+
+         --  Case of full declaration of incomplete type
+
+         elsif Ekind (Prev) = E_Incomplete_Type then
+
+            --  Indicate that the incomplete declaration has a matching
+            --  full declaration. The defining occurrence of the incomplete
+            --  declaration remains the visible one, and the procedure
+            --  Get_Full_View dereferences it whenever the type is used.
+
+            if Present (Full_View (Prev)) then
+               Error_Msg_NE ("invalid redeclaration of }", Id, Prev);
+            end if;
+
+            Set_Full_View (Prev,  Id);
+            Append_Entity (Id, Current_Scope);
+            Set_Is_Public (Id, Is_Public (Prev));
+            Set_Is_Internal (Id);
+            New_Id := Prev;
+
+         --  Case of full declaration of private type
+
+         else
+            if Nkind (Parent (Prev)) /= N_Private_Extension_Declaration then
+               if Etype (Prev) /= Prev then
+
+                  --  Prev is a private subtype or a derived type, and needs
+                  --  no completion.
+
+                  Error_Msg_NE ("invalid redeclaration of }", Id, Prev);
+                  New_Id := Id;
+
+               elsif Ekind (Prev) = E_Private_Type
+                 and then
+                   (Nkind (N) = N_Task_Type_Declaration
+                     or else Nkind (N) = N_Protected_Type_Declaration)
+               then
+                  Error_Msg_N
+                   ("completion of nonlimited type cannot be limited", N);
+               end if;
+
+            elsif Nkind (N) /= N_Full_Type_Declaration
+              or else Nkind (Type_Definition (N)) /= N_Derived_Type_Definition
+            then
+               Error_Msg_N ("full view of private extension must be"
+                 & " an extension", N);
+
+            elsif not (Abstract_Present (Parent (Prev)))
+              and then Abstract_Present (Type_Definition (N))
+            then
+               Error_Msg_N ("full view of non-abstract extension cannot"
+                 & " be abstract", N);
+            end if;
+
+            if not In_Private_Part (Current_Scope) then
+               Error_Msg_N
+                 ("declaration of full view must appear in private part",  N);
+            end if;
+
+            Copy_And_Swap (Prev, Id);
+            Set_Full_View (Id, Prev);
+            Set_Has_Private_Declaration (Prev);
+            Set_Has_Private_Declaration (Id);
+            New_Id := Prev;
+         end if;
+
+         --  Verify that full declaration conforms to incomplete one
+
+         if Is_Incomplete_Or_Private_Type (Prev)
+           and then Present (Discriminant_Specifications (Prev_Par))
+         then
+            if Present (Discriminant_Specifications (N)) then
+               if Ekind (Prev) = E_Incomplete_Type then
+                  Check_Discriminant_Conformance (N, Prev, Prev);
+               else
+                  Check_Discriminant_Conformance (N, Prev, Id);
+               end if;
+
+            else
+               Error_Msg_N
+                 ("missing discriminants in full type declaration", N);
+
+               --  To avoid cascaded errors on subsequent use, share the
+               --  discriminants of the partial view.
+
+               Set_Discriminant_Specifications (N,
+                 Discriminant_Specifications (Prev_Par));
+            end if;
+         end if;
+
+         --  A prior untagged private type can have an associated
+         --  class-wide type due to use of the class attribute,
+         --  and in this case also the full type is required to
+         --  be tagged.
+
+         if Is_Type (Prev)
+           and then (Is_Tagged_Type (Prev)
+                      or else Present (Class_Wide_Type (Prev)))
+         then
+            --  The full declaration is either a tagged record or an
+            --  extension otherwise this is an error
+
+            if Nkind (Type_Definition (N)) = N_Record_Definition then
+               if not Tagged_Present (Type_Definition (N)) then
+                  Error_Msg_NE
+                    ("full declaration of } must be tagged", Prev, Id);
+                  Set_Is_Tagged_Type (Id);
+                  Set_Primitive_Operations (Id, New_Elmt_List);
+               end if;
+
+            elsif Nkind (Type_Definition (N)) = N_Derived_Type_Definition then
+               if No (Record_Extension_Part (Type_Definition (N))) then
+                  Error_Msg_NE (
+                    "full declaration of } must be a record extension",
+                    Prev, Id);
+                  Set_Is_Tagged_Type (Id);
+                  Set_Primitive_Operations (Id, New_Elmt_List);
+               end if;
+
+            else
+               Error_Msg_NE
+                 ("full declaration of } must be a tagged type", Prev, Id);
+
+            end if;
+         end if;
+
+         return New_Id;
+
+      else
+         --  New type declaration
+
+         Enter_Name (Id);
+         return Id;
+      end if;
+   end Find_Type_Name;
+
+   -------------------------
+   -- Find_Type_Of_Object --
+   -------------------------
+
+   function Find_Type_Of_Object
+     (Obj_Def     : Node_Id;
+      Related_Nod : Node_Id)
+      return        Entity_Id
+   is
+      Def_Kind : constant Node_Kind := Nkind (Obj_Def);
+      P        : constant Node_Id   := Parent (Obj_Def);
+      T        : Entity_Id;
+      Nam      : Name_Id;
+
+   begin
+      --  Case of an anonymous array subtype
+
+      if Def_Kind = N_Constrained_Array_Definition
+        or else Def_Kind = N_Unconstrained_Array_Definition
+      then
+         T := Empty;
+         Array_Type_Declaration (T, Obj_Def);
+
+      --  Create an explicit subtype whenever possible.
+
+      elsif Nkind (P) /= N_Component_Declaration
+        and then Def_Kind = N_Subtype_Indication
+      then
+         --  Base name of subtype on object name, which will be unique in
+         --  the current scope.
+
+         --  If this is a duplicate declaration, return base type, to avoid
+         --  generating duplicate anonymous types.
+
+         if Error_Posted (P) then
+            Analyze (Subtype_Mark (Obj_Def));
+            return Entity (Subtype_Mark (Obj_Def));
+         end if;
+
+         Nam :=
+            New_External_Name
+             (Chars (Defining_Identifier (Related_Nod)), 'S', 0, 'T');
+
+         T := Make_Defining_Identifier (Sloc (P), Nam);
+
+         Insert_Action (Obj_Def,
+           Make_Subtype_Declaration (Sloc (P),
+             Defining_Identifier => T,
+             Subtype_Indication  => Relocate_Node (Obj_Def)));
+
+         --  This subtype may need freezing and it will not be done
+         --  automatically if the object declaration is not in a
+         --  declarative part. Since this is an object declaration, the
+         --  type cannot always be frozen here. Deferred constants do not
+         --  freeze their type (which often enough will be private).
+
+         if Nkind (P) = N_Object_Declaration
+           and then Constant_Present (P)
+           and then No (Expression (P))
+         then
+            null;
+
+         else
+            Insert_Actions (Obj_Def, Freeze_Entity (T, Sloc (P)));
+         end if;
+
+      else
+         T := Process_Subtype (Obj_Def, Related_Nod);
+      end if;
+
+      return T;
+   end Find_Type_Of_Object;
+
+   --------------------------------
+   -- Find_Type_Of_Subtype_Indic --
+   --------------------------------
+
+   function Find_Type_Of_Subtype_Indic (S : Node_Id) return Entity_Id is
+      Typ : Entity_Id;
+
+   begin
+      --  Case of subtype mark with a constraint
+
+      if Nkind (S) = N_Subtype_Indication then
+         Find_Type (Subtype_Mark (S));
+         Typ := Entity (Subtype_Mark (S));
+
+         if not
+           Is_Valid_Constraint_Kind (Ekind (Typ), Nkind (Constraint (S)))
+         then
+            Error_Msg_N
+              ("incorrect constraint for this kind of type", Constraint (S));
+            Rewrite (S, New_Copy_Tree (Subtype_Mark (S)));
+         end if;
+
+      --  Otherwise we have a subtype mark without a constraint
+
+      else
+         Find_Type (S);
+         Typ := Entity (S);
+      end if;
+
+      if Typ = Standard_Wide_Character
+        or else Typ = Standard_Wide_String
+      then
+         Check_Restriction (No_Wide_Characters, S);
+      end if;
+
+      return Typ;
+   end Find_Type_Of_Subtype_Indic;
+
+   -------------------------------------
+   -- Floating_Point_Type_Declaration --
+   -------------------------------------
+
+   procedure Floating_Point_Type_Declaration (T : Entity_Id; Def : Node_Id) is
+      Digs          : constant Node_Id := Digits_Expression (Def);
+      Digs_Val      : Uint;
+      Base_Typ      : Entity_Id;
+      Implicit_Base : Entity_Id;
+      Bound         : Node_Id;
+
+      function Can_Derive_From (E : Entity_Id) return Boolean;
+      --  Find if given digits value allows derivation from specified type
+
+      function Can_Derive_From (E : Entity_Id) return Boolean is
+         Spec : constant Entity_Id := Real_Range_Specification (Def);
+
+      begin
+         if Digs_Val > Digits_Value (E) then
+            return False;
+         end if;
+
+         if Present (Spec) then
+            if Expr_Value_R (Type_Low_Bound (E)) >
+               Expr_Value_R (Low_Bound (Spec))
+            then
+               return False;
+            end if;
+
+            if Expr_Value_R (Type_High_Bound (E)) <
+               Expr_Value_R (High_Bound (Spec))
+            then
+               return False;
+            end if;
+         end if;
+
+         return True;
+      end Can_Derive_From;
+
+   --  Start of processing for Floating_Point_Type_Declaration
+
+   begin
+      Check_Restriction (No_Floating_Point, Def);
+
+      --  Create an implicit base type
+
+      Implicit_Base :=
+        Create_Itype (E_Floating_Point_Type, Parent (Def), T, 'B');
+
+      --  Analyze and verify digits value
+
+      Analyze_And_Resolve (Digs, Any_Integer);
+      Check_Digits_Expression (Digs);
+      Digs_Val := Expr_Value (Digs);
+
+      --  Process possible range spec and find correct type to derive from
+
+      Process_Real_Range_Specification (Def);
+
+      if Can_Derive_From (Standard_Short_Float) then
+         Base_Typ := Standard_Short_Float;
+      elsif Can_Derive_From (Standard_Float) then
+         Base_Typ := Standard_Float;
+      elsif Can_Derive_From (Standard_Long_Float) then
+         Base_Typ := Standard_Long_Float;
+      elsif Can_Derive_From (Standard_Long_Long_Float) then
+         Base_Typ := Standard_Long_Long_Float;
+
+      --  If we can't derive from any existing type, use long long float
+      --  and give appropriate message explaining the problem.
+
+      else
+         Base_Typ := Standard_Long_Long_Float;
+
+         if Digs_Val >= Digits_Value (Standard_Long_Long_Float) then
+            Error_Msg_Uint_1 := Digits_Value (Standard_Long_Long_Float);
+            Error_Msg_N ("digits value out of range, maximum is ^", Digs);
+
+         else
+            Error_Msg_N
+              ("range too large for any predefined type",
+               Real_Range_Specification (Def));
+         end if;
+      end if;
+
+      --  If there are bounds given in the declaration use them as the bounds
+      --  of the type, otherwise use the bounds of the predefined base type
+      --  that was chosen based on the Digits value.
+
+      if Present (Real_Range_Specification (Def)) then
+         Set_Scalar_Range (T, Real_Range_Specification (Def));
+         Set_Is_Constrained (T);
+
+         --  The bounds of this range must be converted to machine numbers
+         --  in accordance with RM 4.9(38).
+
+         Bound := Type_Low_Bound (T);
+
+         if Nkind (Bound) = N_Real_Literal then
+            Set_Realval (Bound, Machine (Base_Typ, Realval (Bound), Round));
+            Set_Is_Machine_Number (Bound);
+         end if;
+
+         Bound := Type_High_Bound (T);
+
+         if Nkind (Bound) = N_Real_Literal then
+            Set_Realval (Bound, Machine (Base_Typ, Realval (Bound), Round));
+            Set_Is_Machine_Number (Bound);
+         end if;
+
+      else
+         Set_Scalar_Range (T, Scalar_Range (Base_Typ));
+      end if;
+
+      --  Complete definition of implicit base and declared first subtype
+
+      Set_Etype          (Implicit_Base, Base_Typ);
+
+      Set_Scalar_Range   (Implicit_Base, Scalar_Range   (Base_Typ));
+      Set_Size_Info      (Implicit_Base,                (Base_Typ));
+      Set_RM_Size        (Implicit_Base, RM_Size        (Base_Typ));
+      Set_First_Rep_Item (Implicit_Base, First_Rep_Item (Base_Typ));
+      Set_Digits_Value   (Implicit_Base, Digits_Value   (Base_Typ));
+      Set_Vax_Float      (Implicit_Base, Vax_Float      (Base_Typ));
+
+      Set_Ekind          (T, E_Floating_Point_Subtype);
+      Set_Etype          (T, Implicit_Base);
+
+      Set_Size_Info      (T,                (Implicit_Base));
+      Set_RM_Size        (T, RM_Size        (Implicit_Base));
+      Set_First_Rep_Item (T, First_Rep_Item (Implicit_Base));
+      Set_Digits_Value   (T, Digs_Val);
+
+   end Floating_Point_Type_Declaration;
+
+   ----------------------------
+   -- Get_Discriminant_Value --
+   ----------------------------
+
+   --  This is the situation...
+
+   --  There is a non-derived type
+
+   --       type T0 (Dx, Dy, Dz...)
+
+   --  There are zero or more levels of derivation, with each
+   --  derivation either purely inheriting the discriminants, or
+   --  defining its own.
+
+   --       type Ti      is new Ti-1
+   --  or
+   --       type Ti (Dw) is new Ti-1(Dw, 1, X+Y)
+   --  or
+   --       subtype Ti is ...
+
+   --  The subtype issue is avoided by the use of
+   --    Original_Record_Component, and the fact that derived subtypes
+   --    also derive the constraits.
+
+   --  This chain leads back from
+
+   --       Typ_For_Constraint
+
+   --  Typ_For_Constraint has discriminants, and the value for each
+   --  discriminant is given by its corresponding Elmt of Constraints.
+
+   --  Discriminant is some discriminant in this hierarchy.
+
+   --  We need to return its value.
+
+   --  We do this by recursively searching each level, and looking for
+   --  Discriminant. Once we get to the bottom, we start backing up
+   --  returning the value for it which may in turn be a discriminant
+   --  further up, so on the backup we continue the substitution.
+
+   function Get_Discriminant_Value
+     (Discriminant       : Entity_Id;
+      Typ_For_Constraint : Entity_Id;
+      Constraint         : Elist_Id)
+      return               Node_Id
+   is
+      function Recurse
+        (Ti                    : Entity_Id;
+         Discrim_Values        : Elist_Id;
+         Girder_Discrim_Values : Boolean)
+         return                Node_Or_Entity_Id;
+      --  This is the routine that performs the recursive search of levels
+      --  as described above.
+
+      function Recurse
+        (Ti                    : Entity_Id;
+         Discrim_Values        : Elist_Id;
+         Girder_Discrim_Values : Boolean)
+         return                  Node_Or_Entity_Id
+      is
+         Assoc          : Elmt_Id;
+         Disc           : Entity_Id;
+         Result         : Node_Or_Entity_Id;
+         Result_Entity  : Node_Id;
+
+      begin
+         --  If inappropriate type, return Error, this happens only in
+         --  cascaded error situations, and we want to avoid a blow up.
+
+         if not Is_Composite_Type (Ti) or else Is_Array_Type (Ti) then
+            return Error;
+         end if;
+
+         --  Look deeper if possible. Use Girder_Constraints only for
+         --  untagged types. For tagged types use the given constraint.
+         --  This asymmetry needs explanation???
+
+         if not Girder_Discrim_Values
+           and then Present (Girder_Constraint (Ti))
+           and then not Is_Tagged_Type (Ti)
+         then
+            Result := Recurse (Ti, Girder_Constraint (Ti), True);
+         else
+            declare
+               Td : Entity_Id := Etype (Ti);
+            begin
+
+               if Td = Ti then
+                  Result := Discriminant;
+
+               else
+                  if Present (Girder_Constraint (Ti)) then
+                     Result :=
+                        Recurse (Td, Girder_Constraint (Ti), True);
+                  else
+                     Result :=
+                        Recurse (Td, Discrim_Values, Girder_Discrim_Values);
+                  end if;
+               end if;
+            end;
+         end if;
+
+         --  Extra underlying places to search, if not found above. For
+         --  concurrent types, the relevant discriminant appears in the
+         --  corresponding record. For a type derived from a private type
+         --  without discriminant, the full view inherits the discriminants
+         --  of the full view of the parent.
+
+         if Result = Discriminant then
+            if Is_Concurrent_Type (Ti)
+              and then Present (Corresponding_Record_Type (Ti))
+            then
+               Result :=
+                 Recurse (
+                   Corresponding_Record_Type (Ti),
+                   Discrim_Values,
+                   Girder_Discrim_Values);
+
+            elsif Is_Private_Type (Ti)
+              and then not Has_Discriminants (Ti)
+              and then Present (Full_View (Ti))
+              and then Etype (Full_View (Ti)) /= Ti
+            then
+               Result :=
+                 Recurse (
+                   Full_View (Ti),
+                   Discrim_Values,
+                   Girder_Discrim_Values);
+            end if;
+         end if;
+
+         --  If Result is not a (reference to a) discriminant,
+         --  return it, otherwise set Result_Entity to the discriminant.
+
+         if Nkind (Result) = N_Defining_Identifier then
+
+            pragma Assert (Result = Discriminant);
+
+            Result_Entity := Result;
+
+         else
+            if not Denotes_Discriminant (Result) then
+               return Result;
+            end if;
+
+            Result_Entity := Entity (Result);
+         end if;
+
+         --  See if this level of derivation actually has discriminants
+         --  because tagged derivations can add them, hence the lower
+         --  levels need not have any.
+
+         if not Has_Discriminants (Ti) then
+            return Result;
+         end if;
+
+         --  Scan Ti's discriminants for Result_Entity,
+         --  and return its corresponding value, if any.
+
+         Result_Entity := Original_Record_Component (Result_Entity);
+
+         Assoc := First_Elmt (Discrim_Values);
+
+         if Girder_Discrim_Values then
+            Disc := First_Girder_Discriminant (Ti);
+         else
+            Disc := First_Discriminant (Ti);
+         end if;
+
+         while Present (Disc) loop
+
+            pragma Assert (Present (Assoc));
+
+            if Original_Record_Component (Disc) = Result_Entity then
+               return Node (Assoc);
+            end if;
+
+            Next_Elmt (Assoc);
+
+            if Girder_Discrim_Values then
+               Next_Girder_Discriminant (Disc);
+            else
+               Next_Discriminant (Disc);
+            end if;
+         end loop;
+
+         --  Could not find it
+         --
+         return Result;
+      end Recurse;
+
+      Result : Node_Or_Entity_Id;
+
+   --  Start of processing for Get_Discriminant_Value
+
+   begin
+      --  ??? this routine is a gigantic mess and will be deleted.
+      --  for the time being just test for the trivial case before calling
+      --  recurse.
+
+      if Base_Type (Scope (Discriminant)) = Base_Type (Typ_For_Constraint) then
+         declare
+            D : Entity_Id := First_Discriminant (Typ_For_Constraint);
+            E : Elmt_Id   := First_Elmt (Constraint);
+         begin
+            while Present (D) loop
+               if Chars (D) = Chars (Discriminant) then
+                  return Node (E);
+               end if;
+
+               Next_Discriminant (D);
+               Next_Elmt (E);
+            end loop;
+         end;
+      end if;
+
+      Result := Recurse (Typ_For_Constraint, Constraint, False);
+
+      --  ??? hack to disappear when this routine is gone
+
+      if  Nkind (Result) = N_Defining_Identifier then
+         declare
+            D : Entity_Id := First_Discriminant (Typ_For_Constraint);
+            E : Elmt_Id   := First_Elmt (Constraint);
+         begin
+            while Present (D) loop
+               if Corresponding_Discriminant (D) = Discriminant then
+                  return Node (E);
+               end if;
+
+               Next_Discriminant (D);
+               Next_Elmt (E);
+            end loop;
+         end;
+      end if;
+
+      pragma Assert (Nkind (Result) /= N_Defining_Identifier);
+      return Result;
+   end Get_Discriminant_Value;
+
+   --------------------------
+   -- Has_Range_Constraint --
+   --------------------------
+
+   function Has_Range_Constraint (N : Node_Id) return Boolean is
+      C : constant Node_Id := Constraint (N);
+
+   begin
+      if Nkind (C) = N_Range_Constraint then
+         return True;
+
+      elsif Nkind (C) = N_Digits_Constraint then
+         return
+            Is_Decimal_Fixed_Point_Type (Entity (Subtype_Mark (N)))
+              or else
+            Present (Range_Constraint (C));
+
+      elsif Nkind (C) = N_Delta_Constraint then
+         return Present (Range_Constraint (C));
+
+      else
+         return False;
+      end if;
+   end Has_Range_Constraint;
+
+   ------------------------
+   -- Inherit_Components --
+   ------------------------
+
+   function Inherit_Components
+     (N             : Node_Id;
+      Parent_Base   : Entity_Id;
+      Derived_Base  : Entity_Id;
+      Is_Tagged     : Boolean;
+      Inherit_Discr : Boolean;
+      Discs         : Elist_Id)
+      return          Elist_Id
+   is
+      Assoc_List : Elist_Id := New_Elmt_List;
+
+      procedure Inherit_Component
+        (Old_C          : Entity_Id;
+         Plain_Discrim  : Boolean := False;
+         Girder_Discrim : Boolean := False);
+      --  Inherits component Old_C from Parent_Base to the Derived_Base.
+      --  If Plain_Discrim is True, Old_C is a discriminant.
+      --  If Girder_Discrim is True, Old_C is a girder discriminant.
+      --  If they are both false then Old_C is a regular component.
+
+      -----------------------
+      -- Inherit_Component --
+      -----------------------
+
+      procedure Inherit_Component
+        (Old_C          : Entity_Id;
+         Plain_Discrim  : Boolean := False;
+         Girder_Discrim : Boolean := False)
+      is
+         New_C : Entity_Id := New_Copy (Old_C);
+
+         Discrim      : Entity_Id;
+         Corr_Discrim : Entity_Id;
+
+      begin
+         pragma Assert (not Is_Tagged or else not Girder_Discrim);
+
+         Set_Parent (New_C, Parent (Old_C));
+
+         --  Regular discriminants and components must be inserted
+         --  in the scope of the Derived_Base. Do it here.
+
+         if not Girder_Discrim then
+            Enter_Name (New_C);
+         end if;
+
+         --  For tagged types the Original_Record_Component must point to
+         --  whatever this field was pointing to in the parent type. This has
+         --  already been achieved by the call to New_Copy above.
+
+         if not Is_Tagged then
+            Set_Original_Record_Component (New_C, New_C);
+         end if;
+
+         --  If we have inherited a component then see if its Etype contains
+         --  references to Parent_Base discriminants. In this case, replace
+         --  these references with the constraints given in Discs. We do not
+         --  do this for the partial view of private types because this is
+         --  not needed (only the components of the full view will be used
+         --  for code generation) and cause problem. We also avoid this
+         --  transformation in some error situations.
+
+         if Ekind (New_C) = E_Component then
+            if (Is_Private_Type (Derived_Base)
+                  and then not Is_Generic_Type (Derived_Base))
+              or else (Is_Empty_Elmt_List (Discs)
+                       and then  not Expander_Active)
+            then
+               Set_Etype (New_C, Etype (Old_C));
+            else
+               Set_Etype (New_C, Constrain_Component_Type (Etype (Old_C),
+                 Derived_Base, N, Parent_Base, Discs));
+            end if;
+         end if;
+
+         --  In derived tagged types it is illegal to reference a non
+         --  discriminant component in the parent type. To catch this, mark
+         --  these components with an Ekind of E_Void. This will be reset in
+         --  Record_Type_Definition after processing the record extension of
+         --  the derived type.
+
+         if Is_Tagged and then Ekind (New_C) = E_Component then
+            Set_Ekind (New_C, E_Void);
+         end if;
+
+         if Plain_Discrim then
+            Set_Corresponding_Discriminant (New_C, Old_C);
+            Build_Discriminal (New_C);
+
+         --  If we are explicitely inheriting a girder discriminant it will be
+         --  completely hidden.
+
+         elsif Girder_Discrim then
+            Set_Corresponding_Discriminant (New_C, Empty);
+            Set_Discriminal (New_C, Empty);
+            Set_Is_Completely_Hidden (New_C);
+
+            --  Set the Original_Record_Component of each discriminant in the
+            --  derived base to point to the corresponding girder that we just
+            --  created.
+
+            Discrim := First_Discriminant (Derived_Base);
+            while Present (Discrim) loop
+               Corr_Discrim := Corresponding_Discriminant (Discrim);
+
+               --  Corr_Discrimm could be missing in an error situation.
+
+               if Present (Corr_Discrim)
+                 and then Original_Record_Component (Corr_Discrim) = Old_C
+               then
+                  Set_Original_Record_Component (Discrim, New_C);
+               end if;
+
+               Next_Discriminant (Discrim);
+            end loop;
+
+            Append_Entity (New_C, Derived_Base);
+         end if;
+
+         if not Is_Tagged then
+            Append_Elmt (Old_C, Assoc_List);
+            Append_Elmt (New_C, Assoc_List);
+         end if;
+      end Inherit_Component;
+
+      --  Variables local to Inherit_Components.
+
+      Loc : constant Source_Ptr := Sloc (N);
+
+      Parent_Discrim : Entity_Id;
+      Girder_Discrim : Entity_Id;
+      D              : Entity_Id;
+
+      Component        : Entity_Id;
+
+   --  Start of processing for Inherit_Components
+
+   begin
+      if not Is_Tagged then
+         Append_Elmt (Parent_Base,  Assoc_List);
+         Append_Elmt (Derived_Base, Assoc_List);
+      end if;
+
+      --  Inherit parent discriminants if needed.
+
+      if Inherit_Discr then
+         Parent_Discrim := First_Discriminant (Parent_Base);
+         while Present (Parent_Discrim) loop
+            Inherit_Component (Parent_Discrim, Plain_Discrim => True);
+            Next_Discriminant (Parent_Discrim);
+         end loop;
+      end if;
+
+      --  Create explicit girder discrims for untagged types when necessary.
+
+      if not Has_Unknown_Discriminants (Derived_Base)
+        and then Has_Discriminants (Parent_Base)
+        and then not Is_Tagged
+        and then
+          (not Inherit_Discr
+           or else First_Discriminant (Parent_Base) /=
+                   First_Girder_Discriminant (Parent_Base))
+      then
+         Girder_Discrim := First_Girder_Discriminant (Parent_Base);
+         while Present (Girder_Discrim) loop
+            Inherit_Component (Girder_Discrim, Girder_Discrim => True);
+            Next_Girder_Discriminant (Girder_Discrim);
+         end loop;
+      end if;
+
+      --  See if we can apply the second transformation for derived types, as
+      --  explained in point 6. in the comments above Build_Derived_Record_Type
+      --  This is achieved by appending Derived_Base discriminants into
+      --  Discs, which has the side effect of returning a non empty Discs
+      --  list to the caller of Inherit_Components, which is what we want.
+
+      if Inherit_Discr
+        and then Is_Empty_Elmt_List (Discs)
+        and then (not Is_Private_Type (Derived_Base)
+                   or Is_Generic_Type (Derived_Base))
+      then
+         D := First_Discriminant (Derived_Base);
+         while Present (D) loop
+            Append_Elmt (New_Reference_To (D, Loc), Discs);
+            Next_Discriminant (D);
+         end loop;
+      end if;
+
+      --  Finally, inherit non-discriminant components unless they are not
+      --  visible because defined or inherited from the full view of the
+      --  parent. Don't inherit the _parent field of the parent type.
+
+      Component := First_Entity (Parent_Base);
+      while Present (Component) loop
+         if Ekind (Component) /= E_Component
+           or else Chars (Component) = Name_uParent
+         then
+            null;
+
+         --  If the derived type is within the parent type's declarative
+         --  region, then the components can still be inherited even though
+         --  they aren't visible at this point. This can occur for cases
+         --  such as within public child units where the components must
+         --  become visible upon entering the child unit's private part.
+
+         elsif not Is_Visible_Component (Component)
+           and then not In_Open_Scopes (Scope (Parent_Base))
+         then
+            null;
+
+         elsif Ekind (Derived_Base) = E_Private_Type
+           or else Ekind (Derived_Base) = E_Limited_Private_Type
+         then
+            null;
+
+         else
+            Inherit_Component (Component);
+         end if;
+
+         Next_Entity (Component);
+      end loop;
+
+      --  For tagged derived types, inherited discriminants cannot be used in
+      --  component declarations of the record extension part. To achieve this
+      --  we mark the inherited discriminants as not visible.
+
+      if Is_Tagged and then Inherit_Discr then
+         D := First_Discriminant (Derived_Base);
+         while Present (D) loop
+            Set_Is_Immediately_Visible (D, False);
+            Next_Discriminant (D);
+         end loop;
+      end if;
+
+      return Assoc_List;
+   end Inherit_Components;
+
+   ------------------------------
+   -- Is_Valid_Constraint_Kind --
+   ------------------------------
+
+   function Is_Valid_Constraint_Kind
+     (T_Kind          : Type_Kind;
+      Constraint_Kind : Node_Kind)
+      return            Boolean
+   is
+   begin
+      case T_Kind is
+
+         when Enumeration_Kind |
+              Integer_Kind =>
+            return Constraint_Kind = N_Range_Constraint;
+
+         when Decimal_Fixed_Point_Kind =>
+            return
+              Constraint_Kind = N_Digits_Constraint
+                or else
+              Constraint_Kind = N_Range_Constraint;
+
+         when Ordinary_Fixed_Point_Kind =>
+            return
+              Constraint_Kind = N_Delta_Constraint
+                or else
+              Constraint_Kind = N_Range_Constraint;
+
+         when Float_Kind =>
+            return
+              Constraint_Kind = N_Digits_Constraint
+                or else
+              Constraint_Kind = N_Range_Constraint;
+
+         when Access_Kind       |
+              Array_Kind        |
+              E_Record_Type     |
+              E_Record_Subtype  |
+              Class_Wide_Kind   |
+              E_Incomplete_Type |
+              Private_Kind      |
+              Concurrent_Kind  =>
+            return Constraint_Kind = N_Index_Or_Discriminant_Constraint;
+
+         when others =>
+            return True; -- Error will be detected later.
+      end case;
+
+   end Is_Valid_Constraint_Kind;
+
+   --------------------------
+   -- Is_Visible_Component --
+   --------------------------
+
+   function Is_Visible_Component (C : Entity_Id) return Boolean is
+      Original_Comp  : constant Entity_Id := Original_Record_Component (C);
+      Original_Scope : Entity_Id;
+
+   begin
+      if No (Original_Comp) then
+
+         --  Premature usage, or previous error
+
+         return False;
+
+      else
+         Original_Scope := Scope (Original_Comp);
+      end if;
+
+      --  This test only concern tagged types
+
+      if not Is_Tagged_Type (Original_Scope) then
+         return True;
+
+      --  If it is _Parent or _Tag, there is no visiblity issue
+
+      elsif not Comes_From_Source (Original_Comp) then
+         return True;
+
+      --  If we are in the body of an instantiation, the component is
+      --  visible even when the parent type (possibly defined in an
+      --  enclosing unit or in a parent unit) might not.
+
+      elsif In_Instance_Body then
+         return True;
+
+      --  Discriminants are always visible.
+
+      elsif Ekind (Original_Comp) = E_Discriminant
+        and then not Has_Unknown_Discriminants (Original_Scope)
+      then
+         return True;
+
+      --  If the component has been declared in an ancestor which is
+      --  currently a private type, then it is not visible. The same
+      --  applies if the component's containing type is not in an
+      --  open scope and the original component's enclosing type
+      --  is a visible full type of a private type (which can occur
+      --  in cases where an attempt is being made to reference a
+      --  component in a sibling package that is inherited from
+      --  a visible component of a type in an ancestor package;
+      --  the component in the sibling package should not be
+      --  visible even though the component it inherited from
+      --  is visible). This does not apply however in the case
+      --  where the scope of the type is a private child unit.
+      --  The latter suppression of visibility is needed for cases
+      --  that are tested in B730006.
+
+      elsif (Ekind (Original_Comp) /= E_Discriminant
+              or else Has_Unknown_Discriminants (Original_Scope))
+        and then
+          (Is_Private_Type (Original_Scope)
+            or else
+              (not Is_Private_Descendant (Scope (Base_Type (Scope (C))))
+                and then not In_Open_Scopes (Scope (Base_Type (Scope (C))))
+                and then Has_Private_Declaration (Original_Scope)))
+      then
+         return False;
+
+      --  There is another weird way in which a component may be invisible
+      --  when the private and the full view are not derived from the same
+      --  ancestor. Here is an example :
+
+      --       type A1 is tagged      record F1 : integer; end record;
+      --       type A2 is new A1 with record F2 : integer; end record;
+      --       type T is new A1 with private;
+      --     private
+      --       type T is new A2 with private;
+
+      --  In this case, the full view of T inherits F1 and F2 but the
+      --  private view inherits only F1
+
+      else
+         declare
+            Ancestor : Entity_Id := Scope (C);
+
+         begin
+            loop
+               if Ancestor = Original_Scope then
+                  return True;
+               elsif Ancestor = Etype (Ancestor) then
+                  return False;
+               end if;
+
+               Ancestor := Etype (Ancestor);
+            end loop;
+
+            return True;
+         end;
+      end if;
+   end Is_Visible_Component;
+
+   --------------------------
+   -- Make_Class_Wide_Type --
+   --------------------------
+
+   procedure Make_Class_Wide_Type (T : Entity_Id) is
+      CW_Type : Entity_Id;
+      CW_Name : Name_Id;
+      Next_E  : Entity_Id;
+
+   begin
+      --  The class wide type can have been defined by the partial view in
+      --  which case everything is already done
+
+      if Present (Class_Wide_Type (T)) then
+         return;
+      end if;
+
+      CW_Type :=
+        New_External_Entity (E_Void, Scope (T), Sloc (T), T, 'C', 0, 'T');
+
+      --  Inherit root type characteristics
+
+      CW_Name := Chars (CW_Type);
+      Next_E  := Next_Entity (CW_Type);
+      Copy_Node (T, CW_Type);
+      Set_Comes_From_Source (CW_Type, False);
+      Set_Chars (CW_Type, CW_Name);
+      Set_Parent (CW_Type, Parent (T));
+      Set_Next_Entity (CW_Type, Next_E);
+      Set_Has_Delayed_Freeze (CW_Type);
+
+      --  Customize the class-wide type: It has no prim. op., it cannot be
+      --  abstract and its Etype points back to the root type
+
+      Set_Ekind                (CW_Type, E_Class_Wide_Type);
+      Set_Is_Tagged_Type       (CW_Type, True);
+      Set_Primitive_Operations (CW_Type, New_Elmt_List);
+      Set_Is_Abstract          (CW_Type, False);
+      Set_Etype                (CW_Type, T);
+      Set_Is_Constrained       (CW_Type, False);
+      Set_Is_First_Subtype     (CW_Type, Is_First_Subtype (T));
+      Init_Size_Align          (CW_Type);
+
+      --  If this is the class_wide type of a constrained subtype, it does
+      --  not have discriminants.
+
+      Set_Has_Discriminants (CW_Type,
+        Has_Discriminants (T) and then not Is_Constrained (T));
+
+      Set_Has_Unknown_Discriminants (CW_Type, True);
+      Set_Class_Wide_Type (T, CW_Type);
+      Set_Equivalent_Type (CW_Type, Empty);
+
+      --  The class-wide type of a class-wide type is itself (RM 3.9(14))
+
+      Set_Class_Wide_Type (CW_Type, CW_Type);
+
+   end Make_Class_Wide_Type;
+
+   ----------------
+   -- Make_Index --
+   ----------------
+
+   procedure Make_Index
+     (I            : Node_Id;
+      Related_Nod  : Node_Id;
+      Related_Id   : Entity_Id := Empty;
+      Suffix_Index : Nat := 1)
+   is
+      R      : Node_Id;
+      T      : Entity_Id;
+      Def_Id : Entity_Id := Empty;
+      Found  : Boolean := False;
+
+   begin
+      --  For a discrete range used in a constrained array definition and
+      --  defined by a range, an implicit conversion to the predefined type
+      --  INTEGER is assumed if each bound is either a numeric literal, a named
+      --  number, or an attribute, and the type of both bounds (prior to the
+      --  implicit conversion) is the type universal_integer. Otherwise, both
+      --  bounds must be of the same discrete type, other than universal
+      --  integer; this type must be determinable independently of the
+      --  context, but using the fact that the type must be discrete and that
+      --  both bounds must have the same type.
+
+      --  Character literals also have a universal type in the absence of
+      --  of additional context,  and are resolved to Standard_Character.
+
+      if Nkind (I) = N_Range then
+
+         --  The index is given by a range constraint. The bounds are known
+         --  to be of a consistent type.
+
+         if not Is_Overloaded (I) then
+            T := Etype (I);
+
+            --  If the bounds are universal, choose the specific predefined
+            --  type.
+
+            if T = Universal_Integer then
+               T := Standard_Integer;
+
+            elsif T = Any_Character then
+
+               if not Ada_83 then
+                  Error_Msg_N
+                    ("ambiguous character literals (could be Wide_Character)",
+                      I);
+               end if;
+
+               T := Standard_Character;
+            end if;
+
+         else
+            T := Any_Type;
+
+            declare
+               Ind : Interp_Index;
+               It  : Interp;
+
+            begin
+               Get_First_Interp (I, Ind, It);
+
+               while Present (It.Typ) loop
+                  if Is_Discrete_Type (It.Typ) then
+
+                     if Found
+                       and then not Covers (It.Typ, T)
+                       and then not Covers (T, It.Typ)
+                     then
+                        Error_Msg_N ("ambiguous bounds in discrete range", I);
+                        exit;
+                     else
+                        T := It.Typ;
+                        Found := True;
+                     end if;
+                  end if;
+
+                  Get_Next_Interp (Ind, It);
+               end loop;
+
+               if T = Any_Type then
+                  Error_Msg_N ("discrete type required for range", I);
+                  Set_Etype (I, Any_Type);
+                  return;
+
+               elsif T = Universal_Integer then
+                  T := Standard_Integer;
+               end if;
+            end;
+         end if;
+
+         if not Is_Discrete_Type (T) then
+            Error_Msg_N ("discrete type required for range", I);
+            Set_Etype (I, Any_Type);
+            return;
+         end if;
+
+         R := I;
+         Process_Range_Expr_In_Decl (R, T, Related_Nod);
+
+      elsif Nkind (I) = N_Subtype_Indication then
+
+         --  The index is given by a subtype with a range constraint.
+
+         T :=  Base_Type (Entity (Subtype_Mark (I)));
+
+         if not Is_Discrete_Type (T) then
+            Error_Msg_N ("discrete type required for range", I);
+            Set_Etype (I, Any_Type);
+            return;
+         end if;
+
+         R := Range_Expression (Constraint (I));
+
+         Resolve (R, T);
+         Process_Range_Expr_In_Decl (R,
+           Entity (Subtype_Mark (I)), Related_Nod);
+
+      elsif Nkind (I) = N_Attribute_Reference then
+
+         --  The parser guarantees that the attribute is a RANGE attribute
+
+         --  Is order critical here (setting T before Resolve). If so,
+         --  document why, if not use Analyze_And_Resolve and get T after???
+
+         Analyze (I);
+         T := Etype (I);
+         Resolve (I, T);
+         R := I;
+
+      --  If none of the above, must be a subtype. We convert this to a
+      --  range attribute reference because in the case of declared first
+      --  named subtypes, the types in the range reference can be different
+      --  from the type of the entity. A range attribute normalizes the
+      --  reference and obtains the correct types for the bounds.
+
+      --  This transformation is in the nature of an expansion, is only
+      --  done if expansion is active. In particular, it is not done on
+      --  formal generic types,  because we need to retain the name of the
+      --  original index for instantiation purposes.
+
+      else
+         if not Is_Entity_Name (I) or else not Is_Type (Entity (I)) then
+            Error_Msg_N ("invalid subtype mark in discrete range ", I);
+            Set_Etype (I, Any_Integer);
+            return;
+         else
+            --  The type mark may be that of an incomplete type. It is only
+            --  now that we can get the full view, previous analysis does
+            --  not look specifically for a type mark.
+
+            Set_Entity (I, Get_Full_View (Entity (I)));
+            Set_Etype  (I, Entity (I));
+            Def_Id := Entity (I);
+
+            if not Is_Discrete_Type (Def_Id) then
+               Error_Msg_N ("discrete type required for index", I);
+               Set_Etype (I, Any_Type);
+               return;
+            end if;
+         end if;
+
+         if Expander_Active then
+            Rewrite (I,
+              Make_Attribute_Reference (Sloc (I),
+                Attribute_Name => Name_Range,
+                Prefix         => Relocate_Node (I)));
+
+            --  The original was a subtype mark that does not freeze. This
+            --  means that the rewritten version must not freeze either.
+
+            Set_Must_Not_Freeze (I);
+            Set_Must_Not_Freeze (Prefix (I));
+
+            --  Is order critical??? if so, document why, if not
+            --  use Analyze_And_Resolve
+
+            Analyze (I);
+            T := Etype (I);
+            Resolve (I, T);
+            R := I;
+
+         else
+            --  Type is legal, nothing else to construct.
+            return;
+         end if;
+      end if;
+
+      if not Is_Discrete_Type (T) then
+         Error_Msg_N ("discrete type required for range", I);
+         Set_Etype (I, Any_Type);
+         return;
+
+      elsif T = Any_Type then
+         Set_Etype (I, Any_Type);
+         return;
+      end if;
+
+      --  We will now create the appropriate Itype to describe the
+      --  range, but first a check. If we originally had a subtype,
+      --  then we just label the range with this subtype. Not only
+      --  is there no need to construct a new subtype, but it is wrong
+      --  to do so for two reasons:
+
+      --    1. A legality concern, if we have a subtype, it must not
+      --       freeze, and the Itype would cause freezing incorrectly
+
+      --    2. An efficiency concern, if we created an Itype, it would
+      --       not be recognized as the same type for the purposes of
+      --       eliminating checks in some circumstances.
+
+      --  We signal this case by setting the subtype entity in Def_Id.
+
+      --  It would be nice to also do this optimization for the cases
+      --  of X'Range and also the explicit range X'First .. X'Last,
+      --  but that is not done yet (it is just an efficiency concern) ???
+
+      if No (Def_Id) then
+
+         Def_Id :=
+           Create_Itype (E_Void, Related_Nod, Related_Id, 'D', Suffix_Index);
+         Set_Etype (Def_Id, Base_Type (T));
+
+         if Is_Signed_Integer_Type (T) then
+            Set_Ekind (Def_Id, E_Signed_Integer_Subtype);
+
+         elsif Is_Modular_Integer_Type (T) then
+            Set_Ekind (Def_Id, E_Modular_Integer_Subtype);
+
+         else
+            Set_Ekind             (Def_Id, E_Enumeration_Subtype);
+            Set_Is_Character_Type (Def_Id, Is_Character_Type (T));
+         end if;
+
+         Set_Size_Info      (Def_Id,                  (T));
+         Set_RM_Size        (Def_Id, RM_Size          (T));
+         Set_First_Rep_Item (Def_Id, First_Rep_Item   (T));
+
+         Set_Scalar_Range   (Def_Id, R);
+         Conditional_Delay  (Def_Id, T);
+
+         --  In the subtype indication case, if the immediate parent of the
+         --  new subtype is non-static, then the subtype we create is non-
+         --  static, even if its bounds are static.
+
+         if Nkind (I) = N_Subtype_Indication
+           and then not Is_Static_Subtype (Entity (Subtype_Mark (I)))
+         then
+            Set_Is_Non_Static_Subtype (Def_Id);
+         end if;
+      end if;
+
+      --  Final step is to label the index with this constructed type
+
+      Set_Etype (I, Def_Id);
+   end Make_Index;
+
+   ------------------------------
+   -- Modular_Type_Declaration --
+   ------------------------------
+
+   procedure Modular_Type_Declaration (T : Entity_Id; Def : Node_Id) is
+      Mod_Expr : constant Node_Id := Expression (Def);
+      M_Val    : Uint;
+
+      procedure Set_Modular_Size (Bits : Int);
+      --  Sets RM_Size to Bits, and Esize to normal word size above this
+
+      procedure Set_Modular_Size (Bits : Int) is
+      begin
+         Set_RM_Size (T, UI_From_Int (Bits));
+
+         if Bits <= 8 then
+            Init_Esize (T, 8);
+
+         elsif Bits <= 16 then
+            Init_Esize (T, 16);
+
+         elsif Bits <= 32 then
+            Init_Esize (T, 32);
+
+         else
+            Init_Esize (T, System_Max_Binary_Modulus_Power);
+         end if;
+      end Set_Modular_Size;
+
+   --  Start of processing for Modular_Type_Declaration
+
+   begin
+      Analyze_And_Resolve (Mod_Expr, Any_Integer);
+      Set_Etype (T, T);
+      Set_Ekind (T, E_Modular_Integer_Type);
+      Init_Alignment (T);
+      Set_Is_Constrained (T);
+
+      if not Is_OK_Static_Expression (Mod_Expr) then
+         Error_Msg_N
+           ("non-static expression used for modular type bound", Mod_Expr);
+         M_Val := 2 ** System_Max_Binary_Modulus_Power;
+      else
+         M_Val := Expr_Value (Mod_Expr);
+      end if;
+
+      if M_Val < 1 then
+         Error_Msg_N ("modulus value must be positive", Mod_Expr);
+         M_Val := 2 ** System_Max_Binary_Modulus_Power;
+      end if;
+
+      Set_Modulus (T, M_Val);
+
+      --   Create bounds for the modular type based on the modulus given in
+      --   the type declaration and then analyze and resolve those bounds.
+
+      Set_Scalar_Range (T,
+        Make_Range (Sloc (Mod_Expr),
+          Low_Bound  =>
+            Make_Integer_Literal (Sloc (Mod_Expr), 0),
+          High_Bound =>
+            Make_Integer_Literal (Sloc (Mod_Expr), M_Val - 1)));
+
+      --  Properly analyze the literals for the range. We do this manually
+      --  because we can't go calling Resolve, since we are resolving these
+      --  bounds with the type, and this type is certainly not complete yet!
+
+      Set_Etype (Low_Bound  (Scalar_Range (T)), T);
+      Set_Etype (High_Bound (Scalar_Range (T)), T);
+      Set_Is_Static_Expression (Low_Bound  (Scalar_Range (T)));
+      Set_Is_Static_Expression (High_Bound (Scalar_Range (T)));
+
+      --  Loop through powers of two to find number of bits required
+
+      for Bits in Int range 0 .. System_Max_Binary_Modulus_Power loop
+
+         --  Binary case
+
+         if M_Val = 2 ** Bits then
+            Set_Modular_Size (Bits);
+            return;
+
+         --  Non-binary case
+
+         elsif M_Val < 2 ** Bits then
+            Set_Non_Binary_Modulus (T);
+
+            if Bits > System_Max_Nonbinary_Modulus_Power then
+               Error_Msg_Uint_1 :=
+                 UI_From_Int (System_Max_Nonbinary_Modulus_Power);
+               Error_Msg_N
+                 ("nonbinary modulus exceeds limit (2 '*'*^ - 1)", Mod_Expr);
+               Set_Modular_Size (System_Max_Binary_Modulus_Power);
+               return;
+
+            else
+               --  In the non-binary case, set size as per RM 13.3(55).
+
+               Set_Modular_Size (Bits);
+               return;
+            end if;
+         end if;
+
+      end loop;
+
+      --  If we fall through, then the size exceed System.Max_Binary_Modulus
+      --  so we just signal an error and set the maximum size.
+
+      Error_Msg_Uint_1 := UI_From_Int (System_Max_Binary_Modulus_Power);
+      Error_Msg_N ("modulus exceeds limit (2 '*'*^)", Mod_Expr);
+
+      Set_Modular_Size (System_Max_Binary_Modulus_Power);
+      Init_Alignment (T);
+
+   end Modular_Type_Declaration;
+
+   -------------------------
+   -- New_Binary_Operator --
+   -------------------------
+
+   procedure New_Binary_Operator (Op_Name : Name_Id; Typ : Entity_Id) is
+      Loc : constant Source_Ptr := Sloc (Typ);
+      Op  : Entity_Id;
+
+      function Make_Op_Formal (Typ, Op : Entity_Id) return Entity_Id;
+      --  Create abbreviated declaration for the formal of a predefined
+      --  Operator 'Op' of type 'Typ'
+
+      --------------------
+      -- Make_Op_Formal --
+      --------------------
+
+      function Make_Op_Formal (Typ, Op : Entity_Id) return Entity_Id is
+         Formal : Entity_Id;
+
+      begin
+         Formal := New_Internal_Entity (E_In_Parameter, Op, Loc, 'P');
+         Set_Etype (Formal, Typ);
+         Set_Mechanism (Formal, Default_Mechanism);
+         return Formal;
+      end Make_Op_Formal;
+
+   --  Start of processing for New_Binary_Operator
+
+   begin
+      Op := Make_Defining_Operator_Symbol (Loc, Op_Name);
+
+      Set_Ekind                   (Op, E_Operator);
+      Set_Scope                   (Op, Current_Scope);
+      Set_Etype                   (Op, Typ);
+      Set_Homonym                 (Op, Get_Name_Entity_Id (Op_Name));
+      Set_Is_Immediately_Visible  (Op);
+      Set_Is_Intrinsic_Subprogram (Op);
+      Set_Has_Completion          (Op);
+      Append_Entity               (Op, Current_Scope);
+
+      Set_Name_Entity_Id (Op_Name, Op);
+
+      Append_Entity (Make_Op_Formal (Typ, Op), Op);
+      Append_Entity (Make_Op_Formal (Typ, Op), Op);
+
+   end New_Binary_Operator;
+
+   -------------------------------------------
+   -- Ordinary_Fixed_Point_Type_Declaration --
+   -------------------------------------------
+
+   procedure Ordinary_Fixed_Point_Type_Declaration
+     (T   : Entity_Id;
+      Def : Node_Id)
+   is
+      Loc           : constant Source_Ptr := Sloc (Def);
+      Delta_Expr    : constant Node_Id    := Delta_Expression (Def);
+      RRS           : constant Node_Id    := Real_Range_Specification (Def);
+      Implicit_Base : Entity_Id;
+      Delta_Val     : Ureal;
+      Small_Val     : Ureal;
+      Low_Val       : Ureal;
+      High_Val      : Ureal;
+
+   begin
+      Check_Restriction (No_Fixed_Point, Def);
+
+      --  Create implicit base type
+
+      Implicit_Base :=
+        Create_Itype (E_Ordinary_Fixed_Point_Type, Parent (Def), T, 'B');
+      Set_Etype (Implicit_Base, Implicit_Base);
+
+      --  Analyze and process delta expression
+
+      Analyze_And_Resolve (Delta_Expr, Any_Real);
+
+      Check_Delta_Expression (Delta_Expr);
+      Delta_Val := Expr_Value_R (Delta_Expr);
+
+      Set_Delta_Value (Implicit_Base, Delta_Val);
+
+      --  Compute default small from given delta, which is the largest
+      --  power of two that does not exceed the given delta value.
+
+      declare
+         Tmp   : Ureal := Ureal_1;
+         Scale : Int   := 0;
+
+      begin
+         if Delta_Val < Ureal_1 then
+            while Delta_Val < Tmp loop
+               Tmp := Tmp / Ureal_2;
+               Scale := Scale + 1;
+            end loop;
+
+         else
+            loop
+               Tmp := Tmp * Ureal_2;
+               exit when Tmp > Delta_Val;
+               Scale := Scale - 1;
+            end loop;
+         end if;
+
+         Small_Val := UR_From_Components (Uint_1, UI_From_Int (Scale), 2);
+      end;
+
+      Set_Small_Value (Implicit_Base, Small_Val);
+
+      --  If no range was given, set a dummy range
+
+      if RRS <= Empty_Or_Error then
+         Low_Val  := -Small_Val;
+         High_Val := Small_Val;
+
+      --  Otherwise analyze and process given range
+
+      else
+         declare
+            Low  : constant Node_Id := Low_Bound  (RRS);
+            High : constant Node_Id := High_Bound (RRS);
+
+         begin
+            Analyze_And_Resolve (Low, Any_Real);
+            Analyze_And_Resolve (High, Any_Real);
+            Check_Real_Bound (Low);
+            Check_Real_Bound (High);
+
+            --  Obtain and set the range
+
+            Low_Val  := Expr_Value_R (Low);
+            High_Val := Expr_Value_R (High);
+
+            if Low_Val > High_Val then
+               Error_Msg_NE ("?fixed point type& has null range", Def, T);
+            end if;
+         end;
+      end if;
+
+      --  The range for both the implicit base and the declared first
+      --  subtype cannot be set yet, so we use the special routine
+      --  Set_Fixed_Range to set a temporary range in place. Note that
+      --  the bounds of the base type will be widened to be symmetrical
+      --  and to fill the available bits when the type is frozen.
+
+      --  We could do this with all discrete types, and probably should, but
+      --  we absolutely have to do it for fixed-point, since the end-points
+      --  of the range and the size are determined by the small value, which
+      --  could be reset before the freeze point.
+
+      Set_Fixed_Range (Implicit_Base, Loc, Low_Val, High_Val);
+      Set_Fixed_Range (T, Loc, Low_Val, High_Val);
+
+      Init_Size_Align (Implicit_Base);
+
+      --  Complete definition of first subtype
+
+      Set_Ekind          (T, E_Ordinary_Fixed_Point_Subtype);
+      Set_Etype          (T, Implicit_Base);
+      Init_Size_Align    (T);
+      Set_First_Rep_Item (T, First_Rep_Item (Implicit_Base));
+      Set_Small_Value    (T, Small_Val);
+      Set_Delta_Value    (T, Delta_Val);
+      Set_Is_Constrained (T);
+
+   end Ordinary_Fixed_Point_Type_Declaration;
+
+   ----------------------------------------
+   -- Prepare_Private_Subtype_Completion --
+   ----------------------------------------
+
+   procedure Prepare_Private_Subtype_Completion
+     (Id          : Entity_Id;
+      Related_Nod : Node_Id)
+   is
+      Id_B   : constant Entity_Id := Base_Type (Id);
+      Full_B : constant Entity_Id := Full_View (Id_B);
+      Full   : Entity_Id;
+
+   begin
+      if Present (Full_B) then
+
+         --  The Base_Type is already completed, we can complete the
+         --  subtype now. We have to create a new entity with the same name,
+         --  Thus we can't use Create_Itype.
+         --  This is messy, should be fixed ???
+
+         Full := Make_Defining_Identifier (Sloc (Id), Chars (Id));
+         Set_Is_Itype (Full);
+         Set_Associated_Node_For_Itype (Full, Related_Nod);
+         Complete_Private_Subtype (Id, Full, Full_B, Related_Nod);
+      end if;
+
+      --  The parent subtype may be private, but the base might not, in some
+      --  nested instances. In that case, the subtype does not need to be
+      --  exchanged. It would still be nice to make private subtypes and their
+      --  bases consistent at all times ???
+
+      if Is_Private_Type (Id_B) then
+         Append_Elmt (Id, Private_Dependents (Id_B));
+      end if;
+
+   end Prepare_Private_Subtype_Completion;
+
+   ---------------------------
+   -- Process_Discriminants --
+   ---------------------------
+
+   procedure Process_Discriminants (N : Node_Id) is
+      Id                  : Node_Id;
+      Discr               : Node_Id;
+      Discr_Number        : Uint;
+      Discr_Type          : Entity_Id;
+      Default_Present     : Boolean := False;
+      Default_Not_Present : Boolean := False;
+      Elist               : Elist_Id := New_Elmt_List;
+
+   begin
+      --  A composite type other than an array type can have discriminants.
+      --  Discriminants of non-limited types must have a discrete type.
+      --  On entry, the current scope is the composite type.
+
+      --  The discriminants are initially entered into the scope of the type
+      --  via Enter_Name with the default Ekind of E_Void to prevent premature
+      --  use, as explained at the end of this procedure.
+
+      Discr := First (Discriminant_Specifications (N));
+      while Present (Discr) loop
+         Enter_Name (Defining_Identifier (Discr));
+
+         if Nkind (Discriminant_Type (Discr)) = N_Access_Definition then
+            Discr_Type := Access_Definition (N, Discriminant_Type (Discr));
+
+         else
+            Find_Type (Discriminant_Type (Discr));
+            Discr_Type := Etype (Discriminant_Type (Discr));
+
+            if Error_Posted (Discriminant_Type (Discr)) then
+               Discr_Type := Any_Type;
+            end if;
+         end if;
+
+         if Is_Access_Type (Discr_Type) then
+            Check_Access_Discriminant_Requires_Limited
+              (Discr, Discriminant_Type (Discr));
+
+            if Ada_83 and then Comes_From_Source (Discr) then
+               Error_Msg_N
+                 ("(Ada 83) access discriminant not allowed", Discr);
+            end if;
+
+         elsif not Is_Discrete_Type (Discr_Type) then
+            Error_Msg_N ("discriminants must have a discrete or access type",
+              Discriminant_Type (Discr));
+         end if;
+
+         Set_Etype (Defining_Identifier (Discr), Discr_Type);
+
+         --  If a discriminant specification includes the assignment compound
+         --  delimiter followed by an expression, the expression is the default
+         --  expression of the discriminant; the default expression must be of
+         --  the type of the discriminant. (RM 3.7.1) Since this expression is
+         --  a default expression, we do the special preanalysis, since this
+         --  expression does not freeze (see "Handling of Default Expressions"
+         --  in spec of package Sem).
+
+         if Present (Expression (Discr)) then
+            Analyze_Default_Expression (Expression (Discr), Discr_Type);
+
+            if Nkind (N) = N_Formal_Type_Declaration then
+               Error_Msg_N
+                 ("discriminant defaults not allowed for formal type",
+                  Expression (Discr));
+
+            elsif Is_Tagged_Type (Current_Scope) then
+               Error_Msg_N
+                 ("discriminants of tagged type cannot have defaults",
+                  Expression (Discr));
+
+            else
+               Default_Present := True;
+               Append_Elmt (Expression (Discr), Elist);
+
+               --  Tag the defining identifiers for the discriminants with
+               --  their corresponding default expressions from the tree.
+
+               Set_Discriminant_Default_Value
+                 (Defining_Identifier (Discr), Expression (Discr));
+            end if;
+
+         else
+            Default_Not_Present := True;
+         end if;
+
+         Next (Discr);
+      end loop;
+
+      --  An element list consisting of the default expressions of the
+      --  discriminants is constructed in the above loop and used to set
+      --  the Discriminant_Constraint attribute for the type. If an object
+      --  is declared of this (record or task) type without any explicit
+      --  discriminant constraint given, this element list will form the
+      --  actual parameters for the corresponding initialization procedure
+      --  for the type.
+
+      Set_Discriminant_Constraint (Current_Scope, Elist);
+      Set_Girder_Constraint (Current_Scope, No_Elist);
+
+      --  Default expressions must be provided either for all or for none
+      --  of the discriminants of a discriminant part. (RM 3.7.1)
+
+      if Default_Present and then Default_Not_Present then
+         Error_Msg_N
+           ("incomplete specification of defaults for discriminants", N);
+      end if;
+
+      --  The use of the name of a discriminant is not allowed in default
+      --  expressions of a discriminant part if the specification of the
+      --  discriminant is itself given in the discriminant part. (RM 3.7.1)
+
+      --  To detect this, the discriminant names are entered initially with an
+      --  Ekind of E_Void (which is the default Ekind given by Enter_Name). Any
+      --  attempt to use a void entity (for example in an expression that is
+      --  type-checked) produces the error message: premature usage. Now after
+      --  completing the semantic analysis of the discriminant part, we can set
+      --  the Ekind of all the discriminants appropriately.
+
+      Discr := First (Discriminant_Specifications (N));
+      Discr_Number := Uint_1;
+
+      while Present (Discr) loop
+         Id := Defining_Identifier (Discr);
+         Set_Ekind (Id, E_Discriminant);
+         Init_Component_Location (Id);
+         Init_Esize (Id);
+         Set_Discriminant_Number (Id, Discr_Number);
+
+         --  Make sure this is always set, even in illegal programs
+
+         Set_Corresponding_Discriminant (Id, Empty);
+
+         --  Initialize the Original_Record_Component to the entity itself.
+         --  Inherit_Components will propagate the right value to
+         --  discriminants in derived record types.
+
+         Set_Original_Record_Component (Id, Id);
+
+         --  Create the discriminal for the discriminant.
+
+         Build_Discriminal (Id);
+
+         Next (Discr);
+         Discr_Number := Discr_Number + 1;
+      end loop;
+
+      Set_Has_Discriminants (Current_Scope);
+   end Process_Discriminants;
+
+   -----------------------
+   -- Process_Full_View --
+   -----------------------
+
+   procedure Process_Full_View (N : Node_Id; Full_T, Priv_T : Entity_Id) is
+      Priv_Parent : Entity_Id;
+      Full_Parent : Entity_Id;
+      Full_Indic  : Node_Id;
+
+   begin
+      --  First some sanity checks that must be done after semantic
+      --  decoration of the full view and thus cannot be placed with other
+      --  similar checks in Find_Type_Name
+
+      if not Is_Limited_Type (Priv_T)
+        and then (Is_Limited_Type (Full_T)
+                   or else Is_Limited_Composite (Full_T))
+      then
+         Error_Msg_N
+           ("completion of nonlimited type cannot be limited", Full_T);
+
+      elsif Is_Abstract (Full_T) and then not Is_Abstract (Priv_T) then
+         Error_Msg_N
+           ("completion of nonabstract type cannot be abstract", Full_T);
+
+      elsif Is_Tagged_Type (Priv_T)
+        and then Is_Limited_Type (Priv_T)
+        and then not Is_Limited_Type (Full_T)
+      then
+         --  GNAT allow its own definition of Limited_Controlled to disobey
+         --  this rule in order in ease the implementation. The next test is
+         --  safe because Root_Controlled is defined in a private system child
+
+         if Etype (Full_T) = Full_View (RTE (RE_Root_Controlled)) then
+            Set_Is_Limited_Composite (Full_T);
+         else
+            Error_Msg_N
+              ("completion of limited tagged type must be limited", Full_T);
+         end if;
+
+      elsif Is_Generic_Type (Priv_T) then
+         Error_Msg_N ("generic type cannot have a completion", Full_T);
+      end if;
+
+      if Is_Tagged_Type (Priv_T)
+        and then Nkind (Parent (Priv_T)) = N_Private_Extension_Declaration
+        and then Is_Derived_Type (Full_T)
+      then
+         Priv_Parent := Etype (Priv_T);
+
+         --  The full view of a private extension may have been transformed
+         --  into an unconstrained derived type declaration and a subtype
+         --  declaration (see build_derived_record_type for details).
+
+         if Nkind (N) = N_Subtype_Declaration then
+            Full_Indic  := Subtype_Indication (N);
+            Full_Parent := Etype (Base_Type (Full_T));
+         else
+            Full_Indic  := Subtype_Indication (Type_Definition (N));
+            Full_Parent := Etype (Full_T);
+         end if;
+
+         --  Check that the parent type of the full type is a descendant of
+         --  the ancestor subtype given in the private extension. If either
+         --  entity has an Etype equal to Any_Type then we had some previous
+         --  error situation [7.3(8)].
+
+         if Priv_Parent = Any_Type or else Full_Parent = Any_Type then
+            return;
+
+         elsif not Is_Ancestor (Base_Type (Priv_Parent), Full_Parent) then
+            Error_Msg_N
+              ("parent of full type must descend from parent"
+                  & " of private extension", Full_Indic);
+
+         --  Check the rules of 7.3(10): if the private extension inherits
+         --  known discriminants, then the full type must also inherit those
+         --  discriminants from the same (ancestor) type, and the parent
+         --  subtype of the full type must be constrained if and only if
+         --  the ancestor subtype of the private extension is constrained.
+
+         elsif not Present (Discriminant_Specifications (Parent (Priv_T)))
+           and then not Has_Unknown_Discriminants (Priv_T)
+           and then Has_Discriminants (Base_Type (Priv_Parent))
+         then
+            declare
+               Priv_Indic  : constant Node_Id :=
+                               Subtype_Indication (Parent (Priv_T));
+
+               Priv_Constr : constant Boolean :=
+                               Is_Constrained (Priv_Parent)
+                                 or else
+                                   Nkind (Priv_Indic) = N_Subtype_Indication
+                                 or else Is_Constrained (Entity (Priv_Indic));
+
+               Full_Constr : constant Boolean :=
+                               Is_Constrained (Full_Parent)
+                                 or else
+                                   Nkind (Full_Indic) = N_Subtype_Indication
+                                 or else Is_Constrained (Entity (Full_Indic));
+
+               Priv_Discr : Entity_Id;
+               Full_Discr : Entity_Id;
+
+            begin
+               Priv_Discr := First_Discriminant (Priv_Parent);
+               Full_Discr := First_Discriminant (Full_Parent);
+
+               while Present (Priv_Discr) and then Present (Full_Discr) loop
+                  if Original_Record_Component (Priv_Discr) =
+                     Original_Record_Component (Full_Discr)
+                    or else
+                     Corresponding_Discriminant (Priv_Discr) =
+                     Corresponding_Discriminant (Full_Discr)
+                  then
+                     null;
+                  else
+                     exit;
+                  end if;
+
+                  Next_Discriminant (Priv_Discr);
+                  Next_Discriminant (Full_Discr);
+               end loop;
+
+               if Present (Priv_Discr) or else Present (Full_Discr) then
+                  Error_Msg_N
+                    ("full view must inherit discriminants of the parent type"
+                     & " used in the private extension", Full_Indic);
+
+               elsif Priv_Constr and then not Full_Constr then
+                  Error_Msg_N
+                    ("parent subtype of full type must be constrained",
+                     Full_Indic);
+
+               elsif Full_Constr and then not Priv_Constr then
+                  Error_Msg_N
+                    ("parent subtype of full type must be unconstrained",
+                     Full_Indic);
+               end if;
+            end;
+
+         --  Check the rules of 7.3(12): if a partial view has neither known
+         --  or unknown discriminants, then the full type declaration shall
+         --  define a definite subtype.
+
+         elsif      not Has_Unknown_Discriminants (Priv_T)
+           and then not Has_Discriminants (Priv_T)
+           and then not Is_Constrained (Full_T)
+         then
+            Error_Msg_N
+              ("full view must define a constrained type if partial view"
+               & " has no discriminants", Full_T);
+         end if;
+
+         --  ??????? Do we implement the following properly ?????
+         --  If the ancestor subtype of a private extension has constrained
+         --  discriminants, then the parent subtype of the full view shall
+         --  impose a statically matching constraint on those discriminants
+         --  [7.3(13)].
+
+      else
+         --  For untagged types, verify that a type without discriminants
+         --  is not completed with an unconstrained type.
+
+         if not Is_Indefinite_Subtype (Priv_T)
+           and then Is_Indefinite_Subtype (Full_T)
+         then
+            Error_Msg_N ("full view of type must be definite subtype", Full_T);
+         end if;
+      end if;
+
+      --  Create a full declaration for all its subtypes recorded in
+      --  Private_Dependents and swap them similarly to the base type.
+      --  These are subtypes that have been define before the full
+      --  declaration of the private type. We also swap the entry in
+      --  Private_Dependents list so we can properly restore the
+      --  private view on exit from the scope.
+
+      declare
+         Priv_Elmt : Elmt_Id;
+         Priv      : Entity_Id;
+         Full      : Entity_Id;
+
+      begin
+         Priv_Elmt := First_Elmt (Private_Dependents (Priv_T));
+         while Present (Priv_Elmt) loop
+            Priv := Node (Priv_Elmt);
+
+            if Ekind (Priv) = E_Private_Subtype
+              or else Ekind (Priv) = E_Limited_Private_Subtype
+              or else Ekind (Priv) = E_Record_Subtype_With_Private
+            then
+               Full := Make_Defining_Identifier (Sloc (Priv), Chars (Priv));
+               Set_Is_Itype (Full);
+               Set_Parent (Full, Parent (Priv));
+               Set_Associated_Node_For_Itype (Full, N);
+
+               --  Now we need to complete the private subtype, but since the
+               --  base type has already been swapped, we must also swap the
+               --  subtypes (and thus, reverse the arguments in the call to
+               --  Complete_Private_Subtype).
+
+               Copy_And_Swap (Priv, Full);
+               Complete_Private_Subtype (Full, Priv, Full_T, N);
+               Replace_Elmt (Priv_Elmt, Full);
+            end if;
+
+            Next_Elmt (Priv_Elmt);
+         end loop;
+      end;
+
+      --  If the private view was tagged, copy the new Primitive
+      --  operations from the private view to the full view.
+
+      if Is_Tagged_Type (Full_T) then
+         declare
+            Priv_List : Elist_Id;
+            Full_List : constant Elist_Id := Primitive_Operations (Full_T);
+            P1, P2    : Elmt_Id;
+            Prim      : Entity_Id;
+            D_Type    : Entity_Id;
+
+         begin
+            if Is_Tagged_Type (Priv_T) then
+               Priv_List := Primitive_Operations (Priv_T);
+
+               P1 := First_Elmt (Priv_List);
+               while Present (P1) loop
+                  Prim := Node (P1);
+
+                  --  Transfer explicit primitives, not those inherited from
+                  --  parent of partial view, which will be re-inherited on
+                  --  the full view.
+
+                  if Comes_From_Source (Prim) then
+                     P2 := First_Elmt (Full_List);
+                     while Present (P2) and then Node (P2) /= Prim loop
+                        Next_Elmt (P2);
+                     end loop;
+
+                     --  If not found, that is a new one
+
+                     if No (P2) then
+                        Append_Elmt (Prim, Full_List);
+                     end if;
+                  end if;
+
+                  Next_Elmt (P1);
+               end loop;
+
+            else
+               --  In this case the partial view is untagged, so here we
+               --  locate all of the earlier primitives that need to be
+               --  treated as dispatching (those that appear between the
+               --  two views). Note that these additional operations must
+               --  all be new operations (any earlier operations that
+               --  override inherited operations of the full view will
+               --  already have been inserted in the primitives list and
+               --  marked as dispatching by Check_Operation_From_Private_View.
+               --  Note that implicit "/=" operators are excluded from being
+               --  added to the primitives list since they shouldn't be
+               --  treated as dispatching (tagged "/=" is handled specially).
+
+               Prim := Next_Entity (Full_T);
+               while Present (Prim) and then Prim /= Priv_T loop
+                  if (Ekind (Prim) = E_Procedure
+                       or else Ekind (Prim) = E_Function)
+                  then
+
+                     D_Type := Find_Dispatching_Type (Prim);
+
+                     if D_Type = Full_T
+                       and then (Chars (Prim) /= Name_Op_Ne
+                                  or else Comes_From_Source (Prim))
+                     then
+                        Check_Controlling_Formals (Full_T, Prim);
+
+                        if not Is_Dispatching_Operation (Prim) then
+                           Append_Elmt (Prim, Full_List);
+                           Set_Is_Dispatching_Operation (Prim, True);
+                           Set_DT_Position (Prim, No_Uint);
+                        end if;
+
+                     elsif Is_Dispatching_Operation (Prim)
+                       and then D_Type  /= Full_T
+                     then
+
+                        --  Verify that it is not otherwise controlled by
+                        --  a formal or a return value ot type T.
+
+                        Check_Controlling_Formals (D_Type, Prim);
+                     end if;
+                  end if;
+
+                  Next_Entity (Prim);
+               end loop;
+            end if;
+
+            --  For the tagged case, the two views can share the same
+            --  Primitive Operation list and the same class wide type.
+            --  Update attributes of the class-wide type which depend on
+            --  the full declaration.
+
+            if Is_Tagged_Type (Priv_T) then
+               Set_Primitive_Operations (Priv_T, Full_List);
+               Set_Class_Wide_Type
+                 (Base_Type (Full_T), Class_Wide_Type (Priv_T));
+
+               --  Any other attributes should be propagated to C_W ???
+
+               Set_Has_Task (Class_Wide_Type (Priv_T), Has_Task (Full_T));
+
+            end if;
+         end;
+      end if;
+   end Process_Full_View;
+
+   -----------------------------------
+   -- Process_Incomplete_Dependents --
+   -----------------------------------
+
+   procedure Process_Incomplete_Dependents
+     (N      : Node_Id;
+      Full_T : Entity_Id;
+      Inc_T  : Entity_Id)
+   is
+      Inc_Elmt : Elmt_Id;
+      Priv_Dep : Entity_Id;
+      New_Subt : Entity_Id;
+
+      Disc_Constraint : Elist_Id;
+
+   begin
+      if No (Private_Dependents (Inc_T)) then
+         return;
+
+      else
+         Inc_Elmt := First_Elmt (Private_Dependents (Inc_T));
+
+         --  Itypes that may be generated by the completion of an incomplete
+         --  subtype are not used by the back-end and not attached to the tree.
+         --  They are created only for constraint-checking purposes.
+      end if;
+
+      while Present (Inc_Elmt) loop
+         Priv_Dep := Node (Inc_Elmt);
+
+         if Ekind (Priv_Dep) = E_Subprogram_Type then
+
+            --  An Access_To_Subprogram type may have a return type or a
+            --  parameter type that is incomplete. Replace with the full view.
+
+            if Etype (Priv_Dep) = Inc_T then
+               Set_Etype (Priv_Dep, Full_T);
+            end if;
+
+            declare
+               Formal : Entity_Id;
+
+            begin
+               Formal := First_Formal (Priv_Dep);
+
+               while Present (Formal) loop
+
+                  if Etype (Formal) = Inc_T then
+                     Set_Etype (Formal, Full_T);
+                  end if;
+
+                  Next_Formal (Formal);
+               end loop;
+            end;
+
+         elsif  Is_Overloadable (Priv_Dep) then
+
+            if Is_Tagged_Type (Full_T) then
+
+               --  Subprogram has an access parameter whose designated type
+               --  was incomplete. Reexamine declaration now, because it may
+               --  be a primitive operation of the full type.
+
+               Check_Operation_From_Incomplete_Type (Priv_Dep, Inc_T);
+               Set_Is_Dispatching_Operation (Priv_Dep);
+               Check_Controlling_Formals (Full_T, Priv_Dep);
+            end if;
+
+         elsif Ekind (Priv_Dep) = E_Subprogram_Body then
+
+            --  Can happen during processing of a body before the completion
+            --  of a TA type. Ignore, because spec is also on dependent list.
+
+            return;
+
+         --  Dependent is a subtype
+
+         else
+            --  We build a new subtype indication using the full view of the
+            --  incomplete parent. The discriminant constraints have been
+            --  elaborated already at the point of the subtype declaration.
+
+            New_Subt := Create_Itype (E_Void, N);
+
+            if Has_Discriminants (Full_T) then
+               Disc_Constraint := Discriminant_Constraint (Priv_Dep);
+            else
+               Disc_Constraint := No_Elist;
+            end if;
+
+            Build_Discriminated_Subtype (Full_T, New_Subt, Disc_Constraint, N);
+            Set_Full_View (Priv_Dep, New_Subt);
+         end if;
+
+         Next_Elmt (Inc_Elmt);
+      end loop;
+
+   end Process_Incomplete_Dependents;
+
+   --------------------------------
+   -- Process_Range_Expr_In_Decl --
+   --------------------------------
+
+   procedure Process_Range_Expr_In_Decl
+     (R           : Node_Id;
+      T           : Entity_Id;
+      Related_Nod : Node_Id;
+      Check_List  : List_Id := Empty_List;
+      R_Check_Off : Boolean := False)
+   is
+      Lo, Hi    : Node_Id;
+      R_Checks  : Check_Result;
+      Type_Decl : Node_Id;
+      Def_Id    : Entity_Id;
+
+   begin
+      Analyze_And_Resolve (R, Base_Type (T));
+
+      if Nkind (R) = N_Range then
+         Lo := Low_Bound (R);
+         Hi := High_Bound (R);
+
+         --  If there were errors in the declaration, try and patch up some
+         --  common mistakes in the bounds. The cases handled are literals
+         --  which are Integer where the expected type is Real and vice versa.
+         --  These corrections allow the compilation process to proceed further
+         --  along since some basic assumptions of the format of the bounds
+         --  are guaranteed.
+
+         if Etype (R) = Any_Type then
+
+            if Nkind (Lo) = N_Integer_Literal and then Is_Real_Type (T) then
+               Rewrite (Lo,
+                 Make_Real_Literal (Sloc (Lo), UR_From_Uint (Intval (Lo))));
+
+            elsif Nkind (Hi) = N_Integer_Literal and then Is_Real_Type (T) then
+               Rewrite (Hi,
+                 Make_Real_Literal (Sloc (Hi), UR_From_Uint (Intval (Hi))));
+
+            elsif Nkind (Lo) = N_Real_Literal and then Is_Integer_Type (T) then
+               Rewrite (Lo,
+                 Make_Integer_Literal (Sloc (Lo), UR_To_Uint (Realval (Lo))));
+
+            elsif Nkind (Hi) = N_Real_Literal and then Is_Integer_Type (T) then
+               Rewrite (Hi,
+                 Make_Integer_Literal (Sloc (Hi), UR_To_Uint (Realval (Hi))));
+            end if;
+
+            Set_Etype (Lo, T);
+            Set_Etype (Hi, T);
+         end if;
+
+         --  If the bounds of the range have been mistakenly given as
+         --  string literals (perhaps in place of character literals),
+         --  then an error has already been reported, but we rewrite
+         --  the string literal as a bound of the range's type to
+         --  avoid blowups in later processing that looks at static
+         --  values.
+
+         if Nkind (Lo) = N_String_Literal then
+            Rewrite (Lo,
+              Make_Attribute_Reference (Sloc (Lo),
+                Attribute_Name => Name_First,
+                Prefix => New_Reference_To (T, Sloc (Lo))));
+            Analyze_And_Resolve (Lo);
+         end if;
+
+         if Nkind (Hi) = N_String_Literal then
+            Rewrite (Hi,
+              Make_Attribute_Reference (Sloc (Hi),
+                Attribute_Name => Name_First,
+                Prefix => New_Reference_To (T, Sloc (Hi))));
+            Analyze_And_Resolve (Hi);
+         end if;
+
+         --  If bounds aren't scalar at this point then exit, avoiding
+         --  problems with further processing of the range in this procedure.
+
+         if not Is_Scalar_Type (Etype (Lo)) then
+            return;
+         end if;
+
+         --  Resolve (actually Sem_Eval) has checked that the bounds are in
+         --  then range of the base type. Here we check whether the bounds
+         --  are in the range of the subtype itself. Note that if the bounds
+         --  represent the null range the Constraint_Error exception should
+         --  not be raised.
+
+         --  ??? The following code should be cleaned up as follows
+         --  1. The Is_Null_Range (Lo, Hi) test should disapper since it
+         --     is done in the call to Range_Check (R, T); below
+         --  2. The use of R_Check_Off should be investigated and possibly
+         --     removed, this would clean up things a bit.
+
+         if Is_Null_Range (Lo, Hi) then
+            null;
+
+         else
+            --  We use a flag here instead of suppressing checks on the
+            --  type because the type we check against isn't necessarily the
+            --  place where we put the check.
+
+            if not R_Check_Off then
+               R_Checks := Range_Check (R, T);
+               Type_Decl := Parent (R);
+
+               --  Look up tree to find an appropriate insertion point.
+               --  This seems really junk code, and very brittle, couldn't
+               --  we just use an insert actions call of some kind ???
+
+               while Present (Type_Decl) and then not
+                 (Nkind (Type_Decl) = N_Full_Type_Declaration
+                    or else
+                  Nkind (Type_Decl) = N_Subtype_Declaration
+                    or else
+                  Nkind (Type_Decl) = N_Loop_Statement
+                    or else
+                  Nkind (Type_Decl) = N_Task_Type_Declaration
+                    or else
+                  Nkind (Type_Decl) = N_Single_Task_Declaration
+                    or else
+                  Nkind (Type_Decl) = N_Protected_Type_Declaration
+                    or else
+                  Nkind (Type_Decl) = N_Single_Protected_Declaration)
+               loop
+                  Type_Decl := Parent (Type_Decl);
+               end loop;
+
+               --  Why would Type_Decl not be present???  Without this test,
+               --  short regression tests fail.
+
+               if Present (Type_Decl) then
+                  if Nkind (Type_Decl) = N_Loop_Statement then
+                     declare
+                        Indic : Node_Id := Parent (R);
+                     begin
+                        while Present (Indic) and then not
+                          (Nkind (Indic) = N_Subtype_Indication)
+                        loop
+                           Indic := Parent (Indic);
+                        end loop;
+
+                        if Present (Indic) then
+                           Def_Id := Etype (Subtype_Mark (Indic));
+
+                           Insert_Range_Checks
+                             (R_Checks,
+                              Type_Decl,
+                              Def_Id,
+                              Sloc (Type_Decl),
+                              R,
+                              Do_Before => True);
+                        end if;
+                     end;
+                  else
+                     Def_Id := Defining_Identifier (Type_Decl);
+
+                     if (Ekind (Def_Id) = E_Record_Type
+                          and then Depends_On_Discriminant (R))
+                       or else
+                        (Ekind (Def_Id) = E_Protected_Type
+                          and then Has_Discriminants (Def_Id))
+                     then
+                        Append_Range_Checks
+                          (R_Checks, Check_List, Def_Id, Sloc (Type_Decl), R);
+
+                     else
+                        Insert_Range_Checks
+                          (R_Checks, Type_Decl, Def_Id, Sloc (Type_Decl), R);
+
+                     end if;
+                  end if;
+               end if;
+            end if;
+         end if;
+      end if;
+
+      Get_Index_Bounds (R, Lo, Hi);
+
+      if Expander_Active then
+         Force_Evaluation (Lo);
+         Force_Evaluation (Hi);
+      end if;
+
+   end Process_Range_Expr_In_Decl;
+
+   --------------------------------------
+   -- Process_Real_Range_Specification --
+   --------------------------------------
+
+   procedure Process_Real_Range_Specification (Def : Node_Id) is
+      Spec : constant Node_Id := Real_Range_Specification (Def);
+      Lo   : Node_Id;
+      Hi   : Node_Id;
+      Err  : Boolean := False;
+
+      procedure Analyze_Bound (N : Node_Id);
+      --  Analyze and check one bound
+
+      procedure Analyze_Bound (N : Node_Id) is
+      begin
+         Analyze_And_Resolve (N, Any_Real);
+
+         if not Is_OK_Static_Expression (N) then
+            Error_Msg_N
+              ("bound in real type definition is not static", N);
+            Err := True;
+         end if;
+      end Analyze_Bound;
+
+   begin
+      if Present (Spec) then
+         Lo := Low_Bound (Spec);
+         Hi := High_Bound (Spec);
+         Analyze_Bound (Lo);
+         Analyze_Bound (Hi);
+
+         --  If error, clear away junk range specification
+
+         if Err then
+            Set_Real_Range_Specification (Def, Empty);
+         end if;
+      end if;
+   end Process_Real_Range_Specification;
+
+   ---------------------
+   -- Process_Subtype --
+   ---------------------
+
+   function Process_Subtype
+     (S           : Node_Id;
+      Related_Nod : Node_Id;
+      Related_Id  : Entity_Id := Empty;
+      Suffix      : Character := ' ')
+      return        Entity_Id
+   is
+      P               : Node_Id;
+      Def_Id          : Entity_Id;
+      Full_View_Id    : Entity_Id;
+      Subtype_Mark_Id : Entity_Id;
+      N_Dynamic_Ityp  : Node_Id := Empty;
+
+   begin
+      --  Case of constraint present, so that we have an N_Subtype_Indication
+      --  node (this node is created only if constraints are present).
+
+      if Nkind (S) = N_Subtype_Indication then
+         Find_Type (Subtype_Mark (S));
+
+         if Nkind (Parent (S)) /= N_Access_To_Object_Definition
+           and then not
+            (Nkind (Parent (S)) = N_Subtype_Declaration
+              and then
+             Is_Itype (Defining_Identifier (Parent (S))))
+         then
+            Check_Incomplete (Subtype_Mark (S));
+         end if;
+
+         P := Parent (S);
+         Subtype_Mark_Id := Entity (Subtype_Mark (S));
+
+         if Is_Unchecked_Union (Subtype_Mark_Id)
+           and then Comes_From_Source (Related_Nod)
+         then
+            Error_Msg_N
+              ("cannot create subtype of Unchecked_Union", Related_Nod);
+         end if;
+
+         --  Explicit subtype declaration case
+
+         if Nkind (P) = N_Subtype_Declaration then
+            Def_Id := Defining_Identifier (P);
+
+         --  Explicit derived type definition case
+
+         elsif Nkind (P) = N_Derived_Type_Definition then
+            Def_Id := Defining_Identifier (Parent (P));
+
+         --  Implicit case, the Def_Id must be created as an implicit type.
+         --  The one exception arises in the case of concurrent types,
+         --  array and access types, where other subsidiary implicit types
+         --  may be created and must appear before the main implicit type.
+         --  In these cases we leave Def_Id set to Empty as a signal that
+         --  Create_Itype has not yet been called to create Def_Id.
+
+         else
+            if Is_Array_Type (Subtype_Mark_Id)
+              or else Is_Concurrent_Type (Subtype_Mark_Id)
+              or else Is_Access_Type (Subtype_Mark_Id)
+            then
+               Def_Id := Empty;
+
+            --  For the other cases, we create a new unattached Itype,
+            --  and set the indication to ensure it gets attached later.
+
+            else
+               Def_Id :=
+                 Create_Itype (E_Void, Related_Nod, Related_Id, Suffix);
+            end if;
+
+            N_Dynamic_Ityp := Related_Nod;
+         end if;
+
+         --  If the kind of constraint is invalid for this kind of type,
+         --  then give an error, and then pretend no constraint was given.
+
+         if not Is_Valid_Constraint_Kind
+                   (Ekind (Subtype_Mark_Id), Nkind (Constraint (S)))
+         then
+            Error_Msg_N
+              ("incorrect constraint for this kind of type", Constraint (S));
+
+            Rewrite (S, New_Copy_Tree (Subtype_Mark (S)));
+
+            --  Make recursive call, having got rid of the bogus constraint
+
+            return Process_Subtype (S, Related_Nod, Related_Id, Suffix);
+         end if;
+
+         --  Remaining processing depends on type
+
+         case Ekind (Subtype_Mark_Id) is
+
+            when Access_Kind =>
+               Constrain_Access (Def_Id, S, Related_Nod);
+
+            when Array_Kind =>
+               Constrain_Array (Def_Id, S, Related_Nod, Related_Id, Suffix);
+
+            when Decimal_Fixed_Point_Kind =>
+               Constrain_Decimal (Def_Id, S, N_Dynamic_Ityp);
+
+            when Enumeration_Kind =>
+               Constrain_Enumeration (Def_Id, S, N_Dynamic_Ityp);
+
+            when Ordinary_Fixed_Point_Kind =>
+               Constrain_Ordinary_Fixed (Def_Id, S, N_Dynamic_Ityp);
+
+            when Float_Kind =>
+               Constrain_Float (Def_Id, S, N_Dynamic_Ityp);
+
+            when Integer_Kind =>
+               Constrain_Integer (Def_Id, S, N_Dynamic_Ityp);
+
+            when E_Record_Type     |
+                 E_Record_Subtype  |
+                 Class_Wide_Kind   |
+                 E_Incomplete_Type =>
+               Constrain_Discriminated_Type (Def_Id, S, Related_Nod);
+
+            when Private_Kind =>
+               Constrain_Discriminated_Type (Def_Id, S, Related_Nod);
+               Set_Private_Dependents (Def_Id, New_Elmt_List);
+
+               --  In case of an invalid constraint prevent further processing
+               --  since the type constructed is missing expected fields.
+
+               if Etype (Def_Id) = Any_Type then
+                  return Def_Id;
+               end if;
+
+               --  If the full view is that of a task with discriminants,
+               --  we must constrain both the concurrent type and its
+               --  corresponding record type. Otherwise we will just propagate
+               --  the constraint to the full view, if available.
+
+               if Present (Full_View (Subtype_Mark_Id))
+                 and then Has_Discriminants (Subtype_Mark_Id)
+                 and then Is_Concurrent_Type (Full_View (Subtype_Mark_Id))
+               then
+                  Full_View_Id :=
+                    Create_Itype (E_Void, Related_Nod, Related_Id, Suffix);
+
+                  Set_Entity (Subtype_Mark (S), Full_View (Subtype_Mark_Id));
+                  Constrain_Concurrent (Full_View_Id, S,
+                    Related_Nod, Related_Id, Suffix);
+                  Set_Entity (Subtype_Mark (S), Subtype_Mark_Id);
+                  Set_Full_View (Def_Id, Full_View_Id);
+
+               else
+                  Prepare_Private_Subtype_Completion (Def_Id, Related_Nod);
+               end if;
+
+            when Concurrent_Kind  =>
+               Constrain_Concurrent (Def_Id, S,
+                 Related_Nod, Related_Id, Suffix);
+
+            when others =>
+               Error_Msg_N ("invalid subtype mark in subtype indication", S);
+         end case;
+
+         --  Size and Convention are always inherited from the base type
+
+         Set_Size_Info  (Def_Id,            (Subtype_Mark_Id));
+         Set_Convention (Def_Id, Convention (Subtype_Mark_Id));
+
+         return Def_Id;
+
+      --  Case of no constraints present
+
+      else
+         Find_Type (S);
+         Check_Incomplete (S);
+         return Entity (S);
+      end if;
+   end Process_Subtype;
+
+   -----------------------------
+   -- Record_Type_Declaration --
+   -----------------------------
+
+   procedure Record_Type_Declaration (T : Entity_Id; N : Node_Id) is
+      Def : constant Node_Id := Type_Definition (N);
+      Range_Checks_Suppressed_Flag : Boolean := False;
+
+      Is_Tagged : Boolean;
+      Tag_Comp  : Entity_Id;
+
+   begin
+      --  The flag Is_Tagged_Type might have already been set by Find_Type_Name
+      --  if it detected an error for declaration T. This arises in the case of
+      --  private tagged types where the full view omits the word tagged.
+
+      Is_Tagged := Tagged_Present (Def)
+        or else (Errors_Detected > 0 and then Is_Tagged_Type (T));
+
+      --  Records constitute a scope for the component declarations within.
+      --  The scope is created prior to the processing of these declarations.
+      --  Discriminants are processed first, so that they are visible when
+      --  processing the other components. The Ekind of the record type itself
+      --  is set to E_Record_Type (subtypes appear as E_Record_Subtype).
+
+      --  Enter record scope
+
+      New_Scope (T);
+
+      --  These flags must be initialized before calling Process_Discriminants
+      --  because this routine makes use of them.
+
+      Set_Is_Tagged_Type     (T, Is_Tagged);
+      Set_Is_Limited_Record  (T, Limited_Present (Def));
+
+      --  Type is abstract if full declaration carries keyword, or if
+      --  previous partial view did.
+
+      Set_Is_Abstract (T, Is_Abstract (T) or else Abstract_Present (Def));
+
+      Set_Ekind       (T, E_Record_Type);
+      Set_Etype       (T, T);
+      Init_Size_Align (T);
+
+      Set_Girder_Constraint (T, No_Elist);
+
+      --  If an incomplete or private type declaration was already given for
+      --  the type, then this scope already exists, and the discriminants have
+      --  been declared within. We must verify that the full declaration
+      --  matches the incomplete one.
+
+      Check_Or_Process_Discriminants (N, T);
+
+      Set_Is_Constrained     (T, not Has_Discriminants (T));
+      Set_Has_Delayed_Freeze (T, True);
+
+      --  For tagged types add a manually analyzed component corresponding
+      --  to the component _tag, the corresponding piece of tree will be
+      --  expanded as part of the freezing actions if it is not a CPP_Class.
+
+      if Is_Tagged then
+         --  Do not add the tag unless we are in expansion mode.
+
+         if Expander_Active then
+            Tag_Comp := Make_Defining_Identifier (Sloc (Def), Name_uTag);
+            Enter_Name (Tag_Comp);
+
+            Set_Is_Tag                    (Tag_Comp);
+            Set_Ekind                     (Tag_Comp, E_Component);
+            Set_Etype                     (Tag_Comp, RTE (RE_Tag));
+            Set_DT_Entry_Count            (Tag_Comp, No_Uint);
+            Set_Original_Record_Component (Tag_Comp, Tag_Comp);
+            Init_Component_Location       (Tag_Comp);
+         end if;
+
+         Make_Class_Wide_Type (T);
+         Set_Primitive_Operations (T, New_Elmt_List);
+      end if;
+
+      --  We must suppress range checks when processing the components
+      --  of a record in the presence of discriminants, since we don't
+      --  want spurious checks to be generated during their analysis, but
+      --  must reset the Suppress_Range_Checks flags after having procesed
+      --  the record definition.
+
+      if Has_Discriminants (T) and then not Suppress_Range_Checks (T) then
+         Set_Suppress_Range_Checks (T, True);
+         Range_Checks_Suppressed_Flag := True;
+      end if;
+
+      Record_Type_Definition (Def, T);
+
+      if Range_Checks_Suppressed_Flag then
+         Set_Suppress_Range_Checks (T, False);
+         Range_Checks_Suppressed_Flag := False;
+      end if;
+
+      --  Exit from record scope
+
+      End_Scope;
+   end Record_Type_Declaration;
+
+   ----------------------------
+   -- Record_Type_Definition --
+   ----------------------------
+
+   procedure Record_Type_Definition (Def : Node_Id; T : Entity_Id) is
+      Component          : Entity_Id;
+      Ctrl_Components    : Boolean := False;
+      Final_Storage_Only : Boolean := not Is_Controlled (T);
+
+   begin
+      --  If the component list of a record type is defined by the reserved
+      --  word null and there is no discriminant part, then the record type has
+      --  no components and all records of the type are null records (RM 3.7)
+      --  This procedure is also called to process the extension part of a
+      --  record extension, in which case the current scope may have inherited
+      --  components.
+
+      if No (Def)
+        or else No (Component_List (Def))
+        or else Null_Present (Component_List (Def))
+      then
+         null;
+
+      else
+         Analyze_Declarations (Component_Items (Component_List (Def)));
+
+         if Present (Variant_Part (Component_List (Def))) then
+            Analyze (Variant_Part (Component_List (Def)));
+         end if;
+      end if;
+
+      --  After completing the semantic analysis of the record definition,
+      --  record components, both new and inherited, are accessible. Set
+      --  their kind accordingly.
+
+      Component := First_Entity (Current_Scope);
+      while Present (Component) loop
+
+         if Ekind (Component) = E_Void then
+            Set_Ekind (Component, E_Component);
+            Init_Component_Location (Component);
+         end if;
+
+         if Has_Task (Etype (Component)) then
+            Set_Has_Task (T);
+         end if;
+
+         if Ekind (Component) /= E_Component then
+            null;
+
+         elsif Has_Controlled_Component (Etype (Component))
+           or else (Chars (Component) /= Name_uParent
+                    and then Is_Controlled (Etype (Component)))
+         then
+            Set_Has_Controlled_Component (T, True);
+            Final_Storage_Only := Final_Storage_Only
+              and then Finalize_Storage_Only (Etype (Component));
+            Ctrl_Components := True;
+         end if;
+
+         Next_Entity (Component);
+      end loop;
+
+      --  A type is Finalize_Storage_Only only if all its controlled
+      --  components are so.
+
+      if Ctrl_Components then
+         Set_Finalize_Storage_Only (T, Final_Storage_Only);
+      end if;
+
+      if Present (Def) then
+         Process_End_Label (Def, 'e');
+      end if;
+   end Record_Type_Definition;
+
+   ---------------------
+   -- Set_Fixed_Range --
+   ---------------------
+
+   --  The range for fixed-point types is complicated by the fact that we
+   --  do not know the exact end points at the time of the declaration. This
+   --  is true for three reasons:
+
+   --     A size clause may affect the fudging of the end-points
+   --     A small clause may affect the values of the end-points
+   --     We try to include the end-points if it does not affect the size
+
+   --  This means that the actual end-points must be established at the
+   --  point when the type is frozen. Meanwhile, we first narrow the range
+   --  as permitted (so that it will fit if necessary in a small specified
+   --  size), and then build a range subtree with these narrowed bounds.
+
+   --  Set_Fixed_Range constructs the range from real literal values, and
+   --  sets the range as the Scalar_Range of the given fixed-point type
+   --  entity.
+
+   --  The parent of this range is set to point to the entity so that it
+   --  is properly hooked into the tree (unlike normal Scalar_Range entries
+   --  for other scalar types, which are just pointers to the range in the
+   --  original tree, this would otherwise be an orphan).
+
+   --  The tree is left unanalyzed. When the type is frozen, the processing
+   --  in Freeze.Freeze_Fixed_Point_Type notices that the range is not
+   --  analyzed, and uses this as an indication that it should complete
+   --  work on the range (it will know the final small and size values).
+
+   procedure Set_Fixed_Range
+     (E   : Entity_Id;
+      Loc : Source_Ptr;
+      Lo  : Ureal;
+      Hi  : Ureal)
+   is
+      S : constant Node_Id :=
+            Make_Range (Loc,
+              Low_Bound  => Make_Real_Literal (Loc, Lo),
+              High_Bound => Make_Real_Literal (Loc, Hi));
+
+   begin
+      Set_Scalar_Range (E, S);
+      Set_Parent (S, E);
+   end Set_Fixed_Range;
+
+   --------------------------------------------------------
+   -- Set_Girder_Constraint_From_Discriminant_Constraint --
+   --------------------------------------------------------
+
+   procedure Set_Girder_Constraint_From_Discriminant_Constraint
+     (E : Entity_Id)
+   is
+   begin
+      --  Make sure set if encountered during
+      --  Expand_To_Girder_Constraint
+
+      Set_Girder_Constraint (E, No_Elist);
+
+      --  Give it the right value
+
+      if Is_Constrained (E) and then Has_Discriminants (E) then
+         Set_Girder_Constraint (E,
+           Expand_To_Girder_Constraint (E, Discriminant_Constraint (E)));
+      end if;
+
+   end Set_Girder_Constraint_From_Discriminant_Constraint;
+
+   ----------------------------------
+   -- Set_Scalar_Range_For_Subtype --
+   ----------------------------------
+
+   procedure Set_Scalar_Range_For_Subtype
+     (Def_Id      : Entity_Id;
+      R           : Node_Id;
+      Subt        : Entity_Id;
+      Related_Nod : Node_Id)
+   is
+      Kind : constant Entity_Kind :=  Ekind (Def_Id);
+   begin
+      Set_Scalar_Range (Def_Id, R);
+
+      --  We need to link the range into the tree before resolving it so
+      --  that types that are referenced, including importantly the subtype
+      --  itself, are properly frozen (Freeze_Expression requires that the
+      --  expression be properly linked into the tree). Of course if it is
+      --  already linked in, then we do not disturb the current link.
+
+      if No (Parent (R)) then
+         Set_Parent (R, Def_Id);
+      end if;
+
+      --  Reset the kind of the subtype during analysis of the range, to
+      --  catch possible premature use in the bounds themselves.
+
+      Set_Ekind (Def_Id, E_Void);
+      Process_Range_Expr_In_Decl (R, Subt, Related_Nod);
+      Set_Ekind (Def_Id, Kind);
+
+   end Set_Scalar_Range_For_Subtype;
+
+   -------------------------------------
+   -- Signed_Integer_Type_Declaration --
+   -------------------------------------
+
+   procedure Signed_Integer_Type_Declaration (T : Entity_Id; Def : Node_Id) is
+      Implicit_Base : Entity_Id;
+      Base_Typ      : Entity_Id;
+      Lo_Val        : Uint;
+      Hi_Val        : Uint;
+      Errs          : Boolean := False;
+      Lo            : Node_Id;
+      Hi            : Node_Id;
+
+      function Can_Derive_From (E : Entity_Id) return Boolean;
+      --  Determine whether given bounds allow derivation from specified type
+
+      procedure Check_Bound (Expr : Node_Id);
+      --  Check bound to make sure it is integral and static. If not, post
+      --  appropriate error message and set Errs flag
+
+      function Can_Derive_From (E : Entity_Id) return Boolean is
+         Lo : constant Uint := Expr_Value (Type_Low_Bound (E));
+         Hi : constant Uint := Expr_Value (Type_High_Bound (E));
+
+      begin
+         --  Note we check both bounds against both end values, to deal with
+         --  strange types like ones with a range of 0 .. -12341234.
+
+         return Lo <= Lo_Val and then Lo_Val <= Hi
+                  and then
+                Lo <= Hi_Val and then Hi_Val <= Hi;
+      end Can_Derive_From;
+
+      procedure Check_Bound (Expr : Node_Id) is
+      begin
+         --  If a range constraint is used as an integer type definition, each
+         --  bound of the range must be defined by a static expression of some
+         --  integer type, but the two bounds need not have the same integer
+         --  type (Negative bounds are allowed.) (RM 3.5.4)
+
+         if not Is_Integer_Type (Etype (Expr)) then
+            Error_Msg_N
+              ("integer type definition bounds must be of integer type", Expr);
+            Errs := True;
+
+         elsif not Is_OK_Static_Expression (Expr) then
+            Error_Msg_N
+              ("non-static expression used for integer type bound", Expr);
+            Errs := True;
+
+         --  The bounds are folded into literals, and we set their type to be
+         --  universal, to avoid typing difficulties: we cannot set the type
+         --  of the literal to the new type, because this would be a forward
+         --  reference for the back end,  and if the original type is user-
+         --  defined this can lead to spurious semantic errors (e.g. 2928-003).
+
+         else
+            if Is_Entity_Name (Expr) then
+               Fold_Uint (Expr, Expr_Value (Expr));
+            end if;
+
+            Set_Etype (Expr, Universal_Integer);
+         end if;
+      end Check_Bound;
+
+   --  Start of processing for Signed_Integer_Type_Declaration
+
+   begin
+      --  Create an anonymous base type
+
+      Implicit_Base :=
+        Create_Itype (E_Signed_Integer_Type, Parent (Def), T, 'B');
+
+      --  Analyze and check the bounds, they can be of any integer type
+
+      Lo := Low_Bound (Def);
+      Hi := High_Bound (Def);
+      Analyze_And_Resolve (Lo, Any_Integer);
+      Analyze_And_Resolve (Hi, Any_Integer);
+
+      Check_Bound (Lo);
+      Check_Bound (Hi);
+
+      if Errs then
+         Hi := Type_High_Bound (Standard_Long_Long_Integer);
+         Lo := Type_Low_Bound (Standard_Long_Long_Integer);
+      end if;
+
+      --  Find type to derive from
+
+      Lo_Val := Expr_Value (Lo);
+      Hi_Val := Expr_Value (Hi);
+
+      if Can_Derive_From (Standard_Short_Short_Integer) then
+         Base_Typ := Base_Type (Standard_Short_Short_Integer);
+
+      elsif Can_Derive_From (Standard_Short_Integer) then
+         Base_Typ := Base_Type (Standard_Short_Integer);
+
+      elsif Can_Derive_From (Standard_Integer) then
+         Base_Typ := Base_Type (Standard_Integer);
+
+      elsif Can_Derive_From (Standard_Long_Integer) then
+         Base_Typ := Base_Type (Standard_Long_Integer);
+
+      elsif Can_Derive_From (Standard_Long_Long_Integer) then
+         Base_Typ := Base_Type (Standard_Long_Long_Integer);
+
+      else
+         Base_Typ := Base_Type (Standard_Long_Long_Integer);
+         Error_Msg_N ("integer type definition bounds out of range", Def);
+         Hi := Type_High_Bound (Standard_Long_Long_Integer);
+         Lo := Type_Low_Bound (Standard_Long_Long_Integer);
+      end if;
+
+      --  Complete both implicit base and declared first subtype entities
+
+      Set_Etype          (Implicit_Base, Base_Typ);
+      Set_Scalar_Range   (Implicit_Base, Scalar_Range   (Base_Typ));
+      Set_Size_Info      (Implicit_Base,                (Base_Typ));
+      Set_RM_Size        (Implicit_Base, RM_Size        (Base_Typ));
+      Set_First_Rep_Item (Implicit_Base, First_Rep_Item (Base_Typ));
+
+      Set_Ekind          (T, E_Signed_Integer_Subtype);
+      Set_Etype          (T, Implicit_Base);
+
+      Set_Size_Info      (T,                (Implicit_Base));
+      Set_First_Rep_Item (T, First_Rep_Item (Implicit_Base));
+      Set_Scalar_Range   (T, Def);
+      Set_RM_Size        (T, UI_From_Int (Minimum_Size (T)));
+      Set_Is_Constrained (T);
+
+   end Signed_Integer_Type_Declaration;
+
+end Sem_Ch3;
diff --git a/gcc/ada/sem_ch3.ads b/gcc/ada/sem_ch3.ads
new file mode 100644 (file)
index 0000000..aefb310
--- /dev/null
@@ -0,0 +1,224 @@
+------------------------------------------------------------------------------
+--                                                                          --
+--                         GNAT COMPILER COMPONENTS                         --
+--                                                                          --
+--                              S E M _ C H 3                               --
+--                                                                          --
+--                                 S p e c                                  --
+--                                                                          --
+--                            $Revision: 1.57 $
+--                                                                          --
+--          Copyright (C) 1992-2001 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- --
+-- ware  Foundation;  either version 2,  or (at your option) any later ver- --
+-- sion.  GNAT is distributed in the hope that it will be useful, but WITH- --
+-- OUT ANY WARRANTY;  without even the  implied warranty of MERCHANTABILITY --
+-- or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License --
+-- for  more details.  You should have  received  a copy of the GNU General --
+-- Public License  distributed with GNAT;  see file COPYING.  If not, write --
+-- to  the Free Software Foundation,  59 Temple Place - Suite 330,  Boston, --
+-- MA 02111-1307, USA.                                                      --
+--                                                                          --
+-- GNAT was originally developed  by the GNAT team at  New York University. --
+-- It is now maintained by Ada Core Technologies Inc (http://www.gnat.com). --
+--                                                                          --
+------------------------------------------------------------------------------
+
+with Nlists; use Nlists;
+with Types;  use Types;
+
+package Sem_Ch3  is
+   procedure Analyze_Component_Declaration              (N : Node_Id);
+   procedure Analyze_Incomplete_Type_Decl               (N : Node_Id);
+   procedure Analyze_Itype_Reference                    (N : Node_Id);
+   procedure Analyze_Number_Declaration                 (N : Node_Id);
+   procedure Analyze_Object_Declaration                 (N : Node_Id);
+   procedure Analyze_Others_Choice                      (N : Node_Id);
+   procedure Analyze_Private_Extension_Declaration      (N : Node_Id);
+   procedure Analyze_Subtype_Declaration                (N : Node_Id);
+   procedure Analyze_Subtype_Indication                 (N : Node_Id);
+   procedure Analyze_Type_Declaration                   (N : Node_Id);
+   procedure Analyze_Variant_Part                       (N : Node_Id);
+
+   function Access_Definition
+     (Related_Nod : Node_Id;
+      N           : Node_Id)
+      return        Entity_Id;
+   --  An access definition defines a general access type for a formal
+   --  parameter.  The procedure is called when processing formals, when
+   --  the current scope is the subprogram. The Implicit type is attached
+   --  to the Related_Nod put into the enclosing scope, so that the only
+   --  entities defined in the spec are the formals themselves.
+
+   procedure Access_Subprogram_Declaration
+     (T_Name : Entity_Id;
+      T_Def  : Node_Id);
+   --  The subprogram specification yields the signature of an implicit
+   --  type, whose Ekind is Access_Subprogram_Type. This implicit type is
+   --  the designated type of the declared access type. In subprogram calls,
+   --  the signature of the implicit type works like the profile of a regular
+   --  subprogram.
+
+   procedure Analyze_Declarations (L : List_Id);
+   --  Called to analyze a list of declarations (in what context ???). Also
+   --  performs necessary freezing actions (more description needed ???)
+
+   procedure Analyze_Default_Expression (N : Node_Id; T : Entity_Id);
+   --  Default expressions do not freeze their components, and must be
+   --  analyzed and resolved accordingly, by calling the
+   --  Pre_Analyze_And_Resolve routine and setting the global
+   --  In_Default_Expression flag.
+
+   procedure Array_Type_Declaration (T : in out Entity_Id; Def : Node_Id);
+   --  Process an array type declaration. If the array is constrained, we
+   --  create an implicit parent array type, with the same index types and
+   --  component type.
+
+   procedure Access_Type_Declaration (T : Entity_Id; Def : Node_Id);
+   --  Process an access type declaration
+
+   procedure Check_Abstract_Overriding (T : Entity_Id);
+   --  Check that all abstract subprograms inherited from T's parent type
+   --  have been overridden as required, and that nonabstract subprograms
+   --  have not been incorrectly overridden with an abstract subprogram.
+
+   procedure Check_Aliased_Component_Types (T : Entity_Id);
+   --  Given an array type or record type T, check that if the type is
+   --  nonlimited, then the nominal subtype of any components of T
+   --  that have discriminants must be constrained.
+
+   procedure Check_Completion (Body_Id : Node_Id := Empty);
+   --  At the end of a declarative part, verify that all entities that
+   --  require completion have received one. If Body_Id is absent, the
+   --  error indicating a missing completion is placed on the declaration
+   --  that needs completion. If Body_Id is present, it is the defining
+   --  identifier of a package body, and errors are posted on that node,
+   --  rather than on the declarations that require completion in the package
+   --  declaration.
+
+   procedure Derive_Subprogram
+     (New_Subp       : in out Entity_Id;
+      Parent_Subp    : Entity_Id;
+      Derived_Type   : Entity_Id;
+      Parent_Type    : Entity_Id;
+      Actual_Subp    : Entity_Id := Empty);
+   --  Derive the subprogram Parent_Subp from Parent_Type, and replace the
+   --  subsidiary subtypes with the derived type to build the specification
+   --  of the inherited subprogram (returned in New_Subp). For tagged types,
+   --  the derived subprogram is aliased to that of the actual (in the
+   --  case where Actual_Subp is nonempty) rather than to the corresponding
+   --  subprogram of the parent type.
+
+   procedure Derive_Subprograms
+     (Parent_Type    : Entity_Id;
+      Derived_Type   : Entity_Id;
+      Generic_Actual : Entity_Id := Empty);
+   --  To complete type derivation, collect or retrieve the primitive
+   --  operations of the parent type, and replace the subsidiary subtypes
+   --  with the derived type, to build the specs of the inherited ops.
+   --  For generic actuals, the mapping of the primitive operations to those
+   --  of the parent type is also done by rederiving the operations within
+   --  the instance. For tagged types, the derived subprograms are aliased to
+   --  those of the actual, not those of the ancestor.
+
+   function Expand_To_Girder_Constraint
+     (Typ        : Entity_Id;
+      Constraint : Elist_Id)
+      return       Elist_Id;
+   --  Given a Constraint (ie a list of expressions) on the discriminants of
+   --  Typ, expand it into a constraint on the girder discriminants and
+   --  return the new list of expressions constraining the girder
+   --  discriminants.
+
+   function Find_Type_Name (N : Node_Id) return Entity_Id;
+   --  Enter the identifier in a type definition, or find the entity already
+   --  declared, in the case of the full declaration of an incomplete or
+   --  private type.
+
+   function Get_Discriminant_Value
+     (Discriminant         : Entity_Id;
+      Typ_For_Constraint   : Entity_Id;
+      Constraint           : Elist_Id)
+      return                 Node_Id;
+   --  ??? MORE DOCUMENTATION
+   --  Given a discriminant somewhere in the Typ_For_Constraint tree
+   --  and a Constraint, return the value of that discriminant.
+
+   function Is_Visible_Component (C : Entity_Id) return Boolean;
+   --  Determines if a record component C is visible in the present context.
+   --  Note that even though component C could appear in the entity chain
+   --  of a record type, C may not be visible in the current context. For
+   --  instance, C may be a component inherited in the full view of a private
+   --  extension which is not visible in the current context.
+
+   procedure Make_Index
+     (I            : Node_Id;
+      Related_Nod  : Node_Id;
+      Related_Id   : Entity_Id := Empty;
+      Suffix_Index : Nat := 1);
+   --  Process an index that is given in an array declaration, an entry
+   --  family declaration or a loop iteration. The index is given by an
+   --  index declaration (a 'box'), or by a discrete range. The later can
+   --  be the name of a discrete type, or a subtype indication.
+   --  Related_Nod is the node where the potential generated implicit types
+   --  will be inserted. The 2 last parameters are used for creating the name.
+
+   procedure Make_Class_Wide_Type (T : Entity_Id);
+   --  A Class_Wide_Type is created for each tagged type definition. The
+   --  attributes of a class wide type are inherited from those of the type
+   --  T. If T is introduced by a private declaration, the corresponding
+   --  class wide type is created at the same time, and therefore there is
+   --  a private and a full declaration for the class wide type type as well.
+
+   procedure Process_Full_View (N : Node_Id; Full_T, Priv_T : Entity_Id);
+   --  Process some semantic actions when the full view of a private type is
+   --  encountered and analyzed. The first action is to create the full views
+   --  of the dependant private subtypes. The second action is to recopy the
+   --  primitive operations of the private view (in the tagged case).
+   --  N is the N_Full_Type_Declaration node.
+
+   --    Full_T is the full view of the type whose full declaration is in N.
+   --
+   --    Priv_T is the private view of the type whose full declaration is in N.
+
+   procedure Process_Range_Expr_In_Decl
+     (R           : Node_Id;
+      T           : Entity_Id;
+      Related_Nod : Node_Id;
+      Check_List  : List_Id := Empty_List;
+      R_Check_Off : Boolean := False);
+   --  Process a range expression that appears in a declaration context. The
+   --  range is analyzed and resolved with the base type of the given type,
+   --  and an appropriate check for expressions in non-static contexts made
+   --  on the bounds. R is analyzed and resolved using T, so the caller should
+   --  if necessary link R into the tree before the call, and in particular in
+   --  the case of a subtype declaration, it is appropriate to set the parent
+   --  pointer of R so that the types get properly frozen. The Check_List
+   --  parameter is used when the subprogram is called from
+   --  Build_Record_Init_Proc and is used to return a set of constraint
+   --  checking statements generated by the Checks package. R_Check_Off is
+   --  set to True when the call to Range_Check is to be skipped.
+
+   function Process_Subtype
+     (S           : Node_Id;
+      Related_Nod : Node_Id;
+      Related_Id  : Entity_Id := Empty;
+      Suffix      : Character := ' ')
+      return        Entity_Id;
+   --  Process a subtype indication S and return corresponding entity.
+   --  Related_Nod is the node where the potential generated implicit types
+   --  will be inserted. The Related_Id and Suffix parameters are used to
+   --  build the associated Implicit type name.
+
+   procedure Process_Discriminants (N : Node_Id);
+   --  Process the discriminants contained in an N_Full_Type_Declaration or
+   --  N_Incomplete_Type_Decl node N.
+
+   procedure Set_Girder_Constraint_From_Discriminant_Constraint
+     (E : Entity_Id);
+   --  E is some record type. This routine computes E's Girder_Constraint
+   --  from its Discriminant_Constraint.
+
+end Sem_Ch3;
diff --git a/gcc/ada/sem_ch4.adb b/gcc/ada/sem_ch4.adb
new file mode 100644 (file)
index 0000000..31f244d
--- /dev/null
@@ -0,0 +1,4272 @@
+------------------------------------------------------------------------------
+--                                                                          --
+--                         GNAT COMPILER COMPONENTS                         --
+--                                                                          --
+--                              S E M _ C H 4                               --
+--                                                                          --
+--                                 B o d y                                  --
+--                                                                          --
+--                            $Revision: 1.511 $
+--                                                                          --
+--          Copyright (C) 1992-2001, 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- --
+-- ware  Foundation;  either version 2,  or (at your option) any later ver- --
+-- sion.  GNAT is distributed in the hope that it will be useful, but WITH- --
+-- OUT ANY WARRANTY;  without even the  implied warranty of MERCHANTABILITY --
+-- or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License --
+-- for  more details.  You should have  received  a copy of the GNU General --
+-- Public License  distributed with GNAT;  see file COPYING.  If not, write --
+-- to  the Free Software Foundation,  59 Temple Place - Suite 330,  Boston, --
+-- MA 02111-1307, USA.                                                      --
+--                                                                          --
+-- GNAT was originally developed  by the GNAT team at  New York University. --
+-- It is now maintained by Ada Core Technologies Inc (http://www.gnat.com). --
+--                                                                          --
+------------------------------------------------------------------------------
+
+with Atree;    use Atree;
+with Debug;    use Debug;
+with Einfo;    use Einfo;
+with Errout;   use Errout;
+with Exp_Util; use Exp_Util;
+with Hostparm; use Hostparm;
+with Itypes;   use Itypes;
+with Lib.Xref; use Lib.Xref;
+with Namet;    use Namet;
+with Nlists;   use Nlists;
+with Nmake;    use Nmake;
+with Opt;      use Opt;
+with Output;   use Output;
+with Restrict; use Restrict;
+with Sem;      use Sem;
+with Sem_Cat;  use Sem_Cat;
+with Sem_Ch3;  use Sem_Ch3;
+with Sem_Ch8;  use Sem_Ch8;
+with Sem_Dist; use Sem_Dist;
+with Sem_Eval; use Sem_Eval;
+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 Snames;   use Snames;
+with Tbuild;   use Tbuild;
+
+with GNAT.Spelling_Checker; use GNAT.Spelling_Checker;
+
+package body Sem_Ch4 is
+
+   -----------------------
+   -- Local Subprograms --
+   -----------------------
+
+   procedure Analyze_Expression (N : Node_Id);
+   --  For expressions that are not names, this is just a call to analyze.
+   --  If the expression is a name, it may be a call to a parameterless
+   --  function, and if so must be converted into an explicit call node
+   --  and analyzed as such. This deproceduring must be done during the first
+   --  pass of overload resolution, because otherwise a procedure call with
+   --  overloaded actuals may fail to resolve. See 4327-001 for an example.
+
+   procedure Analyze_Operator_Call (N : Node_Id; Op_Id : Entity_Id);
+   --  Analyze a call of the form "+"(x, y), etc. The prefix of the call
+   --  is an operator name or an expanded name whose selector is an operator
+   --  name, and one possible interpretation is as a predefined operator.
+
+   procedure Analyze_Overloaded_Selected_Component (N : Node_Id);
+   --  If the prefix of a selected_component is overloaded, the proper
+   --  interpretation that yields a record type with the proper selector
+   --  name must be selected.
+
+   procedure Analyze_User_Defined_Binary_Op (N : Node_Id; Op_Id : Entity_Id);
+   --  Procedure to analyze a user defined binary operator, which is resolved
+   --  like a function, but instead of a list of actuals it is presented
+   --  with the left and right operands of an operator node.
+
+   procedure Analyze_User_Defined_Unary_Op (N : Node_Id; Op_Id : Entity_Id);
+   --  Procedure to analyze a user defined unary operator, which is resolved
+   --  like a function, but instead of a list of actuals, it is presented with
+   --  the operand of the operator node.
+
+   procedure Ambiguous_Operands (N : Node_Id);
+   --  for equality, membership, and comparison operators with overloaded
+   --  arguments, list possible interpretations.
+
+   procedure Insert_Explicit_Dereference (N : Node_Id);
+   --  In a context that requires a composite or subprogram type and
+   --  where a prefix is an access type, insert an explicit dereference.
+
+   procedure Analyze_One_Call
+      (N       : Node_Id;
+       Nam     : Entity_Id;
+       Report  : Boolean;
+       Success : out Boolean);
+   --  Check one interpretation of an overloaded subprogram name for
+   --  compatibility with the types of the actuals in a call. If there is a
+   --  single interpretation which does not match, post error if Report is
+   --  set to True.
+   --
+   --  Nam is the entity that provides the formals against which the actuals
+   --  are checked. Nam is either the name of a subprogram, or the internal
+   --  subprogram type constructed for an access_to_subprogram. If the actuals
+   --  are compatible with Nam, then Nam is added to the list of candidate
+   --  interpretations for N, and Success is set to True.
+
+   procedure Check_Misspelled_Selector
+     (Prefix : Entity_Id;
+      Sel    : Node_Id);
+   --  Give possible misspelling diagnostic if Sel is likely to be
+   --  a misspelling of one of the selectors of the Prefix.
+   --  This is called by Analyze_Selected_Component after producing
+   --  an invalid selector error message.
+
+   function Defined_In_Scope (T : Entity_Id; S : Entity_Id) return Boolean;
+   --  Verify that type T is declared in scope S. Used to find intepretations
+   --  for operators given by expanded names. This is abstracted as a separate
+   --  function to handle extensions to System, where S is System, but T is
+   --  declared in the extension.
+
+   procedure Find_Arithmetic_Types
+     (L, R  : Node_Id;
+      Op_Id : Entity_Id;
+      N     : Node_Id);
+   --  L and R are the operands of an arithmetic operator. Find
+   --  consistent pairs of interpretations for L and R that have a
+   --  numeric type consistent with the semantics of the operator.
+
+   procedure Find_Comparison_Types
+     (L, R  : Node_Id;
+      Op_Id : Entity_Id;
+      N     : Node_Id);
+   --  L and R are operands of a comparison operator. Find consistent
+   --  pairs of interpretations for L and R.
+
+   procedure Find_Concatenation_Types
+     (L, R  : Node_Id;
+      Op_Id : Entity_Id;
+      N     : Node_Id);
+   --  For the four varieties of concatenation.
+
+   procedure Find_Equality_Types
+     (L, R  : Node_Id;
+      Op_Id : Entity_Id;
+      N     : Node_Id);
+   --  Ditto for equality operators.
+
+   procedure Find_Boolean_Types
+     (L, R  : Node_Id;
+      Op_Id : Entity_Id;
+      N     : Node_Id);
+   --  Ditto for binary logical operations.
+
+   procedure Find_Negation_Types
+     (R     : Node_Id;
+      Op_Id : Entity_Id;
+      N     : Node_Id);
+   --  Find consistent interpretation for operand of negation operator.
+
+   procedure Find_Non_Universal_Interpretations
+     (N     : Node_Id;
+      R     : Node_Id;
+      Op_Id : Entity_Id;
+      T1    : Entity_Id);
+   --  For equality and comparison operators, the result is always boolean,
+   --  and the legality of the operation is determined from the visibility
+   --  of the operand types. If one of the operands has a universal interpre-
+   --  tation,  the legality check uses some compatible non-universal
+   --  interpretation of the other operand. N can be an operator node, or
+   --  a function call whose name is an operator designator.
+
+   procedure Find_Unary_Types
+     (R     : Node_Id;
+      Op_Id : Entity_Id;
+      N     : Node_Id);
+   --  Unary arithmetic types: plus, minus, abs.
+
+   procedure Check_Arithmetic_Pair
+     (T1, T2 : Entity_Id;
+      Op_Id  : Entity_Id;
+      N      : Node_Id);
+   --  Subsidiary procedure to Find_Arithmetic_Types. T1 and T2 are valid
+   --  types for left and right operand. Determine whether they constitute
+   --  a valid pair for the given operator, and record the corresponding
+   --  interpretation of the operator node. The node N may be an operator
+   --  node (the usual case) or a function call whose prefix is an operator
+   --  designator. In  both cases Op_Id is the operator name itself.
+
+   procedure Diagnose_Call (N : Node_Id; Nam : Node_Id);
+   --  Give detailed information on overloaded call where none of the
+   --  interpretations match. N is the call node, Nam the designator for
+   --  the overloaded entity being called.
+
+   function Junk_Operand (N : Node_Id) return Boolean;
+   --  Test for an operand that is an inappropriate entity (e.g. a package
+   --  name or a label). If so, issue an error message and return True. If
+   --  the operand is not an inappropriate entity kind, return False.
+
+   procedure Operator_Check (N : Node_Id);
+   --  Verify that an operator has received some valid interpretation.
+   --  If none was found, determine whether a use clause would make the
+   --  operation legal. The variable Candidate_Type (defined in Sem_Type) is
+   --  set for every type compatible with the operator, even if the operator
+   --  for the type is not directly visible. The routine uses this type to emit
+   --  a more informative message.
+
+   function Try_Indexed_Call
+     (N      : Node_Id;
+      Nam    : Entity_Id;
+      Typ    : Entity_Id)
+      return   Boolean;
+   --  If a function has defaults for all its actuals, a call to it may
+   --  in fact be an indexing on the result of the call. Try_Indexed_Call
+   --  attempts the interpretation as an indexing, prior to analysis as
+   --  a call. If both are possible,  the node is overloaded with both
+   --  interpretations (same symbol but two different types).
+
+   function Try_Indirect_Call
+     (N      : Node_Id;
+      Nam    : Entity_Id;
+      Typ    : Entity_Id)
+      return   Boolean;
+   --  Similarly, a function F that needs no actuals can return an access
+   --  to a subprogram, and the call F (X)  interpreted as F.all (X). In
+   --  this case the call may be overloaded with both interpretations.
+
+   ------------------------
+   -- Ambiguous_Operands --
+   ------------------------
+
+   procedure Ambiguous_Operands (N : Node_Id) is
+      procedure List_Interps (Opnd : Node_Id);
+
+      procedure List_Interps (Opnd : Node_Id) is
+         Index : Interp_Index;
+         It    : Interp;
+         Nam   : Node_Id;
+         Err   : Node_Id := N;
+
+      begin
+         if Is_Overloaded (Opnd) then
+            if Nkind (Opnd) in N_Op then
+               Nam := Opnd;
+
+            elsif Nkind (Opnd) = N_Function_Call then
+               Nam := Name (Opnd);
+
+            else
+               return;
+            end if;
+
+         else
+            return;
+         end if;
+
+         if Opnd = Left_Opnd (N) then
+            Error_Msg_N
+              ("\left operand has the following interpretations", N);
+         else
+            Error_Msg_N
+              ("\right operand has the following interpretations", N);
+            Err := Opnd;
+         end if;
+
+         Get_First_Interp (Nam, Index, It);
+
+         while Present (It.Nam) loop
+
+            if Scope (It.Nam) = Standard_Standard
+              and then Scope (It.Typ) /= Standard_Standard
+            then
+               Error_Msg_Sloc := Sloc (Parent (It.Typ));
+               Error_Msg_NE ("   & (inherited) declared#!", Err, It.Nam);
+
+            else
+               Error_Msg_Sloc := Sloc (It.Nam);
+               Error_Msg_NE ("   & declared#!", Err, It.Nam);
+            end if;
+
+            Get_Next_Interp (Index, It);
+         end loop;
+      end List_Interps;
+
+   begin
+      if Nkind (N) = N_In
+        or else Nkind (N) = N_Not_In
+      then
+         Error_Msg_N ("ambiguous operands for membership",  N);
+
+      elsif Nkind (N) = N_Op_Eq
+        or else Nkind (N) = N_Op_Ne
+      then
+         Error_Msg_N ("ambiguous operands for equality",  N);
+
+      else
+         Error_Msg_N ("ambiguous operands for comparison",  N);
+      end if;
+
+      if All_Errors_Mode then
+         List_Interps (Left_Opnd  (N));
+         List_Interps (Right_Opnd (N));
+      else
+
+         if OpenVMS then
+            Error_Msg_N (
+               "\use '/'R'E'P'O'R'T'_'E'R'R'O'R'S'='F'U'L'L for details",
+                N);
+         else
+            Error_Msg_N ("\use -gnatf for details", N);
+         end if;
+      end if;
+   end Ambiguous_Operands;
+
+   -----------------------
+   -- Analyze_Aggregate --
+   -----------------------
+
+   --  Most of the analysis of Aggregates requires that the type be known,
+   --  and is therefore put off until resolution.
+
+   procedure Analyze_Aggregate (N : Node_Id) is
+   begin
+      if No (Etype (N)) then
+         Set_Etype (N, Any_Composite);
+      end if;
+   end Analyze_Aggregate;
+
+   -----------------------
+   -- Analyze_Allocator --
+   -----------------------
+
+   procedure Analyze_Allocator (N : Node_Id) is
+      Loc      : constant Source_Ptr := Sloc (N);
+      Sav_Errs : constant Nat        := Errors_Detected;
+      E        : Node_Id             := Expression (N);
+      Acc_Type : Entity_Id;
+      Type_Id  : Entity_Id;
+
+   begin
+      Check_Restriction (No_Allocators, N);
+
+      if Nkind (E) = N_Qualified_Expression then
+         Acc_Type := Create_Itype (E_Allocator_Type, N);
+         Set_Etype (Acc_Type, Acc_Type);
+         Init_Size_Align (Acc_Type);
+         Find_Type (Subtype_Mark (E));
+         Type_Id := Entity (Subtype_Mark (E));
+         Check_Fully_Declared (Type_Id, N);
+         Set_Directly_Designated_Type (Acc_Type, Type_Id);
+
+         if Is_Protected_Type (Type_Id) then
+            Check_Restriction (No_Protected_Type_Allocators, N);
+         end if;
+
+         if Is_Limited_Type (Type_Id)
+           and then Comes_From_Source (N)
+           and then not In_Instance_Body
+         then
+            Error_Msg_N ("initialization not allowed for limited types", N);
+         end if;
+
+         Analyze_And_Resolve (Expression (E), Type_Id);
+
+         --  A qualified expression requires an exact match of the type,
+         --  class-wide matching is not allowed.
+
+         if Is_Class_Wide_Type (Type_Id)
+           and then Base_Type (Etype (Expression (E))) /= Base_Type (Type_Id)
+         then
+            Wrong_Type (Expression (E), Type_Id);
+         end if;
+
+         Check_Non_Static_Context (Expression (E));
+
+         --  We don't analyze the qualified expression itself because it's
+         --  part of the allocator
+
+         Set_Etype  (E, Type_Id);
+
+      else
+         declare
+            Def_Id : Entity_Id;
+
+         begin
+            --  If the allocator includes a N_Subtype_Indication then a
+            --  constraint is present, otherwise the node is a subtype mark.
+            --  Introduce an explicit subtype declaration into the tree
+            --  defining some anonymous subtype and rewrite the allocator to
+            --  use this subtype rather than the subtype indication.
+
+            --  It is important to introduce the explicit subtype declaration
+            --  so that the bounds of the subtype indication are attached to
+            --  the tree in case the allocator is inside a generic unit.
+
+            if Nkind (E) = N_Subtype_Indication then
+
+               --  A constraint is only allowed for a composite type in Ada
+               --  95. In Ada 83, a constraint is also allowed for an
+               --  access-to-composite type, but the constraint is ignored.
+
+               Find_Type (Subtype_Mark (E));
+
+               if Is_Elementary_Type (Entity (Subtype_Mark (E))) then
+                  if not (Ada_83
+                           and then Is_Access_Type (Entity (Subtype_Mark (E))))
+                  then
+                     Error_Msg_N ("constraint not allowed here", E);
+
+                     if Nkind (Constraint (E))
+                       = N_Index_Or_Discriminant_Constraint
+                     then
+                        Error_Msg_N
+                          ("\if qualified expression was meant, " &
+                              "use apostrophe", Constraint (E));
+                     end if;
+                  end if;
+
+                  --  Get rid of the bogus constraint:
+
+                  Rewrite (E, New_Copy_Tree (Subtype_Mark (E)));
+                  Analyze_Allocator (N);
+                  return;
+               end if;
+
+               if Expander_Active then
+                  Def_Id :=
+                    Make_Defining_Identifier (Loc, New_Internal_Name ('S'));
+
+                  Insert_Action (E,
+                    Make_Subtype_Declaration (Loc,
+                      Defining_Identifier => Def_Id,
+                      Subtype_Indication  => Relocate_Node (E)));
+
+                  if Sav_Errs /= Errors_Detected
+                    and then Nkind (Constraint (E))
+                      = N_Index_Or_Discriminant_Constraint
+                  then
+                     Error_Msg_N
+                       ("if qualified expression was meant, " &
+                           "use apostrophe!", Constraint (E));
+                  end if;
+
+                  E := New_Occurrence_Of (Def_Id, Loc);
+                  Rewrite (Expression (N), E);
+               end if;
+            end if;
+
+            Type_Id := Process_Subtype (E, N);
+            Acc_Type := Create_Itype (E_Allocator_Type, N);
+            Set_Etype                    (Acc_Type, Acc_Type);
+            Init_Size_Align              (Acc_Type);
+            Set_Directly_Designated_Type (Acc_Type, Type_Id);
+            Check_Fully_Declared (Type_Id, N);
+
+            --  Check for missing initialization. Skip this check if we already
+            --  had errors on analyzing the allocator, since in that case these
+            --  are probably cascaded errors
+
+            if Is_Indefinite_Subtype (Type_Id)
+              and then Errors_Detected = Sav_Errs
+            then
+               if Is_Class_Wide_Type (Type_Id) then
+                  Error_Msg_N
+                    ("initialization required in class-wide allocation", N);
+               else
+                  Error_Msg_N
+                    ("initialization required in unconstrained allocation", N);
+               end if;
+            end if;
+         end;
+      end if;
+
+      if Is_Abstract (Type_Id) then
+         Error_Msg_N ("cannot allocate abstract object", E);
+      end if;
+
+      if Has_Task (Designated_Type (Acc_Type)) then
+         Check_Restriction (No_Task_Allocators, N);
+      end if;
+
+      Set_Etype (N, Acc_Type);
+
+      if not Is_Library_Level_Entity (Acc_Type) then
+         Check_Restriction (No_Local_Allocators, N);
+      end if;
+
+      if Errors_Detected > Sav_Errs then
+         Set_Error_Posted (N);
+         Set_Etype (N, Any_Type);
+      end if;
+
+   end Analyze_Allocator;
+
+   ---------------------------
+   -- Analyze_Arithmetic_Op --
+   ---------------------------
+
+   procedure Analyze_Arithmetic_Op (N : Node_Id) is
+      L     : constant Node_Id := Left_Opnd (N);
+      R     : constant Node_Id := Right_Opnd (N);
+      Op_Id : Entity_Id;
+
+   begin
+      Candidate_Type := Empty;
+      Analyze_Expression (L);
+      Analyze_Expression (R);
+
+      --  If the entity is already set, the node is the instantiation of
+      --  a generic node with a non-local reference, or was manufactured
+      --  by a call to Make_Op_xxx. In either case the entity is known to
+      --  be valid, and we do not need to collect interpretations, instead
+      --  we just get the single possible interpretation.
+
+      Op_Id := Entity (N);
+
+      if Present (Op_Id) then
+         if Ekind (Op_Id) = E_Operator then
+
+            if (Nkind (N) = N_Op_Divide   or else
+                Nkind (N) = N_Op_Mod      or else
+                Nkind (N) = N_Op_Multiply or else
+                Nkind (N) = N_Op_Rem)
+              and then Treat_Fixed_As_Integer (N)
+            then
+               null;
+            else
+               Set_Etype (N, Any_Type);
+               Find_Arithmetic_Types (L, R, Op_Id, N);
+            end if;
+
+         else
+            Set_Etype (N, Any_Type);
+            Add_One_Interp (N, Op_Id, Etype (Op_Id));
+         end if;
+
+      --  Entity is not already set, so we do need to collect interpretations
+
+      else
+         Op_Id := Get_Name_Entity_Id (Chars (N));
+         Set_Etype (N, Any_Type);
+
+         while Present (Op_Id) loop
+            if Ekind (Op_Id) = E_Operator
+              and then Present (Next_Entity (First_Entity (Op_Id)))
+            then
+               Find_Arithmetic_Types (L, R, Op_Id, N);
+
+            --  The following may seem superfluous, because an operator cannot
+            --  be generic, but this ignores the cleverness of the author of
+            --  ACVC bc1013a.
+
+            elsif Is_Overloadable (Op_Id) then
+               Analyze_User_Defined_Binary_Op (N, Op_Id);
+            end if;
+
+            Op_Id := Homonym (Op_Id);
+         end loop;
+      end if;
+
+      Operator_Check (N);
+   end Analyze_Arithmetic_Op;
+
+   ------------------
+   -- Analyze_Call --
+   ------------------
+
+   --  Function, procedure, and entry calls are checked here. The Name
+   --  in the call may be overloaded. The actuals have been analyzed
+   --  and may themselves be overloaded. On exit from this procedure, the node
+   --  N may have zero, one or more interpretations. In the first case an error
+   --  message is produced. In the last case, the node is flagged as overloaded
+   --  and the interpretations are collected in All_Interp.
+
+   --  If the name is an Access_To_Subprogram, it cannot be overloaded, but
+   --  the type-checking is similar to that of other calls.
+
+   procedure Analyze_Call (N : Node_Id) is
+      Actuals : constant List_Id := Parameter_Associations (N);
+      Nam     : Node_Id          := Name (N);
+      X       : Interp_Index;
+      It      : Interp;
+      Nam_Ent : Entity_Id;
+      Success : Boolean := False;
+
+      function Name_Denotes_Function return Boolean;
+      --  If the type of the name is an access to subprogram, this may be
+      --  the type of a name, or the return type of the function being called.
+      --  If the name is not an entity then it can denote a protected function.
+      --  Until we distinguish Etype from Return_Type, we must use this
+      --  routine to resolve the meaning of the name in the call.
+
+      ---------------------------
+      -- Name_Denotes_Function --
+      ---------------------------
+
+      function Name_Denotes_Function return Boolean is
+      begin
+         if Is_Entity_Name (Nam) then
+            return Ekind (Entity (Nam)) = E_Function;
+
+         elsif Nkind (Nam) = N_Selected_Component then
+            return Ekind (Entity (Selector_Name (Nam))) = E_Function;
+
+         else
+            return False;
+         end if;
+      end Name_Denotes_Function;
+
+   --  Start of processing for Analyze_Call
+
+   begin
+      --  Initialize the type of the result of the call to the error type,
+      --  which will be reset if the type is successfully resolved.
+
+      Set_Etype (N, Any_Type);
+
+      if not Is_Overloaded (Nam) then
+
+         --  Only one interpretation to check
+
+         if Ekind (Etype (Nam)) = E_Subprogram_Type then
+            Nam_Ent := Etype (Nam);
+
+         elsif Is_Access_Type (Etype (Nam))
+           and then Ekind (Designated_Type (Etype (Nam))) = E_Subprogram_Type
+           and then not Name_Denotes_Function
+         then
+            Nam_Ent := Designated_Type (Etype (Nam));
+            Insert_Explicit_Dereference (Nam);
+
+         --  Selected component case. Simple entry or protected operation,
+         --  where the entry name is given by the selector name.
+
+         elsif Nkind (Nam) = N_Selected_Component then
+            Nam_Ent := Entity (Selector_Name (Nam));
+
+            if Ekind (Nam_Ent) /= E_Entry
+              and then Ekind (Nam_Ent) /= E_Entry_Family
+              and then Ekind (Nam_Ent) /= E_Function
+              and then Ekind (Nam_Ent) /= E_Procedure
+            then
+               Error_Msg_N ("name in call is not a callable entity", Nam);
+               Set_Etype (N, Any_Type);
+               return;
+            end if;
+
+         --  If the name is an Indexed component, it can be a call to a member
+         --  of an entry family. The prefix must be a selected component whose
+         --  selector is the entry. Analyze_Procedure_Call normalizes several
+         --  kinds of call into this form.
+
+         elsif Nkind (Nam) = N_Indexed_Component then
+
+            if Nkind (Prefix (Nam)) = N_Selected_Component then
+               Nam_Ent := Entity (Selector_Name (Prefix (Nam)));
+
+            else
+               Error_Msg_N ("name in call is not a callable entity", Nam);
+               Set_Etype (N, Any_Type);
+               return;
+
+            end if;
+
+         elsif not Is_Entity_Name (Nam) then
+            Error_Msg_N ("name in call is not a callable entity", Nam);
+            Set_Etype (N, Any_Type);
+            return;
+
+         else
+            Nam_Ent := Entity (Nam);
+
+            --  If no interpretations, give error message
+
+            if not Is_Overloadable (Nam_Ent) then
+               declare
+                  L : constant Boolean   := Is_List_Member (N);
+                  K : constant Node_Kind := Nkind (Parent (N));
+
+               begin
+                  --  If the node is in a list whose parent is not an
+                  --  expression then it must be an attempted procedure call.
+
+                  if L and then K not in N_Subexpr then
+                     if Ekind (Entity (Nam)) = E_Generic_Procedure then
+                        Error_Msg_NE
+                          ("must instantiate generic procedure& before call",
+                           Nam, Entity (Nam));
+                     else
+                        Error_Msg_N
+                          ("procedure or entry name expected", Nam);
+                     end if;
+
+                  --  Check for tasking cases where only an entry call will do
+
+                  elsif not L
+                    and then (K = N_Entry_Call_Alternative
+                               or else K = N_Triggering_Alternative)
+                  then
+                     Error_Msg_N ("entry name expected", Nam);
+
+                  --  Otherwise give general error message
+
+                  else
+                     Error_Msg_N ("invalid prefix in call", Nam);
+                  end if;
+
+                  return;
+               end;
+            end if;
+         end if;
+
+         Analyze_One_Call (N, Nam_Ent, True, Success);
+
+      else
+         --  An overloaded selected component must denote overloaded
+         --  operations of a concurrent type. The interpretations are
+         --  attached to the simple name of those operations.
+
+         if Nkind (Nam) = N_Selected_Component then
+            Nam := Selector_Name (Nam);
+         end if;
+
+         Get_First_Interp (Nam, X, It);
+
+         while Present (It.Nam) loop
+            Nam_Ent := It.Nam;
+
+            --  Name may be call that returns an access to subprogram, or more
+            --  generally an overloaded expression one of whose interpretations
+            --  yields an access to subprogram. If the name is an entity, we
+            --  do not dereference, because the node is a call that returns
+            --  the access type: note difference between f(x), where the call
+            --  may return an access subprogram type, and f(x)(y), where the
+            --  type returned by the call to f is implicitly dereferenced to
+            --  analyze the outer call.
+
+            if Is_Access_Type (Nam_Ent) then
+               Nam_Ent := Designated_Type (Nam_Ent);
+
+            elsif Is_Access_Type (Etype (Nam_Ent))
+              and then not Is_Entity_Name (Nam)
+              and then Ekind (Designated_Type (Etype (Nam_Ent)))
+                                                          = E_Subprogram_Type
+            then
+               Nam_Ent := Designated_Type (Etype (Nam_Ent));
+            end if;
+
+            Analyze_One_Call (N, Nam_Ent, False, Success);
+
+            --  If the interpretation succeeds, mark the proper type of the
+            --  prefix (any valid candidate will do). If not, remove the
+            --  candidate interpretation. This only needs to be done for
+            --  overloaded protected operations, for other entities disambi-
+            --  guation is done directly in Resolve.
+
+            if Success then
+               Set_Etype (Nam, It.Typ);
+
+            elsif Nkind (Name (N)) = N_Selected_Component then
+               Remove_Interp (X);
+            end if;
+
+            Get_Next_Interp (X, It);
+         end loop;
+
+         --  If the name is the result of a function call, it can only
+         --  be a call to a function returning an access to subprogram.
+         --  Insert explicit dereference.
+
+         if Nkind (Nam) = N_Function_Call then
+            Insert_Explicit_Dereference (Nam);
+         end if;
+
+         if Etype (N) = Any_Type then
+
+            --  None of the interpretations is compatible with the actuals
+
+            Diagnose_Call (N, Nam);
+
+            --  Special checks for uninstantiated put routines
+
+            if Nkind (N) = N_Procedure_Call_Statement
+              and then Is_Entity_Name (Nam)
+              and then Chars (Nam) = Name_Put
+              and then List_Length (Actuals) = 1
+            then
+               declare
+                  Arg : constant Node_Id := First (Actuals);
+                  Typ : Entity_Id;
+
+               begin
+                  if Nkind (Arg) = N_Parameter_Association then
+                     Typ := Etype (Explicit_Actual_Parameter (Arg));
+                  else
+                     Typ := Etype (Arg);
+                  end if;
+
+                  if Is_Signed_Integer_Type (Typ) then
+                     Error_Msg_N
+                       ("possible missing instantiation of " &
+                          "'Text_'I'O.'Integer_'I'O!", Nam);
+
+                  elsif Is_Modular_Integer_Type (Typ) then
+                     Error_Msg_N
+                       ("possible missing instantiation of " &
+                          "'Text_'I'O.'Modular_'I'O!", Nam);
+
+                  elsif Is_Floating_Point_Type (Typ) then
+                     Error_Msg_N
+                       ("possible missing instantiation of " &
+                          "'Text_'I'O.'Float_'I'O!", Nam);
+
+                  elsif Is_Ordinary_Fixed_Point_Type (Typ) then
+                     Error_Msg_N
+                       ("possible missing instantiation of " &
+                          "'Text_'I'O.'Fixed_'I'O!", Nam);
+
+                  elsif Is_Decimal_Fixed_Point_Type (Typ) then
+                     Error_Msg_N
+                       ("possible missing instantiation of " &
+                          "'Text_'I'O.'Decimal_'I'O!", Nam);
+
+                  elsif Is_Enumeration_Type (Typ) then
+                     Error_Msg_N
+                       ("possible missing instantiation of " &
+                          "'Text_'I'O.'Enumeration_'I'O!", Nam);
+                  end if;
+               end;
+            end if;
+
+         elsif not Is_Overloaded (N)
+           and then Is_Entity_Name (Nam)
+         then
+            --  Resolution yields a single interpretation. Verify that
+            --  is has the proper capitalization.
+
+            Set_Entity_With_Style_Check (Nam, Entity (Nam));
+            Generate_Reference (Entity (Nam), Nam);
+
+            Set_Etype (Nam, Etype (Entity (Nam)));
+         end if;
+
+         End_Interp_List;
+      end if;
+   end Analyze_Call;
+
+   ---------------------------
+   -- Analyze_Comparison_Op --
+   ---------------------------
+
+   procedure Analyze_Comparison_Op (N : Node_Id) is
+      L     : constant Node_Id := Left_Opnd (N);
+      R     : constant Node_Id := Right_Opnd (N);
+      Op_Id : Entity_Id        := Entity (N);
+
+   begin
+      Set_Etype (N, Any_Type);
+      Candidate_Type := Empty;
+
+      Analyze_Expression (L);
+      Analyze_Expression (R);
+
+      if Present (Op_Id) then
+
+         if Ekind (Op_Id) = E_Operator then
+            Find_Comparison_Types (L, R, Op_Id, N);
+         else
+            Add_One_Interp (N, Op_Id, Etype (Op_Id));
+         end if;
+
+         if Is_Overloaded (L) then
+            Set_Etype (L, Intersect_Types (L, R));
+         end if;
+
+      else
+         Op_Id := Get_Name_Entity_Id (Chars (N));
+
+         while Present (Op_Id) loop
+
+            if Ekind (Op_Id) = E_Operator then
+               Find_Comparison_Types (L, R, Op_Id, N);
+            else
+               Analyze_User_Defined_Binary_Op (N, Op_Id);
+            end if;
+
+            Op_Id := Homonym (Op_Id);
+         end loop;
+      end if;
+
+      Operator_Check (N);
+   end Analyze_Comparison_Op;
+
+   ---------------------------
+   -- Analyze_Concatenation --
+   ---------------------------
+
+   --  If the only one-dimensional array type in scope is String,
+   --  this is the resulting type of the operation. Otherwise there
+   --  will be a concatenation operation defined for each user-defined
+   --  one-dimensional array.
+
+   procedure Analyze_Concatenation (N : Node_Id) is
+      L     : constant Node_Id := Left_Opnd (N);
+      R     : constant Node_Id := Right_Opnd (N);
+      Op_Id : Entity_Id        := Entity (N);
+      LT    : Entity_Id;
+      RT    : Entity_Id;
+
+   begin
+      Set_Etype (N, Any_Type);
+      Candidate_Type := Empty;
+
+      Analyze_Expression (L);
+      Analyze_Expression (R);
+
+      --  If the entity is present, the  node appears in an instance,
+      --  and denotes a predefined concatenation operation. The resulting
+      --  type is obtained from the arguments when possible.
+
+      if Present (Op_Id) then
+         if Ekind (Op_Id) = E_Operator then
+
+            LT := Base_Type (Etype (L));
+            RT := Base_Type (Etype (R));
+
+            if Is_Array_Type (LT)
+              and then (RT = LT or else RT = Base_Type (Component_Type (LT)))
+            then
+               Add_One_Interp (N, Op_Id, LT);
+
+            elsif Is_Array_Type (RT)
+              and then LT = Base_Type (Component_Type (RT))
+            then
+               Add_One_Interp (N, Op_Id, RT);
+
+            else
+               Add_One_Interp (N, Op_Id, Etype (Op_Id));
+            end if;
+
+         else
+            Add_One_Interp (N, Op_Id, Etype (Op_Id));
+         end if;
+
+      else
+         Op_Id  := Get_Name_Entity_Id (Name_Op_Concat);
+
+         while Present (Op_Id) loop
+            if Ekind (Op_Id) = E_Operator then
+               Find_Concatenation_Types (L, R, Op_Id, N);
+            else
+               Analyze_User_Defined_Binary_Op (N, Op_Id);
+            end if;
+
+            Op_Id := Homonym (Op_Id);
+         end loop;
+      end if;
+
+      Operator_Check (N);
+   end Analyze_Concatenation;
+
+   ------------------------------------
+   -- Analyze_Conditional_Expression --
+   ------------------------------------
+
+   procedure Analyze_Conditional_Expression (N : Node_Id) is
+      Condition : constant Node_Id := First (Expressions (N));
+      Then_Expr : constant Node_Id := Next (Condition);
+      Else_Expr : constant Node_Id := Next (Then_Expr);
+
+   begin
+      Analyze_Expression (Condition);
+      Analyze_Expression (Then_Expr);
+      Analyze_Expression (Else_Expr);
+      Set_Etype (N, Etype (Then_Expr));
+   end Analyze_Conditional_Expression;
+
+   -------------------------
+   -- Analyze_Equality_Op --
+   -------------------------
+
+   procedure Analyze_Equality_Op (N : Node_Id) is
+      Loc    : constant Source_Ptr := Sloc (N);
+      L      : constant Node_Id := Left_Opnd (N);
+      R      : constant Node_Id := Right_Opnd (N);
+      Op_Id  : Entity_Id;
+
+   begin
+      Set_Etype (N, Any_Type);
+      Candidate_Type := Empty;
+
+      Analyze_Expression (L);
+      Analyze_Expression (R);
+
+      --  If the entity is set, the node is a generic instance with a non-local
+      --  reference to the predefined operator or to a user-defined function.
+      --  It can also be an inequality that is expanded into the negation of a
+      --  call to a user-defined equality operator.
+
+      --  For the predefined case, the result is Boolean, regardless of the
+      --  type of the  operands. The operands may even be limited, if they are
+      --  generic actuals. If they are overloaded, label the left argument with
+      --  the common type that must be present, or with the type of the formal
+      --  of the user-defined function.
+
+      if Present (Entity (N)) then
+
+         Op_Id := Entity (N);
+
+         if Ekind (Op_Id) = E_Operator then
+            Add_One_Interp (N, Op_Id, Standard_Boolean);
+         else
+            Add_One_Interp (N, Op_Id, Etype (Op_Id));
+         end if;
+
+         if Is_Overloaded (L) then
+
+            if Ekind (Op_Id) = E_Operator then
+               Set_Etype (L, Intersect_Types (L, R));
+            else
+               Set_Etype (L, Etype (First_Formal (Op_Id)));
+            end if;
+         end if;
+
+      else
+         Op_Id := Get_Name_Entity_Id (Chars (N));
+
+         while Present (Op_Id) loop
+
+            if Ekind (Op_Id) = E_Operator then
+               Find_Equality_Types (L, R, Op_Id, N);
+            else
+               Analyze_User_Defined_Binary_Op (N, Op_Id);
+            end if;
+
+            Op_Id := Homonym (Op_Id);
+         end loop;
+      end if;
+
+      --  If there was no match, and the operator is inequality, this may
+      --  be a case where inequality has not been made explicit, as for
+      --  tagged types. Analyze the node as the negation of an equality
+      --  operation. This cannot be done earlier, because before analysis
+      --  we cannot rule out the presence of an explicit inequality.
+
+      if Etype (N) = Any_Type
+        and then Nkind (N) = N_Op_Ne
+      then
+         Op_Id := Get_Name_Entity_Id (Name_Op_Eq);
+
+         while Present (Op_Id) loop
+
+            if Ekind (Op_Id) = E_Operator then
+               Find_Equality_Types (L, R, Op_Id, N);
+            else
+               Analyze_User_Defined_Binary_Op (N, Op_Id);
+            end if;
+
+            Op_Id := Homonym (Op_Id);
+         end loop;
+
+         if Etype (N) /= Any_Type then
+            Op_Id := Entity (N);
+
+            Rewrite (N,
+              Make_Op_Not (Loc,
+                Right_Opnd =>
+                  Make_Op_Eq (Loc,
+                    Left_Opnd =>  Relocate_Node (Left_Opnd (N)),
+                    Right_Opnd => Relocate_Node (Right_Opnd (N)))));
+
+            Set_Entity (Right_Opnd (N), Op_Id);
+            Analyze (N);
+         end if;
+      end if;
+
+      Operator_Check (N);
+   end Analyze_Equality_Op;
+
+   ----------------------------------
+   -- Analyze_Explicit_Dereference --
+   ----------------------------------
+
+   procedure Analyze_Explicit_Dereference (N : Node_Id) is
+      Loc   : constant Source_Ptr := Sloc (N);
+      P     : constant Node_Id := Prefix (N);
+      T     : Entity_Id;
+      I     : Interp_Index;
+      It    : Interp;
+      New_N : Node_Id;
+
+      function Is_Function_Type return Boolean;
+      --  Check whether node may be interpreted as an implicit function call.
+
+      function Is_Function_Type return Boolean is
+         I     : Interp_Index;
+         It    : Interp;
+
+      begin
+         if not Is_Overloaded (N) then
+            return Ekind (Base_Type (Etype (N))) = E_Subprogram_Type
+              and then Etype (Base_Type (Etype (N))) /= Standard_Void_Type;
+
+         else
+            Get_First_Interp (N, I, It);
+
+            while Present (It.Nam) loop
+               if Ekind (Base_Type (It.Typ)) /= E_Subprogram_Type
+                 or else Etype (Base_Type (It.Typ)) = Standard_Void_Type
+               then
+                  return False;
+               end if;
+
+               Get_Next_Interp (I, It);
+            end loop;
+
+            return True;
+         end if;
+      end Is_Function_Type;
+
+   begin
+      Analyze (P);
+      Set_Etype (N, Any_Type);
+
+      --  Test for remote access to subprogram type, and if so return
+      --  after rewriting the original tree.
+
+      if Remote_AST_E_Dereference (P) then
+         return;
+      end if;
+
+      --  Normal processing for other than remote access to subprogram type
+
+      if not Is_Overloaded (P) then
+         if Is_Access_Type (Etype (P)) then
+
+            --  Set the Etype. We need to go thru Is_For_Access_Subtypes
+            --  to avoid other problems caused by the Private_Subtype
+            --  and it is safe to go to the Base_Type because this is the
+            --  same as converting the access value to its Base_Type.
+
+            declare
+               DT : Entity_Id := Designated_Type (Etype (P));
+
+            begin
+               if Ekind (DT) = E_Private_Subtype
+                 and then Is_For_Access_Subtype (DT)
+               then
+                  DT := Base_Type (DT);
+               end if;
+
+               Set_Etype (N, DT);
+            end;
+
+         elsif Etype (P) /= Any_Type then
+            Error_Msg_N ("prefix of dereference must be an access type", N);
+            return;
+         end if;
+
+      else
+         Get_First_Interp (P, I, It);
+
+         while Present (It.Nam) loop
+            T := It.Typ;
+
+            if Is_Access_Type (T) then
+               Add_One_Interp (N, Designated_Type (T), Designated_Type (T));
+            end if;
+
+            Get_Next_Interp (I, It);
+         end loop;
+
+         End_Interp_List;
+
+         --  Error if no interpretation of the prefix has an access type.
+
+         if Etype (N) = Any_Type then
+            Error_Msg_N
+              ("access type required in prefix of explicit dereference", P);
+            Set_Etype (N, Any_Type);
+            return;
+         end if;
+      end if;
+
+      if Is_Function_Type
+        and then Nkind (Parent (N)) /= N_Indexed_Component
+
+        and then (Nkind (Parent (N)) /= N_Function_Call
+                   or else N /= Name (Parent (N)))
+
+        and then (Nkind (Parent (N)) /= N_Procedure_Call_Statement
+                   or else N /= Name (Parent (N)))
+
+        and then Nkind (Parent (N)) /= N_Subprogram_Renaming_Declaration
+        and then (Nkind (Parent (N)) /= N_Attribute_Reference
+                    or else
+                      (Attribute_Name (Parent (N)) /= Name_Address
+                        and then
+                       Attribute_Name (Parent (N)) /= Name_Access))
+      then
+         --  Name is a function call with no actuals, in a context that
+         --  requires deproceduring (including as an actual in an enclosing
+         --  function or procedure call). We can conceive of pathological cases
+         --  where the prefix might include functions that return access to
+         --  subprograms and others that return a regular type. Disambiguation
+         --  of those will have to take place in Resolve. See e.g. 7117-014.
+
+         New_N :=
+           Make_Function_Call (Loc,
+           Name => Make_Explicit_Dereference (Loc, P),
+           Parameter_Associations => New_List);
+
+         --  If the prefix is overloaded, remove operations that have formals,
+         --  we know that this is a parameterless call.
+
+         if Is_Overloaded (P) then
+            Get_First_Interp (P, I, It);
+
+            while Present (It.Nam) loop
+               T := It.Typ;
+
+               if No (First_Formal (Base_Type (Designated_Type (T)))) then
+                  Set_Etype (P, T);
+               else
+                  Remove_Interp (I);
+               end if;
+
+               Get_Next_Interp (I, It);
+            end loop;
+         end if;
+
+         Rewrite (N, New_N);
+         Analyze (N);
+      end if;
+
+      --  A value of remote access-to-class-wide must not be dereferenced
+      --  (RM E.2.2(16)).
+
+      Validate_Remote_Access_To_Class_Wide_Type (N);
+
+   end Analyze_Explicit_Dereference;
+
+   ------------------------
+   -- Analyze_Expression --
+   ------------------------
+
+   procedure Analyze_Expression (N : Node_Id) is
+   begin
+      Analyze (N);
+      Check_Parameterless_Call (N);
+   end Analyze_Expression;
+
+   ------------------------------------
+   -- Analyze_Indexed_Component_Form --
+   ------------------------------------
+
+   procedure Analyze_Indexed_Component_Form (N : Node_Id) is
+      P   : constant Node_Id := Prefix (N);
+      Exprs : List_Id := Expressions (N);
+      Exp : Node_Id;
+      P_T : Entity_Id;
+      E   : Node_Id;
+      U_N : Entity_Id;
+
+      procedure Process_Function_Call;
+      --  Prefix in indexed component form is an overloadable entity,
+      --  so the node is a function call. Reformat it as such.
+
+      procedure Process_Indexed_Component;
+      --  Prefix in indexed component form is actually an indexed component.
+      --  This routine processes it, knowing that the prefix is already
+      --  resolved.
+
+      procedure Process_Indexed_Component_Or_Slice;
+      --  An indexed component with a single index may designate a slice if
+      --  the index is a subtype mark. This routine disambiguates these two
+      --  cases by resolving the prefix to see if it is a subtype mark.
+
+      procedure Process_Overloaded_Indexed_Component;
+      --  If the prefix of an indexed component is overloaded, the proper
+      --  interpretation is selected by the index types and the context.
+
+      ---------------------------
+      -- Process_Function_Call --
+      ---------------------------
+
+      procedure Process_Function_Call is
+         Actual : Node_Id;
+
+      begin
+         Change_Node (N, N_Function_Call);
+         Set_Name (N, P);
+         Set_Parameter_Associations (N, Exprs);
+         Actual := First (Parameter_Associations (N));
+
+         while Present (Actual) loop
+            Analyze (Actual);
+            Check_Parameterless_Call (Actual);
+            Next_Actual (Actual);
+         end loop;
+
+         Analyze_Call (N);
+      end Process_Function_Call;
+
+      -------------------------------
+      -- Process_Indexed_Component --
+      -------------------------------
+
+      procedure Process_Indexed_Component is
+         Exp          : Node_Id;
+         Array_Type   : Entity_Id;
+         Index        : Node_Id;
+         Entry_Family : Entity_Id;
+
+      begin
+         Exp := First (Exprs);
+
+         if Is_Overloaded (P) then
+            Process_Overloaded_Indexed_Component;
+
+         else
+            Array_Type := Etype (P);
+
+            --  Prefix must be appropriate for an array type.
+            --  Dereference the prefix if it is an access type.
+
+            if Is_Access_Type (Array_Type) then
+               Array_Type := Designated_Type (Array_Type);
+            end if;
+
+            if Is_Array_Type (Array_Type) then
+               null;
+
+            elsif (Is_Entity_Name (P)
+                     and then
+                   Ekind (Entity (P)) = E_Entry_Family)
+               or else
+                 (Nkind (P) = N_Selected_Component
+                    and then
+                  Is_Entity_Name (Selector_Name (P))
+                    and then
+                  Ekind (Entity (Selector_Name (P))) = E_Entry_Family)
+            then
+               if Is_Entity_Name (P) then
+                  Entry_Family := Entity (P);
+               else
+                  Entry_Family := Entity (Selector_Name (P));
+               end if;
+
+               Analyze (Exp);
+               Set_Etype (N, Any_Type);
+
+               if not Has_Compatible_Type
+                 (Exp, Entry_Index_Type (Entry_Family))
+               then
+                  Error_Msg_N ("invalid index type in entry name", N);
+
+               elsif Present (Next (Exp)) then
+                  Error_Msg_N ("too many subscripts in entry reference", N);
+
+               else
+                  Set_Etype (N,  Etype (P));
+               end if;
+
+               return;
+
+            elsif Is_Record_Type (Array_Type)
+              and then Remote_AST_I_Dereference (P)
+            then
+               return;
+
+            elsif Array_Type = Any_Type then
+               Set_Etype (N, Any_Type);
+               return;
+
+            --  Here we definitely have a bad indexing
+
+            else
+               if Nkind (Parent (N)) = N_Requeue_Statement
+                 and then
+                   ((Is_Entity_Name (P)
+                        and then Ekind (Entity (P)) = E_Entry)
+                    or else
+                     (Nkind (P) = N_Selected_Component
+                       and then Is_Entity_Name (Selector_Name (P))
+                       and then Ekind (Entity (Selector_Name (P))) = E_Entry))
+               then
+                  Error_Msg_N
+                    ("REQUEUE does not permit parameters", First (Exprs));
+
+               elsif Is_Entity_Name (P)
+                 and then Etype (P) = Standard_Void_Type
+               then
+                  Error_Msg_NE ("incorrect use of&", P, Entity (P));
+
+               else
+                  Error_Msg_N ("array type required in indexed component", P);
+               end if;
+
+               Set_Etype (N, Any_Type);
+               return;
+            end if;
+
+            Index := First_Index (Array_Type);
+
+            while Present (Index) and then Present (Exp) loop
+               if not Has_Compatible_Type (Exp, Etype (Index)) then
+                  Wrong_Type (Exp, Etype (Index));
+                  Set_Etype (N, Any_Type);
+                  return;
+               end if;
+
+               Next_Index (Index);
+               Next (Exp);
+            end loop;
+
+            Set_Etype (N, Component_Type (Array_Type));
+
+            if Present (Index) then
+               Error_Msg_N
+                 ("too few subscripts in array reference", First (Exprs));
+
+            elsif Present (Exp) then
+               Error_Msg_N ("too many subscripts in array reference", Exp);
+            end if;
+         end if;
+
+      end Process_Indexed_Component;
+
+      ----------------------------------------
+      -- Process_Indexed_Component_Or_Slice --
+      ----------------------------------------
+
+      procedure Process_Indexed_Component_Or_Slice is
+      begin
+         Exp := First (Exprs);
+
+         while Present (Exp) loop
+            Analyze_Expression (Exp);
+            Next (Exp);
+         end loop;
+
+         Exp := First (Exprs);
+
+         --  If one index is present, and it is a subtype name, then the
+         --  node denotes a slice (note that the case of an explicit range
+         --  for a slice was already built as an N_Slice node in the first
+         --  place, so that case is not handled here).
+
+         --  We use a replace rather than a rewrite here because this is one
+         --  of the cases in which the tree built by the parser is plain wrong.
+
+         if No (Next (Exp))
+           and then Is_Entity_Name (Exp)
+           and then Is_Type (Entity (Exp))
+         then
+            Replace (N,
+               Make_Slice (Sloc (N),
+                 Prefix => P,
+                 Discrete_Range => New_Copy (Exp)));
+            Analyze (N);
+
+         --  Otherwise (more than one index present, or single index is not
+         --  a subtype name), then we have the indexed component case.
+
+         else
+            Process_Indexed_Component;
+         end if;
+      end Process_Indexed_Component_Or_Slice;
+
+      ------------------------------------------
+      -- Process_Overloaded_Indexed_Component --
+      ------------------------------------------
+
+      procedure Process_Overloaded_Indexed_Component is
+         Exp   : Node_Id;
+         I     : Interp_Index;
+         It    : Interp;
+         Typ   : Entity_Id;
+         Index : Node_Id;
+         Found : Boolean;
+
+      begin
+         Set_Etype (N, Any_Type);
+         Get_First_Interp (P, I, It);
+
+         while Present (It.Nam) loop
+            Typ := It.Typ;
+
+            if Is_Access_Type (Typ) then
+               Typ := Designated_Type (Typ);
+            end if;
+
+            if Is_Array_Type (Typ) then
+
+               --  Got a candidate: verify that index types are compatible
+
+               Index := First_Index (Typ);
+               Found := True;
+
+               Exp := First (Exprs);
+
+               while Present (Index) and then Present (Exp) loop
+                  if Has_Compatible_Type (Exp, Etype (Index)) then
+                     null;
+                  else
+                     Found := False;
+                     Remove_Interp (I);
+                     exit;
+                  end if;
+
+                  Next_Index (Index);
+                  Next (Exp);
+               end loop;
+
+               if Found and then No (Index) and then No (Exp) then
+                  Add_One_Interp (N,
+                     Etype (Component_Type (Typ)),
+                     Etype (Component_Type (Typ)));
+               end if;
+            end if;
+
+            Get_Next_Interp (I, It);
+         end loop;
+
+         if Etype (N) = Any_Type then
+            Error_Msg_N ("no legal interpetation for indexed component", N);
+            Set_Is_Overloaded (N, False);
+         end if;
+
+         End_Interp_List;
+      end Process_Overloaded_Indexed_Component;
+
+   ------------------------------------
+   -- Analyze_Indexed_Component_Form --
+   ------------------------------------
+
+   begin
+      --  Get name of array, function or type
+
+      Analyze (P);
+      P_T := Base_Type (Etype (P));
+
+      if Is_Entity_Name (P)
+        or else Nkind (P) = N_Operator_Symbol
+      then
+         U_N := Entity (P);
+
+         if Ekind (U_N) in  Type_Kind then
+
+            --  Reformat node as a type conversion.
+
+            E := Remove_Head (Exprs);
+
+            if Present (First (Exprs)) then
+               Error_Msg_N
+                ("argument of type conversion must be single expression", N);
+            end if;
+
+            Change_Node (N, N_Type_Conversion);
+            Set_Subtype_Mark (N, P);
+            Set_Etype (N, U_N);
+            Set_Expression (N, E);
+
+            --  After changing the node, call for the specific Analysis
+            --  routine directly, to avoid a double call to the expander.
+
+            Analyze_Type_Conversion (N);
+            return;
+         end if;
+
+         if Is_Overloadable (U_N) then
+            Process_Function_Call;
+
+         elsif Ekind (Etype (P)) = E_Subprogram_Type
+           or else (Is_Access_Type (Etype (P))
+                      and then
+                    Ekind (Designated_Type (Etype (P))) = E_Subprogram_Type)
+         then
+            --  Call to access_to-subprogram with possible implicit dereference
+
+            Process_Function_Call;
+
+         elsif Ekind (U_N) = E_Generic_Function
+           or else Ekind (U_N) = E_Generic_Procedure
+         then
+            --  A common beginner's (or C++ templates fan) error.
+
+            Error_Msg_N ("generic subprogram cannot be called", N);
+            Set_Etype (N, Any_Type);
+            return;
+
+         else
+            Process_Indexed_Component_Or_Slice;
+         end if;
+
+      --  If not an entity name, prefix is an expression that may denote
+      --  an array or an access-to-subprogram.
+
+      else
+
+         if (Ekind (P_T) = E_Subprogram_Type)
+           or else (Is_Access_Type (P_T)
+                     and then
+                    Ekind (Designated_Type (P_T)) = E_Subprogram_Type)
+         then
+            Process_Function_Call;
+
+         elsif Nkind (P) = N_Selected_Component
+           and then Ekind (Entity (Selector_Name (P))) = E_Function
+         then
+            Process_Function_Call;
+
+         else
+            --  Indexed component, slice, or a call to a member of a family
+            --  entry, which will be converted to an entry call later.
+            Process_Indexed_Component_Or_Slice;
+         end if;
+      end if;
+   end Analyze_Indexed_Component_Form;
+
+   ------------------------
+   -- Analyze_Logical_Op --
+   ------------------------
+
+   procedure Analyze_Logical_Op (N : Node_Id) is
+      L     : constant Node_Id := Left_Opnd (N);
+      R     : constant Node_Id := Right_Opnd (N);
+      Op_Id : Entity_Id := Entity (N);
+
+   begin
+      Set_Etype (N, Any_Type);
+      Candidate_Type := Empty;
+
+      Analyze_Expression (L);
+      Analyze_Expression (R);
+
+      if Present (Op_Id) then
+
+         if Ekind (Op_Id) = E_Operator then
+            Find_Boolean_Types (L, R, Op_Id, N);
+         else
+            Add_One_Interp (N, Op_Id, Etype (Op_Id));
+         end if;
+
+      else
+         Op_Id := Get_Name_Entity_Id (Chars (N));
+
+         while Present (Op_Id) loop
+            if Ekind (Op_Id) = E_Operator then
+               Find_Boolean_Types (L, R, Op_Id, N);
+            else
+               Analyze_User_Defined_Binary_Op (N, Op_Id);
+            end if;
+
+            Op_Id := Homonym (Op_Id);
+         end loop;
+      end if;
+
+      Operator_Check (N);
+   end Analyze_Logical_Op;
+
+   ---------------------------
+   -- Analyze_Membership_Op --
+   ---------------------------
+
+   procedure Analyze_Membership_Op (N : Node_Id) is
+      L     : constant Node_Id := Left_Opnd (N);
+      R     : constant Node_Id := Right_Opnd (N);
+
+      Index : Interp_Index;
+      It    : Interp;
+      Found : Boolean := False;
+      I_F   : Interp_Index;
+      T_F   : Entity_Id;
+
+      procedure Try_One_Interp (T1 : Entity_Id);
+      --  Routine to try one proposed interpretation. Note that the context
+      --  of the operation plays no role in resolving the arguments, so that
+      --  if there is more than one interpretation of the operands that is
+      --  compatible with a membership test, the operation is ambiguous.
+
+      procedure Try_One_Interp (T1 : Entity_Id) is
+      begin
+         if Has_Compatible_Type (R, T1) then
+            if Found
+              and then Base_Type (T1) /= Base_Type (T_F)
+            then
+               It := Disambiguate (L, I_F, Index, Any_Type);
+
+               if It = No_Interp then
+                  Ambiguous_Operands (N);
+                  Set_Etype (L, Any_Type);
+                  return;
+
+               else
+                  T_F := It.Typ;
+               end if;
+
+            else
+               Found := True;
+               T_F   := T1;
+               I_F   := Index;
+            end if;
+
+            Set_Etype (L, T_F);
+         end if;
+
+      end Try_One_Interp;
+
+   --  Start of processing for Analyze_Membership_Op
+
+   begin
+      Analyze_Expression (L);
+
+      if Nkind (R) = N_Range
+        or else (Nkind (R) = N_Attribute_Reference
+                  and then Attribute_Name (R) = Name_Range)
+      then
+         Analyze (R);
+
+         if not Is_Overloaded (L) then
+            Try_One_Interp (Etype (L));
+
+         else
+            Get_First_Interp (L, Index, It);
+
+            while Present (It.Typ) loop
+               Try_One_Interp (It.Typ);
+               Get_Next_Interp (Index, It);
+            end loop;
+         end if;
+
+      --  If not a range, it can only be a subtype mark, or else there
+      --  is a more basic error, to be diagnosed in Find_Type.
+
+      else
+         Find_Type (R);
+
+         if Is_Entity_Name (R) then
+            Check_Fully_Declared (Entity (R), R);
+         end if;
+      end if;
+
+      --  Compatibility between expression and subtype mark or range is
+      --  checked during resolution. The result of the operation is Boolean
+      --  in any case.
+
+      Set_Etype (N, Standard_Boolean);
+   end Analyze_Membership_Op;
+
+   ----------------------
+   -- Analyze_Negation --
+   ----------------------
+
+   procedure Analyze_Negation (N : Node_Id) is
+      R     : constant Node_Id := Right_Opnd (N);
+      Op_Id : Entity_Id := Entity (N);
+
+   begin
+      Set_Etype (N, Any_Type);
+      Candidate_Type := Empty;
+
+      Analyze_Expression (R);
+
+      if Present (Op_Id) then
+         if Ekind (Op_Id) = E_Operator then
+            Find_Negation_Types (R, Op_Id, N);
+         else
+            Add_One_Interp (N, Op_Id, Etype (Op_Id));
+         end if;
+
+      else
+         Op_Id := Get_Name_Entity_Id (Chars (N));
+
+         while Present (Op_Id) loop
+            if Ekind (Op_Id) = E_Operator then
+               Find_Negation_Types (R, Op_Id, N);
+            else
+               Analyze_User_Defined_Unary_Op (N, Op_Id);
+            end if;
+
+            Op_Id := Homonym (Op_Id);
+         end loop;
+      end if;
+
+      Operator_Check (N);
+   end Analyze_Negation;
+
+   -------------------
+   --  Analyze_Null --
+   -------------------
+
+   procedure Analyze_Null (N : Node_Id) is
+   begin
+      Set_Etype (N, Any_Access);
+   end Analyze_Null;
+
+   ----------------------
+   -- Analyze_One_Call --
+   ----------------------
+
+   procedure Analyze_One_Call
+      (N       : Node_Id;
+       Nam     : Entity_Id;
+       Report  : Boolean;
+       Success : out Boolean)
+   is
+      Actuals    : constant List_Id   := Parameter_Associations (N);
+      Prev_T     : constant Entity_Id := Etype (N);
+      Formal     : Entity_Id;
+      Actual     : Node_Id;
+      Is_Indexed : Boolean := False;
+      Subp_Type  : constant Entity_Id := Etype (Nam);
+      Norm_OK    : Boolean;
+
+      procedure Set_Name;
+      --  If candidate interpretation matches, indicate name and type of
+      --  result on call node.
+
+      --------------
+      -- Set_Name --
+      --------------
+
+      procedure Set_Name is
+      begin
+         Add_One_Interp (N, Nam, Etype (Nam));
+         Success := True;
+
+         --  If the prefix of the call is a name, indicate the entity
+         --  being called. If it is not a name,  it is an expression that
+         --  denotes an access to subprogram or else an entry or family. In
+         --  the latter case, the name is a selected component, and the entity
+         --  being called is noted on the selector.
+
+         if not Is_Type (Nam) then
+            if Is_Entity_Name (Name (N))
+              or else Nkind (Name (N)) = N_Operator_Symbol
+            then
+               Set_Entity (Name (N), Nam);
+
+            elsif Nkind (Name (N)) = N_Selected_Component then
+               Set_Entity (Selector_Name (Name (N)),  Nam);
+            end if;
+         end if;
+
+         if Debug_Flag_E and not Report then
+            Write_Str (" Overloaded call ");
+            Write_Int (Int (N));
+            Write_Str (" compatible with ");
+            Write_Int (Int (Nam));
+            Write_Eol;
+         end if;
+      end Set_Name;
+
+   --  Start of processing for Analyze_One_Call
+
+   begin
+      Success := False;
+
+      --  If the subprogram has no formals, or if all the formals have
+      --  defaults, and the return type is an array type, the node may
+      --  denote an indexing of the result of a parameterless call.
+
+      if Needs_No_Actuals (Nam)
+        and then Present (Actuals)
+      then
+         if Is_Array_Type (Subp_Type) then
+            Is_Indexed := Try_Indexed_Call (N, Nam, Subp_Type);
+
+         elsif Is_Access_Type (Subp_Type)
+           and then Is_Array_Type (Designated_Type (Subp_Type))
+         then
+            Is_Indexed :=
+              Try_Indexed_Call (N, Nam, Designated_Type (Subp_Type));
+
+         elsif Is_Access_Type (Subp_Type)
+           and then Ekind (Designated_Type (Subp_Type))  = E_Subprogram_Type
+         then
+            Is_Indexed := Try_Indirect_Call (N, Nam, Subp_Type);
+         end if;
+
+      end if;
+
+      Normalize_Actuals (N, Nam, (Report and not Is_Indexed), Norm_OK);
+
+      if not Norm_OK then
+
+         --  Mismatch in number or names of parameters
+
+         if Debug_Flag_E then
+            Write_Str (" normalization fails in call ");
+            Write_Int (Int (N));
+            Write_Str (" with subprogram ");
+            Write_Int (Int (Nam));
+            Write_Eol;
+         end if;
+
+      --  If the context expects a function call, discard any interpretation
+      --  that is a procedure. If the node is not overloaded, leave as is for
+      --  better error reporting when type mismatch is found.
+
+      elsif Nkind (N) = N_Function_Call
+        and then Is_Overloaded (Name (N))
+        and then Ekind (Nam) = E_Procedure
+      then
+         return;
+
+      --  Ditto for function calls in a procedure context.
+
+      elsif Nkind (N) = N_Procedure_Call_Statement
+         and then Is_Overloaded (Name (N))
+         and then Etype (Nam) /= Standard_Void_Type
+      then
+         return;
+
+      elsif not Present (Actuals) then
+
+         --  If Normalize succeeds, then there are default parameters for
+         --  all formals.
+
+         Set_Name;
+
+      elsif Ekind (Nam) = E_Operator then
+
+         if Nkind (N) = N_Procedure_Call_Statement then
+            return;
+         end if;
+
+         --  This can occur when the prefix of the call is an operator
+         --  name or an expanded name whose selector is an operator name.
+
+         Analyze_Operator_Call (N, Nam);
+
+         if Etype (N) /= Prev_T then
+
+            --  There may be a user-defined operator that hides the
+            --  current interpretation. We must check for this independently
+            --  of the analysis of the call with the user-defined operation,
+            --  because the parameter names may be wrong and yet the hiding
+            --  takes place. Fixes b34014o.
+
+            if Is_Overloaded (Name (N)) then
+               declare
+                  I  : Interp_Index;
+                  It : Interp;
+
+               begin
+                  Get_First_Interp (Name (N), I, It);
+
+                  while Present (It.Nam) loop
+
+                     if Ekind (It.Nam) /= E_Operator
+                        and then Hides_Op (It.Nam, Nam)
+                        and then
+                          Has_Compatible_Type
+                            (First_Actual (N), Etype (First_Formal (It.Nam)))
+                        and then (No (Next_Actual (First_Actual (N)))
+                           or else Has_Compatible_Type
+                            (Next_Actual (First_Actual (N)),
+                             Etype (Next_Formal (First_Formal (It.Nam)))))
+                     then
+                        Set_Etype (N, Prev_T);
+                        return;
+                     end if;
+
+                     Get_Next_Interp (I, It);
+                  end loop;
+               end;
+            end if;
+
+            --  If operator matches formals, record its name on the call.
+            --  If the operator is overloaded, Resolve will select the
+            --  correct one from the list of interpretations. The call
+            --  node itself carries the first candidate.
+
+            Set_Entity (Name (N), Nam);
+            Success := True;
+
+         elsif Report and then Etype (N) = Any_Type then
+            Error_Msg_N ("incompatible arguments for operator", N);
+         end if;
+
+      else
+         --  Normalize_Actuals has chained the named associations in the
+         --  correct order of the formals.
+
+         Actual := First_Actual (N);
+         Formal := First_Formal (Nam);
+
+         while Present (Actual) and then Present (Formal) loop
+
+            if (Nkind (Parent (Actual)) /= N_Parameter_Association
+              or else Chars (Selector_Name (Parent (Actual))) = Chars (Formal))
+            then
+               if Has_Compatible_Type (Actual, Etype (Formal)) then
+                  Next_Actual (Actual);
+                  Next_Formal (Formal);
+
+               else
+                  if Debug_Flag_E then
+                     Write_Str (" type checking fails in call ");
+                     Write_Int (Int (N));
+                     Write_Str (" with formal ");
+                     Write_Int (Int (Formal));
+                     Write_Str (" in subprogram ");
+                     Write_Int (Int (Nam));
+                     Write_Eol;
+                  end if;
+
+                  if Report and not Is_Indexed then
+
+                     Wrong_Type (Actual, Etype (Formal));
+
+                     if Nkind (Actual) = N_Op_Eq
+                       and then Nkind (Left_Opnd (Actual)) = N_Identifier
+                     then
+                        Formal := First_Formal (Nam);
+
+                        while Present (Formal) loop
+
+                           if Chars (Left_Opnd (Actual)) = Chars (Formal) then
+                              Error_Msg_N
+                                ("possible misspelling of `=>`!", Actual);
+                              exit;
+                           end if;
+
+                           Next_Formal (Formal);
+                        end loop;
+                     end if;
+
+                     if All_Errors_Mode then
+                        Error_Msg_Sloc := Sloc (Nam);
+
+                        if Is_Overloadable (Nam)
+                          and then Present (Alias (Nam))
+                          and then not Comes_From_Source (Nam)
+                        then
+                           Error_Msg_NE
+                             ("  ==> in call to &#(inherited)!", Actual, Nam);
+                        else
+                           Error_Msg_NE ("  ==> in call to &#!", Actual, Nam);
+                        end if;
+                     end if;
+                  end if;
+
+                  return;
+               end if;
+
+            else
+               --  Normalize_Actuals has verified that a default value exists
+               --  for this formal. Current actual names a subsequent formal.
+
+               Next_Formal (Formal);
+            end if;
+         end loop;
+
+         --  On exit, all actuals match.
+
+         Set_Name;
+      end if;
+   end Analyze_One_Call;
+
+   ----------------------------
+   --  Analyze_Operator_Call --
+   ----------------------------
+
+   procedure Analyze_Operator_Call (N : Node_Id; Op_Id : Entity_Id) is
+      Op_Name : constant Name_Id := Chars (Op_Id);
+      Act1    : constant Node_Id := First_Actual (N);
+      Act2    : constant Node_Id := Next_Actual (Act1);
+
+   begin
+      if Present (Act2) then
+
+         --  Maybe binary operators
+
+         if Present (Next_Actual (Act2)) then
+
+            --  Too many actuals for an operator
+
+            return;
+
+         elsif     Op_Name = Name_Op_Add
+           or else Op_Name = Name_Op_Subtract
+           or else Op_Name = Name_Op_Multiply
+           or else Op_Name = Name_Op_Divide
+           or else Op_Name = Name_Op_Mod
+           or else Op_Name = Name_Op_Rem
+           or else Op_Name = Name_Op_Expon
+         then
+            Find_Arithmetic_Types (Act1, Act2, Op_Id, N);
+
+         elsif     Op_Name =  Name_Op_And
+           or else Op_Name = Name_Op_Or
+           or else Op_Name = Name_Op_Xor
+         then
+            Find_Boolean_Types (Act1, Act2, Op_Id, N);
+
+         elsif     Op_Name = Name_Op_Lt
+           or else Op_Name = Name_Op_Le
+           or else Op_Name = Name_Op_Gt
+           or else Op_Name = Name_Op_Ge
+         then
+            Find_Comparison_Types (Act1, Act2, Op_Id,  N);
+
+         elsif     Op_Name = Name_Op_Eq
+           or else Op_Name = Name_Op_Ne
+         then
+            Find_Equality_Types (Act1, Act2, Op_Id,  N);
+
+         elsif     Op_Name = Name_Op_Concat then
+            Find_Concatenation_Types (Act1, Act2, Op_Id, N);
+
+         --  Is this else null correct, or should it be an abort???
+
+         else
+            null;
+         end if;
+
+      else
+         --  Unary operators
+
+         if Op_Name = Name_Op_Subtract or else
+            Op_Name = Name_Op_Add      or else
+            Op_Name = Name_Op_Abs
+         then
+            Find_Unary_Types (Act1, Op_Id, N);
+
+         elsif
+            Op_Name = Name_Op_Not
+         then
+            Find_Negation_Types (Act1, Op_Id, N);
+
+         --  Is this else null correct, or should it be an abort???
+
+         else
+            null;
+         end if;
+      end if;
+   end Analyze_Operator_Call;
+
+   -------------------------------------------
+   -- Analyze_Overloaded_Selected_Component --
+   -------------------------------------------
+
+   procedure Analyze_Overloaded_Selected_Component (N : Node_Id) is
+      Comp  : Entity_Id;
+      Nam   : Node_Id := Prefix (N);
+      Sel   : Node_Id := Selector_Name (N);
+      I     : Interp_Index;
+      It    : Interp;
+      T     : Entity_Id;
+
+   begin
+      Get_First_Interp (Nam, I, It);
+
+      Set_Etype (Sel,  Any_Type);
+
+      while Present (It.Typ) loop
+         if Is_Access_Type (It.Typ) then
+            T := Designated_Type (It.Typ);
+         else
+            T := It.Typ;
+         end if;
+
+         if Is_Record_Type (T) then
+            Comp := First_Entity (T);
+
+            while Present (Comp) loop
+
+               if Chars (Comp) = Chars (Sel)
+                 and then Is_Visible_Component (Comp)
+               then
+                  Set_Entity_With_Style_Check (Sel, Comp);
+                  Generate_Reference (Comp, Sel);
+
+                  Set_Etype (Sel, Etype (Comp));
+                  Add_One_Interp (N, Etype (Comp), Etype (Comp));
+
+                  --  This also specifies a candidate to resolve the name.
+                  --  Further overloading will be resolved from context.
+
+                  Set_Etype (Nam, It.Typ);
+               end if;
+
+               Next_Entity (Comp);
+            end loop;
+
+         elsif Is_Concurrent_Type (T) then
+            Comp := First_Entity (T);
+
+            while Present (Comp)
+              and then Comp /= First_Private_Entity (T)
+            loop
+               if Chars (Comp) = Chars (Sel) then
+                  if Is_Overloadable (Comp) then
+                     Add_One_Interp (Sel, Comp, Etype (Comp));
+                  else
+                     Set_Entity_With_Style_Check (Sel, Comp);
+                     Generate_Reference (Comp, Sel);
+                  end if;
+
+                  Set_Etype (Sel, Etype (Comp));
+                  Set_Etype (N,   Etype (Comp));
+                  Set_Etype (Nam, It.Typ);
+
+                  --  For access type case, introduce explicit deference for
+                  --  more uniform treatment of entry calls.
+
+                  if Is_Access_Type (Etype (Nam)) then
+                     Insert_Explicit_Dereference (Nam);
+                  end if;
+               end if;
+
+               Next_Entity (Comp);
+            end loop;
+
+            Set_Is_Overloaded (N, Is_Overloaded (Sel));
+
+         end if;
+
+         Get_Next_Interp (I, It);
+      end loop;
+
+      if Etype (N) = Any_Type then
+         Error_Msg_NE ("undefined selector& for overloaded prefix", N, Sel);
+         Set_Entity (Sel, Any_Id);
+         Set_Etype  (Sel, Any_Type);
+      end if;
+
+   end Analyze_Overloaded_Selected_Component;
+
+   ----------------------------------
+   -- Analyze_Qualified_Expression --
+   ----------------------------------
+
+   procedure Analyze_Qualified_Expression (N : Node_Id) is
+      Mark : constant Entity_Id := Subtype_Mark (N);
+      T    : Entity_Id;
+
+   begin
+      Set_Etype (N, Any_Type);
+      Find_Type (Mark);
+      T := Entity (Mark);
+
+      if T = Any_Type then
+         return;
+      end if;
+      Check_Fully_Declared (T, N);
+
+      Analyze_Expression (Expression (N));
+      Set_Etype  (N, T);
+   end Analyze_Qualified_Expression;
+
+   -------------------
+   -- Analyze_Range --
+   -------------------
+
+   procedure Analyze_Range (N : Node_Id) is
+      L        : constant Node_Id := Low_Bound (N);
+      H        : constant Node_Id := High_Bound (N);
+      I1, I2   : Interp_Index;
+      It1, It2 : Interp;
+
+      procedure Check_Common_Type (T1, T2 : Entity_Id);
+      --  Verify the compatibility of two types,  and choose the
+      --  non universal one if the other is universal.
+
+      procedure Check_High_Bound (T : Entity_Id);
+      --  Test one interpretation of the low bound against all those
+      --  of the high bound.
+
+      -----------------------
+      -- Check_Common_Type --
+      -----------------------
+
+      procedure Check_Common_Type (T1, T2 : Entity_Id) is
+      begin
+         if Covers (T1, T2) or else Covers (T2, T1) then
+            if T1 = Universal_Integer
+              or else T1 = Universal_Real
+              or else T1 = Any_Character
+            then
+               Add_One_Interp (N, Base_Type (T2), Base_Type (T2));
+
+            elsif (T1 = T2) then
+               Add_One_Interp (N, T1, T1);
+
+            else
+               Add_One_Interp (N, Base_Type (T1), Base_Type (T1));
+            end if;
+         end if;
+      end Check_Common_Type;
+
+      ----------------------
+      -- Check_High_Bound --
+      ----------------------
+
+      procedure Check_High_Bound (T : Entity_Id) is
+      begin
+         if not Is_Overloaded (H) then
+            Check_Common_Type (T, Etype (H));
+         else
+            Get_First_Interp (H, I2, It2);
+
+            while Present (It2.Typ) loop
+               Check_Common_Type (T, It2.Typ);
+               Get_Next_Interp (I2, It2);
+            end loop;
+         end if;
+      end Check_High_Bound;
+
+   --  Start of processing for Analyze_Range
+
+   begin
+      Set_Etype (N, Any_Type);
+      Analyze_Expression (L);
+      Analyze_Expression (H);
+
+      if Etype (L) = Any_Type or else Etype (H) = Any_Type then
+         return;
+
+      else
+         if not Is_Overloaded (L) then
+            Check_High_Bound (Etype (L));
+         else
+            Get_First_Interp (L, I1, It1);
+
+            while Present (It1.Typ) loop
+               Check_High_Bound (It1.Typ);
+               Get_Next_Interp (I1, It1);
+            end loop;
+         end if;
+
+         --  If result is Any_Type, then we did not find a compatible pair
+
+         if Etype (N) = Any_Type then
+            Error_Msg_N ("incompatible types in range ", N);
+         end if;
+      end if;
+   end Analyze_Range;
+
+   -----------------------
+   -- Analyze_Reference --
+   -----------------------
+
+   procedure Analyze_Reference (N : Node_Id) is
+      P        : constant Node_Id := Prefix (N);
+      Acc_Type : Entity_Id;
+
+   begin
+      Analyze (P);
+      Acc_Type := Create_Itype (E_Allocator_Type, N);
+      Set_Etype                    (Acc_Type,  Acc_Type);
+      Init_Size_Align              (Acc_Type);
+      Set_Directly_Designated_Type (Acc_Type, Etype (P));
+      Set_Etype (N, Acc_Type);
+   end Analyze_Reference;
+
+   --------------------------------
+   -- Analyze_Selected_Component --
+   --------------------------------
+
+   --  Prefix is a record type or a task or protected type. In the
+   --  later case, the selector must denote a visible entry.
+
+   procedure Analyze_Selected_Component (N : Node_Id) is
+      Name        : constant Node_Id := Prefix (N);
+      Sel         : constant Node_Id := Selector_Name (N);
+      Comp        : Entity_Id;
+      Entity_List : Entity_Id;
+      Prefix_Type : Entity_Id;
+      Act_Decl    : Node_Id;
+      In_Scope    : Boolean;
+      Parent_N    : Node_Id;
+
+   --  Start of processing for Analyze_Selected_Component
+
+   begin
+      Set_Etype (N, Any_Type);
+
+      if Is_Overloaded (Name) then
+         Analyze_Overloaded_Selected_Component (N);
+         return;
+
+      elsif Etype (Name) = Any_Type then
+         Set_Entity (Sel, Any_Id);
+         Set_Etype (Sel, Any_Type);
+         return;
+
+      else
+         --  Function calls that are prefixes of selected components must be
+         --  fully resolved in case we need to build an actual subtype, or
+         --  do some other operation requiring a fully resolved prefix.
+
+         --  Note: Resolving all Nkinds of nodes here doesn't work.
+         --  (Breaks 2129-008) ???.
+
+         if Nkind (Name) = N_Function_Call then
+            Resolve (Name, Etype (Name));
+         end if;
+
+         Prefix_Type := Etype (Name);
+      end if;
+
+      if Is_Access_Type (Prefix_Type) then
+         if Is_Remote_Access_To_Class_Wide_Type (Prefix_Type)
+           and then Comes_From_Source (N)
+         then
+            --  A RACW object can never be used as prefix of a selected
+            --  component since that means it is dereferenced without
+            --  being a controlling operand of a dispatching operation
+            --  (RM E.2.2(15)).
+
+            Error_Msg_N
+              ("invalid dereference of a remote access to class-wide value",
+               N);
+         end if;
+         Prefix_Type := Designated_Type (Prefix_Type);
+      end if;
+
+      if Ekind (Prefix_Type) = E_Private_Subtype then
+         Prefix_Type := Base_Type (Prefix_Type);
+      end if;
+
+      Entity_List := Prefix_Type;
+
+      --  For class-wide types, use the entity list of the root type. This
+      --  indirection is specially important for private extensions because
+      --  only the root type get switched (not the class-wide type).
+
+      if Is_Class_Wide_Type (Prefix_Type) then
+         Entity_List := Root_Type (Prefix_Type);
+      end if;
+
+      Comp := First_Entity (Entity_List);
+
+      --  If the selector has an original discriminant, the node appears in
+      --  an instance. Replace the discriminant with the corresponding one
+      --  in the current discriminated type. For nested generics, this must
+      --  be done transitively, so note the new original discriminant.
+
+      if Nkind (Sel) = N_Identifier
+        and then Present (Original_Discriminant (Sel))
+      then
+         Comp := Find_Corresponding_Discriminant (Sel, Prefix_Type);
+
+         --  Mark entity before rewriting, for completeness and because
+         --  subsequent semantic checks might examine the original node.
+
+         Set_Entity (Sel, Comp);
+         Rewrite (Selector_Name (N),
+           New_Occurrence_Of (Comp, Sloc (N)));
+         Set_Original_Discriminant (Selector_Name (N), Comp);
+         Set_Etype (N, Etype (Comp));
+
+         if Is_Access_Type (Etype (Name)) then
+            Insert_Explicit_Dereference (Name);
+         end if;
+
+      elsif Is_Record_Type (Prefix_Type) then
+
+         --  Find component with given name
+
+         while Present (Comp) loop
+
+            if Chars (Comp) = Chars (Sel)
+              and then Is_Visible_Component (Comp)
+            then
+               Set_Entity_With_Style_Check (Sel, Comp);
+               Generate_Reference (Comp, Sel);
+
+               Set_Etype (Sel, Etype (Comp));
+
+               if Ekind (Comp) = E_Discriminant then
+                  if Is_Unchecked_Union (Prefix_Type) then
+                     Error_Msg_N
+                       ("cannot reference discriminant of Unchecked_Union",
+                        Sel);
+                  end if;
+
+                  if Is_Generic_Type (Prefix_Type)
+                       or else
+                     Is_Generic_Type (Root_Type (Prefix_Type))
+                  then
+                     Set_Original_Discriminant (Sel, Comp);
+                  end if;
+               end if;
+
+               --  Resolve the prefix early otherwise it is not possible to
+               --  build the actual subtype of the component: it may need
+               --  to duplicate this prefix and duplication is only allowed
+               --  on fully resolved expressions.
+
+               Resolve (Name, Etype (Name));
+
+               --  We never need an actual subtype for the case of a selection
+               --  for a indexed component of a non-packed array, since in
+               --  this case gigi generates all the checks and can find the
+               --  necessary bounds information.
+
+               --  We also do not need an actual subtype for the case of
+               --  a first, last, length, or range attribute applied to a
+               --  non-packed array, since gigi can again get the bounds in
+               --  these cases (gigi cannot handle the packed case, since it
+               --  has the bounds of the packed array type, not the original
+               --  bounds of the type). However, if the prefix is itself a
+               --  selected component, as in a.b.c (i), gigi may regard a.b.c
+               --  as a dynamic-sized temporary, so we do generate an actual
+               --  subtype for this case.
+
+               Parent_N := Parent (N);
+
+               if not Is_Packed (Etype (Comp))
+                 and then
+                   ((Nkind (Parent_N) = N_Indexed_Component
+                      and then Nkind (Name) /= N_Selected_Component)
+                     or else
+                      (Nkind (Parent_N) = N_Attribute_Reference
+                         and then (Attribute_Name (Parent_N) = Name_First
+                                    or else
+                                   Attribute_Name (Parent_N) = Name_Last
+                                    or else
+                                   Attribute_Name (Parent_N) = Name_Length
+                                    or else
+                                   Attribute_Name (Parent_N) = Name_Range)))
+               then
+                  Set_Etype (N, Etype (Comp));
+
+               --  In all other cases, we currently build an actual subtype. It
+               --  seems likely that many of these cases can be avoided, but
+               --  right now, the front end makes direct references to the
+               --  bounds (e.g. in egnerating a length check), and if we do
+               --  not make an actual subtype, we end up getting a direct
+               --  reference to a discriminant which will not do.
+
+               else
+                  Act_Decl :=
+                    Build_Actual_Subtype_Of_Component (Etype (Comp), N);
+                  Insert_Action (N, Act_Decl);
+
+                  if No (Act_Decl) then
+                     Set_Etype (N, Etype (Comp));
+
+                  else
+                     --  Component type depends on discriminants. Enter the
+                     --  main attributes of the subtype.
+
+                     declare
+                        Subt : Entity_Id := Defining_Identifier (Act_Decl);
+
+                     begin
+                        Set_Etype (Subt, Base_Type (Etype (Comp)));
+                        Set_Ekind (Subt, Ekind (Etype (Comp)));
+                        Set_Etype (N, Subt);
+                     end;
+                  end if;
+               end if;
+
+               return;
+            end if;
+
+            Next_Entity (Comp);
+         end loop;
+
+      elsif Is_Private_Type (Prefix_Type) then
+
+         --  Allow access only to discriminants of the type. If the
+         --  type has no full view, gigi uses the parent type for
+         --  the components, so we do the same here.
+
+         if No (Full_View (Prefix_Type)) then
+            Entity_List := Root_Type (Base_Type (Prefix_Type));
+            Comp := First_Entity (Entity_List);
+         end if;
+
+         while Present (Comp) loop
+
+            if Chars (Comp) = Chars (Sel) then
+               if Ekind (Comp) = E_Discriminant then
+                  Set_Entity_With_Style_Check (Sel, Comp);
+                  Generate_Reference (Comp, Sel);
+
+                  Set_Etype (Sel, Etype (Comp));
+                  Set_Etype (N,   Etype (Comp));
+
+                  if Is_Generic_Type (Prefix_Type)
+                    or else
+                     Is_Generic_Type (Root_Type (Prefix_Type))
+                  then
+                     Set_Original_Discriminant (Sel, Comp);
+                  end if;
+
+               else
+                  Error_Msg_NE
+                    ("invisible selector for }",
+                     N, First_Subtype (Prefix_Type));
+                  Set_Entity (Sel, Any_Id);
+                  Set_Etype (N, Any_Type);
+               end if;
+
+               return;
+            end if;
+
+            Next_Entity (Comp);
+         end loop;
+
+      elsif Is_Concurrent_Type (Prefix_Type) then
+
+         --  Prefix is concurrent type. Find visible operation with given name
+         --  For a task, this can only include entries or discriminants if
+         --  the task type is not an enclosing scope. If it is an enclosing
+         --  scope (e.g. in an inner task) then all entities are visible, but
+         --  the prefix must denote the enclosing scope, i.e. can only be
+         --  a direct name or an expanded name.
+
+         Set_Etype (Sel,  Any_Type);
+         In_Scope := In_Open_Scopes (Prefix_Type);
+
+         while Present (Comp) loop
+            if Chars (Comp) = Chars (Sel) then
+               if Is_Overloadable (Comp) then
+                  Add_One_Interp (Sel, Comp, Etype (Comp));
+
+               elsif Ekind (Comp) = E_Discriminant
+                 or else Ekind (Comp) = E_Entry_Family
+                 or else (In_Scope
+                   and then Is_Entity_Name (Name))
+               then
+                  Set_Entity_With_Style_Check (Sel, Comp);
+                  Generate_Reference (Comp, Sel);
+
+               else
+                  goto Next_Comp;
+               end if;
+
+               Set_Etype (Sel, Etype (Comp));
+               Set_Etype (N,   Etype (Comp));
+
+               if Ekind (Comp) = E_Discriminant then
+                  Set_Original_Discriminant (Sel, Comp);
+               end if;
+
+               --  For access type case, introduce explicit deference for
+               --  more uniform treatment of entry calls.
+
+               if Is_Access_Type (Etype (Name)) then
+                  Insert_Explicit_Dereference (Name);
+               end if;
+            end if;
+
+            <<Next_Comp>>
+               Next_Entity (Comp);
+               exit when not In_Scope
+                 and then Comp = First_Private_Entity (Prefix_Type);
+         end loop;
+
+         Set_Is_Overloaded (N, Is_Overloaded (Sel));
+
+      else
+         --  Invalid prefix
+
+         Error_Msg_NE ("invalid prefix in selected component&", N, Sel);
+      end if;
+
+      --  If N still has no type, the component is not defined in the prefix.
+
+      if Etype (N) = Any_Type then
+
+         --  If the prefix is a single concurrent object, use its name in
+         --  the error message, rather than that of its anonymous type.
+
+         if Is_Concurrent_Type (Prefix_Type)
+           and then Is_Internal_Name (Chars (Prefix_Type))
+           and then not Is_Derived_Type (Prefix_Type)
+           and then Is_Entity_Name (Name)
+         then
+
+            Error_Msg_Node_2 := Entity (Name);
+            Error_Msg_NE ("no selector& for&", N, Sel);
+
+            Check_Misspelled_Selector (Entity_List, Sel);
+
+         else
+            if Ekind (Prefix_Type) = E_Record_Subtype then
+
+               --  Check whether this is a component of the base type
+               --  which is absent from a statically constrained subtype.
+               --  This will raise constraint error at run-time, but is
+               --  not a compile-time error. When the selector is illegal
+               --  for base type as well fall through and generate a
+               --  compilation error anyway.
+
+               Comp := First_Component (Base_Type (Prefix_Type));
+
+               while Present (Comp) loop
+
+                  if Chars (Comp) = Chars (Sel)
+                    and then Is_Visible_Component (Comp)
+                  then
+                     Set_Entity_With_Style_Check (Sel, Comp);
+                     Generate_Reference (Comp, Sel);
+                     Set_Etype (Sel, Etype (Comp));
+                     Set_Etype (N,   Etype (Comp));
+
+                     --  Emit appropriate message. Gigi will replace the
+                     --  node subsequently with the appropriate Raise.
+
+                     Apply_Compile_Time_Constraint_Error
+                       (N, "component not present in }?",
+                        Ent => Prefix_Type, Rep => False);
+                     Set_Raises_Constraint_Error (N);
+                     return;
+                  end if;
+
+                  Next_Component (Comp);
+               end loop;
+
+            end if;
+
+            Error_Msg_Node_2 := First_Subtype (Prefix_Type);
+            Error_Msg_NE ("no selector& for}", N, Sel);
+
+            Check_Misspelled_Selector (Entity_List, Sel);
+
+         end if;
+
+         Set_Entity (Sel, Any_Id);
+         Set_Etype (Sel, Any_Type);
+      end if;
+   end Analyze_Selected_Component;
+
+   ---------------------------
+   -- Analyze_Short_Circuit --
+   ---------------------------
+
+   procedure Analyze_Short_Circuit (N : Node_Id) is
+      L   : constant Node_Id := Left_Opnd  (N);
+      R   : constant Node_Id := Right_Opnd (N);
+      Ind : Interp_Index;
+      It  : Interp;
+
+   begin
+      Analyze_Expression (L);
+      Analyze_Expression (R);
+      Set_Etype (N, Any_Type);
+
+      if not Is_Overloaded (L) then
+
+         if Root_Type (Etype (L)) = Standard_Boolean
+           and then Has_Compatible_Type (R, Etype (L))
+         then
+            Add_One_Interp (N, Etype (L), Etype (L));
+         end if;
+
+      else
+         Get_First_Interp (L, Ind, It);
+
+         while Present (It.Typ) loop
+            if Root_Type (It.Typ) = Standard_Boolean
+              and then Has_Compatible_Type (R, It.Typ)
+            then
+               Add_One_Interp (N, It.Typ, It.Typ);
+            end if;
+
+            Get_Next_Interp (Ind, It);
+         end loop;
+      end if;
+
+      --  Here we have failed to find an interpretation. Clearly we
+      --  know that it is not the case that both operands can have
+      --  an interpretation of Boolean, but this is by far the most
+      --  likely intended interpretation. So we simply resolve both
+      --  operands as Booleans, and at least one of these resolutions
+      --  will generate an error message, and we do not need to give
+      --  a further error message on the short circuit operation itself.
+
+      if Etype (N) = Any_Type then
+         Resolve (L, Standard_Boolean);
+         Resolve (R, Standard_Boolean);
+         Set_Etype (N, Standard_Boolean);
+      end if;
+   end Analyze_Short_Circuit;
+
+   -------------------
+   -- Analyze_Slice --
+   -------------------
+
+   procedure Analyze_Slice (N : Node_Id) is
+      P          : constant Node_Id := Prefix (N);
+      D          : constant Node_Id := Discrete_Range (N);
+      Array_Type : Entity_Id;
+
+      procedure Analyze_Overloaded_Slice;
+      --  If the prefix is overloaded, select those interpretations that
+      --  yield a one-dimensional array type.
+
+      procedure Analyze_Overloaded_Slice is
+         I   : Interp_Index;
+         It  : Interp;
+         Typ : Entity_Id;
+
+      begin
+         Set_Etype (N, Any_Type);
+         Get_First_Interp (P, I, It);
+
+         while Present (It.Nam) loop
+            Typ := It.Typ;
+
+            if Is_Access_Type (Typ) then
+               Typ := Designated_Type (Typ);
+            end if;
+
+            if Is_Array_Type (Typ)
+              and then Number_Dimensions (Typ) = 1
+              and then Has_Compatible_Type (D, Etype (First_Index (Typ)))
+            then
+               Add_One_Interp (N, Typ, Typ);
+            end if;
+
+            Get_Next_Interp (I, It);
+         end loop;
+
+         if Etype (N) = Any_Type then
+            Error_Msg_N ("expect array type in prefix of slice",  N);
+         end if;
+      end Analyze_Overloaded_Slice;
+
+   --  Start of processing for Analyze_Slice
+
+   begin
+      --  Analyze the prefix if not done already
+
+      if No (Etype (P)) then
+         Analyze (P);
+      end if;
+
+      Analyze (D);
+
+      if Is_Overloaded (P) then
+         Analyze_Overloaded_Slice;
+
+      else
+         Array_Type := Etype (P);
+         Set_Etype (N, Any_Type);
+
+         if Is_Access_Type (Array_Type) then
+            Array_Type := Designated_Type (Array_Type);
+         end if;
+
+         if not Is_Array_Type (Array_Type) then
+            Wrong_Type (P, Any_Array);
+
+         elsif Number_Dimensions (Array_Type) > 1 then
+            Error_Msg_N
+              ("type is not one-dimensional array in slice prefix", N);
+
+         elsif not
+           Has_Compatible_Type (D, Etype (First_Index (Array_Type)))
+         then
+            Wrong_Type (D, Etype (First_Index (Array_Type)));
+
+         else
+            Set_Etype (N, Array_Type);
+         end if;
+      end if;
+   end Analyze_Slice;
+
+   -----------------------------
+   -- Analyze_Type_Conversion --
+   -----------------------------
+
+   procedure Analyze_Type_Conversion (N : Node_Id) is
+      Expr : constant Node_Id := Expression (N);
+      T    : Entity_Id;
+
+   begin
+      --  If Conversion_OK is set, then the Etype is already set, and the
+      --  only processing required is to analyze the expression. This is
+      --  used to construct certain "illegal" conversions which are not
+      --  allowed by Ada semantics, but can be handled OK by Gigi, see
+      --  Sinfo for further details.
+
+      if Conversion_OK (N) then
+         Analyze (Expr);
+         return;
+      end if;
+
+      --  Otherwise full type analysis is required, as well as some semantic
+      --  checks to make sure the argument of the conversion is appropriate.
+
+      Find_Type (Subtype_Mark (N));
+      T := Entity (Subtype_Mark (N));
+      Set_Etype (N, T);
+      Check_Fully_Declared (T, N);
+      Analyze_Expression (Expr);
+      Validate_Remote_Type_Type_Conversion (N);
+
+      --  Only remaining step is validity checks on the argument. These
+      --  are skipped if the conversion does not come from the source.
+
+      if not Comes_From_Source (N) then
+         return;
+
+      elsif Nkind (Expr) = N_Null then
+         Error_Msg_N ("argument of conversion cannot be null", N);
+         Error_Msg_N ("\use qualified expression instead", N);
+         Set_Etype (N, Any_Type);
+
+      elsif Nkind (Expr) = N_Aggregate then
+         Error_Msg_N ("argument of conversion cannot be aggregate", N);
+         Error_Msg_N ("\use qualified expression instead", N);
+
+      elsif Nkind (Expr) = N_Allocator then
+         Error_Msg_N ("argument of conversion cannot be an allocator", N);
+         Error_Msg_N ("\use qualified expression instead", N);
+
+      elsif Nkind (Expr) = N_String_Literal then
+         Error_Msg_N ("argument of conversion cannot be string literal", N);
+         Error_Msg_N ("\use qualified expression instead", N);
+
+      elsif Nkind (Expr) = N_Character_Literal then
+         if Ada_83 then
+            Resolve (Expr, T);
+         else
+            Error_Msg_N ("argument of conversion cannot be character literal",
+              N);
+            Error_Msg_N ("\use qualified expression instead", N);
+         end if;
+
+      elsif Nkind (Expr) = N_Attribute_Reference
+        and then
+          (Attribute_Name (Expr) = Name_Access            or else
+           Attribute_Name (Expr) = Name_Unchecked_Access  or else
+           Attribute_Name (Expr) = Name_Unrestricted_Access)
+      then
+         Error_Msg_N ("argument of conversion cannot be access", N);
+         Error_Msg_N ("\use qualified expression instead", N);
+      end if;
+
+   end Analyze_Type_Conversion;
+
+   ----------------------
+   -- Analyze_Unary_Op --
+   ----------------------
+
+   procedure Analyze_Unary_Op (N : Node_Id) is
+      R     : constant Node_Id := Right_Opnd (N);
+      Op_Id : Entity_Id := Entity (N);
+
+   begin
+      Set_Etype (N, Any_Type);
+      Candidate_Type := Empty;
+
+      Analyze_Expression (R);
+
+      if Present (Op_Id) then
+         if Ekind (Op_Id) = E_Operator then
+            Find_Unary_Types (R, Op_Id,  N);
+         else
+            Add_One_Interp (N, Op_Id, Etype (Op_Id));
+         end if;
+
+      else
+         Op_Id := Get_Name_Entity_Id (Chars (N));
+
+         while Present (Op_Id) loop
+
+            if Ekind (Op_Id) = E_Operator then
+               if No (Next_Entity (First_Entity (Op_Id))) then
+                  Find_Unary_Types (R, Op_Id,  N);
+               end if;
+
+            elsif Is_Overloadable (Op_Id) then
+               Analyze_User_Defined_Unary_Op (N, Op_Id);
+            end if;
+
+            Op_Id := Homonym (Op_Id);
+         end loop;
+      end if;
+
+      Operator_Check (N);
+   end Analyze_Unary_Op;
+
+   ----------------------------------
+   -- Analyze_Unchecked_Expression --
+   ----------------------------------
+
+   procedure Analyze_Unchecked_Expression (N : Node_Id) is
+   begin
+      Analyze (Expression (N), Suppress => All_Checks);
+      Set_Etype (N, Etype (Expression (N)));
+      Save_Interps (Expression (N), N);
+   end Analyze_Unchecked_Expression;
+
+   ---------------------------------------
+   -- Analyze_Unchecked_Type_Conversion --
+   ---------------------------------------
+
+   procedure Analyze_Unchecked_Type_Conversion (N : Node_Id) is
+   begin
+      Find_Type (Subtype_Mark (N));
+      Analyze_Expression (Expression (N));
+      Set_Etype (N, Entity (Subtype_Mark (N)));
+   end Analyze_Unchecked_Type_Conversion;
+
+   ------------------------------------
+   -- Analyze_User_Defined_Binary_Op --
+   ------------------------------------
+
+   procedure Analyze_User_Defined_Binary_Op
+     (N     : Node_Id;
+      Op_Id : Entity_Id)
+   is
+   begin
+      --  Only do analysis if the operator Comes_From_Source, since otherwise
+      --  the operator was generated by the expander, and all such operators
+      --  always refer to the operators in package Standard.
+
+      if Comes_From_Source (N) then
+         declare
+            F1 : constant Entity_Id := First_Formal (Op_Id);
+            F2 : constant Entity_Id := Next_Formal (F1);
+
+         begin
+            --  Verify that Op_Id is a visible binary function. Note that since
+            --  we know Op_Id is overloaded, potentially use visible means use
+            --  visible for sure (RM 9.4(11)).
+
+            if Ekind (Op_Id) = E_Function
+              and then Present (F2)
+              and then (Is_Immediately_Visible (Op_Id)
+                         or else Is_Potentially_Use_Visible (Op_Id))
+              and then Has_Compatible_Type (Left_Opnd (N), Etype (F1))
+              and then Has_Compatible_Type (Right_Opnd (N), Etype (F2))
+            then
+               Add_One_Interp (N, Op_Id, Etype (Op_Id));
+
+               if Debug_Flag_E then
+                  Write_Str ("user defined operator ");
+                  Write_Name (Chars (Op_Id));
+                  Write_Str (" on node ");
+                  Write_Int (Int (N));
+                  Write_Eol;
+               end if;
+            end if;
+         end;
+      end if;
+   end Analyze_User_Defined_Binary_Op;
+
+   -----------------------------------
+   -- Analyze_User_Defined_Unary_Op --
+   -----------------------------------
+
+   procedure Analyze_User_Defined_Unary_Op
+     (N     : Node_Id;
+      Op_Id : Entity_Id)
+   is
+   begin
+      --  Only do analysis if the operator Comes_From_Source, since otherwise
+      --  the operator was generated by the expander, and all such operators
+      --  always refer to the operators in package Standard.
+
+      if Comes_From_Source (N) then
+         declare
+            F : constant Entity_Id := First_Formal (Op_Id);
+
+         begin
+            --  Verify that Op_Id is a visible unary function. Note that since
+            --  we know Op_Id is overloaded, potentially use visible means use
+            --  visible for sure (RM 9.4(11)).
+
+            if Ekind (Op_Id) = E_Function
+              and then No (Next_Formal (F))
+              and then (Is_Immediately_Visible (Op_Id)
+                         or else Is_Potentially_Use_Visible (Op_Id))
+              and then Has_Compatible_Type (Right_Opnd (N), Etype (F))
+            then
+               Add_One_Interp (N, Op_Id, Etype (Op_Id));
+            end if;
+         end;
+      end if;
+   end Analyze_User_Defined_Unary_Op;
+
+   ---------------------------
+   -- Check_Arithmetic_Pair --
+   ---------------------------
+
+   procedure Check_Arithmetic_Pair
+     (T1, T2 : Entity_Id;
+      Op_Id  : Entity_Id;
+      N      : Node_Id)
+   is
+      Op_Name : constant Name_Id   := Chars (Op_Id);
+
+      function Specific_Type (T1, T2 : Entity_Id) return Entity_Id;
+      --  Get specific type (i.e. non-universal type if there is one)
+
+      function Specific_Type (T1, T2 : Entity_Id) return Entity_Id is
+      begin
+         if T1 = Universal_Integer or else T1 = Universal_Real then
+            return Base_Type (T2);
+         else
+            return Base_Type (T1);
+         end if;
+      end Specific_Type;
+
+   --  Start of processing for Check_Arithmetic_Pair
+
+   begin
+      if Op_Name = Name_Op_Add or else Op_Name = Name_Op_Subtract then
+
+         if Is_Numeric_Type (T1)
+           and then Is_Numeric_Type (T2)
+           and then (Covers (T1, T2) or else Covers (T2, T1))
+         then
+            Add_One_Interp (N, Op_Id, Specific_Type (T1, T2));
+         end if;
+
+      elsif Op_Name = Name_Op_Multiply or else Op_Name = Name_Op_Divide then
+
+         if Is_Fixed_Point_Type (T1)
+           and then (Is_Fixed_Point_Type (T2)
+                       or else T2 = Universal_Real)
+         then
+            --  If Treat_Fixed_As_Integer is set then the Etype is already set
+            --  and no further processing is required (this is the case of an
+            --  operator constructed by Exp_Fixd for a fixed point operation)
+            --  Otherwise add one interpretation with universal fixed result
+            --  If the operator is given in  functional notation, it comes
+            --  from source and Fixed_As_Integer cannot apply.
+
+            if Nkind (N) not in N_Op
+              or else not Treat_Fixed_As_Integer (N) then
+               Add_One_Interp (N, Op_Id, Universal_Fixed);
+            end if;
+
+         elsif Is_Fixed_Point_Type (T2)
+           and then (Nkind (N) not in N_Op
+                      or else not Treat_Fixed_As_Integer (N))
+           and then T1 = Universal_Real
+         then
+            Add_One_Interp (N, Op_Id, Universal_Fixed);
+
+         elsif Is_Numeric_Type (T1)
+           and then Is_Numeric_Type (T2)
+           and then (Covers (T1, T2) or else Covers (T2, T1))
+         then
+            Add_One_Interp (N, Op_Id, Specific_Type (T1, T2));
+
+         elsif Is_Fixed_Point_Type (T1)
+           and then (Base_Type (T2) = Base_Type (Standard_Integer)
+                       or else T2 = Universal_Integer)
+         then
+            Add_One_Interp (N, Op_Id, T1);
+
+         elsif T2 = Universal_Real
+           and then Base_Type (T1) = Base_Type (Standard_Integer)
+           and then Op_Name = Name_Op_Multiply
+         then
+            Add_One_Interp (N, Op_Id, Any_Fixed);
+
+         elsif T1 = Universal_Real
+           and then Base_Type (T2) = Base_Type (Standard_Integer)
+         then
+            Add_One_Interp (N, Op_Id, Any_Fixed);
+
+         elsif Is_Fixed_Point_Type (T2)
+           and then (Base_Type (T1) = Base_Type (Standard_Integer)
+                       or else T1 = Universal_Integer)
+           and then Op_Name = Name_Op_Multiply
+         then
+            Add_One_Interp (N, Op_Id, T2);
+
+         elsif T1 = Universal_Real and then T2 = Universal_Integer then
+            Add_One_Interp (N, Op_Id, T1);
+
+         elsif T2 = Universal_Real
+           and then T1 = Universal_Integer
+           and then Op_Name = Name_Op_Multiply
+         then
+            Add_One_Interp (N, Op_Id, T2);
+         end if;
+
+      elsif Op_Name = Name_Op_Mod or else Op_Name = Name_Op_Rem then
+
+         --  Note: The fixed-point operands case with Treat_Fixed_As_Integer
+         --  set does not require any special processing, since the Etype is
+         --  already set (case of operation constructed by Exp_Fixed).
+
+         if Is_Integer_Type (T1)
+           and then (Covers (T1, T2) or else Covers (T2, T1))
+         then
+            Add_One_Interp (N, Op_Id, Specific_Type (T1, T2));
+         end if;
+
+      elsif Op_Name = Name_Op_Expon then
+
+         if Is_Numeric_Type (T1)
+           and then not Is_Fixed_Point_Type (T1)
+           and then (Base_Type (T2) = Base_Type (Standard_Integer)
+                      or else T2 = Universal_Integer)
+         then
+            Add_One_Interp (N, Op_Id, Base_Type (T1));
+         end if;
+
+      else pragma Assert (Nkind (N) in N_Op_Shift);
+
+         --  If not one of the predefined operators, the node may be one
+         --  of the intrinsic functions. Its kind is always specific, and
+         --  we can use it directly, rather than the name of the operation.
+
+         if Is_Integer_Type (T1)
+           and then (Base_Type (T2) = Base_Type (Standard_Integer)
+                      or else T2 = Universal_Integer)
+         then
+            Add_One_Interp (N, Op_Id, Base_Type (T1));
+         end if;
+      end if;
+   end Check_Arithmetic_Pair;
+
+   -------------------------------
+   -- Check_Misspelled_Selector --
+   -------------------------------
+
+   procedure Check_Misspelled_Selector
+     (Prefix : Entity_Id;
+      Sel    : Node_Id)
+   is
+      Max_Suggestions   : constant := 2;
+      Nr_Of_Suggestions : Natural := 0;
+
+      Suggestion_1 : Entity_Id := Empty;
+      Suggestion_2 : Entity_Id := Empty;
+
+      Comp : Entity_Id;
+
+   begin
+      --  All the components of the prefix of selector Sel are matched
+      --  against  Sel and a count is maintained of possible misspellings.
+      --  When at the end of the analysis there are one or two (not more!)
+      --  possible misspellings, these misspellings will be suggested as
+      --  possible correction.
+
+      if not (Is_Private_Type (Prefix) or Is_Record_Type (Prefix)) then
+         --  Concurrent types should be handled as well ???
+         return;
+      end if;
+
+      Get_Name_String (Chars (Sel));
+
+      declare
+         S  : constant String (1 .. Name_Len) :=
+                Name_Buffer (1 .. Name_Len);
+
+      begin
+         Comp  := First_Entity (Prefix);
+
+         while Nr_Of_Suggestions <= Max_Suggestions
+            and then Present (Comp)
+         loop
+
+            if Is_Visible_Component (Comp) then
+               Get_Name_String (Chars (Comp));
+
+               if Is_Bad_Spelling_Of (Name_Buffer (1 .. Name_Len), S) then
+                  Nr_Of_Suggestions := Nr_Of_Suggestions + 1;
+
+                  case Nr_Of_Suggestions is
+                     when 1      => Suggestion_1 := Comp;
+                     when 2      => Suggestion_2 := Comp;
+                     when others => exit;
+                  end case;
+               end if;
+            end if;
+
+            Comp := Next_Entity (Comp);
+         end loop;
+
+         --  Report at most two suggestions
+
+         if Nr_Of_Suggestions = 1 then
+            Error_Msg_NE ("\possible misspelling of&", Sel, Suggestion_1);
+
+         elsif Nr_Of_Suggestions = 2 then
+            Error_Msg_Node_2 := Suggestion_2;
+            Error_Msg_NE ("\possible misspelling of& or&",
+              Sel, Suggestion_1);
+         end if;
+      end;
+   end Check_Misspelled_Selector;
+
+   ----------------------
+   -- Defined_In_Scope --
+   ----------------------
+
+   function Defined_In_Scope (T : Entity_Id; S : Entity_Id) return Boolean
+   is
+      S1 : constant Entity_Id := Scope (Base_Type (T));
+
+   begin
+      return S1 = S
+        or else (S1 = System_Aux_Id and then S = Scope (S1));
+   end Defined_In_Scope;
+
+   -------------------
+   -- Diagnose_Call --
+   -------------------
+
+   procedure Diagnose_Call (N : Node_Id; Nam : Node_Id) is
+      Actual  : Node_Id;
+      X       : Interp_Index;
+      It      : Interp;
+      Success : Boolean;
+
+   begin
+      if Extensions_Allowed then
+         Actual := First_Actual (N);
+
+         while Present (Actual) loop
+            if not Analyzed (Etype (Actual))
+             and then From_With_Type (Etype (Actual))
+            then
+               Error_Msg_Qual_Level := 1;
+               Error_Msg_NE
+                ("missing with_clause for scope of imported type&",
+                  Actual, Etype (Actual));
+               Error_Msg_Qual_Level := 0;
+            end if;
+
+            Next_Actual (Actual);
+         end loop;
+      end if;
+
+      if All_Errors_Mode then
+
+         --   Analyze each candidate call again, with full error reporting
+         --   for each.
+
+         Error_Msg_N ("\no candidate interpretations "
+           & "match the actuals:!", Nam);
+
+         Get_First_Interp (Nam, X, It);
+
+         while Present (It.Nam) loop
+            Analyze_One_Call (N, It.Nam, True, Success);
+            Get_Next_Interp (X, It);
+         end loop;
+
+      else
+         if OpenVMS then
+            Error_Msg_N
+              ("invalid parameter list in call " &
+               "('/'R'E'P'O'R'T'_'E'R'R'O'R'S'='F'U'L'L for details)!",
+                Nam);
+         else
+            Error_Msg_N
+              ("invalid parameter list in call (use -gnatf for details)!",
+                Nam);
+         end if;
+      end if;
+
+      if Nkind (N) = N_Function_Call then
+         Get_First_Interp (Nam, X, It);
+
+         while Present (It.Nam) loop
+            if Ekind (It.Nam) = E_Function
+              or else Ekind (It.Nam) = E_Operator
+            then
+               return;
+            else
+               Get_Next_Interp (X, It);
+            end if;
+         end loop;
+
+         --  If all interpretations are procedures, this deserves a
+         --  more precise message. Ditto if this appears as the prefix
+         --  of a selected component, which may be a lexical error.
+
+         Error_Msg_N (
+         "\context requires function call, found procedure name", Nam);
+
+         if Nkind (Parent (N)) = N_Selected_Component
+           and then N = Prefix (Parent (N))
+         then
+            Error_Msg_N (
+              "\period should probably be semicolon", Parent (N));
+         end if;
+      end if;
+   end Diagnose_Call;
+
+   ---------------------------
+   -- Find_Arithmetic_Types --
+   ---------------------------
+
+   procedure Find_Arithmetic_Types
+     (L, R  : Node_Id;
+      Op_Id : Entity_Id;
+      N     : Node_Id)
+   is
+      Index1, Index2 : Interp_Index;
+      It1, It2 : Interp;
+
+      procedure Check_Right_Argument (T : Entity_Id);
+      --  Check right operand of operator
+
+      procedure Check_Right_Argument (T : Entity_Id) is
+      begin
+         if not Is_Overloaded (R) then
+            Check_Arithmetic_Pair (T, Etype (R), Op_Id,  N);
+         else
+            Get_First_Interp (R, Index2, It2);
+
+            while Present (It2.Typ) loop
+               Check_Arithmetic_Pair (T, It2.Typ, Op_Id, N);
+               Get_Next_Interp (Index2, It2);
+            end loop;
+         end if;
+      end Check_Right_Argument;
+
+   --  Start processing for Find_Arithmetic_Types
+
+   begin
+      if not Is_Overloaded (L) then
+         Check_Right_Argument (Etype (L));
+
+      else
+         Get_First_Interp (L, Index1, It1);
+
+         while Present (It1.Typ) loop
+            Check_Right_Argument (It1.Typ);
+            Get_Next_Interp (Index1, It1);
+         end loop;
+      end if;
+
+   end Find_Arithmetic_Types;
+
+   ------------------------
+   -- Find_Boolean_Types --
+   ------------------------
+
+   procedure Find_Boolean_Types
+     (L, R  : Node_Id;
+      Op_Id : Entity_Id;
+      N     : Node_Id)
+   is
+      Index : Interp_Index;
+      It    : Interp;
+
+      procedure Check_Numeric_Argument (T : Entity_Id);
+      --  Special case for logical operations one of whose operands is an
+      --  integer literal. If both are literal the result is any modular type.
+
+      procedure Check_Numeric_Argument (T : Entity_Id) is
+      begin
+         if T = Universal_Integer then
+            Add_One_Interp (N, Op_Id, Any_Modular);
+
+         elsif Is_Modular_Integer_Type (T) then
+            Add_One_Interp (N, Op_Id, T);
+         end if;
+      end Check_Numeric_Argument;
+
+   --  Start of processing for Find_Boolean_Types
+
+   begin
+      if not Is_Overloaded (L) then
+
+         if Etype (L) = Universal_Integer
+           or else Etype (L) = Any_Modular
+         then
+            if not Is_Overloaded (R) then
+               Check_Numeric_Argument (Etype (R));
+
+            else
+               Get_First_Interp (R, Index, It);
+
+               while Present (It.Typ) loop
+                  Check_Numeric_Argument (It.Typ);
+
+                  Get_Next_Interp (Index, It);
+               end loop;
+            end if;
+
+         elsif Valid_Boolean_Arg (Etype (L))
+           and then Has_Compatible_Type (R, Etype (L))
+         then
+            Add_One_Interp (N, Op_Id, Etype (L));
+         end if;
+
+      else
+         Get_First_Interp (L, Index, It);
+
+         while Present (It.Typ) loop
+            if Valid_Boolean_Arg (It.Typ)
+              and then Has_Compatible_Type (R, It.Typ)
+            then
+               Add_One_Interp (N, Op_Id, It.Typ);
+            end if;
+
+            Get_Next_Interp (Index, It);
+         end loop;
+      end if;
+   end Find_Boolean_Types;
+
+   ---------------------------
+   -- Find_Comparison_Types --
+   ---------------------------
+
+   procedure Find_Comparison_Types
+     (L, R  : Node_Id;
+      Op_Id : Entity_Id;
+      N     : Node_Id)
+   is
+      Index : Interp_Index;
+      It    : Interp;
+      Found : Boolean := False;
+      I_F   : Interp_Index;
+      T_F   : Entity_Id;
+      Scop  : Entity_Id := Empty;
+
+      procedure Try_One_Interp (T1 : Entity_Id);
+      --  Routine to try one proposed interpretation. Note that the context
+      --  of the operator plays no role in resolving the arguments, so that
+      --  if there is more than one interpretation of the operands that is
+      --  compatible with comparison, the operation is ambiguous.
+
+      procedure Try_One_Interp (T1 : Entity_Id) is
+      begin
+
+         --  If the operator is an expanded name, then the type of the operand
+         --  must be defined in the corresponding scope. If the type is
+         --  universal, the context will impose the correct type.
+
+         if Present (Scop)
+            and then not Defined_In_Scope (T1, Scop)
+            and then T1 /= Universal_Integer
+            and then T1 /= Universal_Real
+            and then T1 /= Any_String
+            and then T1 /= Any_Composite
+         then
+            return;
+         end if;
+
+         if Valid_Comparison_Arg (T1)
+           and then Has_Compatible_Type (R, T1)
+         then
+            if Found
+              and then Base_Type (T1) /= Base_Type (T_F)
+            then
+               It := Disambiguate (L, I_F, Index, Any_Type);
+
+               if It = No_Interp then
+                  Ambiguous_Operands (N);
+                  Set_Etype (L, Any_Type);
+                  return;
+
+               else
+                  T_F := It.Typ;
+               end if;
+
+            else
+               Found := True;
+               T_F   := T1;
+               I_F   := Index;
+            end if;
+
+            Set_Etype (L, T_F);
+            Find_Non_Universal_Interpretations (N, R, Op_Id, T1);
+
+         end if;
+      end Try_One_Interp;
+
+   --  Start processing for Find_Comparison_Types
+
+   begin
+
+      if Nkind (N) = N_Function_Call
+         and then Nkind (Name (N)) = N_Expanded_Name
+      then
+         Scop := Entity (Prefix (Name (N)));
+
+         --  The prefix may be a package renaming, and the subsequent test
+         --  requires the original package.
+
+         if Ekind (Scop) = E_Package
+           and then Present (Renamed_Entity (Scop))
+         then
+            Scop := Renamed_Entity (Scop);
+            Set_Entity (Prefix (Name (N)), Scop);
+         end if;
+      end if;
+
+      if not Is_Overloaded (L) then
+         Try_One_Interp (Etype (L));
+
+      else
+         Get_First_Interp (L, Index, It);
+
+         while Present (It.Typ) loop
+            Try_One_Interp (It.Typ);
+            Get_Next_Interp (Index, It);
+         end loop;
+      end if;
+   end Find_Comparison_Types;
+
+   ----------------------------------------
+   -- Find_Non_Universal_Interpretations --
+   ----------------------------------------
+
+   procedure Find_Non_Universal_Interpretations
+     (N     : Node_Id;
+      R     : Node_Id;
+      Op_Id : Entity_Id;
+      T1    : Entity_Id)
+   is
+      Index : Interp_Index;
+      It   : Interp;
+
+   begin
+      if T1 = Universal_Integer
+        or else T1 = Universal_Real
+      then
+         if not Is_Overloaded (R) then
+            Add_One_Interp
+              (N, Op_Id, Standard_Boolean, Base_Type (Etype (R)));
+         else
+            Get_First_Interp (R, Index, It);
+
+            while Present (It.Typ) loop
+               if Covers (It.Typ, T1) then
+                  Add_One_Interp
+                    (N, Op_Id, Standard_Boolean, Base_Type (It.Typ));
+               end if;
+
+               Get_Next_Interp (Index, It);
+            end loop;
+         end if;
+      else
+         Add_One_Interp (N, Op_Id, Standard_Boolean, Base_Type (T1));
+      end if;
+   end Find_Non_Universal_Interpretations;
+
+   ------------------------------
+   -- Find_Concatenation_Types --
+   ------------------------------
+
+   procedure Find_Concatenation_Types
+     (L, R  : Node_Id;
+      Op_Id : Entity_Id;
+      N     : Node_Id)
+   is
+      Op_Type : constant Entity_Id := Etype (Op_Id);
+
+   begin
+      if Is_Array_Type (Op_Type)
+        and then not Is_Limited_Type (Op_Type)
+
+        and then (Has_Compatible_Type (L, Op_Type)
+                    or else
+                  Has_Compatible_Type (L, Component_Type (Op_Type)))
+
+        and then (Has_Compatible_Type (R, Op_Type)
+                    or else
+                  Has_Compatible_Type (R, Component_Type (Op_Type)))
+      then
+         Add_One_Interp (N, Op_Id, Op_Type);
+      end if;
+   end Find_Concatenation_Types;
+
+   -------------------------
+   -- Find_Equality_Types --
+   -------------------------
+
+   procedure Find_Equality_Types
+     (L, R  : Node_Id;
+      Op_Id : Entity_Id;
+      N     : Node_Id)
+   is
+      Index : Interp_Index;
+      It    : Interp;
+      Found : Boolean := False;
+      I_F   : Interp_Index;
+      T_F   : Entity_Id;
+      Scop  : Entity_Id := Empty;
+
+      procedure Try_One_Interp (T1 : Entity_Id);
+      --  The context of the operator plays no role in resolving the
+      --  arguments,  so that if there is more than one interpretation
+      --  of the operands that is compatible with equality, the construct
+      --  is ambiguous and an error can be emitted now, after trying to
+      --  disambiguate, i.e. applying preference rules.
+
+      procedure Try_One_Interp (T1 : Entity_Id) is
+      begin
+
+         --  If the operator is an expanded name, then the type of the operand
+         --  must be defined in the corresponding scope. If the type is
+         --  universal, the context will impose the correct type. An anonymous
+         --  type for a 'Access reference is also universal in this sense, as
+         --  the actual type is obtained from context.
+
+         if Present (Scop)
+            and then not Defined_In_Scope (T1, Scop)
+            and then T1 /= Universal_Integer
+            and then T1 /= Universal_Real
+            and then T1 /= Any_Access
+            and then T1 /= Any_String
+            and then T1 /= Any_Composite
+            and then (Ekind (T1) /= E_Access_Subprogram_Type
+                        or else Comes_From_Source (T1))
+         then
+            return;
+         end if;
+
+         if T1 /= Standard_Void_Type
+           and then not Is_Limited_Type (T1)
+           and then not Is_Limited_Composite (T1)
+           and then Ekind (T1) /= E_Anonymous_Access_Type
+           and then Has_Compatible_Type (R, T1)
+         then
+            if Found
+              and then Base_Type (T1) /= Base_Type (T_F)
+            then
+               It := Disambiguate (L, I_F, Index, Any_Type);
+
+               if It = No_Interp then
+                  Ambiguous_Operands (N);
+                  Set_Etype (L, Any_Type);
+                  return;
+
+               else
+                  T_F := It.Typ;
+               end if;
+
+            else
+               Found := True;
+               T_F   := T1;
+               I_F   := Index;
+            end if;
+
+            if not Analyzed (L) then
+               Set_Etype (L, T_F);
+            end if;
+
+            Find_Non_Universal_Interpretations (N, R, Op_Id, T1);
+
+            if Etype (N) = Any_Type then
+
+               --  Operator was not visible.
+
+               Found := False;
+            end if;
+         end if;
+      end Try_One_Interp;
+
+   --  Start of processing for Find_Equality_Types
+
+   begin
+
+      if Nkind (N) = N_Function_Call
+         and then Nkind (Name (N)) = N_Expanded_Name
+      then
+         Scop := Entity (Prefix (Name (N)));
+
+         --  The prefix may be a package renaming, and the subsequent test
+         --  requires the original package.
+
+         if Ekind (Scop) = E_Package
+           and then Present (Renamed_Entity (Scop))
+         then
+            Scop := Renamed_Entity (Scop);
+            Set_Entity (Prefix (Name (N)), Scop);
+         end if;
+      end if;
+
+      if not Is_Overloaded (L) then
+         Try_One_Interp (Etype (L));
+      else
+
+         Get_First_Interp (L, Index, It);
+
+         while Present (It.Typ) loop
+            Try_One_Interp (It.Typ);
+            Get_Next_Interp (Index, It);
+         end loop;
+      end if;
+   end Find_Equality_Types;
+
+   -------------------------
+   -- Find_Negation_Types --
+   -------------------------
+
+   procedure Find_Negation_Types
+     (R     : Node_Id;
+      Op_Id : Entity_Id;
+      N     : Node_Id)
+   is
+      Index : Interp_Index;
+      It    : Interp;
+
+   begin
+      if not Is_Overloaded (R) then
+
+         if Etype (R) = Universal_Integer then
+            Add_One_Interp (N, Op_Id, Any_Modular);
+
+         elsif Valid_Boolean_Arg (Etype (R)) then
+            Add_One_Interp (N, Op_Id, Etype (R));
+         end if;
+
+      else
+         Get_First_Interp (R, Index, It);
+
+         while Present (It.Typ) loop
+            if Valid_Boolean_Arg (It.Typ) then
+               Add_One_Interp (N, Op_Id, It.Typ);
+            end if;
+
+            Get_Next_Interp (Index, It);
+         end loop;
+      end if;
+   end Find_Negation_Types;
+
+   ----------------------
+   -- Find_Unary_Types --
+   ----------------------
+
+   procedure Find_Unary_Types
+     (R     : Node_Id;
+      Op_Id : Entity_Id;
+      N     : Node_Id)
+   is
+      Index : Interp_Index;
+      It    : Interp;
+
+   begin
+      if not Is_Overloaded (R) then
+         if Is_Numeric_Type (Etype (R)) then
+            Add_One_Interp (N, Op_Id, Base_Type (Etype (R)));
+         end if;
+
+      else
+         Get_First_Interp (R, Index, It);
+
+         while Present (It.Typ) loop
+            if Is_Numeric_Type (It.Typ) then
+               Add_One_Interp (N, Op_Id, Base_Type (It.Typ));
+            end if;
+
+            Get_Next_Interp (Index, It);
+         end loop;
+      end if;
+   end Find_Unary_Types;
+
+   ---------------------------------
+   -- Insert_Explicit_Dereference --
+   ---------------------------------
+
+   procedure Insert_Explicit_Dereference (N : Node_Id) is
+      New_Prefix : Node_Id := Relocate_Node (N);
+      I          : Interp_Index;
+      It         : Interp;
+      T          : Entity_Id;
+
+   begin
+      Save_Interps (N, New_Prefix);
+      Rewrite (N,
+        Make_Explicit_Dereference (Sloc (N), Prefix => New_Prefix));
+
+      Set_Etype (N, Designated_Type (Etype (New_Prefix)));
+
+      if Is_Overloaded (New_Prefix) then
+
+         --  The deference is also overloaded, and its interpretations are the
+         --  designated types of the interpretations of the original node.
+
+         Set_Is_Overloaded (N);
+         Get_First_Interp (New_Prefix, I, It);
+
+         while Present (It.Nam) loop
+            T := It.Typ;
+
+            if Is_Access_Type (T) then
+               Add_One_Interp (N, Designated_Type (T), Designated_Type (T));
+            end if;
+
+            Get_Next_Interp (I, It);
+         end loop;
+
+         End_Interp_List;
+      end if;
+
+   end Insert_Explicit_Dereference;
+
+   ------------------
+   -- Junk_Operand --
+   ------------------
+
+   function Junk_Operand (N : Node_Id) return Boolean is
+      Enode : Node_Id;
+
+   begin
+      if Error_Posted (N) then
+         return False;
+      end if;
+
+      --  Get entity to be tested
+
+      if Is_Entity_Name (N)
+        and then Present (Entity (N))
+      then
+         Enode := N;
+
+      --  An odd case, a procedure name gets converted to a very peculiar
+      --  function call, and here is where we detect this happening.
+
+      elsif Nkind (N) = N_Function_Call
+        and then Is_Entity_Name (Name (N))
+        and then Present (Entity (Name (N)))
+      then
+         Enode := Name (N);
+
+      --  Another odd case, there are at least some cases of selected
+      --  components where the selected component is not marked as having
+      --  an entity, even though the selector does have an entity
+
+      elsif Nkind (N) = N_Selected_Component
+        and then Present (Entity (Selector_Name (N)))
+      then
+         Enode := Selector_Name (N);
+
+      else
+         return False;
+      end if;
+
+      --  Now test the entity we got to see if it a bad case
+
+      case Ekind (Entity (Enode)) is
+
+         when E_Package =>
+            Error_Msg_N
+              ("package name cannot be used as operand", Enode);
+
+         when Generic_Unit_Kind =>
+            Error_Msg_N
+              ("generic unit name cannot be used as operand", Enode);
+
+         when Type_Kind =>
+            Error_Msg_N
+              ("subtype name cannot be used as operand", Enode);
+
+         when Entry_Kind =>
+            Error_Msg_N
+              ("entry name cannot be used as operand", Enode);
+
+         when E_Procedure =>
+            Error_Msg_N
+              ("procedure name cannot be used as operand", Enode);
+
+         when E_Exception =>
+            Error_Msg_N
+              ("exception name cannot be used as operand", Enode);
+
+         when E_Block | E_Label | E_Loop =>
+            Error_Msg_N
+              ("label name cannot be used as operand", Enode);
+
+         when others =>
+            return False;
+
+      end case;
+
+      return True;
+   end Junk_Operand;
+
+   --------------------
+   -- Operator_Check --
+   --------------------
+
+   procedure Operator_Check (N : Node_Id) is
+   begin
+      --  Test for case of no interpretation found for operator
+
+      if Etype (N) = Any_Type then
+         declare
+            L : Node_Id;
+            R : Node_Id;
+
+         begin
+            R := Right_Opnd (N);
+
+            if Nkind (N) in N_Binary_Op then
+               L := Left_Opnd (N);
+            else
+               L := Empty;
+            end if;
+
+            --  If either operand has no type, then don't complain further,
+            --  since this simply means that we have a propragated error.
+
+            if R = Error
+              or else Etype (R) = Any_Type
+              or else (Nkind (N) in N_Binary_Op and then Etype (L) = Any_Type)
+            then
+               return;
+
+            --  We explicitly check for the case of concatenation of
+            --  component with component to avoid reporting spurious
+            --  matching array types that might happen to be lurking
+            --  in distant packages (such as run-time packages). This
+            --  also prevents inconsistencies in the messages for certain
+            --  ACVC B tests, which can vary depending on types declared
+            --  in run-time interfaces. A further improvement, when
+            --  aggregates are present, is to look for a well-typed operand.
+
+            elsif Present (Candidate_Type)
+              and then (Nkind (N) /= N_Op_Concat
+                         or else Is_Array_Type (Etype (L))
+                         or else Is_Array_Type (Etype (R)))
+            then
+
+               if Nkind (N) = N_Op_Concat then
+                  if Etype (L) /= Any_Composite
+                    and then Is_Array_Type (Etype (L))
+                  then
+                     Candidate_Type := Etype (L);
+
+                  elsif Etype (R) /= Any_Composite
+                    and then Is_Array_Type (Etype (R))
+                  then
+                     Candidate_Type := Etype (R);
+                  end if;
+               end if;
+
+               Error_Msg_NE
+                 ("operator for} is not directly visible!",
+                  N, First_Subtype (Candidate_Type));
+               Error_Msg_N ("use clause would make operation legal!",  N);
+               return;
+
+            --  If either operand is a junk operand (e.g. package name), then
+            --  post appropriate error messages, but do not complain further.
+
+            --  Note that the use of OR in this test instead of OR ELSE
+            --  is quite deliberate, we may as well check both operands
+            --  in the binary operator case.
+
+            elsif Junk_Operand (R)
+              or (Nkind (N) in N_Binary_Op and then Junk_Operand (L))
+            then
+               return;
+
+            --  If we have a logical operator, one of whose operands is
+            --  Boolean, then we know that the other operand cannot resolve
+            --  to Boolean (since we got no interpretations), but in that
+            --  case we pretty much know that the other operand should be
+            --  Boolean, so resolve it that way (generating an error)
+
+            elsif Nkind (N) = N_Op_And
+                    or else
+                  Nkind (N) = N_Op_Or
+                    or else
+                  Nkind (N) = N_Op_Xor
+            then
+               if Etype (L) = Standard_Boolean then
+                  Resolve (R, Standard_Boolean);
+                  return;
+               elsif Etype (R) = Standard_Boolean then
+                  Resolve (L, Standard_Boolean);
+                  return;
+               end if;
+
+            --  For an arithmetic operator or comparison operator, if one
+            --  of the operands is numeric, then we know the other operand
+            --  is not the same numeric type. If it is a non-numeric type,
+            --  then probably it is intended to match the other operand.
+
+            elsif Nkind (N) = N_Op_Add      or else
+                  Nkind (N) = N_Op_Divide   or else
+                  Nkind (N) = N_Op_Ge       or else
+                  Nkind (N) = N_Op_Gt       or else
+                  Nkind (N) = N_Op_Le       or else
+                  Nkind (N) = N_Op_Lt       or else
+                  Nkind (N) = N_Op_Mod      or else
+                  Nkind (N) = N_Op_Multiply or else
+                  Nkind (N) = N_Op_Rem      or else
+                  Nkind (N) = N_Op_Subtract
+            then
+               if Is_Numeric_Type (Etype (L))
+                 and then not Is_Numeric_Type (Etype (R))
+               then
+                  Resolve (R, Etype (L));
+                  return;
+
+               elsif Is_Numeric_Type (Etype (R))
+                 and then not Is_Numeric_Type (Etype (L))
+               then
+                  Resolve (L, Etype (R));
+                  return;
+               end if;
+
+            --  Comparisons on A'Access are common enough to deserve a
+            --  special message.
+
+            elsif (Nkind (N) = N_Op_Eq  or else
+                   Nkind (N) = N_Op_Ne)
+               and then Ekind (Etype (L)) = E_Access_Attribute_Type
+               and then Ekind (Etype (R)) = E_Access_Attribute_Type
+            then
+               Error_Msg_N
+                 ("two access attributes cannot be compared directly", N);
+               Error_Msg_N
+                 ("\they must be converted to an explicit type for comparison",
+                   N);
+               return;
+
+            --  Another one for C programmers
+
+            elsif Nkind (N) = N_Op_Concat
+              and then Valid_Boolean_Arg (Etype (L))
+              and then Valid_Boolean_Arg (Etype (R))
+            then
+               Error_Msg_N ("invalid operands for concatenation", N);
+               Error_Msg_N ("\maybe AND was meant", N);
+               return;
+
+            --  A special case for comparison of access parameter with null
+
+            elsif Nkind (N) = N_Op_Eq
+              and then Is_Entity_Name (L)
+              and then Nkind (Parent (Entity (L))) = N_Parameter_Specification
+              and then Nkind (Parameter_Type (Parent (Entity (L)))) =
+                                                  N_Access_Definition
+              and then Nkind (R) = N_Null
+            then
+               Error_Msg_N ("access parameter is not allowed to be null", L);
+               Error_Msg_N ("\(call would raise Constraint_Error)", L);
+               return;
+            end if;
+
+            --  If we fall through then just give general message. Note
+            --  that in the following messages, if the operand is overloaded
+            --  we choose an arbitrary type to complain about, but that is
+            --  probably more useful than not giving a type at all.
+
+            if Nkind (N) in N_Unary_Op then
+               Error_Msg_Node_2 := Etype (R);
+               Error_Msg_N ("operator& not defined for}", N);
+               return;
+
+            else
+               Error_Msg_N ("invalid operand types for operator&", N);
+
+               if Nkind (N) in N_Binary_Op
+                 and then Nkind (N) /= N_Op_Concat
+               then
+                  Error_Msg_NE ("\left operand has}!",  N, Etype (L));
+                  Error_Msg_NE ("\right operand has}!", N, Etype (R));
+               end if;
+            end if;
+         end;
+      end if;
+   end Operator_Check;
+
+   -----------------------
+   -- Try_Indirect_Call --
+   -----------------------
+
+   function Try_Indirect_Call
+     (N      : Node_Id;
+      Nam    : Entity_Id;
+      Typ    : Entity_Id)
+      return   Boolean
+   is
+      Actuals    : List_Id   := Parameter_Associations (N);
+      Actual     : Node_Id   := First (Actuals);
+      Formal     : Entity_Id := First_Formal (Designated_Type (Typ));
+
+   begin
+      while Present (Actual)
+        and then Present (Formal)
+      loop
+         if not Has_Compatible_Type (Actual, Etype (Formal)) then
+            return False;
+         end if;
+
+         Next (Actual);
+         Next_Formal (Formal);
+      end loop;
+
+      if No (Actual) and then No (Formal) then
+         Add_One_Interp (N, Nam, Etype (Designated_Type (Typ)));
+
+         --  Nam is a candidate interpretation for the name in the call,
+         --  if it is not an indirect call.
+
+         if not Is_Type (Nam)
+            and then Is_Entity_Name (Name (N))
+         then
+            Set_Entity (Name (N), Nam);
+         end if;
+
+         return True;
+      else
+         return False;
+      end if;
+   end Try_Indirect_Call;
+
+   ----------------------
+   -- Try_Indexed_Call --
+   ----------------------
+
+   function Try_Indexed_Call
+     (N      : Node_Id;
+      Nam    : Entity_Id;
+      Typ    : Entity_Id)
+      return   Boolean
+   is
+      Actuals    : List_Id   := Parameter_Associations (N);
+      Actual     : Node_Id   := First (Actuals);
+      Index      : Entity_Id := First_Index (Typ);
+
+   begin
+      while Present (Actual)
+        and then Present (Index)
+      loop
+         --  If the parameter list has a named association, the expression
+         --  is definitely a call and not an indexed component.
+
+         if Nkind (Actual) = N_Parameter_Association then
+            return False;
+         end if;
+
+         if not Has_Compatible_Type (Actual, Etype (Index)) then
+            return False;
+         end if;
+
+         Next (Actual);
+         Next_Index (Index);
+      end loop;
+
+      if No (Actual) and then No (Index) then
+         Add_One_Interp (N, Nam, Component_Type (Typ));
+
+         --  Nam is a candidate interpretation for the name in the call,
+         --  if it is not an indirect call.
+
+         if not Is_Type (Nam)
+            and then Is_Entity_Name (Name (N))
+         then
+            Set_Entity (Name (N), Nam);
+         end if;
+
+         return True;
+      else
+         return False;
+      end if;
+
+   end Try_Indexed_Call;
+
+end Sem_Ch4;
diff --git a/gcc/ada/sem_ch4.ads b/gcc/ada/sem_ch4.ads
new file mode 100644 (file)
index 0000000..236785f
--- /dev/null
@@ -0,0 +1,66 @@
+------------------------------------------------------------------------------
+--                                                                          --
+--                         GNAT COMPILER COMPONENTS                         --
+--                                                                          --
+--                              S E M _ C H 4                               --
+--                                                                          --
+--                                 S p e c                                  --
+--                                                                          --
+--                            $Revision: 1.18 $                             --
+--                                                                          --
+--   Copyright (C) 1992,1993,1994,1995,1996 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- --
+-- ware  Foundation;  either version 2,  or (at your option) any later ver- --
+-- sion.  GNAT is distributed in the hope that it will be useful, but WITH- --
+-- OUT ANY WARRANTY;  without even the  implied warranty of MERCHANTABILITY --
+-- or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License --
+-- for  more details.  You should have  received  a copy of the GNU General --
+-- Public License  distributed with GNAT;  see file COPYING.  If not, write --
+-- to  the Free Software Foundation,  59 Temple Place - Suite 330,  Boston, --
+-- MA 02111-1307, USA.                                                      --
+--                                                                          --
+-- GNAT was originally developed  by the GNAT team at  New York University. --
+-- It is now maintained by Ada Core Technologies Inc (http://www.gnat.com). --
+--                                                                          --
+------------------------------------------------------------------------------
+
+with Types; use Types;
+
+package Sem_Ch4  is
+   procedure Analyze_Aggregate                          (N : Node_Id);
+   procedure Analyze_Allocator                          (N : Node_Id);
+   procedure Analyze_Arithmetic_Op                      (N : Node_Id);
+   procedure Analyze_Call                               (N : Node_Id);
+   procedure Analyze_Comparison_Op                      (N : Node_Id);
+   procedure Analyze_Concatenation                      (N : Node_Id);
+   procedure Analyze_Conditional_Expression             (N : Node_Id);
+   procedure Analyze_Equality_Op                        (N : Node_Id);
+   procedure Analyze_Explicit_Dereference               (N : Node_Id);
+   procedure Analyze_Logical_Op                         (N : Node_Id);
+   procedure Analyze_Membership_Op                      (N : Node_Id);
+   procedure Analyze_Negation                           (N : Node_Id);
+   procedure Analyze_Null                               (N : Node_Id);
+   procedure Analyze_Qualified_Expression               (N : Node_Id);
+   procedure Analyze_Range                              (N : Node_Id);
+   procedure Analyze_Reference                          (N : Node_Id);
+   procedure Analyze_Selected_Component                 (N : Node_Id);
+   procedure Analyze_Short_Circuit                      (N : Node_Id);
+   procedure Analyze_Slice                              (N : Node_Id);
+   procedure Analyze_Type_Conversion                    (N : Node_Id);
+   procedure Analyze_Unary_Op                           (N : Node_Id);
+   procedure Analyze_Unchecked_Expression               (N : Node_Id);
+   procedure Analyze_Unchecked_Type_Conversion          (N : Node_Id);
+
+   procedure Analyze_Indexed_Component_Form (N : Node_Id);
+   --  Prior to semantic analysis, an indexed component node can denote any
+   --  of the following syntactic constructs:
+   --    a) An indexed component of an array
+   --    b) A function call
+   --    c) A conversion
+   --    d) A slice
+   --  The resolution of the construct requires some semantic information
+   --  on the prefix and the indices.
+
+end Sem_Ch4;
diff --git a/gcc/ada/sem_ch5.adb b/gcc/ada/sem_ch5.adb
new file mode 100644 (file)
index 0000000..658a685
--- /dev/null
@@ -0,0 +1,1256 @@
+------------------------------------------------------------------------------
+--                                                                          --
+--                         GNAT COMPILER COMPONENTS                         --
+--                                                                          --
+--                              S E M _ C H 5                               --
+--                                                                          --
+--                                 B o d y                                  --
+--                                                                          --
+--                            $Revision: 1.262 $
+--                                                                          --
+--          Copyright (C) 1992-2001 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- --
+-- ware  Foundation;  either version 2,  or (at your option) any later ver- --
+-- sion.  GNAT is distributed in the hope that it will be useful, but WITH- --
+-- OUT ANY WARRANTY;  without even the  implied warranty of MERCHANTABILITY --
+-- or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License --
+-- for  more details.  You should have  received  a copy of the GNU General --
+-- Public License  distributed with GNAT;  see file COPYING.  If not, write --
+-- to  the Free Software Foundation,  59 Temple Place - Suite 330,  Boston, --
+-- MA 02111-1307, USA.                                                      --
+--                                                                          --
+-- GNAT was originally developed  by the GNAT team at  New York University. --
+-- It is now maintained by Ada Core Technologies Inc (http://www.gnat.com). --
+--                                                                          --
+------------------------------------------------------------------------------
+
+with Atree;    use Atree;
+with Checks;   use Checks;
+with Einfo;    use Einfo;
+with Errout;   use Errout;
+with Expander; use Expander;
+with Exp_Util; use Exp_Util;
+with Freeze;   use Freeze;
+with Lib.Xref; use Lib.Xref;
+with Nlists;   use Nlists;
+with Opt;      use Opt;
+with Sem;      use Sem;
+with Sem_Case; use Sem_Case;
+with Sem_Ch3;  use Sem_Ch3;
+with Sem_Ch8;  use Sem_Ch8;
+with Sem_Disp; use Sem_Disp;
+with Sem_Eval; use Sem_Eval;
+with Sem_Res;  use Sem_Res;
+with Sem_Type; use Sem_Type;
+with Sem_Util; use Sem_Util;
+with Sem_Warn; use Sem_Warn;
+with Stand;    use Stand;
+with Sinfo;    use Sinfo;
+with Tbuild;   use Tbuild;
+with Uintp;    use Uintp;
+
+package body Sem_Ch5 is
+
+   Unblocked_Exit_Count : Nat := 0;
+   --  This variable is used when processing if statements or case
+   --  statements, it counts the number of branches of the conditional
+   --  that are not blocked by unconditional transfer instructions. At
+   --  the end of processing, if the count is zero, it means that control
+   --  cannot fall through the conditional statement. This is used for
+   --  the generation of warning messages. This variable is recursively
+   --  saved on entry to processing an if or case, and restored on exit.
+
+   -----------------------
+   -- Local Subprograms --
+   -----------------------
+
+   procedure Analyze_Iteration_Scheme (N : Node_Id);
+
+   ------------------------
+   -- Analyze_Assignment --
+   ------------------------
+
+   procedure Analyze_Assignment (N : Node_Id) is
+      Lhs    : constant Node_Id := Name (N);
+      Rhs    : constant Node_Id := Expression (N);
+      T1, T2 : Entity_Id;
+      Decl   : Node_Id;
+
+      procedure Diagnose_Non_Variable_Lhs (N : Node_Id);
+      --  N is the node for the left hand side of an assignment, and it
+      --  is not a variable. This routine issues an appropriate diagnostic.
+
+      procedure Set_Assignment_Type
+        (Opnd      : Node_Id;
+         Opnd_Type : in out Entity_Id);
+      --  Opnd is either the Lhs or Rhs of the assignment, and Opnd_Type
+      --  is the nominal subtype. This procedure is used to deal with cases
+      --  where the nominal subtype must be replaced by the actual subtype.
+
+      -------------------------------
+      -- Diagnose_Non_Variable_Lhs --
+      -------------------------------
+
+      procedure Diagnose_Non_Variable_Lhs (N : Node_Id) is
+      begin
+         --  Not worth posting another error if left hand side already
+         --  flagged as being illegal in some respect
+
+         if Error_Posted (N) then
+            return;
+
+         --  Some special bad cases of entity names
+
+         elsif Is_Entity_Name (N) then
+
+            if Ekind (Entity (N)) = E_In_Parameter then
+               Error_Msg_N
+                 ("assignment to IN mode parameter not allowed", N);
+               return;
+
+            --  Private declarations in a protected object are turned into
+            --  constants when compiling a protected function.
+
+            elsif Present (Scope (Entity (N)))
+              and then Is_Protected_Type (Scope (Entity (N)))
+              and then
+                (Ekind (Current_Scope) = E_Function
+                  or else
+                 Ekind (Enclosing_Dynamic_Scope (Current_Scope)) = E_Function)
+            then
+               Error_Msg_N
+                 ("protected function cannot modify protected object", N);
+               return;
+
+            elsif Ekind (Entity (N)) = E_Loop_Parameter then
+               Error_Msg_N
+                 ("assignment to loop parameter not allowed", N);
+               return;
+
+            end if;
+
+         --  For indexed components, or selected components, test prefix
+
+         elsif Nkind (N) = N_Indexed_Component
+           or else Nkind (N) = N_Selected_Component
+         then
+            Diagnose_Non_Variable_Lhs (Prefix (N));
+            return;
+         end if;
+
+         --  If we fall through, we have no special message to issue!
+
+         Error_Msg_N ("left hand side of assignment must be a variable", N);
+
+      end Diagnose_Non_Variable_Lhs;
+
+      -------------------------
+      -- Set_Assignment_Type --
+      -------------------------
+
+      procedure Set_Assignment_Type
+        (Opnd      : Node_Id;
+         Opnd_Type : in out Entity_Id)
+      is
+      begin
+         --  If the assignment operand is an in-out or out parameter, then we
+         --  get the actual subtype (needed for the unconstrained case).
+
+         if Is_Entity_Name (Opnd)
+           and then (Ekind (Entity (Opnd)) = E_Out_Parameter
+                      or else Ekind (Entity (Opnd)) =
+                           E_In_Out_Parameter
+                      or else Ekind (Entity (Opnd)) =
+                           E_Generic_In_Out_Parameter)
+         then
+            Opnd_Type := Get_Actual_Subtype (Opnd);
+
+         --  If assignment operand is a component reference, then we get the
+         --  actual subtype of the component for the unconstrained case.
+
+         elsif Nkind (Opnd) = N_Selected_Component
+           or else Nkind (Opnd) = N_Explicit_Dereference
+         then
+            Decl := Build_Actual_Subtype_Of_Component (Opnd_Type, Opnd);
+
+            if Present (Decl) then
+               Insert_Action (N, Decl);
+               Mark_Rewrite_Insertion (Decl);
+               Analyze (Decl);
+               Opnd_Type := Defining_Identifier (Decl);
+               Set_Etype (Opnd, Opnd_Type);
+               Freeze_Itype (Opnd_Type, N);
+
+            elsif Is_Constrained (Etype (Opnd)) then
+               Opnd_Type := Etype (Opnd);
+            end if;
+
+         --  For slice, use the constrained subtype created for the slice
+
+         elsif Nkind (Opnd) = N_Slice then
+            Opnd_Type := Etype (Opnd);
+         end if;
+      end Set_Assignment_Type;
+
+   --  Start of processing for Analyze_Assignment
+
+   begin
+      Analyze (Rhs);
+      Analyze (Lhs);
+      T1 := Etype (Lhs);
+
+      --  In the most general case, both Lhs and Rhs can be overloaded, and we
+      --  must compute the intersection of the possible types on each side.
+
+      if Is_Overloaded (Lhs) then
+         declare
+            I  : Interp_Index;
+            It : Interp;
+
+         begin
+            T1 := Any_Type;
+            Get_First_Interp (Lhs, I, It);
+
+            while Present (It.Typ) loop
+               if Has_Compatible_Type (Rhs, It.Typ) then
+
+                  if T1 /= Any_Type then
+
+                     --  An explicit dereference is overloaded if the prefix
+                     --  is. Try to remove the ambiguity on the prefix, the
+                     --  error will be posted there if the ambiguity is real.
+
+                     if Nkind (Lhs) = N_Explicit_Dereference then
+                        declare
+                           PI    : Interp_Index;
+                           PI1   : Interp_Index := 0;
+                           PIt   : Interp;
+                           Found : Boolean;
+
+                        begin
+                           Found := False;
+                           Get_First_Interp (Prefix (Lhs), PI, PIt);
+
+                           while Present (PIt.Typ) loop
+                              if Has_Compatible_Type (Rhs,
+                                Designated_Type (PIt.Typ))
+                              then
+                                 if Found then
+                                    PIt :=
+                                      Disambiguate (Prefix (Lhs),
+                                        PI1, PI, Any_Type);
+
+                                    if PIt = No_Interp then
+                                       return;
+                                    else
+                                       Resolve (Prefix (Lhs), PIt.Typ);
+                                    end if;
+
+                                    exit;
+                                 else
+                                    Found := True;
+                                    PI1 := PI;
+                                 end if;
+                              end if;
+
+                              Get_Next_Interp (PI, PIt);
+                           end loop;
+                        end;
+
+                     else
+                        Error_Msg_N
+                          ("ambiguous left-hand side in assignment", Lhs);
+                        exit;
+                     end if;
+                  else
+                     T1 := It.Typ;
+                  end if;
+               end if;
+
+               Get_Next_Interp (I, It);
+            end loop;
+         end;
+
+         if T1 = Any_Type then
+            Error_Msg_N
+              ("no valid types for left-hand side for assignment", Lhs);
+            return;
+         end if;
+      end if;
+
+      Resolve (Lhs, T1);
+
+      if not Is_Variable (Lhs) then
+         Diagnose_Non_Variable_Lhs (Lhs);
+         return;
+
+      elsif Is_Limited_Type (T1)
+        and then not Assignment_OK (Lhs)
+        and then not Assignment_OK (Original_Node (Lhs))
+      then
+         Error_Msg_N
+           ("left hand of assignment must not be limited type", Lhs);
+         return;
+      end if;
+
+      --  Resolution may have updated the subtype, in case the left-hand
+      --  side is a private protected component. Use the correct subtype
+      --  to avoid scoping issues in the back-end.
+
+      T1 := Etype (Lhs);
+      Set_Assignment_Type (Lhs, T1);
+
+      Resolve (Rhs, T1);
+
+      --  Remaining steps are skipped if Rhs was synatactically in error
+
+      if Rhs = Error then
+         return;
+      end if;
+
+      T2 := Etype (Rhs);
+      Check_Unset_Reference (Rhs);
+      Note_Possible_Modification (Lhs);
+
+      if Covers (T1, T2) then
+         null;
+      else
+         Wrong_Type (Rhs, Etype (Lhs));
+         return;
+      end if;
+
+      Set_Assignment_Type (Rhs, T2);
+
+      if T1 = Any_Type or else T2 = Any_Type then
+         return;
+      end if;
+
+      if (Is_Class_Wide_Type (T2) or else Is_Dynamically_Tagged (Rhs))
+        and then not Is_Class_Wide_Type (T1)
+      then
+         Error_Msg_N ("dynamically tagged expression not allowed!", Rhs);
+
+      elsif Is_Class_Wide_Type (T1)
+        and then not Is_Class_Wide_Type (T2)
+        and then not Is_Tag_Indeterminate (Rhs)
+        and then not Is_Dynamically_Tagged (Rhs)
+      then
+         Error_Msg_N ("dynamically tagged expression required!", Rhs);
+      end if;
+
+      --  Tag propagation is done only in semantics mode only. If expansion
+      --  is on, the rhs tag indeterminate function call has been expanded
+      --  and tag propagation would have happened too late, so the
+      --  propagation take place in expand_call instead.
+
+      if not Expander_Active
+        and then Is_Class_Wide_Type (T1)
+        and then Is_Tag_Indeterminate (Rhs)
+      then
+         Propagate_Tag (Lhs, Rhs);
+      end if;
+
+      if Is_Scalar_Type (T1) then
+         Apply_Scalar_Range_Check (Rhs, Etype (Lhs));
+
+      elsif Is_Array_Type (T1) then
+
+         --  Assignment verifies that the length of the Lsh and Rhs are equal,
+         --  but of course the indices do not have to match.
+
+         Apply_Length_Check (Rhs, Etype (Lhs));
+
+      else
+         --  Discriminant checks are applied in the course of expansion.
+         null;
+      end if;
+
+      --  ??? a real accessibility check is needed when ???
+
+      --  Post warning for useless assignment
+
+      if Warn_On_Redundant_Constructs
+
+         --  We only warn for source constructs
+
+         and then Comes_From_Source (N)
+
+         --  Where the entity is the same on both sides
+
+         and then Is_Entity_Name (Lhs)
+         and then Is_Entity_Name (Rhs)
+         and then Entity (Lhs) = Entity (Rhs)
+
+         --  But exclude the case where the right side was an operation
+         --  that got rewritten (e.g. JUNK + K, where K was known to be
+         --  zero). We don't want to warn in such a case, since it is
+         --  reasonable to write such expressions especially when K is
+         --  defined symbolically in some other package.
+
+        and then Nkind (Original_Node (Rhs)) not in N_Op
+      then
+         Error_Msg_NE
+           ("?useless assignment of & to itself", N, Entity (Lhs));
+      end if;
+   end Analyze_Assignment;
+
+   -----------------------------
+   -- Analyze_Block_Statement --
+   -----------------------------
+
+   procedure Analyze_Block_Statement (N : Node_Id) is
+      Decls : constant List_Id := Declarations (N);
+      Id    : constant Node_Id := Identifier (N);
+      Ent   : Entity_Id;
+
+   begin
+      --  If a label is present analyze it and mark it as referenced
+
+      if Present (Id) then
+         Analyze (Id);
+         Ent := Entity (Id);
+         Set_Ekind (Ent, E_Block);
+         Generate_Reference (Ent, N, ' ');
+         Generate_Definition (Ent);
+
+         if Nkind (Parent (Ent)) = N_Implicit_Label_Declaration then
+            Set_Label_Construct (Parent (Ent), N);
+         end if;
+
+      --  Otherwise create a label entity
+
+      else
+         Ent := New_Internal_Entity (E_Block, Current_Scope, Sloc (N), 'B');
+         Set_Identifier (N, New_Occurrence_Of (Ent, Sloc (N)));
+      end if;
+
+      Set_Etype (Ent, Standard_Void_Type);
+      Set_Block_Node (Ent, N);
+      New_Scope (Ent);
+
+      if Present (Decls) then
+         Analyze_Declarations (Decls);
+         Check_Completion;
+      end if;
+
+      Analyze (Handled_Statement_Sequence (N));
+      Process_End_Label (Handled_Statement_Sequence (N), 'e');
+
+      --  Analyze exception handlers if present. Note that the test for
+      --  HSS being present is an error defence against previous errors.
+
+      if Present (Handled_Statement_Sequence (N))
+        and then Present (Exception_Handlers (Handled_Statement_Sequence (N)))
+      then
+         declare
+            S : Entity_Id := Scope (Ent);
+
+         begin
+            --  Indicate that enclosing scopes contain a block with handlers.
+            --  Only non-generic scopes need to be marked.
+
+            loop
+               Set_Has_Nested_Block_With_Handler (S);
+               exit when Is_Overloadable (S)
+                 or else Ekind (S) = E_Package
+                 or else Ekind (S) = E_Generic_Function
+                 or else Ekind (S) = E_Generic_Package
+                 or else Ekind (S) = E_Generic_Procedure;
+               S := Scope (S);
+            end loop;
+         end;
+      end if;
+
+      Check_References (Ent);
+      End_Scope;
+   end Analyze_Block_Statement;
+
+   ----------------------------
+   -- Analyze_Case_Statement --
+   ----------------------------
+
+   procedure Analyze_Case_Statement (N : Node_Id) is
+
+      Statements_Analyzed : Boolean := False;
+      --  Set True if at least some statement sequences get analyzed.
+      --  If False on exit, means we had a serious error that prevented
+      --  full analysis of the case statement, and as a result it is not
+      --  a good idea to output warning messages about unreachable code.
+
+      Save_Unblocked_Exit_Count : constant Nat := Unblocked_Exit_Count;
+      --  Recursively save value of this global, will be restored on exit
+
+      procedure Non_Static_Choice_Error (Choice : Node_Id);
+      --  Error routine invoked by the generic instantiation below when
+      --  the case statment has a non static choice.
+
+      procedure Process_Statements (Alternative : Node_Id);
+      --  Analyzes all the statements associated to a case alternative.
+      --  Needed by the generic instantiation below.
+
+      package Case_Choices_Processing is new
+        Generic_Choices_Processing
+          (Get_Alternatives          => Alternatives,
+           Get_Choices               => Discrete_Choices,
+           Process_Empty_Choice      => No_OP,
+           Process_Non_Static_Choice => Non_Static_Choice_Error,
+           Process_Associated_Node   => Process_Statements);
+      use Case_Choices_Processing;
+      --  Instantiation of the generic choice processing package.
+
+      -----------------------------
+      -- Non_Static_Choice_Error --
+      -----------------------------
+
+      procedure Non_Static_Choice_Error (Choice : Node_Id) is
+      begin
+         Error_Msg_N ("choice given in case statement is not static", Choice);
+      end Non_Static_Choice_Error;
+
+      ------------------------
+      -- Process_Statements --
+      ------------------------
+
+      procedure Process_Statements (Alternative : Node_Id) is
+      begin
+         Unblocked_Exit_Count := Unblocked_Exit_Count + 1;
+         Statements_Analyzed := True;
+         Analyze_Statements (Statements (Alternative));
+      end Process_Statements;
+
+      --  Variables local to Analyze_Case_Statement.
+
+      Exp       : Node_Id;
+      Exp_Type  : Entity_Id;
+      Exp_Btype : Entity_Id;
+
+      Case_Table     : Choice_Table_Type (1 .. Number_Of_Choices (N));
+      Last_Choice    : Nat;
+      Dont_Care      : Boolean;
+      Others_Present : Boolean;
+
+   --  Start of processing for Analyze_Case_Statement
+
+   begin
+      Unblocked_Exit_Count := 0;
+      Exp := Expression (N);
+      Analyze_And_Resolve (Exp, Any_Discrete);
+      Check_Unset_Reference (Exp);
+      Exp_Type  := Etype (Exp);
+      Exp_Btype := Base_Type (Exp_Type);
+
+      --  The expression must be of a discrete type which must be determinable
+      --  independently of the context in which the expression occurs, but
+      --  using the fact that the expression must be of a discrete type.
+      --  Moreover, the type this expression must not be a character literal
+      --  (which is always ambiguous) or, for Ada-83, a generic formal type.
+
+      --  If error already reported by Resolve, nothing more to do
+
+      if Exp_Btype = Any_Discrete
+        or else Exp_Btype = Any_Type
+      then
+         return;
+
+      elsif Exp_Btype = Any_Character then
+         Error_Msg_N
+           ("character literal as case expression is ambiguous", Exp);
+         return;
+
+      elsif Ada_83
+        and then (Is_Generic_Type (Exp_Btype)
+                    or else Is_Generic_Type (Root_Type (Exp_Btype)))
+      then
+         Error_Msg_N
+           ("(Ada 83) case expression cannot be of a generic type", Exp);
+         return;
+      end if;
+
+      --  If the case expression is a formal object of mode in out,
+      --  then treat it as having a nonstatic subtype by forcing
+      --  use of the base type (which has to get passed to
+      --  Check_Case_Choices below).  Also use base type when
+      --  the case expression is parenthesized.
+
+      if Paren_Count (Exp) > 0
+        or else (Is_Entity_Name (Exp)
+                  and then Ekind (Entity (Exp)) = E_Generic_In_Out_Parameter)
+      then
+         Exp_Type := Exp_Btype;
+      end if;
+
+      --  Call the instantiated Analyze_Choices which does the rest of the work
+
+      Analyze_Choices
+        (N, Exp_Type, Case_Table, Last_Choice, Dont_Care, Others_Present);
+
+      if Exp_Type = Universal_Integer and then not Others_Present then
+         Error_Msg_N ("case on universal integer requires OTHERS choice", Exp);
+      end if;
+
+      --  If all our exits were blocked by unconditional transfers of control,
+      --  then the entire CASE statement acts as an unconditional transfer of
+      --  control, so treat it like one, and check unreachable code. Skip this
+      --  test if we had serious errors preventing any statement analysis.
+
+      if Unblocked_Exit_Count = 0 and then Statements_Analyzed then
+         Unblocked_Exit_Count := Save_Unblocked_Exit_Count;
+         Check_Unreachable_Code (N);
+      else
+         Unblocked_Exit_Count := Save_Unblocked_Exit_Count;
+      end if;
+   end Analyze_Case_Statement;
+
+   ----------------------------
+   -- Analyze_Exit_Statement --
+   ----------------------------
+
+   --  If the exit includes a name, it must be the name of a currently open
+   --  loop. Otherwise there must be an innermost open loop on the stack,
+   --  to which the statement implicitly refers.
+
+   procedure Analyze_Exit_Statement (N : Node_Id) is
+      Target   : constant Node_Id := Name (N);
+      Cond     : constant Node_Id := Condition (N);
+      Scope_Id : Entity_Id;
+      U_Name   : Entity_Id;
+      Kind     : Entity_Kind;
+
+   begin
+      if No (Cond) then
+         Check_Unreachable_Code (N);
+      end if;
+
+      if Present (Target) then
+         Analyze (Target);
+         U_Name := Entity (Target);
+
+         if not In_Open_Scopes (U_Name) or else Ekind (U_Name) /= E_Loop then
+            Error_Msg_N ("invalid loop name in exit statement", N);
+            return;
+         else
+            Set_Has_Exit (U_Name);
+         end if;
+
+      else
+         U_Name := Empty;
+      end if;
+
+      for J in reverse 0 .. Scope_Stack.Last loop
+         Scope_Id := Scope_Stack.Table (J).Entity;
+         Kind := Ekind (Scope_Id);
+
+         if Kind = E_Loop
+           and then (No (Target) or else Scope_Id = U_Name) then
+            Set_Has_Exit (Scope_Id);
+            exit;
+
+         elsif Kind = E_Block or else Kind = E_Loop then
+            null;
+
+         else
+            Error_Msg_N
+              ("cannot exit from program unit or accept statement", N);
+            exit;
+         end if;
+      end loop;
+
+      --  Verify that if present the condition is a Boolean expression.
+
+      if Present (Cond) then
+         Analyze_And_Resolve (Cond, Any_Boolean);
+         Check_Unset_Reference (Cond);
+      end if;
+   end Analyze_Exit_Statement;
+
+   ----------------------------
+   -- Analyze_Goto_Statement --
+   ----------------------------
+
+   procedure Analyze_Goto_Statement (N : Node_Id) is
+      Label       : constant Node_Id := Name (N);
+      Scope_Id    : Entity_Id;
+      Label_Scope : Entity_Id;
+
+   begin
+      Check_Unreachable_Code (N);
+
+      Analyze (Label);
+
+      if Entity (Label) = Any_Id then
+         return;
+
+      elsif Ekind (Entity (Label)) /= E_Label then
+         Error_Msg_N ("target of goto statement must be a label", Label);
+         return;
+
+      elsif not Reachable (Entity (Label)) then
+         Error_Msg_N ("target of goto statement is not reachable", Label);
+         return;
+      end if;
+
+      Label_Scope := Enclosing_Scope (Entity (Label));
+
+      for J in reverse 0 .. Scope_Stack.Last loop
+         Scope_Id := Scope_Stack.Table (J).Entity;
+
+         if Label_Scope = Scope_Id
+           or else (Ekind (Scope_Id) /= E_Block
+                     and then Ekind (Scope_Id) /= E_Loop)
+         then
+            if Scope_Id /= Label_Scope then
+               Error_Msg_N
+                 ("cannot exit from program unit or accept statement", N);
+            end if;
+
+            return;
+         end if;
+      end loop;
+
+      raise Program_Error;
+
+   end Analyze_Goto_Statement;
+
+   --------------------------
+   -- Analyze_If_Statement --
+   --------------------------
+
+   --  A special complication arises in the analysis of if statements.
+   --  The expander has circuitry to completely deleted code that it
+   --  can tell will not be executed (as a result of compile time known
+   --  conditions). In the analyzer, we ensure that code that will be
+   --  deleted in this manner is analyzed but not expanded. This is
+   --  obviously more efficient, but more significantly, difficulties
+   --  arise if code is expanded and then eliminated (e.g. exception
+   --  table entries disappear).
+
+   procedure Analyze_If_Statement (N : Node_Id) is
+      E : Node_Id;
+
+      Save_Unblocked_Exit_Count : constant Nat := Unblocked_Exit_Count;
+      --  Recursively save value of this global, will be restored on exit
+
+      Del : Boolean := False;
+      --  This flag gets set True if a True condition has been found,
+      --  which means that remaining ELSE/ELSIF parts are deleted.
+
+      procedure Analyze_Cond_Then (Cnode : Node_Id);
+      --  This is applied to either the N_If_Statement node itself or
+      --  to an N_Elsif_Part node. It deals with analyzing the condition
+      --  and the THEN statements associated with it.
+
+      procedure Analyze_Cond_Then (Cnode : Node_Id) is
+         Cond : constant Node_Id := Condition (Cnode);
+         Tstm : constant List_Id := Then_Statements (Cnode);
+
+      begin
+         Unblocked_Exit_Count := Unblocked_Exit_Count + 1;
+         Analyze_And_Resolve (Cond, Any_Boolean);
+         Check_Unset_Reference (Cond);
+
+         --  If already deleting, then just analyze then statements
+
+         if Del then
+            Analyze_Statements (Tstm);
+
+         --  Compile time known value, not deleting yet
+
+         elsif Compile_Time_Known_Value (Cond) then
+
+            --  If condition is True, then analyze the THEN statements
+            --  and set no expansion for ELSE and ELSIF parts.
+
+            if Is_True (Expr_Value (Cond)) then
+               Analyze_Statements (Tstm);
+               Del := True;
+               Expander_Mode_Save_And_Set (False);
+
+            --  If condition is False, analyze THEN with expansion off
+
+            else -- Is_False (Expr_Value (Cond))
+               Expander_Mode_Save_And_Set (False);
+               Analyze_Statements (Tstm);
+               Expander_Mode_Restore;
+            end if;
+
+         --  Not known at compile time, not deleting, normal analysis
+
+         else
+            Analyze_Statements (Tstm);
+         end if;
+      end Analyze_Cond_Then;
+
+   --  Start of Analyze_If_Statement
+
+   begin
+      --  Initialize exit count for else statements. If there is no else
+      --  part, this count will stay non-zero reflecting the fact that the
+      --  uncovered else case is an unblocked exit.
+
+      Unblocked_Exit_Count := 1;
+      Analyze_Cond_Then (N);
+
+      --  Now to analyze the elsif parts if any are present
+
+      if Present (Elsif_Parts (N)) then
+         E := First (Elsif_Parts (N));
+         while Present (E) loop
+            Analyze_Cond_Then (E);
+            Next (E);
+         end loop;
+      end if;
+
+      if Present (Else_Statements (N)) then
+         Analyze_Statements (Else_Statements (N));
+      end if;
+
+      --  If all our exits were blocked by unconditional transfers of control,
+      --  then the entire IF statement acts as an unconditional transfer of
+      --  control, so treat it like one, and check unreachable code.
+
+      if Unblocked_Exit_Count = 0 then
+         Unblocked_Exit_Count := Save_Unblocked_Exit_Count;
+         Check_Unreachable_Code (N);
+      else
+         Unblocked_Exit_Count := Save_Unblocked_Exit_Count;
+      end if;
+
+      if Del then
+         Expander_Mode_Restore;
+      end if;
+
+   end Analyze_If_Statement;
+
+   ----------------------------------------
+   -- Analyze_Implicit_Label_Declaration --
+   ----------------------------------------
+
+   --  An implicit label declaration is generated in the innermost
+   --  enclosing declarative part. This is done for labels as well as
+   --  block and loop names.
+
+   --  Note: any changes in this routine may need to be reflected in
+   --  Analyze_Label_Entity.
+
+   procedure Analyze_Implicit_Label_Declaration (N : Node_Id) is
+      Id : Node_Id := Defining_Identifier (N);
+
+   begin
+      Enter_Name (Id);
+      Set_Ekind           (Id, E_Label);
+      Set_Etype           (Id, Standard_Void_Type);
+      Set_Enclosing_Scope (Id, Current_Scope);
+   end Analyze_Implicit_Label_Declaration;
+
+   ------------------------------
+   -- Analyze_Iteration_Scheme --
+   ------------------------------
+
+   procedure Analyze_Iteration_Scheme (N : Node_Id) is
+   begin
+      --  For an infinite loop, there is no iteration scheme
+
+      if No (N) then
+         return;
+
+      else
+         declare
+            Cond : constant Node_Id := Condition (N);
+
+         begin
+            --  For WHILE loop, verify that the condition is a Boolean
+            --  expression and resolve and check it.
+
+            if Present (Cond) then
+               Analyze_And_Resolve (Cond, Any_Boolean);
+               Check_Unset_Reference (Cond);
+
+            --  Else we have a FOR loop
+
+            else
+               declare
+                  LP : constant Node_Id   := Loop_Parameter_Specification (N);
+                  Id : constant Entity_Id := Defining_Identifier (LP);
+                  DS : constant Node_Id   := Discrete_Subtype_Definition (LP);
+                  F  : List_Id;
+
+               begin
+                  Enter_Name (Id);
+
+                  --  We always consider the loop variable to be referenced,
+                  --  since the loop may be used just for counting purposes.
+
+                  Generate_Reference (Id, N, ' ');
+
+                  --  Check for case of loop variable hiding a local
+                  --  variable (used later on to give a nice warning
+                  --  if the hidden variable is never assigned).
+
+                  declare
+                     H : constant Entity_Id := Homonym (Id);
+
+                  begin
+                     if Present (H)
+                       and then Enclosing_Dynamic_Scope (H) =
+                                Enclosing_Dynamic_Scope (Id)
+                       and then Ekind (H) = E_Variable
+                       and then Is_Discrete_Type (Etype (H))
+                     then
+                        Set_Hiding_Loop_Variable (H, Id);
+                     end if;
+                  end;
+
+                  --  Now analyze the subtype definition
+
+                  Analyze (DS);
+
+                  if DS = Error then
+                     return;
+                  end if;
+
+                  --  The subtype indication may denote the completion
+                  --  of an incomplete type declaration.
+
+                  if Is_Entity_Name (DS)
+                    and then Present (Entity (DS))
+                    and then Is_Type (Entity (DS))
+                    and then Ekind (Entity (DS)) = E_Incomplete_Type
+                  then
+                     Set_Entity (DS, Get_Full_View (Entity (DS)));
+                     Set_Etype  (DS, Entity (DS));
+                  end if;
+
+                  if not Is_Discrete_Type (Etype (DS)) then
+                     Wrong_Type (DS, Any_Discrete);
+                     Set_Etype (DS, Any_Type);
+                  end if;
+
+                  Make_Index (DS, LP);
+
+                  Set_Ekind          (Id, E_Loop_Parameter);
+                  Set_Etype          (Id, Etype (DS));
+                  Set_Is_Known_Valid (Id, True);
+
+                  --  The loop is not a declarative part, so the only entity
+                  --  declared "within" must be frozen explicitly. Since the
+                  --  type of this entity has already been frozen, this cannot
+                  --  generate any freezing actions.
+
+                  F := Freeze_Entity (Id, Sloc (LP));
+                  pragma Assert (F = No_List);
+
+                  --  Check for null or possibly null range and issue warning
+
+                  if Nkind (DS) = N_Range
+                    and then Comes_From_Source (N)
+                    and then not Inside_A_Generic
+                  then
+                     declare
+                        L : constant Node_Id := Low_Bound  (DS);
+                        H : constant Node_Id := High_Bound (DS);
+
+                        Llo : Uint;
+                        Lhi : Uint;
+                        LOK : Boolean;
+                        Hlo : Uint;
+                        Hhi : Uint;
+                        HOK : Boolean;
+
+                     begin
+                        Determine_Range (L, LOK, Llo, Lhi);
+                        Determine_Range (H, HOK, Hlo, Hhi);
+
+                        --  If range of loop is null, issue warning
+
+                        if (LOK and HOK) and then Llo > Hhi then
+                           Warn_On_Instance := True;
+                           Error_Msg_N
+                             ("?loop range is null, loop will not execute",
+                              DS);
+                           Warn_On_Instance := False;
+
+                        --  The other case for a warning is a reverse loop
+                        --  where the upper bound is the integer literal
+                        --  zero or one, and the lower bound can be positive.
+
+                        elsif Reverse_Present (LP)
+                          and then Nkind (H) = N_Integer_Literal
+                          and then (Intval (H) = Uint_0
+                                      or else
+                                    Intval (H) = Uint_1)
+                          and then Lhi > Hhi
+                        then
+                           Warn_On_Instance := True;
+                           Error_Msg_N ("?loop range may be null", DS);
+                           Warn_On_Instance := False;
+                        end if;
+                     end;
+                  end if;
+               end;
+            end if;
+         end;
+      end if;
+   end Analyze_Iteration_Scheme;
+
+   -------------------
+   -- Analyze_Label --
+   -------------------
+
+   --  Important note: normally this routine is called from Analyze_Statements
+   --  which does a prescan, to make sure that the Reachable flags are set on
+   --  all labels before encountering a possible goto to one of these labels.
+   --  If expanded code analyzes labels via the normal Sem path, then it must
+   --  ensure that Reachable is set early enough to avoid problems in the case
+   --  of a forward goto.
+
+   procedure Analyze_Label (N : Node_Id) is
+      Lab : Entity_Id;
+
+   begin
+      Analyze (Identifier (N));
+      Lab := Entity (Identifier (N));
+
+      --  If we found a label mark it as reachable.
+
+      if Ekind (Lab) = E_Label then
+         Generate_Definition (Lab);
+         Set_Reachable (Lab);
+
+         if Nkind (Parent (Lab)) = N_Implicit_Label_Declaration then
+            Set_Label_Construct (Parent (Lab), N);
+         end if;
+
+      --  If we failed to find a label, it means the implicit declaration
+      --  of the label was hidden.  A for-loop parameter can do this to a
+      --  label with the same name inside the loop, since the implicit label
+      --  declaration is in the innermost enclosing body or block statement.
+
+      else
+         Error_Msg_Sloc := Sloc (Lab);
+         Error_Msg_N
+           ("implicit label declaration for & is hidden#",
+            Identifier (N));
+      end if;
+   end Analyze_Label;
+
+   --------------------------
+   -- Analyze_Label_Entity --
+   --------------------------
+
+   procedure Analyze_Label_Entity (E : Entity_Id) is
+   begin
+      Set_Ekind           (E, E_Label);
+      Set_Etype           (E, Standard_Void_Type);
+      Set_Enclosing_Scope (E, Current_Scope);
+      Set_Reachable       (E, True);
+   end Analyze_Label_Entity;
+
+   ----------------------------
+   -- Analyze_Loop_Statement --
+   ----------------------------
+
+   procedure Analyze_Loop_Statement (N : Node_Id) is
+      Id  : constant Node_Id := Identifier (N);
+      Ent : Entity_Id;
+
+   begin
+      if Present (Id) then
+
+         --  Make name visible, e.g. for use in exit statements. Loop
+         --  labels are always considered to be referenced.
+
+         Analyze (Id);
+         Ent := Entity (Id);
+         Generate_Reference  (Ent, N, ' ');
+         Generate_Definition (Ent);
+
+         --  If we found a label, mark its type. If not, ignore it, since it
+         --  means we have a conflicting declaration, which would already have
+         --  been diagnosed at declaration time. Set Label_Construct of the
+         --  implicit label declaration, which is not created by the parser
+         --  for generic units.
+
+         if Ekind (Ent) = E_Label then
+            Set_Ekind (Ent, E_Loop);
+
+            if Nkind (Parent (Ent)) = N_Implicit_Label_Declaration then
+               Set_Label_Construct (Parent (Ent), N);
+            end if;
+         end if;
+
+      --  Case of no identifier present
+
+      else
+         Ent := New_Internal_Entity (E_Loop, Current_Scope, Sloc (N), 'L');
+         Set_Etype (Ent,  Standard_Void_Type);
+         Set_Parent (Ent, N);
+      end if;
+
+      New_Scope (Ent);
+      Analyze_Iteration_Scheme (Iteration_Scheme (N));
+      Analyze_Statements (Statements (N));
+      Process_End_Label (N, 'e');
+      End_Scope;
+   end Analyze_Loop_Statement;
+
+   ----------------------------
+   -- Analyze_Null_Statement --
+   ----------------------------
+
+   --  Note: the semantics of the null statement is implemented by a single
+   --  null statement, too bad everything isn't as simple as this!
+
+   procedure Analyze_Null_Statement (N : Node_Id) is
+   begin
+      null;
+   end Analyze_Null_Statement;
+
+   ------------------------
+   -- Analyze_Statements --
+   ------------------------
+
+   procedure Analyze_Statements (L : List_Id) is
+      S : Node_Id;
+
+   begin
+      --  The labels declared in the statement list are reachable from
+      --  statements in the list. We do this as a prepass so that any
+      --  goto statement will be properly flagged if its target is not
+      --  reachable. This is not required, but is nice behavior!
+
+      S := First (L);
+
+      while Present (S) loop
+         if Nkind (S) = N_Label then
+            Analyze_Label (S);
+         end if;
+
+         Next (S);
+      end loop;
+
+      --  Perform semantic analysis on all statements
+
+      S := First (L);
+
+      while Present (S) loop
+
+         if Nkind (S) /= N_Label then
+            Analyze (S);
+         end if;
+
+         Next (S);
+      end loop;
+
+      --  Make labels unreachable. Visibility is not sufficient, because
+      --  labels in one if-branch for example are not reachable from the
+      --  other branch, even though their declarations are in the enclosing
+      --  declarative part.
+
+      S := First (L);
+
+      while Present (S) loop
+         if Nkind (S) = N_Label then
+            Set_Reachable (Entity (Identifier (S)), False);
+         end if;
+
+         Next (S);
+      end loop;
+   end Analyze_Statements;
+
+   ----------------------------
+   -- Check_Unreachable_Code --
+   ----------------------------
+
+   procedure Check_Unreachable_Code (N : Node_Id) is
+      Error_Loc : Source_Ptr;
+      P         : Node_Id;
+
+   begin
+      if Is_List_Member (N)
+        and then Comes_From_Source (N)
+      then
+         declare
+            Nxt : Node_Id;
+
+         begin
+            Nxt := Original_Node (Next (N));
+
+            if Present (Nxt)
+              and then Comes_From_Source (Nxt)
+              and then Is_Statement (Nxt)
+            then
+               --  Special very annoying exception. If we have a return that
+               --  follows a raise, then we allow it without a warning, since
+               --  the Ada RM annoyingly requires a useless return here!
+
+               if Nkind (Original_Node (N)) /= N_Raise_Statement
+                 or else Nkind (Nxt) /= N_Return_Statement
+               then
+                  --  The rather strange shenanigans with the warning message
+                  --  here reflects the fact that Kill_Dead_Code is very good
+                  --  at removing warnings in deleted code, and this is one
+                  --  warning we would prefer NOT to have removed :-)
+
+                  Error_Loc := Sloc (Nxt);
+
+                  --  If we have unreachable code, analyze and remove the
+                  --  unreachable code, since it is useless and we don't
+                  --  want to generate junk warnings.
+
+                  --  We skip this step if we are not in code generation mode.
+                  --  This is the one case where we remove dead code in the
+                  --  semantics as opposed to the expander, and we do not want
+                  --  to remove code if we are not in code generation mode,
+                  --  since this messes up the ASIS trees.
+
+                  --  Note that one might react by moving the whole circuit to
+                  --  exp_ch5, but then we lose the warning in -gnatc mode.
+
+                  if Operating_Mode = Generate_Code then
+                     loop
+                        Nxt := Next (N);
+                        exit when No (Nxt) or else not Is_Statement (Nxt);
+                        Analyze (Nxt);
+                        Remove (Nxt);
+                        Kill_Dead_Code (Nxt);
+                     end loop;
+                  end if;
+
+                  --  Now issue the warning
+
+                  Error_Msg ("?unreachable code", Error_Loc);
+               end if;
+
+            --  If the unconditional transfer of control instruction is
+            --  the last statement of a sequence, then see if our parent
+            --  is an IF statement, and if so adjust the unblocked exit
+            --  count of the if statement to reflect the fact that this
+            --  branch of the if is indeed blocked by a transfer of control.
+
+            else
+               P := Parent (N);
+
+               if Nkind (P) = N_If_Statement then
+                  null;
+
+               elsif Nkind (P) = N_Elsif_Part then
+                  P := Parent (P);
+                  pragma Assert (Nkind (P) = N_If_Statement);
+
+               elsif Nkind (P) = N_Case_Statement_Alternative then
+                  P := Parent (P);
+                  pragma Assert (Nkind (P) = N_Case_Statement);
+
+               else
+                  return;
+               end if;
+
+               Unblocked_Exit_Count := Unblocked_Exit_Count - 1;
+            end if;
+         end;
+      end if;
+   end Check_Unreachable_Code;
+
+end Sem_Ch5;
diff --git a/gcc/ada/sem_ch5.ads b/gcc/ada/sem_ch5.ads
new file mode 100644 (file)
index 0000000..c7d9468
--- /dev/null
@@ -0,0 +1,58 @@
+------------------------------------------------------------------------------
+--                                                                          --
+--                         GNAT COMPILER COMPONENTS                         --
+--                                                                          --
+--                              S E M _ C H 5                               --
+--                                                                          --
+--                                 S p e c                                  --
+--                                                                          --
+--                            $Revision: 1.16 $                             --
+--                                                                          --
+--          Copyright (C) 1992-1998 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- --
+-- ware  Foundation;  either version 2,  or (at your option) any later ver- --
+-- sion.  GNAT is distributed in the hope that it will be useful, but WITH- --
+-- OUT ANY WARRANTY;  without even the  implied warranty of MERCHANTABILITY --
+-- or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License --
+-- for  more details.  You should have  received  a copy of the GNU General --
+-- Public License  distributed with GNAT;  see file COPYING.  If not, write --
+-- to  the Free Software Foundation,  59 Temple Place - Suite 330,  Boston, --
+-- MA 02111-1307, USA.                                                      --
+--                                                                          --
+-- GNAT was originally developed  by the GNAT team at  New York University. --
+-- It is now maintained by Ada Core Technologies Inc (http://www.gnat.com). --
+--                                                                          --
+------------------------------------------------------------------------------
+
+with Types; use Types;
+
+package Sem_Ch5 is
+
+   procedure Analyze_Assignment                 (N : Node_Id);
+   procedure Analyze_Block_Statement            (N : Node_Id);
+   procedure Analyze_Case_Statement             (N : Node_Id);
+   procedure Analyze_Exit_Statement             (N : Node_Id);
+   procedure Analyze_Goto_Statement             (N : Node_Id);
+   procedure Analyze_If_Statement               (N : Node_Id);
+   procedure Analyze_Implicit_Label_Declaration (N : Node_Id);
+   procedure Analyze_Label                      (N : Node_Id);
+   procedure Analyze_Loop_Statement             (N : Node_Id);
+   procedure Analyze_Null_Statement             (N : Node_Id);
+   procedure Analyze_Statements                 (L : List_Id);
+
+   procedure Analyze_Label_Entity (E : Entity_Id);
+   --  This procedure performs direct analysis of the label entity E. It
+   --  is used when a label is created by the expander without bothering
+   --  to insert an N_Implicit_Label_Declaration in the tree. It also takes
+   --  care of setting Reachable, since labels defined by the expander can
+   --  be assumed to be reachable.
+
+   procedure Check_Unreachable_Code (N : Node_Id);
+   --  This procedure is called with N being the node for a statement that
+   --  is an unconditional transfer of control. It checks to see if the
+   --  statement is followed by some other statement, and if so generates
+   --  an appropriate warning for unreachable code.
+
+end Sem_Ch5;
diff --git a/gcc/ada/sem_ch6.adb b/gcc/ada/sem_ch6.adb
new file mode 100644 (file)
index 0000000..f8e0b4f
--- /dev/null
@@ -0,0 +1,4779 @@
+------------------------------------------------------------------------------
+--                                                                          --
+--                         GNAT COMPILER COMPONENTS                         --
+--                                                                          --
+--                              S E M _ C H 6                               --
+--                                                                          --
+--                                 B o d y                                  --
+--                                                                          --
+--                            $Revision: 1.508 $
+--                                                                          --
+--          Copyright (C) 1992-2001, 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- --
+-- ware  Foundation;  either version 2,  or (at your option) any later ver- --
+-- sion.  GNAT is distributed in the hope that it will be useful, but WITH- --
+-- OUT ANY WARRANTY;  without even the  implied warranty of MERCHANTABILITY --
+-- or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License --
+-- for  more details.  You should have  received  a copy of the GNU General --
+-- Public License  distributed with GNAT;  see file COPYING.  If not, write --
+-- to  the Free Software Foundation,  59 Temple Place - Suite 330,  Boston, --
+-- MA 02111-1307, USA.                                                      --
+--                                                                          --
+-- GNAT was originally developed  by the GNAT team at  New York University. --
+-- It is now maintained by Ada Core Technologies Inc (http://www.gnat.com). --
+--                                                                          --
+------------------------------------------------------------------------------
+
+with Atree;    use Atree;
+with Checks;   use Checks;
+with Debug;    use Debug;
+with Einfo;    use Einfo;
+with Elists;   use Elists;
+with Errout;   use Errout;
+with Expander; use Expander;
+with Exp_Ch7;  use Exp_Ch7;
+with Freeze;   use Freeze;
+with Lib.Xref; use Lib.Xref;
+with Namet;    use Namet;
+with Lib;      use Lib;
+with Nlists;   use Nlists;
+with Nmake;    use Nmake;
+with Opt;      use Opt;
+with Output;   use Output;
+with Rtsfind;  use Rtsfind;
+with Sem;      use Sem;
+with Sem_Cat;  use Sem_Cat;
+with Sem_Ch3;  use Sem_Ch3;
+with Sem_Ch4;  use Sem_Ch4;
+with Sem_Ch5;  use Sem_Ch5;
+with Sem_Ch8;  use Sem_Ch8;
+with Sem_Ch12; use Sem_Ch12;
+with Sem_Disp; use Sem_Disp;
+with Sem_Dist; use Sem_Dist;
+with Sem_Elim; use Sem_Elim;
+with Sem_Eval; use Sem_Eval;
+with Sem_Mech; use Sem_Mech;
+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 Sem_Warn; use Sem_Warn;
+with Sinput;   use Sinput;
+with Stand;    use Stand;
+with Sinfo;    use Sinfo;
+with Sinfo.CN; use Sinfo.CN;
+with Snames;   use Snames;
+with Stringt;  use Stringt;
+with Style;
+with Stylesw;  use Stylesw;
+with Tbuild;   use Tbuild;
+with Uintp;    use Uintp;
+with Urealp;   use Urealp;
+with Validsw;  use Validsw;
+
+package body Sem_Ch6 is
+
+   -----------------------
+   -- Local Subprograms --
+   -----------------------
+
+   procedure Analyze_Generic_Subprogram_Body (N : Node_Id; Gen_Id : Entity_Id);
+   --  Analyze a generic subprogram body
+
+   function Build_Body_To_Inline
+     (N         : Node_Id;
+      Subp      : Entity_Id;
+      Orig_Body : Node_Id)
+      return      Boolean;
+   --  If a subprogram has pragma Inline and inlining is active, use generic
+   --  machinery to build an unexpanded body for the subprogram. This body is
+   --  subsequenty used for inline expansions at call sites. If subprogram can
+   --  be inlined (depending on size and nature of local declarations) this
+   --  function returns true. Otherwise subprogram body is treated normally.
+
+   type Conformance_Type is
+     (Type_Conformant, Mode_Conformant, Subtype_Conformant, Fully_Conformant);
+
+   procedure Check_Conformance
+     (New_Id   : Entity_Id;
+      Old_Id   : Entity_Id;
+      Ctype    : Conformance_Type;
+      Errmsg   : Boolean;
+      Conforms : out Boolean;
+      Err_Loc  : Node_Id := Empty;
+      Get_Inst : Boolean := False);
+   --  Given two entities, this procedure checks that the profiles associated
+   --  with these entities meet the conformance criterion given by the third
+   --  parameter. If they conform, Conforms is set True and control returns
+   --  to the caller. If they do not conform, Conforms is set to False, and
+   --  in addition, if Errmsg is True on the call, proper messages are output
+   --  to complain about the conformance failure. If Err_Loc is non_Empty
+   --  the error messages are placed on Err_Loc, if Err_Loc is empty, then
+   --  error messages are placed on the appropriate part of the construct
+   --  denoted by New_Id. If Get_Inst is true, then this is a mode conformance
+   --  against a formal access-to-subprogram type so Get_Instance_Of must
+   --  be called.
+
+   procedure Check_Subprogram_Order (N : Node_Id);
+   --  N is the N_Subprogram_Body node for a subprogram. This routine applies
+   --  the alpha ordering rule for N if this ordering requirement applicable.
+
+   function Is_Non_Overriding_Operation
+     (Prev_E : Entity_Id;
+      New_E  : Entity_Id)
+      return   Boolean;
+   --  Enforce the rule given in 12.3(18): a private operation in an instance
+   --  overrides an inherited operation only if the corresponding operation
+   --  was overriding in the generic. This can happen for primitive operations
+   --  of types derived (in the generic unit) from formal private or formal
+   --  derived types.
+
+   procedure Check_Returns
+     (HSS  : Node_Id;
+      Mode : Character;
+      Err  : out Boolean);
+   --  Called to check for missing return statements in a function body,
+   --  or for returns present in a procedure body which has No_Return set.
+   --  L is the handled statement sequence for the subprogram body. This
+   --  procedure checks all flow paths to make sure they either have a
+   --  return (Mode = 'F') or do not have a return (Mode = 'P'). The flag
+   --  Err is set if there are any control paths not explicitly terminated
+   --  by a return in the function case, and is True otherwise.
+
+   function Conforming_Types
+     (T1       : Entity_Id;
+      T2       : Entity_Id;
+      Ctype    : Conformance_Type;
+      Get_Inst : Boolean := False)
+      return     Boolean;
+   --  Check that two formal parameter types conform, checking both
+   --  for equality of base types, and where required statically
+   --  matching subtypes, depending on the setting of Ctype.
+
+   procedure Enter_Overloaded_Entity (S : Entity_Id);
+   --  This procedure makes S, a new overloaded entity, into the first
+   --  visible entity with that name.
+
+   procedure Install_Entity (E : Entity_Id);
+   --  Make single entity visible. Used for generic formals as well.
+
+   procedure Install_Formals (Id : Entity_Id);
+   --  On entry to a subprogram body, make the formals visible. Note
+   --  that simply placing the subprogram on the scope stack is not
+   --  sufficient: the formals must become the current entities for
+   --  their names.
+
+   procedure Make_Inequality_Operator (S : Entity_Id);
+   --  Create the declaration for an inequality operator that is implicitly
+   --  created by a user-defined equality operator that yields a boolean.
+
+   procedure May_Need_Actuals (Fun : Entity_Id);
+   --  Flag functions that can be called without parameters, i.e. those that
+   --  have no parameters, or those for which defaults exist for all parameters
+
+   procedure Set_Formal_Validity (Formal_Id : Entity_Id);
+   --  Formal_Id is an formal parameter entity. This procedure deals with
+   --  setting the proper validity status for this entity, which depends
+   --  on the kind of parameter and the validity checking mode.
+
+   ---------------------------------------------
+   -- Analyze_Abstract_Subprogram_Declaration --
+   ---------------------------------------------
+
+   procedure Analyze_Abstract_Subprogram_Declaration (N : Node_Id) is
+      Designator : constant Entity_Id := Analyze_Spec (Specification (N));
+      Scop       : constant Entity_Id := Current_Scope;
+
+   begin
+      Generate_Definition (Designator);
+      Set_Is_Abstract (Designator);
+      New_Overloaded_Entity (Designator);
+      Check_Delayed_Subprogram (Designator);
+
+      Set_Is_Pure (Designator,
+        Is_Pure (Scop) and then Is_Library_Level_Entity (Designator));
+      Set_Is_Remote_Call_Interface (
+        Designator, Is_Remote_Call_Interface (Scop));
+      Set_Is_Remote_Types (Designator, Is_Remote_Types (Scop));
+
+      if Ekind (Scope (Designator)) = E_Protected_Type then
+         Error_Msg_N
+           ("abstract subprogram not allowed in protected type", N);
+      end if;
+   end Analyze_Abstract_Subprogram_Declaration;
+
+   ----------------------------
+   -- Analyze_Function_Call  --
+   ----------------------------
+
+   procedure Analyze_Function_Call (N : Node_Id) is
+      P      : constant Node_Id := Name (N);
+      L      : constant List_Id := Parameter_Associations (N);
+      Actual : Node_Id;
+
+   begin
+      Analyze (P);
+
+      --  If error analyzing name, then set Any_Type as result type and return
+
+      if Etype (P) = Any_Type then
+         Set_Etype (N, Any_Type);
+         return;
+      end if;
+
+      --  Otherwise analyze the parameters
+
+      if Present (L) then
+         Actual := First (L);
+
+         while Present (Actual) loop
+            Analyze (Actual);
+            Check_Parameterless_Call (Actual);
+            Next (Actual);
+         end loop;
+      end if;
+
+      Analyze_Call (N);
+
+   end Analyze_Function_Call;
+
+   -------------------------------------
+   -- Analyze_Generic_Subprogram_Body --
+   -------------------------------------
+
+   procedure Analyze_Generic_Subprogram_Body
+     (N      : Node_Id;
+      Gen_Id : Entity_Id)
+   is
+      Gen_Decl : constant Node_Id := Unit_Declaration_Node (Gen_Id);
+      Spec     : Node_Id;
+      Kind     : constant Entity_Kind := Ekind (Gen_Id);
+      Nam      : Entity_Id;
+      New_N    : Node_Id;
+
+   begin
+      --  Copy body and disable expansion while analyzing the generic
+      --  For a stub, do not copy the stub (which would load the proper body),
+      --  this will be done when the proper body is analyzed.
+
+      if Nkind (N) /= N_Subprogram_Body_Stub then
+         New_N := Copy_Generic_Node (N, Empty, Instantiating => False);
+         Rewrite (N, New_N);
+         Start_Generic;
+      end if;
+
+      Spec := Specification (N);
+
+      --  Within the body of the generic, the subprogram is callable, and
+      --  behaves like the corresponding non-generic unit.
+
+      Nam := Defining_Entity (Spec);
+
+      if Kind = E_Generic_Procedure
+        and then Nkind (Spec) /= N_Procedure_Specification
+      then
+         Error_Msg_N ("invalid body for generic procedure ", Nam);
+         return;
+
+      elsif Kind = E_Generic_Function
+        and then Nkind (Spec) /= N_Function_Specification
+      then
+         Error_Msg_N ("invalid body for generic function ", Nam);
+         return;
+      end if;
+
+      Set_Corresponding_Body (Gen_Decl, Nam);
+
+      if Has_Completion (Gen_Id)
+        and then Nkind (Parent (N)) /= N_Subunit
+      then
+         Error_Msg_N ("duplicate generic body", N);
+         return;
+      else
+         Set_Has_Completion (Gen_Id);
+      end if;
+
+      if Nkind (N) = N_Subprogram_Body_Stub then
+         Set_Ekind (Defining_Entity (Specification (N)), Kind);
+      else
+         Set_Corresponding_Spec (N, Gen_Id);
+      end if;
+
+      if Nkind (Parent (N)) = N_Compilation_Unit then
+         Set_Cunit_Entity (Current_Sem_Unit, Defining_Entity (N));
+      end if;
+
+      --  Make generic parameters immediately visible in the body. They are
+      --  needed to process the formals declarations. Then make the formals
+      --  visible in a separate step.
+
+      New_Scope (Gen_Id);
+
+      declare
+         E         : Entity_Id;
+         First_Ent : Entity_Id;
+
+      begin
+         First_Ent := First_Entity (Gen_Id);
+
+         E := First_Ent;
+         while Present (E) and then not Is_Formal (E) loop
+            Install_Entity (E);
+            Next_Entity (E);
+         end loop;
+
+         Set_Use (Generic_Formal_Declarations (Gen_Decl));
+
+         --  Now generic formals are visible, and the specification can be
+         --  analyzed, for subsequent conformance check.
+
+         Nam := Analyze_Spec (Spec);
+
+         if Nkind (N) = N_Subprogram_Body_Stub then
+
+            --  Nothing to do if no body to process
+
+            Set_Ekind (Nam, Kind);
+            End_Scope;
+            return;
+         end if;
+
+         if Present (E) then
+
+            --  E is the first formal parameter, which must be the first
+            --  entity in the subprogram body.
+
+            Set_First_Entity (Gen_Id, E);
+
+            --  Now make formal parameters visible
+
+            while Present (E) loop
+               Install_Entity (E);
+               Next_Formal (E);
+            end loop;
+         end if;
+
+         --  Visible generic entity is callable within its own body.
+
+         Set_Ekind (Gen_Id, Ekind (Nam));
+         Set_Convention (Nam, Convention (Gen_Id));
+         Set_Scope (Nam, Scope (Gen_Id));
+         Check_Fully_Conformant (Nam, Gen_Id, Nam);
+
+         --  If this is a compilation unit, it must be made visible
+         --  explicitly, because the compilation of the declaration,
+         --  unlike other library unit declarations, does not. If it
+         --  is not a unit, the following is redundant but harmless.
+
+         Set_Is_Immediately_Visible (Gen_Id);
+
+         Set_Actual_Subtypes (N, Current_Scope);
+         Analyze_Declarations (Declarations (N));
+         Check_Completion;
+         Analyze (Handled_Statement_Sequence (N));
+
+         Save_Global_References (Original_Node (N));
+
+         --  Prior to exiting the scope, include generic formals again
+         --  (if any are present) in the set of local entities.
+
+         if Present (First_Ent) then
+            Set_First_Entity (Gen_Id, First_Ent);
+         end if;
+
+      end;
+
+      End_Scope;
+      Check_Subprogram_Order (N);
+
+      --  Outside of its body, unit is generic again.
+
+      Set_Ekind (Gen_Id, Kind);
+      Set_Ekind (Nam, E_Subprogram_Body);
+      Generate_Reference (Gen_Id, Nam, 'b');
+      Style.Check_Identifier (Nam, Gen_Id);
+      End_Generic;
+
+   end Analyze_Generic_Subprogram_Body;
+
+   -----------------------------
+   -- Analyze_Operator_Symbol --
+   -----------------------------
+
+   --  An operator symbol such as "+" or "and" may appear in context where
+   --  the literal denotes an entity name, such as  "+"(x, y) or in a
+   --  context when it is just a string, as in  (conjunction = "or"). In
+   --  these cases the parser generates this node, and the semantics does
+   --  the disambiguation. Other such case are actuals in an instantiation,
+   --  the generic unit in an instantiation, and pragma arguments.
+
+   procedure Analyze_Operator_Symbol (N : Node_Id) is
+      Par : constant Node_Id := Parent (N);
+
+   begin
+      if        (Nkind (Par) = N_Function_Call and then N = Name (Par))
+        or else  Nkind (Par) = N_Function_Instantiation
+        or else (Nkind (Par) = N_Indexed_Component and then N = Prefix (Par))
+        or else (Nkind (Par) = N_Pragma_Argument_Association
+                   and then not Is_Pragma_String_Literal (Par))
+        or else  Nkind (Par) = N_Subprogram_Renaming_Declaration
+        or else  (Nkind (Par) = N_Attribute_Reference
+                   and then Attribute_Name (Par) /= Name_Value)
+      then
+         Find_Direct_Name (N);
+
+      else
+         Change_Operator_Symbol_To_String_Literal (N);
+         Analyze (N);
+      end if;
+   end Analyze_Operator_Symbol;
+
+   -----------------------------------
+   -- Analyze_Parameter_Association --
+   -----------------------------------
+
+   procedure Analyze_Parameter_Association (N : Node_Id) is
+   begin
+      Analyze (Explicit_Actual_Parameter (N));
+   end Analyze_Parameter_Association;
+
+   ----------------------------
+   -- Analyze_Procedure_Call --
+   ----------------------------
+
+   procedure Analyze_Procedure_Call (N : Node_Id) is
+      Loc     : constant Source_Ptr := Sloc (N);
+      P       : constant Node_Id    := Name (N);
+      Actuals : constant List_Id    := Parameter_Associations (N);
+      Actual  : Node_Id;
+      New_N   : Node_Id;
+
+      procedure Analyze_Call_And_Resolve;
+      --  Do Analyze and Resolve calls for procedure call
+
+      procedure Analyze_Call_And_Resolve is
+      begin
+         if Nkind (N) = N_Procedure_Call_Statement then
+            Analyze_Call (N);
+            Resolve (N, Standard_Void_Type);
+         else
+            Analyze (N);
+         end if;
+      end Analyze_Call_And_Resolve;
+
+   --  Start of processing for Analyze_Procedure_Call
+
+   begin
+      --  The syntactic construct: PREFIX ACTUAL_PARAMETER_PART can denote
+      --  a procedure call or an entry call. The prefix may denote an access
+      --  to subprogram type, in which case an implicit dereference applies.
+      --  If the prefix is an indexed component (without implicit defererence)
+      --  then the construct denotes a call to a member of an entire family.
+      --  If the prefix is a simple name, it may still denote a call to a
+      --  parameterless member of an entry family. Resolution of these various
+      --  interpretations is delicate.
+
+      Analyze (P);
+
+      --  If error analyzing prefix, then set Any_Type as result and return
+
+      if Etype (P) = Any_Type then
+         Set_Etype (N, Any_Type);
+         return;
+      end if;
+
+      --  Otherwise analyze the parameters
+
+      if Present (Actuals) then
+         Actual := First (Actuals);
+
+         while Present (Actual) loop
+            Analyze (Actual);
+            Check_Parameterless_Call (Actual);
+            Next (Actual);
+         end loop;
+      end if;
+
+      --  Special processing for Elab_Spec and Elab_Body calls
+
+      if Nkind (P) = N_Attribute_Reference
+        and then (Attribute_Name (P) = Name_Elab_Spec
+                   or else Attribute_Name (P) = Name_Elab_Body)
+      then
+         if Present (Actuals) then
+            Error_Msg_N
+              ("no parameters allowed for this call", First (Actuals));
+            return;
+         end if;
+
+         Set_Etype (N, Standard_Void_Type);
+         Set_Analyzed (N);
+
+      elsif Is_Entity_Name (P)
+        and then Is_Record_Type (Etype (Entity (P)))
+        and then Remote_AST_I_Dereference (P)
+      then
+         return;
+
+      elsif Is_Entity_Name (P)
+        and then Ekind (Entity (P)) /= E_Entry_Family
+      then
+         if Is_Access_Type (Etype (P))
+           and then Ekind (Designated_Type (Etype (P))) = E_Subprogram_Type
+           and then No (Actuals)
+           and then Comes_From_Source (N)
+         then
+            Error_Msg_N ("missing explicit dereference in call", N);
+         end if;
+
+         Analyze_Call_And_Resolve;
+
+      --  If the prefix is the simple name of an entry family, this is
+      --  a parameterless call from within the task body itself.
+
+      elsif Is_Entity_Name (P)
+        and then Nkind (P) = N_Identifier
+        and then Ekind (Entity (P)) = E_Entry_Family
+        and then Present (Actuals)
+        and then No (Next (First (Actuals)))
+      then
+         --  Can be call to parameterless entry family. What appears to be
+         --  the sole argument is in fact the entry index. Rewrite prefix
+         --  of node accordingly. Source representation is unchanged by this
+         --  transformation.
+
+         New_N :=
+           Make_Indexed_Component (Loc,
+             Prefix =>
+               Make_Selected_Component (Loc,
+                 Prefix => New_Occurrence_Of (Scope (Entity (P)), Loc),
+                 Selector_Name => New_Occurrence_Of (Entity (P), Loc)),
+             Expressions => Actuals);
+         Set_Name (N, New_N);
+         Set_Etype (New_N, Standard_Void_Type);
+         Set_Parameter_Associations (N, No_List);
+         Analyze_Call_And_Resolve;
+
+      elsif Nkind (P) = N_Explicit_Dereference then
+         if Ekind (Etype (P)) = E_Subprogram_Type then
+            Analyze_Call_And_Resolve;
+         else
+            Error_Msg_N ("expect access to procedure in call", P);
+         end if;
+
+      --  The name can be a selected component or an indexed component
+      --  that yields an access to subprogram. Such a prefix is legal if
+      --  the call has parameter associations.
+
+      elsif Is_Access_Type (Etype (P))
+        and then Ekind (Designated_Type (Etype (P))) = E_Subprogram_Type
+      then
+         if Present (Actuals) then
+            Analyze_Call_And_Resolve;
+         else
+            Error_Msg_N ("missing explicit dereference in call ", N);
+         end if;
+
+      --  If not an access to subprogram, then the prefix must resolve to
+      --  the name of an entry, entry family, or protected operation.
+
+      --  For the case of a simple entry call, P is a selected component
+      --  where the prefix is the task and the selector name is the entry.
+      --  A call to a protected procedure will have the same syntax. If
+      --  the protected object contains overloaded operations, the entity
+      --  may appear as a function, the context will select the operation
+      --  whose type is Void.
+
+      elsif Nkind (P) = N_Selected_Component
+        and then (Ekind (Entity (Selector_Name (P))) = E_Entry
+                    or else
+                  Ekind (Entity (Selector_Name (P))) = E_Procedure
+                    or else
+                  Ekind (Entity (Selector_Name (P))) = E_Function)
+      then
+         Analyze_Call_And_Resolve;
+
+      elsif Nkind (P) = N_Selected_Component
+        and then Ekind (Entity (Selector_Name (P))) = E_Entry_Family
+        and then Present (Actuals)
+        and then No (Next (First (Actuals)))
+      then
+         --  Can be call to parameterless entry family. What appears to be
+         --  the sole argument is in fact the entry index. Rewrite prefix
+         --  of node accordingly. Source representation is unchanged by this
+         --  transformation.
+
+         New_N :=
+           Make_Indexed_Component (Loc,
+             Prefix => New_Copy (P),
+             Expressions => Actuals);
+         Set_Name (N, New_N);
+         Set_Etype (New_N, Standard_Void_Type);
+         Set_Parameter_Associations (N, No_List);
+         Analyze_Call_And_Resolve;
+
+      --  For the case of a reference to an element of an entry family, P is
+      --  an indexed component whose prefix is a selected component (task and
+      --  entry family), and whose index is the entry family index.
+
+      elsif Nkind (P) = N_Indexed_Component
+        and then Nkind (Prefix (P)) = N_Selected_Component
+        and then Ekind (Entity (Selector_Name (Prefix (P)))) = E_Entry_Family
+      then
+         Analyze_Call_And_Resolve;
+
+      --  If the prefix is the name of an entry family, it is a call from
+      --  within the task body itself.
+
+      elsif Nkind (P) = N_Indexed_Component
+        and then Nkind (Prefix (P)) = N_Identifier
+        and then Ekind (Entity (Prefix (P))) = E_Entry_Family
+      then
+         New_N :=
+           Make_Selected_Component (Loc,
+             Prefix => New_Occurrence_Of (Scope (Entity (Prefix (P))), Loc),
+             Selector_Name => New_Occurrence_Of (Entity (Prefix (P)), Loc));
+         Rewrite (Prefix (P), New_N);
+         Analyze (P);
+         Analyze_Call_And_Resolve;
+
+      --  Anything else is an error.
+
+      else
+         Error_Msg_N ("Invalid procedure or entry call", N);
+      end if;
+   end Analyze_Procedure_Call;
+
+   ------------------------------
+   -- Analyze_Return_Statement --
+   ------------------------------
+
+   procedure Analyze_Return_Statement (N : Node_Id) is
+      Loc      : constant Source_Ptr := Sloc (N);
+      Expr     : Node_Id;
+      Scope_Id : Entity_Id;
+      Kind     : Entity_Kind;
+      R_Type   : Entity_Id;
+
+   begin
+      --  Find subprogram or accept statement enclosing the return statement
+
+      Scope_Id := Empty;
+      for J in reverse 0 .. Scope_Stack.Last loop
+         Scope_Id := Scope_Stack.Table (J).Entity;
+         exit when Ekind (Scope_Id) /= E_Block and then
+                   Ekind (Scope_Id) /= E_Loop;
+      end loop;
+
+      pragma Assert (Present (Scope_Id));
+
+      Kind := Ekind (Scope_Id);
+      Expr := Expression (N);
+
+      if Kind /= E_Function
+        and then Kind /= E_Generic_Function
+        and then Kind /= E_Procedure
+        and then Kind /= E_Generic_Procedure
+        and then Kind /= E_Entry
+        and then Kind /= E_Entry_Family
+      then
+         Error_Msg_N ("illegal context for return statement", N);
+
+      elsif Present (Expr) then
+         if Kind = E_Function or else Kind = E_Generic_Function then
+            Set_Return_Present (Scope_Id);
+            R_Type := Etype (Scope_Id);
+            Set_Return_Type (N, R_Type);
+            Analyze_And_Resolve (Expr, R_Type);
+
+            if (Is_Class_Wide_Type (Etype (Expr))
+                 or else Is_Dynamically_Tagged (Expr))
+              and then not Is_Class_Wide_Type (R_Type)
+            then
+               Error_Msg_N
+                 ("dynamically tagged expression not allowed!", Expr);
+            end if;
+
+            Apply_Constraint_Check (Expr, R_Type);
+
+            --  ??? A real run-time accessibility check is needed
+            --  in cases involving dereferences of access parameters.
+            --  For now we just check the static cases.
+
+            if Is_Return_By_Reference_Type (Etype (Scope_Id))
+              and then Object_Access_Level (Expr)
+                > Subprogram_Access_Level (Scope_Id)
+            then
+               Rewrite (N, Make_Raise_Program_Error (Loc));
+               Analyze (N);
+
+               Error_Msg_N
+                 ("cannot return a local value by reference?", N);
+               Error_Msg_NE
+                 ("& will be raised at run time?!",
+                  N, Standard_Program_Error);
+            end if;
+
+         elsif Kind = E_Procedure or else Kind = E_Generic_Procedure then
+            Error_Msg_N ("procedure cannot return value (use function)", N);
+
+         else
+            Error_Msg_N ("accept statement cannot return value", N);
+         end if;
+
+      --  No expression present
+
+      else
+         if Kind = E_Function or Kind = E_Generic_Function then
+            Error_Msg_N ("missing expression in return from function", N);
+         end if;
+
+         if (Ekind (Scope_Id) = E_Procedure
+              or else Ekind (Scope_Id) = E_Generic_Procedure)
+           and then  No_Return (Scope_Id)
+         then
+            Error_Msg_N
+              ("RETURN statement not allowed (No_Return)", N);
+         end if;
+      end if;
+
+      Check_Unreachable_Code (N);
+   end Analyze_Return_Statement;
+
+   ------------------
+   -- Analyze_Spec --
+   ------------------
+
+   function Analyze_Spec (N : Node_Id) return Entity_Id is
+      Designator : constant Entity_Id := Defining_Entity (N);
+      Formals    : constant List_Id   := Parameter_Specifications (N);
+      Typ        : Entity_Id;
+
+   begin
+      Generate_Definition (Designator);
+
+      if Nkind (N) = N_Function_Specification then
+         Set_Ekind (Designator, E_Function);
+         Set_Mechanism (Designator, Default_Mechanism);
+
+         if Subtype_Mark (N) /= Error then
+            Find_Type (Subtype_Mark (N));
+            Typ := Entity (Subtype_Mark (N));
+            Set_Etype (Designator, Typ);
+
+            if (Ekind (Typ) = E_Incomplete_Type
+                 or else (Is_Class_Wide_Type (Typ)
+                           and then
+                             Ekind (Root_Type (Typ)) = E_Incomplete_Type))
+            then
+               Error_Msg_N
+                 ("invalid use of incomplete type", Subtype_Mark (N));
+            end if;
+
+         else
+            Set_Etype (Designator, Any_Type);
+         end if;
+
+      else
+         Set_Ekind (Designator, E_Procedure);
+         Set_Etype (Designator, Standard_Void_Type);
+      end if;
+
+      if Present (Formals) then
+         Set_Scope (Designator, Current_Scope);
+         New_Scope (Designator);
+         Process_Formals (Designator, Formals, N);
+         End_Scope;
+      end if;
+
+      if Nkind (N) = N_Function_Specification then
+         if Nkind (Designator) = N_Defining_Operator_Symbol then
+            Valid_Operator_Definition (Designator);
+         end if;
+
+         May_Need_Actuals (Designator);
+
+         if Is_Abstract (Etype (Designator))
+           and then Nkind (Parent (N)) /= N_Abstract_Subprogram_Declaration
+         then
+            Error_Msg_N
+              ("function that returns abstract type must be abstract", N);
+         end if;
+      end if;
+
+      return Designator;
+   end Analyze_Spec;
+
+   -----------------------------
+   -- Analyze_Subprogram_Body --
+   -----------------------------
+
+   --  This procedure is called for regular subprogram bodies, generic bodies,
+   --  and for subprogram stubs of both kinds. In the case of stubs, only the
+   --  specification matters, and is used to create a proper declaration for
+   --  the subprogram, or to perform conformance checks.
+
+   procedure Analyze_Subprogram_Body (N : Node_Id) is
+      Body_Spec : constant Node_Id    := Specification (N);
+      Body_Id   : Entity_Id           := Defining_Entity (Body_Spec);
+      Prev_Id   : constant Entity_Id  := Current_Entity_In_Scope (Body_Id);
+
+      HSS         : Node_Id;
+      Spec_Id     : Entity_Id;
+      Spec_Decl   : Node_Id   := Empty;
+      Last_Formal : Entity_Id := Empty;
+      Conformant  : Boolean;
+      Missing_Ret : Boolean;
+
+   begin
+      if Debug_Flag_C then
+         Write_Str ("====  Compiling subprogram body ");
+         Write_Name (Chars (Body_Id));
+         Write_Str (" from ");
+         Write_Location (Sloc (N));
+         Write_Eol;
+      end if;
+
+      Trace_Scope (N, Body_Id, " Analyze subprogram");
+
+      --  Generic subprograms are handled separately. They always have
+      --  a generic specification. Determine whether current scope has
+      --  a previous declaration.
+
+      --  If the subprogram body is defined within an instance of the
+      --  same name, the instance appears as a package renaming, and
+      --  will be hidden within the subprogram.
+
+      if Present (Prev_Id)
+        and then not Is_Overloadable (Prev_Id)
+        and then (Nkind (Parent (Prev_Id)) /= N_Package_Renaming_Declaration
+                   or else Comes_From_Source (Prev_Id))
+      then
+         if Ekind (Prev_Id) = E_Generic_Procedure
+           or else Ekind (Prev_Id) = E_Generic_Function
+         then
+            Spec_Id := Prev_Id;
+            Set_Is_Compilation_Unit (Body_Id, Is_Compilation_Unit (Spec_Id));
+            Set_Is_Child_Unit       (Body_Id, Is_Child_Unit       (Spec_Id));
+
+            Analyze_Generic_Subprogram_Body (N, Spec_Id);
+            return;
+
+         else
+            --  Previous entity conflicts with subprogram name.
+            --  Attempting to enter name will post error.
+
+            Enter_Name (Body_Id);
+            return;
+         end if;
+
+      --  Non-generic case, find the subprogram declaration, if one was
+      --  seen, or enter new overloaded entity in the current scope.
+      --  If the current_entity is the body_id itself, the unit is being
+      --  analyzed as part of the context of one of its subunits. No need
+      --  to redo the analysis.
+
+      elsif Prev_Id = Body_Id
+        and then Has_Completion (Body_Id)
+      then
+         return;
+
+      else
+         Body_Id := Analyze_Spec (Body_Spec);
+
+         if Nkind (N) = N_Subprogram_Body_Stub
+           or else No (Corresponding_Spec (N))
+         then
+            Spec_Id := Find_Corresponding_Spec (N);
+
+            --  If this is a duplicate body, no point in analyzing it
+
+            if Error_Posted (N) then
+               return;
+            end if;
+
+            --  A subprogram body should cause freezing of its own
+            --  declaration, but if there was no previous explicit
+            --  declaration, then the subprogram will get frozen too
+            --  late (there may be code within the body that depends
+            --  on the subprogram having been frozen, such as uses of
+            --  extra formals), so we force it to be frozen here.
+            --  Same holds if the body and the spec are compilation units.
+
+            if No (Spec_Id) then
+               Freeze_Before (N, Body_Id);
+
+            elsif Nkind (Parent (N)) = N_Compilation_Unit then
+               Freeze_Before (N, Spec_Id);
+            end if;
+         else
+            Spec_Id := Corresponding_Spec (N);
+         end if;
+      end if;
+
+      if No (Spec_Id)
+        and then Comes_From_Source (N)
+        and then Is_Protected_Type (Current_Scope)
+      then
+         --  Fully private operation in the body of the protected type. We
+         --  must create a declaration for the subprogram, in order to attach
+         --  the protected subprogram that will be used in internal calls.
+
+         declare
+            Loc      : constant Source_Ptr := Sloc (N);
+            Decl     : Node_Id;
+            Plist    : List_Id;
+            Formal   : Entity_Id;
+            New_Spec : Node_Id;
+
+         begin
+            Formal := First_Formal (Body_Id);
+
+            --  The protected operation always has at least one formal,
+            --  namely the object itself, but it is only placed in the
+            --  parameter list if expansion is enabled.
+
+            if Present (Formal)
+              or else Expander_Active
+            then
+               Plist := New_List;
+
+            else
+               Plist := No_List;
+            end if;
+
+            while Present (Formal) loop
+               Append
+                 (Make_Parameter_Specification (Loc,
+                   Defining_Identifier =>
+                     Make_Defining_Identifier (Sloc (Formal),
+                       Chars => Chars (Formal)),
+                   In_Present  => In_Present (Parent (Formal)),
+                   Out_Present => Out_Present (Parent (Formal)),
+                   Parameter_Type =>
+                     New_Reference_To (Etype (Formal), Loc),
+                   Expression =>
+                     New_Copy_Tree (Expression (Parent (Formal)))),
+                 Plist);
+
+               Next_Formal (Formal);
+            end loop;
+
+            if Nkind (Body_Spec) = N_Procedure_Specification then
+               New_Spec :=
+                 Make_Procedure_Specification (Loc,
+                    Defining_Unit_Name =>
+                      Make_Defining_Identifier (Sloc (Body_Id),
+                        Chars => Chars (Body_Id)),
+                    Parameter_Specifications => Plist);
+            else
+               New_Spec :=
+                 Make_Function_Specification (Loc,
+                    Defining_Unit_Name =>
+                      Make_Defining_Identifier (Sloc (Body_Id),
+                        Chars => Chars (Body_Id)),
+                    Parameter_Specifications => Plist,
+                    Subtype_Mark => New_Occurrence_Of (Etype (Body_Id), Loc));
+            end if;
+
+            Decl :=
+              Make_Subprogram_Declaration (Loc,
+                Specification => New_Spec);
+            Insert_Before (N, Decl);
+            Analyze (Decl);
+            Spec_Id := Defining_Unit_Name (New_Spec);
+            Set_Has_Completion (Spec_Id);
+            Set_Convention (Spec_Id, Convention_Protected);
+         end;
+
+      elsif Present (Spec_Id) then
+         Spec_Decl := Unit_Declaration_Node (Spec_Id);
+      end if;
+
+      --  Place subprogram on scope stack, and make formals visible. If there
+      --  is a spec, the visible entity remains that of the spec.
+
+      if Present (Spec_Id) then
+         Generate_Reference (Spec_Id, Body_Id, 'b');
+         Style.Check_Identifier (Body_Id, Spec_Id);
+
+         Set_Is_Compilation_Unit (Body_Id, Is_Compilation_Unit (Spec_Id));
+         Set_Is_Child_Unit       (Body_Id, Is_Child_Unit       (Spec_Id));
+
+         if Is_Abstract (Spec_Id) then
+            Error_Msg_N ("an abstract subprogram cannot have a body", N);
+            return;
+         else
+            Set_Convention (Body_Id, Convention (Spec_Id));
+            Set_Has_Completion (Spec_Id);
+
+            if Is_Protected_Type (Scope (Spec_Id)) then
+               Set_Privals_Chain (Spec_Id, New_Elmt_List);
+            end if;
+
+            --  If this is a body generated for a renaming, do not check for
+            --  full conformance. The check is redundant, because the spec of
+            --  the body is a copy of the spec in the renaming declaration,
+            --  and the test can lead to spurious errors on nested defaults.
+
+            if Present (Spec_Decl)
+              and then Nkind (Original_Node (Spec_Decl)) =
+                N_Subprogram_Renaming_Declaration
+              and then not Comes_From_Source (N)
+            then
+               Conformant := True;
+            else
+               Check_Conformance
+                 (Body_Id, Spec_Id,
+                   Fully_Conformant, True, Conformant, Body_Id);
+            end if;
+
+            --  If the body is not fully conformant, we have to decide if we
+            --  should analyze it or not. If it has a really messed up profile
+            --  then we probably should not analyze it, since we will get too
+            --  many bogus messages.
+
+            --  Our decision is to go ahead in the non-fully conformant case
+            --  only if it is at least mode conformant with the spec. Note
+            --  that the call to Check_Fully_Conformant has issued the proper
+            --  error messages to complain about the lack of conformance.
+
+            if not Conformant
+              and then not Mode_Conformant (Body_Id, Spec_Id)
+            then
+               return;
+            end if;
+         end if;
+
+         --  Generate references from body formals to spec formals
+         --  and also set the Spec_Entity fields for all formals
+
+         if Spec_Id /= Body_Id then
+            declare
+               Fs : Entity_Id;
+               Fb : Entity_Id;
+
+            begin
+               Fs := First_Formal (Spec_Id);
+               Fb := First_Formal (Body_Id);
+               while Present (Fs) loop
+                  Generate_Reference (Fs, Fb, 'b');
+                  Style.Check_Identifier (Fb, Fs);
+                  Set_Spec_Entity (Fb, Fs);
+                  Next_Formal (Fs);
+                  Next_Formal (Fb);
+               end loop;
+            end;
+         end if;
+
+         if Nkind (N) /= N_Subprogram_Body_Stub then
+            Set_Corresponding_Spec (N, Spec_Id);
+            Install_Formals (Spec_Id);
+            Last_Formal := Last_Entity (Spec_Id);
+            New_Scope (Spec_Id);
+
+            --  Make sure that the subprogram is immediately visible. For
+            --  child units that have no separate spec this is indispensable.
+            --  Otherwise it is safe albeit redundant.
+
+            Set_Is_Immediately_Visible (Spec_Id);
+         end if;
+
+         Set_Corresponding_Body (Unit_Declaration_Node (Spec_Id), Body_Id);
+         Set_Ekind (Body_Id, E_Subprogram_Body);
+         Set_Scope (Body_Id, Scope (Spec_Id));
+
+      --  Case of subprogram body with no previous spec
+
+      else
+         if Style_Check
+           and then Comes_From_Source (Body_Id)
+           and then not Suppress_Style_Checks (Body_Id)
+           and then not In_Instance
+         then
+            Style.Body_With_No_Spec (N);
+         end if;
+
+         New_Overloaded_Entity (Body_Id);
+
+         if Nkind (N) /= N_Subprogram_Body_Stub then
+            Set_Acts_As_Spec (N);
+            Generate_Definition (Body_Id);
+            Install_Formals (Body_Id);
+            New_Scope (Body_Id);
+         end if;
+      end if;
+
+      --  If this is the proper body of a stub, we must verify that the stub
+      --  conforms to the body, and to the previous spec if one was present.
+      --  we know already that the body conforms to that spec. This test is
+      --  only required for subprograms that come from source.
+
+      if Nkind (Parent (N)) = N_Subunit
+        and then Comes_From_Source (N)
+        and then not Error_Posted (Body_Id)
+      then
+         declare
+            Conformant : Boolean := False;
+            Old_Id     : Entity_Id :=
+                           Defining_Entity
+                             (Specification (Corresponding_Stub (Parent (N))));
+
+         begin
+            if No (Spec_Id) then
+               Check_Fully_Conformant (Body_Id, Old_Id);
+
+            else
+               Check_Conformance
+                 (Body_Id, Old_Id, Fully_Conformant, False, Conformant);
+
+               if not Conformant then
+
+                  --  The stub was taken to be a new declaration. Indicate
+                  --  that it lacks a body.
+
+                  Set_Has_Completion (Old_Id, False);
+               end if;
+            end if;
+         end;
+      end if;
+
+      Set_Has_Completion (Body_Id);
+      Check_Eliminated (Body_Id);
+
+      if Nkind (N) = N_Subprogram_Body_Stub then
+         return;
+
+      elsif  Present (Spec_Id)
+        and then Expander_Active
+        and then Has_Pragma_Inline (Spec_Id)
+        and then (Front_End_Inlining
+                   or else
+                 (No_Run_Time and then Is_Always_Inlined (Spec_Id)))
+      then
+         if Build_Body_To_Inline (N, Spec_Id, Copy_Separate_Tree (N)) then
+            null;
+         end if;
+      end if;
+
+      --  Here we have a real body, not a stub
+
+      HSS := Handled_Statement_Sequence (N);
+      Set_Actual_Subtypes (N, Current_Scope);
+      Analyze_Declarations (Declarations (N));
+      Check_Completion;
+      Analyze (HSS);
+      Process_End_Label (HSS, 't');
+      End_Scope;
+      Check_Subprogram_Order (N);
+
+      --  If we have a separate spec, then the analysis of the declarations
+      --  caused the entities in the body to be chained to the spec id, but
+      --  we want them chained to the body id. Only the formal parameters
+      --  end up chained to the spec id in this case.
+
+      if Present (Spec_Id) then
+
+         --  If a parent unit is categorized, the context of a subunit
+         --  must conform to the categorization. Conversely, if a child
+         --  unit is categorized, the parents themselves must conform.
+
+         if Nkind (Parent (N)) = N_Subunit then
+            Validate_Categorization_Dependency (N, Spec_Id);
+
+         elsif Is_Child_Unit (Spec_Id) then
+            Validate_Categorization_Dependency
+              (Unit_Declaration_Node (Spec_Id), Spec_Id);
+         end if;
+
+         if Present (Last_Formal) then
+            Set_Next_Entity
+              (Last_Entity (Body_Id), Next_Entity (Last_Formal));
+            Set_Next_Entity (Last_Formal, Empty);
+            Set_Last_Entity (Body_Id, Last_Entity (Spec_Id));
+            Set_Last_Entity (Spec_Id, Last_Formal);
+
+         else
+            Set_First_Entity (Body_Id, First_Entity (Spec_Id));
+            Set_Last_Entity  (Body_Id, Last_Entity (Spec_Id));
+            Set_First_Entity (Spec_Id, Empty);
+            Set_Last_Entity  (Spec_Id, Empty);
+         end if;
+      end if;
+
+      --  If function, check return statements
+
+      if Nkind (Body_Spec) = N_Function_Specification then
+         declare
+            Id : Entity_Id;
+
+         begin
+            if Present (Spec_Id) then
+               Id := Spec_Id;
+            else
+               Id := Body_Id;
+            end if;
+
+            if Return_Present (Id) then
+               Check_Returns (HSS, 'F', Missing_Ret);
+
+               if Missing_Ret then
+                  Set_Has_Missing_Return (Id);
+               end if;
+
+            elsif not Is_Machine_Code_Subprogram (Id) then
+               Error_Msg_N ("missing RETURN statement in function body", N);
+            end if;
+         end;
+
+      --  If procedure with No_Return, check returns
+
+      elsif Nkind (Body_Spec) = N_Procedure_Specification
+        and then Present (Spec_Id)
+        and then No_Return (Spec_Id)
+      then
+         Check_Returns (HSS, 'P', Missing_Ret);
+      end if;
+
+      --  Don't worry about checking for variables that are never modified
+      --  if the first statement of the body is a raise statement, since
+      --  we assume this is some kind of stub. We ignore a label generated
+      --  by the exception stuff for the purpose of this test.
+
+      declare
+         Stm : Node_Id := First (Statements (HSS));
+
+      begin
+         if Nkind (Stm) = N_Label then
+            Next (Stm);
+         end if;
+
+         if Nkind (Original_Node (Stm)) = N_Raise_Statement then
+            return;
+         end if;
+      end;
+
+      --  Check for variables that are never modified
+
+      declare
+         E1, E2 : Entity_Id;
+
+      begin
+         --  If there is a separate spec, then transfer Not_Source_Assigned
+         --  flags from out parameters to the corresponding entities in the
+         --  body. The reason we do that is we want to post error flags on
+         --  the body entities, not the spec entities.
+
+         if Present (Spec_Id) then
+            E1 := First_Entity (Spec_Id);
+
+            while Present (E1) loop
+               if Ekind (E1) = E_Out_Parameter then
+                  E2 := First_Entity (Body_Id);
+
+                  loop
+                     --  If no matching body entity, then we already had
+                     --  a detected error of some kind, so just forget
+                     --  about worrying about these warnings.
+
+                     if No (E2) then
+                        return;
+                     end if;
+
+                     exit when Chars (E1) = Chars (E2);
+                     Next_Entity (E2);
+                  end loop;
+
+                  Set_Not_Source_Assigned (E2, Not_Source_Assigned (E1));
+               end if;
+
+               Next_Entity (E1);
+            end loop;
+         end if;
+
+         Check_References (Body_Id);
+      end;
+   end Analyze_Subprogram_Body;
+
+   ------------------------------------
+   -- Analyze_Subprogram_Declaration --
+   ------------------------------------
+
+   procedure Analyze_Subprogram_Declaration (N : Node_Id) is
+      Designator : constant Entity_Id := Analyze_Spec (Specification (N));
+      Scop        : constant Entity_Id := Current_Scope;
+
+   --  Start of processing for Analyze_Subprogram_Declaration
+
+   begin
+      Generate_Definition (Designator);
+
+      --  Check for RCI unit subprogram declarations against in-lined
+      --  subprograms and subprograms having access parameter or limited
+      --  parameter without Read and Write (RM E.2.3(12-13)).
+
+      Validate_RCI_Subprogram_Declaration (N);
+
+      Trace_Scope
+        (N,
+         Defining_Entity (N),
+         " Analyze subprogram spec. ");
+
+      if Debug_Flag_C then
+         Write_Str ("====  Compiling subprogram spec ");
+         Write_Name (Chars (Designator));
+         Write_Str (" from ");
+         Write_Location (Sloc (N));
+         Write_Eol;
+      end if;
+
+      New_Overloaded_Entity (Designator);
+      Check_Delayed_Subprogram (Designator);
+      Set_Suppress_Elaboration_Checks
+        (Designator, Elaboration_Checks_Suppressed (Designator));
+
+      if Scop /= Standard_Standard
+        and then not Is_Child_Unit (Designator)
+      then
+         Set_Is_Pure (Designator,
+           Is_Pure (Scop) and then Is_Library_Level_Entity (Designator));
+         Set_Is_Remote_Call_Interface (
+           Designator, Is_Remote_Call_Interface (Scop));
+         Set_Is_Remote_Types (Designator, Is_Remote_Types (Scop));
+
+      else
+         --  For a compilation unit, check for library-unit pragmas.
+
+         New_Scope (Designator);
+         Set_Categorization_From_Pragmas (N);
+         Validate_Categorization_Dependency (N, Designator);
+         Pop_Scope;
+      end if;
+
+      --  For a compilation unit, set body required. This flag will only be
+      --  reset if a valid Import or Interface pragma is processed later on.
+
+      if Nkind (Parent (N)) = N_Compilation_Unit then
+         Set_Body_Required (Parent (N), True);
+      end if;
+
+      Check_Eliminated (Designator);
+   end Analyze_Subprogram_Declaration;
+
+   --------------------------
+   -- Build_Body_To_Inline --
+   --------------------------
+
+   function Build_Body_To_Inline
+     (N         : Node_Id;
+      Subp      : Entity_Id;
+      Orig_Body : Node_Id) return Boolean
+   is
+      Decl : constant Node_Id := Unit_Declaration_Node (Subp);
+      Original_Body   : Node_Id;
+      Body_To_Analyze : Node_Id;
+      Max_Size        : constant := 10;
+      Stat_Count      : Integer := 0;
+
+      function Has_Excluded_Declaration (Decls : List_Id) return Boolean;
+      --  Check for declarations that make inlining not worthwhile.
+
+      function Has_Excluded_Statement   (Stats : List_Id) return Boolean;
+      --  Check for statements that make inlining not worthwhile: any
+      --  tasking statement, nested at any level. Keep track of total
+      --  number of elementary statements, as a measure of acceptable size.
+
+      function Has_Pending_Instantiation return Boolean;
+      --  If some enclosing body contains instantiations that appear before
+      --  the corresponding generic body, the enclosing body has a freeze node
+      --  so that it can be elaborated after the generic itself. This might
+      --  conflict with subsequent inlinings, so that it is unsafe to try to
+      --  inline in such a case.
+
+      -------------------
+      -- Cannot_Inline --
+      -------------------
+
+      procedure Cannot_Inline (Msg : String; N : Node_Id);
+      --  If subprogram has pragma Inline_Always, it is an error if
+      --  it cannot be inlined. Otherwise, emit a warning.
+
+      procedure Cannot_Inline (Msg : String; N : Node_Id) is
+      begin
+         if Is_Always_Inlined (Subp) then
+            Error_Msg_NE (Msg (1 .. Msg'Length - 1), N, Subp);
+
+         elsif Ineffective_Inline_Warnings then
+            Error_Msg_NE (Msg, N, Subp);
+         end if;
+      end Cannot_Inline;
+
+      ------------------------------
+      -- Has_Excluded_Declaration --
+      ------------------------------
+
+      function Has_Excluded_Declaration (Decls : List_Id) return Boolean is
+         D : Node_Id;
+
+      begin
+         D := First (Decls);
+
+         while Present (D) loop
+            if        Nkind (D) = N_Function_Instantiation
+              or else Nkind (D) = N_Protected_Type_Declaration
+              or else Nkind (D) = N_Package_Declaration
+              or else Nkind (D) = N_Package_Instantiation
+              or else Nkind (D) = N_Subprogram_Body
+              or else Nkind (D) = N_Procedure_Instantiation
+              or else Nkind (D) = N_Task_Type_Declaration
+            then
+               Cannot_Inline
+                 ("\declaration prevents front-end inlining of&?", D);
+               return True;
+            end if;
+
+            Next (D);
+         end loop;
+
+         return False;
+
+      end Has_Excluded_Declaration;
+
+      ----------------------------
+      -- Has_Excluded_Statement --
+      ----------------------------
+
+      function Has_Excluded_Statement (Stats : List_Id) return Boolean is
+         S : Node_Id;
+         E : Node_Id;
+
+      begin
+         S := First (Stats);
+
+         while Present (S) loop
+            Stat_Count := Stat_Count + 1;
+
+            if Nkind (S) = N_Abort_Statement
+              or else Nkind (S) = N_Asynchronous_Select
+              or else Nkind (S) = N_Conditional_Entry_Call
+              or else Nkind (S) = N_Delay_Relative_Statement
+              or else Nkind (S) = N_Delay_Until_Statement
+              or else Nkind (S) = N_Selective_Accept
+              or else Nkind (S) = N_Timed_Entry_Call
+            then
+               Cannot_Inline
+                 ("\statement prevents front-end inlining of&?", S);
+               return True;
+
+            elsif Nkind (S) = N_Block_Statement then
+               if Present (Declarations (S))
+                 and then Has_Excluded_Declaration (Declarations (S))
+               then
+                  return True;
+
+               elsif Present (Handled_Statement_Sequence (S))
+                  and then
+                    (Present
+                      (Exception_Handlers (Handled_Statement_Sequence (S)))
+                     or else
+                       Has_Excluded_Statement
+                         (Statements (Handled_Statement_Sequence (S))))
+               then
+                  return True;
+               end if;
+
+            elsif Nkind (S) = N_Case_Statement then
+               E := First (Alternatives (S));
+
+               while Present (E) loop
+                  if Has_Excluded_Statement (Statements (E)) then
+                     return True;
+                  end if;
+
+                  Next (E);
+               end loop;
+
+            elsif Nkind (S) = N_If_Statement then
+               if Has_Excluded_Statement (Then_Statements (S)) then
+                  return True;
+               end if;
+
+               if Present (Elsif_Parts (S)) then
+                  E := First (Elsif_Parts (S));
+
+                  while Present (E) loop
+                     if Has_Excluded_Statement (Then_Statements (E)) then
+                        return True;
+                     end if;
+                     Next (E);
+                  end loop;
+               end if;
+
+               if Present (Else_Statements (S))
+                 and then Has_Excluded_Statement (Else_Statements (S))
+               then
+                  return True;
+               end if;
+
+            elsif Nkind (S) = N_Loop_Statement
+              and then Has_Excluded_Statement (Statements (S))
+            then
+               return True;
+            end if;
+
+            Next (S);
+         end loop;
+
+         return False;
+      end Has_Excluded_Statement;
+
+      -------------------------------
+      -- Has_Pending_Instantiation --
+      -------------------------------
+
+      function Has_Pending_Instantiation return Boolean is
+         S : Entity_Id := Current_Scope;
+
+      begin
+         while Present (S) loop
+            if Is_Compilation_Unit (S)
+              or else Is_Child_Unit (S)
+            then
+               return False;
+            elsif Ekind (S) = E_Package
+              and then Has_Forward_Instantiation (S)
+            then
+               return True;
+            end if;
+
+            S := Scope (S);
+         end loop;
+
+         return False;
+      end Has_Pending_Instantiation;
+
+   --  Start of processing for Build_Body_To_Inline
+
+   begin
+      if Nkind (Decl) = N_Subprogram_Declaration
+        and then Present (Body_To_Inline (Decl))
+      then
+         return True;    --  Done already.
+
+      --  Functions that return unconstrained composite types will require
+      --  secondary stack handling, and cannot currently be inlined.
+
+      elsif Ekind (Subp) = E_Function
+        and then not Is_Scalar_Type (Etype (Subp))
+        and then not Is_Access_Type (Etype (Subp))
+        and then not Is_Constrained (Etype (Subp))
+      then
+         Cannot_Inline
+           ("unconstrained return type prevents front-end inlining of&?", N);
+         return False;
+      end if;
+
+      --  We need to capture references to the formals in order to substitute
+      --  the actuals at the point of inlining, i.e. instantiation. To treat
+      --  the formals as globals to the body to inline, we nest it within
+      --  a dummy parameterless subprogram, declared within the real one.
+
+      Original_Body := Orig_Body;
+
+      --  Within an instance, the current tree is already the result of
+      --  a generic copy, and not what we need for subsequent inlining.
+      --  We create the required body by doing an instantiating copy, to
+      --  obtain the proper partially analyzed tree.
+
+      if In_Instance then
+         if No (Generic_Parent (Specification (N))) then
+            return False;
+
+         elsif Is_Child_Unit (Scope (Current_Scope)) then
+            return False;
+
+         elsif Scope (Current_Scope) = Cunit_Entity (Main_Unit) then
+
+            --  compiling an instantiation. There is no point in generating
+            --  bodies to inline, because they will not be used.
+
+            return False;
+
+         else
+            Body_To_Analyze :=
+              Copy_Generic_Node
+                (Generic_Parent (Specification (N)), Empty,
+                   Instantiating => True);
+         end if;
+      else
+         Body_To_Analyze :=
+           Copy_Generic_Node (Original_Body, Empty,
+             Instantiating => False);
+      end if;
+
+      Set_Parameter_Specifications (Specification (Original_Body), No_List);
+      Set_Defining_Unit_Name (Specification (Original_Body),
+        Make_Defining_Identifier (Sloc (N), New_Internal_Name ('S')));
+      Set_Corresponding_Spec (Original_Body, Empty);
+
+      if Ekind (Subp) = E_Function then
+         Set_Subtype_Mark (Specification (Original_Body),
+           New_Occurrence_Of (Etype (Subp), Sloc (N)));
+      end if;
+
+      if Present (Declarations (Orig_Body))
+        and then Has_Excluded_Declaration (Declarations (Orig_Body))
+      then
+         return False;
+      end if;
+
+      if Present (Handled_Statement_Sequence (N)) then
+         if
+          (Present (Exception_Handlers (Handled_Statement_Sequence (N))))
+         then
+            Cannot_Inline ("handler prevents front-end inlining of&?",
+               First (Exception_Handlers (Handled_Statement_Sequence (N))));
+            return False;
+         elsif
+           Has_Excluded_Statement
+             (Statements (Handled_Statement_Sequence (N)))
+         then
+            return False;
+         end if;
+      end if;
+
+      --  We do not inline a subprogram  that is too large, unless it is
+      --  marked Inline_Always. This pragma does not suppress the other
+      --  checks on inlining (forbidden declarations, handlers, etc).
+
+      if Stat_Count > Max_Size
+        and then not Is_Always_Inlined (Subp)
+      then
+         Cannot_Inline ("body is too large for front-end inlining of&?", N);
+         return False;
+      end if;
+
+      if Has_Pending_Instantiation then
+         Cannot_Inline
+           ("cannot inline& because of forward instance within enclosing body",
+             N);
+         return False;
+      end if;
+
+      Body_To_Analyze := Copy_Generic_Node (Original_Body, Empty, False);
+
+      --  Set return type of function, which is also global and does not need
+      --  to be resolved.
+
+      if Ekind (Subp) = E_Function then
+         Set_Subtype_Mark (Specification (Body_To_Analyze),
+           New_Occurrence_Of (Etype (Subp), Sloc (N)));
+      end if;
+
+      if No (Declarations (N)) then
+         Set_Declarations (N, New_List (Body_To_Analyze));
+      else
+         Append (Body_To_Analyze, Declarations (N));
+      end if;
+
+      Expander_Mode_Save_And_Set (False);
+
+      Analyze (Body_To_Analyze);
+      New_Scope (Defining_Entity (Body_To_Analyze));
+      Save_Global_References (Original_Body);
+      End_Scope;
+      Remove (Body_To_Analyze);
+
+      Expander_Mode_Restore;
+      Set_Body_To_Inline (Decl, Original_Body);
+      Set_Is_Inlined (Subp);
+      return True;
+
+   end Build_Body_To_Inline;
+
+   -----------------------
+   -- Check_Conformance --
+   -----------------------
+
+   procedure Check_Conformance
+     (New_Id   : Entity_Id;
+      Old_Id   : Entity_Id;
+      Ctype    : Conformance_Type;
+      Errmsg   : Boolean;
+      Conforms : out Boolean;
+      Err_Loc  : Node_Id := Empty;
+      Get_Inst : Boolean := False)
+   is
+      Old_Type   : constant Entity_Id := Etype (Old_Id);
+      New_Type   : constant Entity_Id := Etype (New_Id);
+      Old_Formal : Entity_Id;
+      New_Formal : Entity_Id;
+
+      procedure Conformance_Error (Msg : String; N : Node_Id := New_Id);
+      --  Post error message for conformance error on given node.
+      --  Two messages are output. The first points to the previous
+      --  declaration with a general "no conformance" message.
+      --  The second is the detailed reason, supplied as Msg. The
+      --  parameter N provide information for a possible & insertion
+      --  in the message, and also provides the location for posting
+      --  the message in the absence of a specified Err_Loc location.
+
+      -----------------------
+      -- Conformance_Error --
+      -----------------------
+
+      procedure Conformance_Error (Msg : String; N : Node_Id := New_Id) is
+         Enode : Node_Id;
+
+      begin
+         Conforms := False;
+
+         if Errmsg then
+            if No (Err_Loc) then
+               Enode := N;
+            else
+               Enode := Err_Loc;
+            end if;
+
+            Error_Msg_Sloc := Sloc (Old_Id);
+
+            case Ctype is
+               when Type_Conformant =>
+                  Error_Msg_N
+                    ("not type conformant with declaration#!", Enode);
+
+               when Mode_Conformant =>
+                  Error_Msg_N
+                    ("not mode conformant with declaration#!", Enode);
+
+               when Subtype_Conformant =>
+                  Error_Msg_N
+                    ("not subtype conformant with declaration#!", Enode);
+
+               when Fully_Conformant =>
+                  Error_Msg_N
+                    ("not fully conformant with declaration#!", Enode);
+            end case;
+
+            Error_Msg_NE (Msg, Enode, N);
+         end if;
+      end Conformance_Error;
+
+   --  Start of processing for Check_Conformance
+
+   begin
+      Conforms := True;
+
+      --  We need a special case for operators, since they don't
+      --  appear explicitly.
+
+      if Ctype = Type_Conformant then
+         if Ekind (New_Id) = E_Operator
+           and then Operator_Matches_Spec (New_Id, Old_Id)
+         then
+            return;
+         end if;
+      end if;
+
+      --  If both are functions/operators, check return types conform
+
+      if Old_Type /= Standard_Void_Type
+        and then New_Type /= Standard_Void_Type
+      then
+         if not Conforming_Types (Old_Type, New_Type, Ctype, Get_Inst) then
+            Conformance_Error ("return type does not match!", New_Id);
+            return;
+         end if;
+
+      --  If either is a function/operator and the other isn't, error
+
+      elsif Old_Type /= Standard_Void_Type
+        or else New_Type /= Standard_Void_Type
+      then
+         Conformance_Error ("functions can only match functions!", New_Id);
+         return;
+      end if;
+
+      --  In subtype conformant case, conventions must match (RM 6.3.1(16))
+      --  If this is a renaming as body, refine error message to indicate that
+      --  the conflict is with the original declaration. If the entity is not
+      --  frozen, the conventions don't have to match, the one of the renamed
+      --  entity is inherited.
+
+      if Ctype >= Subtype_Conformant then
+
+         if Convention (Old_Id) /= Convention (New_Id) then
+
+            if not Is_Frozen (New_Id) then
+               null;
+
+            elsif Present (Err_Loc)
+              and then Nkind (Err_Loc) = N_Subprogram_Renaming_Declaration
+              and then Present (Corresponding_Spec (Err_Loc))
+            then
+               Error_Msg_Name_1 := Chars (New_Id);
+               Error_Msg_Name_2 :=
+                 Name_Ada + Convention_Id'Pos (Convention (New_Id));
+
+               Conformance_Error ("prior declaration for% has convention %!");
+
+            else
+               Conformance_Error ("calling conventions do not match!");
+            end if;
+
+            return;
+
+         elsif Is_Formal_Subprogram (Old_Id)
+           or else Is_Formal_Subprogram (New_Id)
+         then
+            Conformance_Error ("formal subprograms not allowed!");
+            return;
+         end if;
+      end if;
+
+      --  Deal with parameters
+
+      --  Note: we use the entity information, rather than going directly
+      --  to the specification in the tree. This is not only simpler, but
+      --  absolutely necessary for some cases of conformance tests between
+      --  operators, where the declaration tree simply does not exist!
+
+      Old_Formal := First_Formal (Old_Id);
+      New_Formal := First_Formal (New_Id);
+
+      while Present (Old_Formal) and then Present (New_Formal) loop
+
+         --  Types must always match. In the visible part of an instance,
+         --  usual overloading rules for dispatching operations apply, and
+         --  we check base types (not the actual subtypes).
+
+         if In_Instance_Visible_Part
+           and then Is_Dispatching_Operation (New_Id)
+         then
+            if not Conforming_Types
+              (Base_Type (Etype (Old_Formal)),
+                 Base_Type (Etype (New_Formal)), Ctype, Get_Inst)
+            then
+               Conformance_Error ("type of & does not match!", New_Formal);
+               return;
+            end if;
+
+         elsif not Conforming_Types
+           (Etype (Old_Formal), Etype (New_Formal), Ctype, Get_Inst)
+         then
+            Conformance_Error ("type of & does not match!", New_Formal);
+            return;
+         end if;
+
+         --  For mode conformance, mode must match
+
+         if Ctype >= Mode_Conformant
+           and then Parameter_Mode (Old_Formal) /= Parameter_Mode (New_Formal)
+         then
+            Conformance_Error ("mode of & does not match!", New_Formal);
+            return;
+         end if;
+
+         --  Full conformance checks
+
+         if Ctype = Fully_Conformant then
+
+            --  Names must match
+
+            if Chars (Old_Formal) /= Chars (New_Formal) then
+               Conformance_Error ("name & does not match!", New_Formal);
+               return;
+
+            --  And default expressions for in parameters
+
+            elsif Parameter_Mode (Old_Formal) = E_In_Parameter then
+               declare
+                  NewD : constant Boolean :=
+                           Present (Default_Value (New_Formal));
+                  OldD : constant Boolean :=
+                           Present (Default_Value (Old_Formal));
+               begin
+                  if NewD or OldD then
+
+                     --  The old default value has been analyzed and expanded,
+                     --  because the current full declaration will have frozen
+                     --  everything before. The new default values have not
+                     --  been expanded, so expand now to check conformance.
+
+                     if NewD then
+                        New_Scope (New_Id);
+                        Analyze_Default_Expression
+                         (Default_Value (New_Formal), Etype (New_Formal));
+                        End_Scope;
+                     end if;
+
+                     if not (NewD and OldD)
+                       or else not Fully_Conformant_Expressions
+                                    (Default_Value (Old_Formal),
+                                     Default_Value (New_Formal))
+                     then
+                        Conformance_Error
+                          ("default expression for & does not match!",
+                           New_Formal);
+                        return;
+                     end if;
+                  end if;
+               end;
+            end if;
+         end if;
+
+         --  A couple of special checks for Ada 83 mode. These checks are
+         --  skipped if either entity is an operator in package Standard.
+         --  or if either old or new instance is not from the source program.
+
+         if Ada_83
+           and then Sloc (Old_Id) > Standard_Location
+           and then Sloc (New_Id) > Standard_Location
+           and then Comes_From_Source (Old_Id)
+           and then Comes_From_Source (New_Id)
+         then
+            declare
+               Old_Param : constant Node_Id := Declaration_Node (Old_Formal);
+               New_Param : constant Node_Id := Declaration_Node (New_Formal);
+
+            begin
+               --  Explicit IN must be present or absent in both cases. This
+               --  test is required only in the full conformance case.
+
+               if In_Present (Old_Param) /= In_Present (New_Param)
+                 and then Ctype = Fully_Conformant
+               then
+                  Conformance_Error
+                    ("(Ada 83) IN must appear in both declarations",
+                     New_Formal);
+                  return;
+               end if;
+
+               --  Grouping (use of comma in param lists) must be the same
+               --  This is where we catch a misconformance like:
+
+               --    A,B : Integer
+               --    A : Integer; B : Integer
+
+               --  which are represented identically in the tree except
+               --  for the setting of the flags More_Ids and Prev_Ids.
+
+               if More_Ids (Old_Param) /= More_Ids (New_Param)
+                 or else Prev_Ids (Old_Param) /= Prev_Ids (New_Param)
+               then
+                  Conformance_Error
+                    ("grouping of & does not match!", New_Formal);
+                  return;
+               end if;
+            end;
+         end if;
+
+         Next_Formal (Old_Formal);
+         Next_Formal (New_Formal);
+      end loop;
+
+      if Present (Old_Formal) then
+         Conformance_Error ("too few parameters!");
+         return;
+
+      elsif Present (New_Formal) then
+         Conformance_Error ("too many parameters!", New_Formal);
+         return;
+      end if;
+
+   end Check_Conformance;
+
+   ------------------------------
+   -- Check_Delayed_Subprogram --
+   ------------------------------
+
+   procedure Check_Delayed_Subprogram (Designator : Entity_Id) is
+      F : Entity_Id;
+
+      procedure Possible_Freeze (T : Entity_Id);
+      --  T is the type of either a formal parameter or of the return type.
+      --  If T is not yet frozen and needs a delayed freeze, then the
+      --  subprogram itself must be delayed.
+
+      procedure Possible_Freeze (T : Entity_Id) is
+      begin
+         if Has_Delayed_Freeze (T)
+           and then not Is_Frozen (T)
+         then
+            Set_Has_Delayed_Freeze (Designator);
+
+         elsif Is_Access_Type (T)
+           and then Has_Delayed_Freeze (Designated_Type (T))
+           and then not Is_Frozen (Designated_Type (T))
+         then
+            Set_Has_Delayed_Freeze (Designator);
+         end if;
+      end Possible_Freeze;
+
+   --  Start of processing for Check_Delayed_Subprogram
+
+   begin
+      --  Never need to freeze abstract subprogram
+
+      if Is_Abstract (Designator) then
+         null;
+      else
+         --  Need delayed freeze if return type itself needs a delayed
+         --  freeze and is not yet frozen.
+
+         Possible_Freeze (Etype (Designator));
+         Possible_Freeze (Base_Type (Etype (Designator))); -- needed ???
+
+         --  Need delayed freeze if any of the formal types themselves need
+         --  a delayed freeze and are not yet frozen.
+
+         F := First_Formal (Designator);
+         while Present (F) loop
+            Possible_Freeze (Etype (F));
+            Possible_Freeze (Base_Type (Etype (F))); -- needed ???
+            Next_Formal (F);
+         end loop;
+      end if;
+
+      --  Mark functions that return by reference. Note that it cannot be
+      --  done for delayed_freeze subprograms because the underlying
+      --  returned type may not be known yet (for private types)
+
+      if not Has_Delayed_Freeze (Designator)
+        and then Expander_Active
+      then
+         declare
+            Typ  : constant Entity_Id := Etype (Designator);
+            Utyp : constant Entity_Id := Underlying_Type (Typ);
+
+         begin
+            if Is_Return_By_Reference_Type (Typ) then
+               Set_Returns_By_Ref (Designator);
+
+            elsif Present (Utyp) and then Controlled_Type (Utyp) then
+               Set_Returns_By_Ref (Designator);
+            end if;
+         end;
+      end if;
+   end Check_Delayed_Subprogram;
+
+   ------------------------------------
+   -- Check_Discriminant_Conformance --
+   ------------------------------------
+
+   procedure Check_Discriminant_Conformance
+     (N        : Node_Id;
+      Prev     : Entity_Id;
+      Prev_Loc : Node_Id)
+   is
+      Old_Discr      : Entity_Id := First_Discriminant (Prev);
+      New_Discr      : Node_Id   := First (Discriminant_Specifications (N));
+      New_Discr_Id   : Entity_Id;
+      New_Discr_Type : Entity_Id;
+
+      procedure Conformance_Error (Msg : String; N : Node_Id);
+      --  Post error message for conformance error on given node.
+      --  Two messages are output. The first points to the previous
+      --  declaration with a general "no conformance" message.
+      --  The second is the detailed reason, supplied as Msg. The
+      --  parameter N provide information for a possible & insertion
+      --  in the message.
+
+      -----------------------
+      -- Conformance_Error --
+      -----------------------
+
+      procedure Conformance_Error (Msg : String; N : Node_Id) is
+      begin
+         Error_Msg_Sloc := Sloc (Prev_Loc);
+         Error_Msg_N ("not fully conformant with declaration#!", N);
+         Error_Msg_NE (Msg, N, N);
+      end Conformance_Error;
+
+   --  Start of processing for Check_Discriminant_Conformance
+
+   begin
+      while Present (Old_Discr) and then Present (New_Discr) loop
+
+         New_Discr_Id := Defining_Identifier (New_Discr);
+
+         --  The subtype mark of the discriminant on the full type
+         --  has not been analyzed so we do it here. For an access
+         --  discriminant a new type is created.
+
+         if Nkind (Discriminant_Type (New_Discr)) = N_Access_Definition then
+            New_Discr_Type :=
+              Access_Definition (N, Discriminant_Type (New_Discr));
+
+         else
+            Analyze (Discriminant_Type (New_Discr));
+            New_Discr_Type := Etype (Discriminant_Type (New_Discr));
+         end if;
+
+         if not Conforming_Types
+                  (Etype (Old_Discr), New_Discr_Type, Fully_Conformant)
+         then
+            Conformance_Error ("type of & does not match!", New_Discr_Id);
+            return;
+         end if;
+
+         --  Names must match
+
+         if Chars (Old_Discr) /= Chars (Defining_Identifier (New_Discr)) then
+            Conformance_Error ("name & does not match!", New_Discr_Id);
+            return;
+         end if;
+
+         --  Default expressions must match
+
+         declare
+            NewD : constant Boolean :=
+                     Present (Expression (New_Discr));
+            OldD : constant Boolean :=
+                     Present (Expression (Parent (Old_Discr)));
+
+         begin
+            if NewD or OldD then
+
+               --  The old default value has been analyzed and expanded,
+               --  because the current full declaration will have frozen
+               --  everything before. The new default values have not
+               --  been expanded, so expand now to check conformance.
+
+               if NewD then
+                  Analyze_Default_Expression
+                    (Expression (New_Discr), New_Discr_Type);
+               end if;
+
+               if not (NewD and OldD)
+                 or else not Fully_Conformant_Expressions
+                              (Expression (Parent (Old_Discr)),
+                               Expression (New_Discr))
+
+               then
+                  Conformance_Error
+                    ("default expression for & does not match!",
+                     New_Discr_Id);
+                  return;
+               end if;
+            end if;
+         end;
+
+         --  In Ada 83 case, grouping must match: (A,B : X) /= (A : X; B : X)
+
+         if Ada_83 then
+            declare
+               Old_Disc : constant Node_Id := Declaration_Node (Old_Discr);
+
+            begin
+               --  Grouping (use of comma in param lists) must be the same
+               --  This is where we catch a misconformance like:
+
+               --    A,B : Integer
+               --    A : Integer; B : Integer
+
+               --  which are represented identically in the tree except
+               --  for the setting of the flags More_Ids and Prev_Ids.
+
+               if More_Ids (Old_Disc) /= More_Ids (New_Discr)
+                 or else Prev_Ids (Old_Disc) /= Prev_Ids (New_Discr)
+               then
+                  Conformance_Error
+                    ("grouping of & does not match!", New_Discr_Id);
+                  return;
+               end if;
+            end;
+         end if;
+
+         Next_Discriminant (Old_Discr);
+         Next (New_Discr);
+      end loop;
+
+      if Present (Old_Discr) then
+         Conformance_Error ("too few discriminants!", Defining_Identifier (N));
+         return;
+
+      elsif Present (New_Discr) then
+         Conformance_Error
+           ("too many discriminants!", Defining_Identifier (New_Discr));
+         return;
+      end if;
+   end Check_Discriminant_Conformance;
+
+   ----------------------------
+   -- Check_Fully_Conformant --
+   ----------------------------
+
+   procedure Check_Fully_Conformant
+     (New_Id  : Entity_Id;
+      Old_Id  : Entity_Id;
+      Err_Loc : Node_Id := Empty)
+   is
+      Result : Boolean;
+
+   begin
+      Check_Conformance
+        (New_Id, Old_Id, Fully_Conformant, True, Result, Err_Loc);
+   end Check_Fully_Conformant;
+
+   ---------------------------
+   -- Check_Mode_Conformant --
+   ---------------------------
+
+   procedure Check_Mode_Conformant
+     (New_Id   : Entity_Id;
+      Old_Id   : Entity_Id;
+      Err_Loc  : Node_Id := Empty;
+      Get_Inst : Boolean := False)
+   is
+      Result : Boolean;
+
+   begin
+      Check_Conformance
+        (New_Id, Old_Id, Mode_Conformant, True, Result, Err_Loc, Get_Inst);
+   end Check_Mode_Conformant;
+
+   -------------------
+   -- Check_Returns --
+   -------------------
+
+   procedure Check_Returns
+     (HSS  : Node_Id;
+      Mode : Character;
+      Err  : out Boolean)
+   is
+      Handler : Node_Id;
+
+      procedure Check_Statement_Sequence (L : List_Id);
+      --  Internal recursive procedure to check a list of statements for proper
+      --  termination by a return statement (or a transfer of control or a
+      --  compound statement that is itself internally properly terminated).
+
+      ------------------------------
+      -- Check_Statement_Sequence --
+      ------------------------------
+
+      procedure Check_Statement_Sequence (L : List_Id) is
+         Last_Stm : Node_Id;
+         Kind     : Node_Kind;
+
+         Raise_Exception_Call : Boolean;
+         --  Set True if statement sequence terminated by Raise_Exception call
+         --  or a Reraise_Occurrence call.
+
+      begin
+         Raise_Exception_Call := False;
+
+         --  Get last real statement
+
+         Last_Stm := Last (L);
+
+         --  Don't count pragmas
+
+         while Nkind (Last_Stm) = N_Pragma
+
+         --  Don't count call to SS_Release (can happen after Raise_Exception)
+
+           or else
+             (Nkind (Last_Stm) = N_Procedure_Call_Statement
+                and then
+              Nkind (Name (Last_Stm)) = N_Identifier
+                and then
+              Is_RTE (Entity (Name (Last_Stm)), RE_SS_Release))
+
+         --  Don't count exception junk
+
+           or else
+             ((Nkind (Last_Stm) = N_Goto_Statement
+                 or else Nkind (Last_Stm) = N_Label
+                 or else Nkind (Last_Stm) = N_Object_Declaration)
+               and then Exception_Junk (Last_Stm))
+         loop
+            Prev (Last_Stm);
+         end loop;
+
+         --  Here we have the "real" last statement
+
+         Kind := Nkind (Last_Stm);
+
+         --  Transfer of control, OK. Note that in the No_Return procedure
+         --  case, we already diagnosed any explicit return statements, so
+         --  we can treat them as OK in this context.
+
+         if Is_Transfer (Last_Stm) then
+            return;
+
+         --  Check cases of explicit non-indirect procedure calls
+
+         elsif Kind = N_Procedure_Call_Statement
+           and then Is_Entity_Name (Name (Last_Stm))
+         then
+            --  Check call to Raise_Exception procedure which is treated
+            --  specially, as is a call to Reraise_Occurrence.
+
+            --  We suppress the warning in these cases since it is likely that
+            --  the programmer really does not expect to deal with the case
+            --  of Null_Occurrence, and thus would find a warning about a
+            --  missing return curious, and raising Program_Error does not
+            --  seem such a bad behavior if this does occur.
+
+            if Is_RTE (Entity (Name (Last_Stm)), RE_Raise_Exception)
+                 or else
+               Is_RTE (Entity (Name (Last_Stm)), RE_Reraise_Occurrence)
+            then
+               Raise_Exception_Call := True;
+
+               --  For Raise_Exception call, test first argument, if it is
+               --  an attribute reference for a 'Identity call, then we know
+               --  that the call cannot possibly return.
+
+               declare
+                  Arg : constant Node_Id :=
+                          Original_Node (First_Actual (Last_Stm));
+
+               begin
+                  if Nkind (Arg) = N_Attribute_Reference
+                    and then Attribute_Name (Arg) = Name_Identity
+                  then
+                     return;
+                  end if;
+               end;
+            end if;
+
+         --  If statement, need to look inside if there is an else and check
+         --  each constituent statement sequence for proper termination.
+
+         elsif Kind = N_If_Statement
+           and then Present (Else_Statements (Last_Stm))
+         then
+            Check_Statement_Sequence (Then_Statements (Last_Stm));
+            Check_Statement_Sequence (Else_Statements (Last_Stm));
+
+            if Present (Elsif_Parts (Last_Stm)) then
+               declare
+                  Elsif_Part : Node_Id := First (Elsif_Parts (Last_Stm));
+
+               begin
+                  while Present (Elsif_Part) loop
+                     Check_Statement_Sequence (Then_Statements (Elsif_Part));
+                     Next (Elsif_Part);
+                  end loop;
+               end;
+            end if;
+
+            return;
+
+         --  Case statement, check each case for proper termination
+
+         elsif Kind = N_Case_Statement then
+            declare
+               Case_Alt : Node_Id;
+
+            begin
+               Case_Alt := First_Non_Pragma (Alternatives (Last_Stm));
+               while Present (Case_Alt) loop
+                  Check_Statement_Sequence (Statements (Case_Alt));
+                  Next_Non_Pragma (Case_Alt);
+               end loop;
+            end;
+
+            return;
+
+         --  Block statement, check its handled sequence of statements
+
+         elsif Kind = N_Block_Statement then
+            declare
+               Err1 : Boolean;
+
+            begin
+               Check_Returns
+                 (Handled_Statement_Sequence (Last_Stm), Mode, Err1);
+
+               if Err1 then
+                  Err := True;
+               end if;
+
+               return;
+            end;
+
+         --  Loop statement. If there is an iteration scheme, we can definitely
+         --  fall out of the loop. Similarly if there is an exit statement, we
+         --  can fall out. In either case we need a following return.
+
+         elsif Kind = N_Loop_Statement then
+            if Present (Iteration_Scheme (Last_Stm))
+              or else Has_Exit (Entity (Identifier (Last_Stm)))
+            then
+               null;
+
+            --  A loop with no exit statement or iteration scheme if either
+            --  an inifite loop, or it has some other exit (raise/return).
+            --  In either case, no warning is required.
+
+            else
+               return;
+            end if;
+
+         --  Timed entry call, check entry call and delay alternatives
+
+         --  Note: in expanded code, the timed entry call has been converted
+         --  to a set of expanded statements on which the check will work
+         --  correctly in any case.
+
+         elsif Kind = N_Timed_Entry_Call then
+            declare
+               ECA : constant Node_Id := Entry_Call_Alternative (Last_Stm);
+               DCA : constant Node_Id := Delay_Alternative      (Last_Stm);
+
+            begin
+               --  If statement sequence of entry call alternative is missing,
+               --  then we can definitely fall through, and we post the error
+               --  message on the entry call alternative itself.
+
+               if No (Statements (ECA)) then
+                  Last_Stm := ECA;
+
+               --  If statement sequence of delay alternative is missing, then
+               --  we can definitely fall through, and we post the error
+               --  message on the delay alternative itself.
+
+               --  Note: if both ECA and DCA are missing the return, then we
+               --  post only one message, should be enough to fix the bugs.
+               --  If not we will get a message next time on the DCA when the
+               --  ECA is fixed!
+
+               elsif No (Statements (DCA)) then
+                  Last_Stm := DCA;
+
+               --  Else check both statement sequences
+
+               else
+                  Check_Statement_Sequence (Statements (ECA));
+                  Check_Statement_Sequence (Statements (DCA));
+                  return;
+               end if;
+            end;
+
+         --  Conditional entry call, check entry call and else part
+
+         --  Note: in expanded code, the conditional entry call has been
+         --  converted to a set of expanded statements on which the check
+         --  will work correctly in any case.
+
+         elsif Kind = N_Conditional_Entry_Call then
+            declare
+               ECA : constant Node_Id := Entry_Call_Alternative (Last_Stm);
+
+            begin
+               --  If statement sequence of entry call alternative is missing,
+               --  then we can definitely fall through, and we post the error
+               --  message on the entry call alternative itself.
+
+               if No (Statements (ECA)) then
+                  Last_Stm := ECA;
+
+               --  Else check statement sequence and else part
+
+               else
+                  Check_Statement_Sequence (Statements (ECA));
+                  Check_Statement_Sequence (Else_Statements (Last_Stm));
+                  return;
+               end if;
+            end;
+         end if;
+
+         --  If we fall through, issue appropriate message
+
+         if Mode = 'F' then
+
+            if not Raise_Exception_Call then
+               Error_Msg_N
+                 ("?RETURN statement missing following this statement!",
+                  Last_Stm);
+               Error_Msg_N
+                 ("\?Program_Error may be raised at run time",
+                  Last_Stm);
+            end if;
+
+            --  Note: we set Err even though we have not issued a warning
+            --  because we still have a case of a missing return. This is
+            --  an extremely marginal case, probably will never be noticed
+            --  but we might as well get it right.
+
+            Err := True;
+
+         else
+            Error_Msg_N
+              ("implied return after this statement not allowed (No_Return)",
+               Last_Stm);
+         end if;
+      end Check_Statement_Sequence;
+
+   --  Start of processing for Check_Returns
+
+   begin
+      Err := False;
+      Check_Statement_Sequence (Statements (HSS));
+
+      if Present (Exception_Handlers (HSS)) then
+         Handler := First_Non_Pragma (Exception_Handlers (HSS));
+         while Present (Handler) loop
+            Check_Statement_Sequence (Statements (Handler));
+            Next_Non_Pragma (Handler);
+         end loop;
+      end if;
+   end Check_Returns;
+
+   ----------------------------
+   -- Check_Subprogram_Order --
+   ----------------------------
+
+   procedure Check_Subprogram_Order (N : Node_Id) is
+
+      function Subprogram_Name_Greater (S1, S2 : String) return Boolean;
+      --  This is used to check if S1 > S2 in the sense required by this
+      --  test, for example nameab < namec, but name2 < name10.
+
+      function Subprogram_Name_Greater (S1, S2 : String) return Boolean is
+         L1, L2 : Positive;
+         N1, N2 : Natural;
+
+      begin
+         --  Remove trailing numeric parts
+
+         L1 := S1'Last;
+         while S1 (L1) in '0' .. '9' loop
+            L1 := L1 - 1;
+         end loop;
+
+         L2 := S2'Last;
+         while S2 (L2) in '0' .. '9' loop
+            L2 := L2 - 1;
+         end loop;
+
+         --  If non-numeric parts non-equal, that's decisive
+
+         if S1 (S1'First .. L1) < S2 (S2'First .. L2) then
+            return False;
+
+         elsif S1 (S1'First .. L1) > S2 (S2'First .. L2) then
+            return True;
+
+         --  If non-numeric parts equal, compare suffixed numeric parts. Note
+         --  that a missing suffix is treated as numeric zero in this test.
+
+         else
+            N1 := 0;
+            while L1 < S1'Last loop
+               L1 := L1 + 1;
+               N1 := N1 * 10 + Character'Pos (S1 (L1)) - Character'Pos ('0');
+            end loop;
+
+            N2 := 0;
+            while L2 < S2'Last loop
+               L2 := L2 + 1;
+               N2 := N2 * 10 + Character'Pos (S2 (L2)) - Character'Pos ('0');
+            end loop;
+
+            return N1 > N2;
+         end if;
+      end Subprogram_Name_Greater;
+
+   --  Start of processing for Check_Subprogram_Order
+
+   begin
+      --  Check body in alpha order if this is option
+
+      if Style_Check_Subprogram_Order
+        and then Nkind (N) = N_Subprogram_Body
+        and then Comes_From_Source (N)
+        and then In_Extended_Main_Source_Unit (N)
+      then
+         declare
+            LSN : String_Ptr
+                    renames Scope_Stack.Table
+                              (Scope_Stack.Last).Last_Subprogram_Name;
+
+            Body_Id : constant Entity_Id :=
+                        Defining_Entity (Specification (N));
+
+         begin
+            Get_Decoded_Name_String (Chars (Body_Id));
+
+            if LSN /= null then
+               if Subprogram_Name_Greater
+                    (LSN.all, Name_Buffer (1 .. Name_Len))
+               then
+                  Style.Subprogram_Not_In_Alpha_Order (Body_Id);
+               end if;
+
+               Free (LSN);
+            end if;
+
+            LSN := new String'(Name_Buffer (1 .. Name_Len));
+         end;
+      end if;
+   end Check_Subprogram_Order;
+
+   ------------------------------
+   -- Check_Subtype_Conformant --
+   ------------------------------
+
+   procedure Check_Subtype_Conformant
+     (New_Id  : Entity_Id;
+      Old_Id  : Entity_Id;
+      Err_Loc : Node_Id := Empty)
+   is
+      Result : Boolean;
+
+   begin
+      Check_Conformance
+        (New_Id, Old_Id, Subtype_Conformant, True, Result, Err_Loc);
+   end Check_Subtype_Conformant;
+
+   ---------------------------
+   -- Check_Type_Conformant --
+   ---------------------------
+
+   procedure Check_Type_Conformant
+     (New_Id  : Entity_Id;
+      Old_Id  : Entity_Id;
+      Err_Loc : Node_Id := Empty)
+   is
+      Result : Boolean;
+
+   begin
+      Check_Conformance
+        (New_Id, Old_Id, Type_Conformant, True, Result, Err_Loc);
+   end Check_Type_Conformant;
+
+   ----------------------
+   -- Conforming_Types --
+   ----------------------
+
+   function Conforming_Types
+     (T1       : Entity_Id;
+      T2       : Entity_Id;
+      Ctype    : Conformance_Type;
+      Get_Inst : Boolean := False)
+      return     Boolean
+   is
+      Type_1 : Entity_Id := T1;
+      Type_2 : Entity_Id := T2;
+
+      function Base_Types_Match (T1, T2 : Entity_Id) return Boolean;
+      --  If neither T1 nor T2 are generic actual types, then verify
+      --  that the base types are equal. Otherwise T1 and T2 must be
+      --  on the same subtype chain. The whole purpose of this procedure
+      --  is to prevent spurious ambiguities in an instantiation that may
+      --  arise if two distinct generic types are instantiated with the
+      --  same actual.
+
+      ----------------------
+      -- Base_Types_Match --
+      ----------------------
+
+      function Base_Types_Match (T1, T2 : Entity_Id) return Boolean is
+      begin
+         if T1 = T2 then
+            return True;
+
+         elsif Base_Type (T1) = Base_Type (T2) then
+
+            --  The following is too permissive. A more precise test must
+            --  check that the generic actual is an ancestor subtype of the
+            --  other ???.
+
+            return not Is_Generic_Actual_Type (T1)
+              or else not Is_Generic_Actual_Type (T2);
+
+         else
+            return False;
+         end if;
+      end Base_Types_Match;
+
+   begin
+      --  The context is an instance association for a formal
+      --  access-to-subprogram type; the formal parameter types
+      --  require mapping because they may denote other formal
+      --  parameters of the generic unit.
+
+      if Get_Inst then
+         Type_1 := Get_Instance_Of (T1);
+         Type_2 := Get_Instance_Of (T2);
+      end if;
+
+      --  First see if base types match
+
+      if Base_Types_Match (Type_1, Type_2) then
+         return Ctype <= Mode_Conformant
+           or else Subtypes_Statically_Match (Type_1, Type_2);
+
+      elsif Is_Incomplete_Or_Private_Type (Type_1)
+        and then Present (Full_View (Type_1))
+        and then Base_Types_Match (Full_View (Type_1), Type_2)
+      then
+         return Ctype <= Mode_Conformant
+           or else Subtypes_Statically_Match (Full_View (Type_1), Type_2);
+
+      elsif Ekind (Type_2) = E_Incomplete_Type
+        and then Present (Full_View (Type_2))
+        and then Base_Types_Match (Type_1, Full_View (Type_2))
+      then
+         return Ctype <= Mode_Conformant
+           or else Subtypes_Statically_Match (Type_1, Full_View (Type_2));
+      end if;
+
+      --  Test anonymous access type case. For this case, static subtype
+      --  matching is required for mode conformance (RM 6.3.1(15))
+
+      if Ekind (Type_1) = E_Anonymous_Access_Type
+        and then Ekind (Type_2) = E_Anonymous_Access_Type
+      then
+         declare
+            Desig_1 : Entity_Id;
+            Desig_2 : Entity_Id;
+
+         begin
+            Desig_1 := Directly_Designated_Type (Type_1);
+
+            --  An access parameter can designate an incomplete type.
+
+            if Ekind (Desig_1) = E_Incomplete_Type
+              and then Present (Full_View (Desig_1))
+            then
+               Desig_1 := Full_View (Desig_1);
+            end if;
+
+            Desig_2 := Directly_Designated_Type (Type_2);
+
+            if Ekind (Desig_2) = E_Incomplete_Type
+              and then Present (Full_View (Desig_2))
+            then
+               Desig_2 := Full_View (Desig_2);
+            end if;
+
+            --  The context is an instance association for a formal
+            --  access-to-subprogram type; formal access parameter
+            --  designated types require mapping because they may
+            --  denote other formal parameters of the generic unit.
+
+            if Get_Inst then
+               Desig_1 := Get_Instance_Of (Desig_1);
+               Desig_2 := Get_Instance_Of (Desig_2);
+            end if;
+
+            --  It is possible for a Class_Wide_Type to be introduced for
+            --  an incomplete type, in which case there is a separate class_
+            --  wide type for the full view. The types conform if their
+            --  Etypes conform, i.e. one may be the full view of the other.
+            --  This can only happen in the context of an access parameter,
+            --  other uses of an incomplete Class_Wide_Type are illegal.
+
+            if Ekind (Desig_1) = E_Class_Wide_Type
+              and then Ekind (Desig_2) = E_Class_Wide_Type
+            then
+               return
+                 Conforming_Types (Etype (Desig_1), Etype (Desig_2), Ctype);
+            else
+               return Base_Type (Desig_1) = Base_Type (Desig_2)
+                and then (Ctype = Type_Conformant
+                          or else
+                        Subtypes_Statically_Match (Desig_1, Desig_2));
+            end if;
+         end;
+
+      --  Otherwise definitely no match
+
+      else
+         return False;
+      end if;
+
+   end Conforming_Types;
+
+   --------------------------
+   -- Create_Extra_Formals --
+   --------------------------
+
+   procedure Create_Extra_Formals (E : Entity_Id) is
+      Formal      : Entity_Id;
+      Last_Formal : Entity_Id;
+      Last_Extra  : Entity_Id;
+      Formal_Type : Entity_Id;
+      P_Formal    : Entity_Id := Empty;
+
+      function Add_Extra_Formal (Typ : Entity_Id) return Entity_Id;
+      --  Add an extra formal, associated with the current Formal. The
+      --  extra formal is added to the list of extra formals, and also
+      --  returned as the result. These formals are always of mode IN.
+
+      function Add_Extra_Formal (Typ : Entity_Id) return Entity_Id is
+         EF : constant Entity_Id :=
+                Make_Defining_Identifier (Sloc (Formal),
+                  Chars => New_External_Name (Chars (Formal), 'F'));
+
+      begin
+         --  We never generate extra formals if expansion is not active
+         --  because we don't need them unless we are generating code.
+
+         if not Expander_Active then
+            return Empty;
+         end if;
+
+         --  A little optimization. Never generate an extra formal for
+         --  the _init operand of an initialization procedure, since it
+         --  could never be used.
+
+         if Chars (Formal) = Name_uInit then
+            return Empty;
+         end if;
+
+         Set_Ekind           (EF, E_In_Parameter);
+         Set_Actual_Subtype  (EF, Typ);
+         Set_Etype           (EF, Typ);
+         Set_Scope           (EF, Scope (Formal));
+         Set_Mechanism       (EF, Default_Mechanism);
+         Set_Formal_Validity (EF);
+
+         Set_Extra_Formal (Last_Extra, EF);
+         Last_Extra := EF;
+         return EF;
+      end Add_Extra_Formal;
+
+   --  Start of processing for Create_Extra_Formals
+
+   begin
+      --  If this is a derived subprogram then the subtypes of the
+      --  parent subprogram's formal parameters will be used to
+      --  to determine the need for extra formals.
+
+      if Is_Overloadable (E) and then Present (Alias (E)) then
+         P_Formal := First_Formal (Alias (E));
+      end if;
+
+      Last_Extra := Empty;
+      Formal := First_Formal (E);
+      while Present (Formal) loop
+         Last_Extra := Formal;
+         Next_Formal (Formal);
+      end loop;
+
+      --  If Extra_formals where already created, don't do it again
+      --  This situation may arise for subprogram types created as part
+      --  of dispatching calls (see Expand_Dispatch_Call)
+
+      if Present (Last_Extra) and then
+        Present (Extra_Formal (Last_Extra))
+      then
+         return;
+      end if;
+
+      Formal := First_Formal (E);
+
+      while Present (Formal) loop
+
+         --  Create extra formal for supporting the attribute 'Constrained.
+         --  The case of a private type view without discriminants also
+         --  requires the extra formal if the underlying type has defaulted
+         --  discriminants.
+
+         if Ekind (Formal) /= E_In_Parameter then
+            if Present (P_Formal) then
+               Formal_Type := Etype (P_Formal);
+            else
+               Formal_Type := Etype (Formal);
+            end if;
+
+            if not Has_Discriminants (Formal_Type)
+              and then Ekind (Formal_Type) in Private_Kind
+              and then Present (Underlying_Type (Formal_Type))
+            then
+               Formal_Type := Underlying_Type (Formal_Type);
+            end if;
+
+            if Has_Discriminants (Formal_Type)
+              and then
+                ((not Is_Constrained (Formal_Type)
+                    and then not Is_Indefinite_Subtype (Formal_Type))
+                  or else Present (Extra_Formal (Formal)))
+            then
+               Set_Extra_Constrained
+                 (Formal, Add_Extra_Formal (Standard_Boolean));
+            end if;
+         end if;
+
+         --  Create extra formal for supporting accessibility checking
+
+         --  This is suppressed if we specifically suppress accessibility
+         --  checks for either the subprogram, or the package in which it
+         --  resides. However, we do not suppress it simply if the scope
+         --  has accessibility checks suppressed, since this could cause
+         --  trouble when clients are compiled with a different suppression
+         --  setting. The explicit checks are safe from this point of view.
+
+         if Ekind (Etype (Formal)) = E_Anonymous_Access_Type
+           and then not
+             (Suppress_Accessibility_Checks (E)
+               or else
+              Suppress_Accessibility_Checks (Scope (E)))
+           and then
+             (not Present (P_Formal)
+               or else Present (Extra_Accessibility (P_Formal)))
+         then
+            --  Temporary kludge: for now we avoid creating the extra
+            --  formal for access parameters of protected operations
+            --  because of problem with the case of internal protected
+            --  calls. ???
+
+            if Nkind (Parent (Parent (Parent (E)))) /= N_Protected_Definition
+              and then Nkind (Parent (Parent (Parent (E)))) /= N_Protected_Body
+            then
+               Set_Extra_Accessibility
+                 (Formal, Add_Extra_Formal (Standard_Natural));
+            end if;
+         end if;
+
+         if Present (P_Formal) then
+            Next_Formal (P_Formal);
+         end if;
+
+         Last_Formal := Formal;
+         Next_Formal (Formal);
+      end loop;
+   end Create_Extra_Formals;
+
+   -----------------------------
+   -- Enter_Overloaded_Entity --
+   -----------------------------
+
+   procedure Enter_Overloaded_Entity (S : Entity_Id) is
+      E   : Entity_Id := Current_Entity_In_Scope (S);
+      C_E : Entity_Id := Current_Entity (S);
+
+   begin
+      if Present (E) then
+         Set_Has_Homonym (E);
+         Set_Has_Homonym (S);
+      end if;
+
+      Set_Is_Immediately_Visible (S);
+      Set_Scope (S, Current_Scope);
+
+      --  Chain new entity if front of homonym in current scope, so that
+      --  homonyms are contiguous.
+
+      if Present (E)
+        and then E /= C_E
+      then
+         while Homonym (C_E) /= E loop
+            C_E := Homonym (C_E);
+         end loop;
+
+         Set_Homonym (C_E, S);
+
+      else
+         E := C_E;
+         Set_Current_Entity (S);
+      end if;
+
+      Set_Homonym (S, E);
+
+      Append_Entity (S, Current_Scope);
+      Set_Public_Status (S);
+
+      if Debug_Flag_E then
+         Write_Str ("New overloaded entity chain: ");
+         Write_Name (Chars (S));
+         E := S;
+
+         while Present (E) loop
+            Write_Str (" "); Write_Int (Int (E));
+            E := Homonym (E);
+         end loop;
+
+         Write_Eol;
+      end if;
+
+      --  Generate warning for hiding
+
+      if Warn_On_Hiding
+        and then Comes_From_Source (S)
+        and then In_Extended_Main_Source_Unit (S)
+      then
+         E := S;
+         loop
+            E := Homonym (E);
+            exit when No (E);
+
+            --  Warn unless genuine overloading
+
+            if (not Is_Overloadable (E))
+              or else Subtype_Conformant (E, S)
+            then
+               Error_Msg_Sloc := Sloc (E);
+               Error_Msg_N ("declaration of & hides one#?", S);
+            end if;
+         end loop;
+      end if;
+   end Enter_Overloaded_Entity;
+
+   -----------------------------
+   -- Find_Corresponding_Spec --
+   -----------------------------
+
+   function Find_Corresponding_Spec (N : Node_Id) return Entity_Id is
+      Spec       : constant Node_Id   := Specification (N);
+      Designator : constant Entity_Id := Defining_Entity (Spec);
+
+      E : Entity_Id;
+
+   begin
+      E := Current_Entity (Designator);
+
+      while Present (E) loop
+
+         --  We are looking for a matching spec. It must have the same scope,
+         --  and the same name, and either be type conformant, or be the case
+         --  of a library procedure spec and its body (which belong to one
+         --  another regardless of whether they are type conformant or not).
+
+         if Scope (E) = Current_Scope then
+            if (Current_Scope = Standard_Standard
+                  or else (Ekind (E) = Ekind (Designator)
+                and then
+                  Type_Conformant (E, Designator)))
+            then
+               --  Within an instantiation, we know that spec and body are
+               --  subtype conformant, because they were subtype conformant
+               --  in the generic. We choose the subtype-conformant entity
+               --  here as well, to resolve spurious ambiguities in the
+               --  instance that were not present in the generic (i.e. when
+               --  two different types are given the same actual). If we are
+               --  looking for a spec to match a body, full conformance is
+               --  expected.
+
+               if In_Instance then
+                  Set_Convention (Designator, Convention (E));
+
+                  if Nkind (N) = N_Subprogram_Body
+                    and then Present (Homonym (E))
+                    and then not Fully_Conformant (E, Designator)
+                  then
+                     goto Next_Entity;
+
+                  elsif not Subtype_Conformant (E, Designator) then
+                     goto Next_Entity;
+                  end if;
+               end if;
+
+               if not Has_Completion (E) then
+
+                  if Nkind (N) /= N_Subprogram_Body_Stub then
+                     Set_Corresponding_Spec (N, E);
+                  end if;
+
+                  Set_Has_Completion (E);
+                  return E;
+
+               elsif Nkind (Parent (N)) = N_Subunit then
+
+                  --  If this is the proper body of a subunit, the completion
+                  --  flag is set when analyzing the stub.
+
+                  return E;
+
+               --  If body already exists, this is an error unless the
+               --  previous declaration is the implicit declaration of
+               --  a derived subprogram, or this is a spurious overloading
+               --  in an instance.
+
+               elsif No (Alias (E))
+                 and then not Is_Intrinsic_Subprogram (E)
+                 and then not In_Instance
+               then
+                  Error_Msg_Sloc := Sloc (E);
+                  Error_Msg_NE ("duplicate body for & declared#", N, E);
+               end if;
+
+            elsif Is_Child_Unit (E)
+              and then
+                Nkind (Unit_Declaration_Node (Designator)) = N_Subprogram_Body
+              and then
+                Nkind (Parent (Unit_Declaration_Node (Designator)))
+                  = N_Compilation_Unit
+            then
+
+               --  Child units cannot be overloaded, so a conformance mismatch
+               --  between body and a previous spec is an error.
+
+               Error_Msg_N
+                 ("body of child unit does not match previous declaration", N);
+            end if;
+         end if;
+
+         <<Next_Entity>>
+            E := Homonym (E);
+      end loop;
+
+      --  On exit, we know that no previous declaration of subprogram exists
+
+      return Empty;
+   end Find_Corresponding_Spec;
+
+   ----------------------
+   -- Fully_Conformant --
+   ----------------------
+
+   function Fully_Conformant (New_Id, Old_Id : Entity_Id) return Boolean is
+      Result : Boolean;
+
+   begin
+      Check_Conformance (New_Id, Old_Id, Fully_Conformant, False, Result);
+      return Result;
+   end Fully_Conformant;
+
+   ----------------------------------
+   -- Fully_Conformant_Expressions --
+   ----------------------------------
+
+   function Fully_Conformant_Expressions
+     (Given_E1 : Node_Id;
+      Given_E2 : Node_Id)
+      return     Boolean
+   is
+      E1 : constant Node_Id := Original_Node (Given_E1);
+      E2 : constant Node_Id := Original_Node (Given_E2);
+      --  We always test conformance on original nodes, since it is possible
+      --  for analysis and/or expansion to make things look as though they
+      --  conform when they do not, e.g. by converting 1+2 into 3.
+
+      function FCE (Given_E1, Given_E2 : Node_Id) return Boolean
+        renames Fully_Conformant_Expressions;
+
+      function FCL (L1, L2 : List_Id) return Boolean;
+      --  Compare elements of two lists for conformance. Elements have to
+      --  be conformant, and actuals inserted as default parameters do not
+      --  match explicit actuals with the same value.
+
+      function FCO (Op_Node, Call_Node : Node_Id) return Boolean;
+      --  Compare an operator node with a function call.
+
+      ---------
+      -- FCL --
+      ---------
+
+      function FCL (L1, L2 : List_Id) return Boolean is
+         N1, N2 : Node_Id;
+
+      begin
+         if L1 = No_List then
+            N1 := Empty;
+         else
+            N1 := First (L1);
+         end if;
+
+         if L2 = No_List then
+            N2 := Empty;
+         else
+            N2 := First (L2);
+         end if;
+
+         --  Compare two lists, skipping rewrite insertions (we want to
+         --  compare the original trees, not the expanded versions!)
+
+         loop
+            if Is_Rewrite_Insertion (N1) then
+               Next (N1);
+            elsif Is_Rewrite_Insertion (N2) then
+               Next (N2);
+            elsif No (N1) then
+               return No (N2);
+            elsif No (N2) then
+               return False;
+            elsif not FCE (N1, N2) then
+               return False;
+            else
+               Next (N1);
+               Next (N2);
+            end if;
+         end loop;
+      end FCL;
+
+      ---------
+      -- FCO --
+      ---------
+
+      function FCO (Op_Node, Call_Node : Node_Id) return Boolean is
+         Actuals : constant List_Id := Parameter_Associations (Call_Node);
+         Act     : Node_Id;
+
+      begin
+         if No (Actuals)
+            or else Entity (Op_Node) /= Entity (Name (Call_Node))
+         then
+            return False;
+
+         else
+            Act := First (Actuals);
+
+            if Nkind (Op_Node) in N_Binary_Op then
+
+               if not FCE (Left_Opnd (Op_Node), Act) then
+                  return False;
+               end if;
+
+               Next (Act);
+            end if;
+
+            return Present (Act)
+              and then FCE (Right_Opnd (Op_Node), Act)
+              and then No (Next (Act));
+         end if;
+      end FCO;
+
+   --  Start of processing for Fully_Conformant_Expressions
+
+   begin
+      --  Non-conformant if paren count does not match. Note: if some idiot
+      --  complains that we don't do this right for more than 3 levels of
+      --  parentheses, they will be treated with the respect they deserve :-)
+
+      if Paren_Count (E1) /= Paren_Count (E2) then
+         return False;
+
+      --  If same entities are referenced, then they are conformant
+      --  even if they have different forms (RM 8.3.1(19-20)).
+
+      elsif Is_Entity_Name (E1) and then Is_Entity_Name (E2) then
+         if Present (Entity (E1)) then
+            return Entity (E1) = Entity (E2)
+              or else (Chars (Entity (E1)) = Chars (Entity (E2))
+                        and then Ekind (Entity (E1)) = E_Discriminant
+                        and then Ekind (Entity (E2)) = E_In_Parameter);
+
+         elsif Nkind (E1) = N_Expanded_Name
+           and then Nkind (E2) = N_Expanded_Name
+           and then Nkind (Selector_Name (E1)) = N_Character_Literal
+           and then Nkind (Selector_Name (E2)) = N_Character_Literal
+         then
+            return Chars (Selector_Name (E1)) = Chars (Selector_Name (E2));
+
+         else
+            --  Identifiers in component associations don't always have
+            --  entities, but their names must conform.
+
+            return Nkind  (E1) = N_Identifier
+              and then Nkind (E2) = N_Identifier
+              and then Chars (E1) = Chars (E2);
+         end if;
+
+      elsif Nkind (E1) = N_Character_Literal
+        and then Nkind (E2) = N_Expanded_Name
+      then
+         return Nkind (Selector_Name (E2)) = N_Character_Literal
+           and then Chars (E1) = Chars (Selector_Name (E2));
+
+      elsif Nkind (E2) = N_Character_Literal
+        and then Nkind (E1) = N_Expanded_Name
+      then
+         return Nkind (Selector_Name (E1)) = N_Character_Literal
+           and then Chars (E2) = Chars (Selector_Name (E1));
+
+      elsif Nkind (E1) in N_Op
+        and then Nkind (E2) = N_Function_Call
+      then
+         return FCO (E1, E2);
+
+      elsif Nkind (E2) in N_Op
+        and then Nkind (E1) = N_Function_Call
+      then
+         return FCO (E2, E1);
+
+      --  Otherwise we must have the same syntactic entity
+
+      elsif Nkind (E1) /= Nkind (E2) then
+         return False;
+
+      --  At this point, we specialize by node type
+
+      else
+         case Nkind (E1) is
+
+            when N_Aggregate =>
+               return
+                 FCL (Expressions (E1), Expressions (E2))
+                   and then FCL (Component_Associations (E1),
+                                 Component_Associations (E2));
+
+            when N_Allocator =>
+               if Nkind (Expression (E1)) = N_Qualified_Expression
+                    or else
+                  Nkind (Expression (E2)) = N_Qualified_Expression
+               then
+                  return FCE (Expression (E1), Expression (E2));
+
+               --  Check that the subtype marks and any constraints
+               --  are conformant
+
+               else
+                  declare
+                     Indic1 : constant Node_Id := Expression (E1);
+                     Indic2 : constant Node_Id := Expression (E2);
+                     Elt1   : Node_Id;
+                     Elt2   : Node_Id;
+
+                  begin
+                     if Nkind (Indic1) /= N_Subtype_Indication then
+                        return
+                          Nkind (Indic2) /= N_Subtype_Indication
+                            and then Entity (Indic1) = Entity (Indic2);
+
+                     elsif Nkind (Indic2) /= N_Subtype_Indication then
+                        return
+                          Nkind (Indic1) /= N_Subtype_Indication
+                            and then Entity (Indic1) = Entity (Indic2);
+
+                     else
+                        if Entity (Subtype_Mark (Indic1)) /=
+                          Entity (Subtype_Mark (Indic2))
+                        then
+                           return False;
+                        end if;
+
+                        Elt1 := First (Constraints (Constraint (Indic1)));
+                        Elt2 := First (Constraints (Constraint (Indic2)));
+
+                        while Present (Elt1) and then Present (Elt2) loop
+                           if not FCE (Elt1, Elt2) then
+                              return False;
+                           end if;
+
+                           Next (Elt1);
+                           Next (Elt2);
+                        end loop;
+
+                        return True;
+                     end if;
+                  end;
+               end if;
+
+            when N_Attribute_Reference =>
+               return
+                 Attribute_Name (E1) = Attribute_Name (E2)
+                   and then FCL (Expressions (E1), Expressions (E2));
+
+            when N_Binary_Op =>
+               return
+                 Entity (E1) = Entity (E2)
+                   and then FCE (Left_Opnd  (E1), Left_Opnd  (E2))
+                   and then FCE (Right_Opnd (E1), Right_Opnd (E2));
+
+            when N_And_Then | N_Or_Else | N_In | N_Not_In =>
+               return
+                 FCE (Left_Opnd  (E1), Left_Opnd  (E2))
+                   and then
+                 FCE (Right_Opnd (E1), Right_Opnd (E2));
+
+            when N_Character_Literal =>
+               return
+                 Char_Literal_Value (E1) = Char_Literal_Value (E2);
+
+            when N_Component_Association =>
+               return
+                 FCL (Choices (E1), Choices (E2))
+                   and then FCE (Expression (E1), Expression (E2));
+
+            when N_Conditional_Expression =>
+               return
+                 FCL (Expressions (E1), Expressions (E2));
+
+            when N_Explicit_Dereference =>
+               return
+                 FCE (Prefix (E1), Prefix (E2));
+
+            when N_Extension_Aggregate =>
+               return
+                 FCL (Expressions (E1), Expressions (E2))
+                   and then Null_Record_Present (E1) =
+                            Null_Record_Present (E2)
+                   and then FCL (Component_Associations (E1),
+                               Component_Associations (E2));
+
+            when N_Function_Call =>
+               return
+                 FCE (Name (E1), Name (E2))
+                   and then FCL (Parameter_Associations (E1),
+                                 Parameter_Associations (E2));
+
+            when N_Indexed_Component =>
+               return
+                 FCE (Prefix (E1), Prefix (E2))
+                   and then FCL (Expressions (E1), Expressions (E2));
+
+            when N_Integer_Literal =>
+               return (Intval (E1) = Intval (E2));
+
+            when N_Null =>
+               return True;
+
+            when N_Operator_Symbol =>
+               return
+                 Chars (E1) = Chars (E2);
+
+            when N_Others_Choice =>
+               return True;
+
+            when N_Parameter_Association =>
+               return
+
+                 Chars (Selector_Name (E1))  = Chars (Selector_Name (E2))
+                   and then FCE (Explicit_Actual_Parameter (E1),
+                                 Explicit_Actual_Parameter (E2));
+
+            when N_Qualified_Expression =>
+               return
+                 FCE (Subtype_Mark (E1), Subtype_Mark (E2))
+                   and then FCE (Expression (E1), Expression (E2));
+
+            when N_Range =>
+               return
+                 FCE (Low_Bound (E1), Low_Bound (E2))
+                   and then FCE (High_Bound (E1), High_Bound (E2));
+
+            when N_Real_Literal =>
+               return (Realval (E1) = Realval (E2));
+
+            when N_Selected_Component =>
+               return
+                 FCE (Prefix (E1), Prefix (E2))
+                   and then FCE (Selector_Name (E1), Selector_Name (E2));
+
+            when N_Slice =>
+               return
+                 FCE (Prefix (E1), Prefix (E2))
+                   and then FCE (Discrete_Range (E1), Discrete_Range (E2));
+
+            when N_String_Literal =>
+               declare
+                  S1 : constant String_Id := Strval (E1);
+                  S2 : constant String_Id := Strval (E2);
+                  L1 : constant Nat       := String_Length (S1);
+                  L2 : constant Nat       := String_Length (S2);
+
+               begin
+                  if L1 /= L2 then
+                     return False;
+
+                  else
+                     for J in 1 .. L1 loop
+                        if Get_String_Char (S1, J) /=
+                           Get_String_Char (S2, J)
+                        then
+                           return False;
+                        end if;
+                     end loop;
+
+                     return True;
+                  end if;
+               end;
+
+            when N_Type_Conversion =>
+               return
+                 FCE (Subtype_Mark (E1), Subtype_Mark (E2))
+                   and then FCE (Expression (E1), Expression (E2));
+
+            when N_Unary_Op =>
+               return
+                 Entity (E1) = Entity (E2)
+                   and then FCE (Right_Opnd (E1), Right_Opnd (E2));
+
+            when N_Unchecked_Type_Conversion =>
+               return
+                 FCE (Subtype_Mark (E1), Subtype_Mark (E2))
+                   and then FCE (Expression (E1), Expression (E2));
+
+            --  All other node types cannot appear in this context. Strictly
+            --  we should raise a fatal internal error. Instead we just ignore
+            --  the nodes. This means that if anyone makes a mistake in the
+            --  expander and mucks an expression tree irretrievably, the
+            --  result will be a failure to detect a (probably very obscure)
+            --  case of non-conformance, which is better than bombing on some
+            --  case where two expressions do in fact conform.
+
+            when others =>
+               return True;
+
+         end case;
+      end if;
+   end Fully_Conformant_Expressions;
+
+   --------------------
+   -- Install_Entity --
+   --------------------
+
+   procedure Install_Entity (E : Entity_Id) is
+      Prev : constant Entity_Id := Current_Entity (E);
+
+   begin
+      Set_Is_Immediately_Visible (E);
+      Set_Current_Entity (E);
+      Set_Homonym (E, Prev);
+   end Install_Entity;
+
+   ---------------------
+   -- Install_Formals --
+   ---------------------
+
+   procedure Install_Formals (Id : Entity_Id) is
+      F : Entity_Id;
+
+   begin
+      F := First_Formal (Id);
+
+      while Present (F) loop
+         Install_Entity (F);
+         Next_Formal (F);
+      end loop;
+   end Install_Formals;
+
+   ---------------------------------
+   -- Is_Non_Overriding_Operation --
+   ---------------------------------
+
+   function Is_Non_Overriding_Operation
+     (Prev_E : Entity_Id;
+      New_E  : Entity_Id)
+      return Boolean
+   is
+      Formal : Entity_Id;
+      F_Typ  : Entity_Id;
+      G_Typ  : Entity_Id := Empty;
+
+      function Get_Generic_Parent_Type (F_Typ : Entity_Id) return Entity_Id;
+      --  If F_Type is a derived type associated with a generic actual
+      --  subtype, then return its Generic_Parent_Type attribute, else
+      --  return Empty.
+
+      function Types_Correspond
+        (P_Type : Entity_Id;
+         N_Type : Entity_Id)
+         return   Boolean;
+      --  Returns true if and only if the types (or designated types
+      --  in the case of anonymous access types) are the same or N_Type
+      --  is derived directly or indirectly from P_Type.
+
+      -----------------------------
+      -- Get_Generic_Parent_Type --
+      -----------------------------
+
+      function Get_Generic_Parent_Type (F_Typ : Entity_Id) return Entity_Id is
+         G_Typ : Entity_Id;
+         Indic : Node_Id;
+
+      begin
+         if Is_Derived_Type (F_Typ)
+           and then Nkind (Parent (F_Typ)) = N_Full_Type_Declaration
+         then
+            --  The tree must be traversed to determine the parent
+            --  subtype in the generic unit, which unfortunately isn't
+            --  always available via semantic attributes. ???
+            --  (Note: The use of Original_Node is needed for cases
+            --  where a full derived type has been rewritten.)
+
+            Indic := Subtype_Indication
+                       (Type_Definition (Original_Node (Parent (F_Typ))));
+
+            if Nkind (Indic) = N_Subtype_Indication then
+               G_Typ := Entity (Subtype_Mark (Indic));
+            else
+               G_Typ := Entity (Indic);
+            end if;
+
+            if Nkind (Parent (G_Typ)) = N_Subtype_Declaration
+              and then Present (Generic_Parent_Type (Parent (G_Typ)))
+            then
+               return Generic_Parent_Type (Parent (G_Typ));
+            end if;
+         end if;
+
+         return Empty;
+      end Get_Generic_Parent_Type;
+
+      ----------------------
+      -- Types_Correspond --
+      ----------------------
+
+      function Types_Correspond
+        (P_Type : Entity_Id;
+         N_Type : Entity_Id)
+         return   Boolean
+      is
+         Prev_Type : Entity_Id := Base_Type (P_Type);
+         New_Type  : Entity_Id := Base_Type (N_Type);
+
+      begin
+         if Ekind (Prev_Type) = E_Anonymous_Access_Type then
+            Prev_Type := Designated_Type (Prev_Type);
+         end if;
+
+         if Ekind (New_Type) = E_Anonymous_Access_Type then
+            New_Type := Designated_Type (New_Type);
+         end if;
+
+         if Prev_Type = New_Type then
+            return True;
+
+         elsif not Is_Class_Wide_Type (New_Type) then
+            while Etype (New_Type) /= New_Type loop
+               New_Type := Etype (New_Type);
+               if New_Type = Prev_Type then
+                  return True;
+               end if;
+            end loop;
+         end if;
+         return False;
+      end Types_Correspond;
+
+   --  Start of processing for Is_Non_Overriding_Operation
+
+   begin
+      --  In the case where both operations are implicit derived
+      --  subprograms then neither overrides the other. This can
+      --  only occur in certain obscure cases (e.g., derivation
+      --  from homographs created in a generic instantiation).
+
+      if Present (Alias (Prev_E)) and then Present (Alias (New_E)) then
+         return True;
+
+      elsif Ekind (Current_Scope) = E_Package
+        and then Is_Generic_Instance (Current_Scope)
+        and then In_Private_Part (Current_Scope)
+        and then Comes_From_Source (New_E)
+      then
+         --  We examine the formals and result subtype of the inherited
+         --  operation, to determine whether their type is derived from
+         --  (the instance of) a generic type.
+
+         Formal := First_Formal (Prev_E);
+
+         while Present (Formal) loop
+            F_Typ := Base_Type (Etype (Formal));
+
+            if Ekind (F_Typ) = E_Anonymous_Access_Type then
+               F_Typ := Designated_Type (F_Typ);
+            end if;
+
+            G_Typ := Get_Generic_Parent_Type (F_Typ);
+
+            Next_Formal (Formal);
+         end loop;
+
+         if not Present (G_Typ) and then Ekind (Prev_E) = E_Function then
+            G_Typ := Get_Generic_Parent_Type (Base_Type (Etype (Prev_E)));
+         end if;
+
+         if No (G_Typ) then
+            return False;
+         end if;
+
+         --  If the generic type is a private type, then the original
+         --  operation was not overriding in the generic, because there was
+         --  no primitive operation to override.
+
+         if Nkind (Parent (G_Typ)) = N_Formal_Type_Declaration
+           and then Nkind (Formal_Type_Definition (Parent (G_Typ))) =
+             N_Formal_Private_Type_Definition
+         then
+            return True;
+
+         --  The generic parent type is the ancestor of a formal derived
+         --  type declaration. We need to check whether it has a primitive
+         --  operation that should be overridden by New_E in the generic.
+
+         else
+            declare
+               P_Formal : Entity_Id;
+               N_Formal : Entity_Id;
+               P_Typ    : Entity_Id;
+               N_Typ    : Entity_Id;
+               P_Prim   : Entity_Id;
+               Prim_Elt : Elmt_Id := First_Elmt (Primitive_Operations (G_Typ));
+
+            begin
+               while Present (Prim_Elt) loop
+                  P_Prim := Node (Prim_Elt);
+                  if Chars (P_Prim) = Chars (New_E)
+                    and then Ekind (P_Prim) = Ekind (New_E)
+                  then
+                     P_Formal := First_Formal (P_Prim);
+                     N_Formal := First_Formal (New_E);
+                     while Present (P_Formal) and then Present (N_Formal) loop
+                        P_Typ := Etype (P_Formal);
+                        N_Typ := Etype (N_Formal);
+
+                        if not Types_Correspond (P_Typ, N_Typ) then
+                           exit;
+                        end if;
+
+                        Next_Entity (P_Formal);
+                        Next_Entity (N_Formal);
+                     end loop;
+
+                     --  Found a matching primitive operation belonging to
+                     --  the formal ancestor type, so the new subprogram
+                     --  is overriding.
+
+                     if not Present (P_Formal)
+                       and then not Present (N_Formal)
+                       and then (Ekind (New_E) /= E_Function
+                                  or else
+                                 Types_Correspond
+                                   (Etype (P_Prim), Etype (New_E)))
+                     then
+                        return False;
+                     end if;
+                  end if;
+
+                  Next_Elmt (Prim_Elt);
+               end loop;
+
+               --  If no match found, then the new subprogram does
+               --  not override in the generic (nor in the instance).
+
+               return True;
+            end;
+         end if;
+      else
+         return False;
+      end if;
+   end Is_Non_Overriding_Operation;
+
+   ------------------------------
+   -- Make_Inequality_Operator --
+   ------------------------------
+
+   --  S is the defining identifier of an equality operator. We build a
+   --  subprogram declaration with the right signature. This operation is
+   --  intrinsic, because it is always expanded as the negation of the
+   --  call to the equality function.
+
+   procedure Make_Inequality_Operator (S : Entity_Id) is
+      Loc     : constant Source_Ptr := Sloc (S);
+      Decl    : Node_Id;
+      Formals : List_Id;
+      Op_Name : Entity_Id;
+
+      A : Entity_Id;
+      B : Entity_Id;
+
+   begin
+      --  Check that equality was properly defined.
+
+      if  No (Next_Formal (First_Formal (S))) then
+         return;
+      end if;
+
+      A := Make_Defining_Identifier (Loc, Chars (First_Formal (S)));
+      B := Make_Defining_Identifier (Loc,
+             Chars (Next_Formal (First_Formal (S))));
+
+      Op_Name := Make_Defining_Operator_Symbol (Loc, Name_Op_Ne);
+
+      Formals := New_List (
+        Make_Parameter_Specification (Loc,
+          Defining_Identifier => A,
+          Parameter_Type =>
+            New_Reference_To (Etype (First_Formal (S)), Loc)),
+
+        Make_Parameter_Specification (Loc,
+          Defining_Identifier => B,
+          Parameter_Type =>
+            New_Reference_To (Etype (Next_Formal (First_Formal (S))), Loc)));
+
+      Decl :=
+        Make_Subprogram_Declaration (Loc,
+          Specification =>
+            Make_Function_Specification (Loc,
+              Defining_Unit_Name => Op_Name,
+              Parameter_Specifications => Formals,
+              Subtype_Mark => New_Reference_To (Standard_Boolean, Loc)));
+
+      --  Insert inequality right after equality if it is explicit or after
+      --  the derived type when implicit. These entities are created only
+      --  for visibility purposes, and eventually replaced in the course of
+      --  expansion, so they do not need to be attached to the tree and seen
+      --  by the back-end. Keeping them internal also avoids spurious freezing
+      --  problems. The parent field is set simply to make analysis safe.
+
+      if No (Alias (S)) then
+         Set_Parent (Decl, Parent (Unit_Declaration_Node (S)));
+      else
+         Set_Parent (Decl, Parent (Parent (Etype (First_Formal (S)))));
+      end if;
+
+      Mark_Rewrite_Insertion (Decl);
+      Set_Is_Intrinsic_Subprogram (Op_Name);
+      Analyze (Decl);
+      Set_Has_Completion (Op_Name);
+      Set_Corresponding_Equality (Op_Name, S);
+      Set_Is_Abstract (Op_Name, Is_Abstract (S));
+
+   end Make_Inequality_Operator;
+
+   ----------------------
+   -- May_Need_Actuals --
+   ----------------------
+
+   procedure May_Need_Actuals (Fun : Entity_Id) is
+      F : Entity_Id;
+      B : Boolean;
+
+   begin
+      F := First_Formal (Fun);
+      B := True;
+
+      while Present (F) loop
+         if No (Default_Value (F)) then
+            B := False;
+            exit;
+         end if;
+
+         Next_Formal (F);
+      end loop;
+
+      Set_Needs_No_Actuals (Fun, B);
+   end May_Need_Actuals;
+
+   ---------------------
+   -- Mode_Conformant --
+   ---------------------
+
+   function Mode_Conformant (New_Id, Old_Id : Entity_Id) return Boolean is
+      Result : Boolean;
+
+   begin
+      Check_Conformance (New_Id, Old_Id, Mode_Conformant, False, Result);
+      return Result;
+   end Mode_Conformant;
+
+   ---------------------------
+   -- New_Overloaded_Entity --
+   ---------------------------
+
+   procedure New_Overloaded_Entity
+     (S            : Entity_Id;
+      Derived_Type : Entity_Id := Empty)
+   is
+      E        : Entity_Id := Current_Entity_In_Scope (S);
+      Prev_Vis : Entity_Id := Empty;
+
+      function Is_Private_Declaration (E : Entity_Id) return Boolean;
+      --  Check that E is declared in the private part of the current package,
+      --  or in the package body, where it may hide a previous declaration.
+      --  We can' use In_Private_Part by itself because this flag is also
+      --  set when freezing entities, so we must examine the place of the
+      --  declaration in the tree, and recognize wrapper packages as well.
+
+      procedure Maybe_Primitive_Operation (Overriding : Boolean := False);
+      --  If the subprogram being analyzed is a primitive operation of
+      --  the type of one of its formals, set the corresponding flag.
+
+      ----------------------------
+      -- Is_Private_Declaration --
+      ----------------------------
+
+      function Is_Private_Declaration (E : Entity_Id) return Boolean is
+         Priv_Decls : List_Id;
+         Decl       : constant Node_Id := Unit_Declaration_Node (E);
+
+      begin
+         if Is_Package (Current_Scope)
+           and then In_Private_Part (Current_Scope)
+         then
+            Priv_Decls :=
+              Private_Declarations (
+                Specification (Unit_Declaration_Node (Current_Scope)));
+
+            return In_Package_Body (Current_Scope)
+              or else List_Containing (Decl) = Priv_Decls
+              or else (Nkind (Parent (Decl)) = N_Package_Specification
+                         and then not Is_Compilation_Unit (
+                           Defining_Entity (Parent (Decl)))
+                         and then List_Containing (Parent (Parent (Decl)))
+                           = Priv_Decls);
+         else
+            return False;
+         end if;
+      end Is_Private_Declaration;
+
+      -------------------------------
+      -- Maybe_Primitive_Operation --
+      -------------------------------
+
+      procedure Maybe_Primitive_Operation (Overriding : Boolean := False) is
+         Formal : Entity_Id;
+         F_Typ  : Entity_Id;
+
+         function Visible_Part_Type (T : Entity_Id) return Boolean;
+         --  Returns true if T is declared in the visible part of
+         --  the current package scope; otherwise returns false.
+         --  Assumes that T is declared in a package.
+
+         procedure Check_Private_Overriding (T : Entity_Id);
+         --  Checks that if a primitive abstract subprogram of a visible
+         --  abstract type is declared in a private part, then it must
+         --  override an abstract subprogram declared in the visible part.
+         --  Also checks that if a primitive function with a controlling
+         --  result is declared in a private part, then it must override
+         --  a function declared in the visible part.
+
+         ------------------------------
+         -- Check_Private_Overriding --
+         ------------------------------
+
+         procedure Check_Private_Overriding (T : Entity_Id) is
+         begin
+            if Ekind (Current_Scope) = E_Package
+              and then In_Private_Part (Current_Scope)
+              and then Visible_Part_Type (T)
+              and then not In_Instance
+            then
+               if Is_Abstract (T)
+                 and then Is_Abstract (S)
+                 and then (not Overriding or else not Is_Abstract (E))
+               then
+                  Error_Msg_N ("abstract subprograms must be visible "
+                                & "('R'M 3.9.3(10))!", S);
+
+               elsif Ekind (S) = E_Function
+                 and then Is_Tagged_Type (T)
+                 and then T = Base_Type (Etype (S))
+                 and then not Overriding
+               then
+                  Error_Msg_N
+                    ("private function with tagged result must"
+                     & " override visible-part function", S);
+                  Error_Msg_N
+                    ("\move subprogram to the visible part"
+                     & " ('R'M 3.9.3(10))", S);
+               end if;
+            end if;
+         end Check_Private_Overriding;
+
+         -----------------------
+         -- Visible_Part_Type --
+         -----------------------
+
+         function Visible_Part_Type (T : Entity_Id) return Boolean is
+            P : Node_Id := Unit_Declaration_Node (Scope (T));
+            N : Node_Id := First (Visible_Declarations (Specification (P)));
+
+         begin
+            --  If the entity is a private type, then it must be
+            --  declared in a visible part.
+
+            if Ekind (T) in Private_Kind then
+               return True;
+            end if;
+
+            --  Otherwise, we traverse the visible part looking for its
+            --  corresponding declaration. We cannot use the declaration
+            --  node directly because in the private part the entity of a
+            --  private type is the one in the full view, which does not
+            --  indicate that it is the completion of something visible.
+
+            while Present (N) loop
+               if Nkind (N) = N_Full_Type_Declaration
+                 and then Present (Defining_Identifier (N))
+                 and then T = Defining_Identifier (N)
+               then
+                  return True;
+
+               elsif (Nkind (N) = N_Private_Type_Declaration
+                       or else
+                      Nkind (N) = N_Private_Extension_Declaration)
+                 and then Present (Defining_Identifier (N))
+                 and then T = Full_View (Defining_Identifier (N))
+               then
+                  return True;
+               end if;
+
+               Next (N);
+            end loop;
+
+            return False;
+         end Visible_Part_Type;
+
+      --  Start of processing for Maybe_Primitive_Operation
+
+      begin
+         if not Comes_From_Source (S) then
+            null;
+
+         elsif (Ekind (Current_Scope) = E_Package
+                 and then not In_Package_Body (Current_Scope))
+           or else Overriding
+         then
+
+            if Ekind (S) = E_Function
+              and then Scope (Base_Type (Etype (S))) = Current_Scope
+            then
+               Set_Has_Primitive_Operations (Base_Type (Etype (S)));
+               Check_Private_Overriding (Base_Type (Etype (S)));
+            end if;
+
+            Formal := First_Formal (S);
+
+            while Present (Formal) loop
+               if Ekind (Etype (Formal)) = E_Anonymous_Access_Type then
+                  F_Typ := Designated_Type (Etype (Formal));
+               else
+                  F_Typ := Etype (Formal);
+               end if;
+
+               if Scope (Base_Type (F_Typ)) = Current_Scope then
+                  Set_Has_Primitive_Operations (Base_Type (F_Typ));
+                  Check_Private_Overriding (Base_Type (F_Typ));
+               end if;
+
+               Next_Formal (Formal);
+            end loop;
+
+         end if;
+      end Maybe_Primitive_Operation;
+
+   --  Start of processing for New_Overloaded_Entity
+
+   begin
+      if No (E) then
+         Enter_Overloaded_Entity (S);
+         Check_Dispatching_Operation (S, Empty);
+         Maybe_Primitive_Operation;
+
+      elsif not Is_Overloadable (E) then
+
+         --  Check for spurious conflict produced by a subprogram that has the
+         --  same name as that of the enclosing generic package. The conflict
+         --  occurs within an instance, between the subprogram and the renaming
+         --  declaration for the package. After the subprogram, the package
+         --  renaming declaration becomes hidden.
+
+         if Ekind (E) = E_Package
+           and then Present (Renamed_Object (E))
+           and then Renamed_Object (E) = Current_Scope
+           and then Nkind (Parent (Renamed_Object (E))) =
+                                                     N_Package_Specification
+           and then Present (Generic_Parent (Parent (Renamed_Object (E))))
+         then
+            Set_Is_Hidden (E);
+            Set_Is_Immediately_Visible (E, False);
+            Enter_Overloaded_Entity (S);
+            Set_Homonym (S, Homonym (E));
+            Check_Dispatching_Operation (S, Empty);
+
+         --  If the subprogram is implicit it is hidden by the previous
+         --  declaration. However if it is dispatching, it must appear in
+         --  the dispatch table anyway, because it can be dispatched to
+         --  even if it cannot be called directly.
+
+         elsif Present (Alias (S))
+           and then not Comes_From_Source (S)
+         then
+            Set_Scope (S, Current_Scope);
+
+            if Is_Dispatching_Operation (Alias (S)) then
+               Check_Dispatching_Operation (S, Empty);
+            end if;
+
+            return;
+
+         else
+            Error_Msg_Sloc := Sloc (E);
+            Error_Msg_N ("& conflicts with declaration#", S);
+
+            --  Useful additional warning.
+
+            if Is_Generic_Unit (E) then
+               Error_Msg_N ("\previous generic unit cannot be overloaded", S);
+            end if;
+
+            return;
+         end if;
+
+      else
+         --  E exists and is overloadable. Determine whether S is the body
+         --  of E, a new overloaded entity with a different signature, or
+         --  an error altogether.
+
+         while Present (E) loop
+            if Scope (E) /= Current_Scope then
+               null;
+
+            elsif Type_Conformant (E, S) then
+
+               --  If the old and new entities have the same profile and
+               --  one is not the body of the other, then this is an error,
+               --  unless one of them is implicitly declared.
+
+               --  There are some cases when both can be implicit, for example
+               --  when both a literal and a function that overrides it are
+               --  inherited in a derivation, or when an inhertited operation
+               --  of a tagged full type overrides the ineherited operation of
+               --  a private extension. Ada 83 had a special rule for the
+               --  the literal case. In Ada95, the later implicit operation
+               --  hides the former, and the literal is always the former.
+               --  In the odd case where both are derived operations declared
+               --  at the same point, both operations should be declared,
+               --  and in that case we bypass the following test and proceed
+               --  to the next part (this can only occur for certain obscure
+               --  cases involving homographs in instances and can't occur for
+               --  dispatching operations ???). Note that the following
+               --  condition is less than clear. For example, it's not at
+               --  all clear why there's a test for E_Entry here. ???
+
+               if Present (Alias (S))
+                 and then (No (Alias (E))
+                            or else Comes_From_Source (E)
+                            or else Is_Dispatching_Operation (E))
+                 and then
+                   (Ekind (E) = E_Entry
+                     or else Ekind (E) /= E_Enumeration_Literal)
+               then
+                  --  When an derived operation is overloaded it may be due
+                  --  to the fact that the full view of a private extension
+                  --  re-inherits. It has to be dealt with.
+
+                  if Is_Package (Current_Scope)
+                    and then In_Private_Part (Current_Scope)
+                  then
+                     Check_Operation_From_Private_View (S, E);
+                  end if;
+
+                  --  In any case the implicit operation remains hidden by
+                  --  the existing declaration.
+
+                  return;
+
+                  --  Within an instance, the renaming declarations for
+                  --  actual subprograms may become ambiguous, but they do
+                  --  not hide each other.
+
+               elsif Ekind (E) /= E_Entry
+                 and then not Comes_From_Source (E)
+                 and then not Is_Generic_Instance (E)
+                 and then (Present (Alias (E))
+                            or else Is_Intrinsic_Subprogram (E))
+                 and then (not In_Instance
+                            or else No (Parent (E))
+                            or else Nkind (Unit_Declaration_Node (E)) /=
+                               N_Subprogram_Renaming_Declaration)
+               then
+                  --  A subprogram child unit is not allowed to override
+                  --  an inherited subprogram (10.1.1(20)).
+
+                  if Is_Child_Unit (S) then
+                     Error_Msg_N
+                       ("child unit overrides inherited subprogram in parent",
+                        S);
+                     return;
+                  end if;
+
+                  if Is_Non_Overriding_Operation (E, S) then
+                     Enter_Overloaded_Entity (S);
+                     if not Present (Derived_Type)
+                       or else Is_Tagged_Type (Derived_Type)
+                     then
+                        Check_Dispatching_Operation (S, Empty);
+                     end if;
+
+                     return;
+                  end if;
+
+                  --  E is a derived operation or an internal operator which
+                  --  is being overridden. Remove E from further visibility.
+                  --  Furthermore, if E is a dispatching operation, it must be
+                  --  replaced in the list of primitive operations of its type
+                  --  (see Override_Dispatching_Operation).
+
+                  declare
+                     Prev : Entity_Id;
+
+                  begin
+                     Prev := First_Entity (Current_Scope);
+
+                     while Present (Prev)
+                       and then Next_Entity (Prev) /= E
+                     loop
+                        Next_Entity (Prev);
+                     end loop;
+
+                     --  It is possible for E to be in the current scope and
+                     --  yet not in the entity chain. This can only occur in a
+                     --  generic context where E is an implicit concatenation
+                     --  in the formal part, because in a generic body the
+                     --  entity chain starts with the formals.
+
+                     pragma Assert
+                       (Present (Prev) or else Chars (E) = Name_Op_Concat);
+
+                     --  E must be removed both from the entity_list of the
+                     --  current scope, and from the visibility chain
+
+                     if Debug_Flag_E then
+                        Write_Str ("Override implicit operation ");
+                        Write_Int (Int (E));
+                        Write_Eol;
+                     end if;
+
+                     --  If E is a predefined concatenation, it stands for four
+                     --  different operations. As a result, a single explicit
+                     --  declaration does not hide it. In a possible ambiguous
+                     --  situation, Disambiguate chooses the user-defined op,
+                     --  so it is correct to retain the previous internal one.
+
+                     if Chars (E) /= Name_Op_Concat
+                       or else Ekind (E) /= E_Operator
+                     then
+                        --  For nondispatching derived operations that are
+                        --  overridden by a subprogram declared in the private
+                        --  part of a package, we retain the derived subprogram
+                        --  but mark it as not immediately visible. If the
+                        --  derived operation was declared in the visible part
+                        --  then this ensures that it will still be visible
+                        --  outside the package with the proper signature
+                        --  (calls from outside must also be directed to this
+                        --  version rather than the overriding one, unlike the
+                        --  dispatching case). Calls from inside the package
+                        --  will still resolve to the overriding subprogram
+                        --  since the derived one is marked as not visible
+                        --  within the package.
+
+                        --  If the private operation is dispatching, we achieve
+                        --  the overriding by keeping the implicit operation
+                        --  but setting its alias to be the overring one. In
+                        --  this fashion the proper body is executed in all
+                        --  cases, but the original signature is used outside
+                        --  of the package.
+
+                        --  If the overriding is not in the private part, we
+                        --  remove the implicit operation altogether.
+
+                        if Is_Private_Declaration (S) then
+
+                           if not Is_Dispatching_Operation (E) then
+                              Set_Is_Immediately_Visible (E, False);
+                           else
+
+                              --  work done in Override_Dispatching_Operation.
+
+                              null;
+                           end if;
+                        else
+
+                           --  Find predecessor of E in Homonym chain.
+
+                           if E = Current_Entity (E) then
+                              Prev_Vis := Empty;
+                           else
+                              Prev_Vis := Current_Entity (E);
+                              while Homonym (Prev_Vis) /= E loop
+                                 Prev_Vis := Homonym (Prev_Vis);
+                              end loop;
+                           end if;
+
+                           if Prev_Vis /= Empty then
+
+                              --  Skip E in the visibility chain
+
+                              Set_Homonym (Prev_Vis, Homonym (E));
+
+                           else
+                              Set_Name_Entity_Id (Chars (E), Homonym (E));
+                           end if;
+
+                           Set_Next_Entity (Prev, Next_Entity (E));
+
+                           if No (Next_Entity (Prev)) then
+                              Set_Last_Entity (Current_Scope, Prev);
+                           end if;
+
+                        end if;
+                     end if;
+
+                     Enter_Overloaded_Entity (S);
+
+                     if Is_Dispatching_Operation (E) then
+                        --  An overriding dispatching subprogram inherits
+                        --  the convention of the overridden subprogram
+                        --  (by AI-117).
+
+                        Set_Convention (S, Convention (E));
+
+                        Check_Dispatching_Operation (S, E);
+                     else
+                        Check_Dispatching_Operation (S, Empty);
+                     end if;
+
+                     Maybe_Primitive_Operation (Overriding => True);
+                     goto Check_Inequality;
+                  end;
+
+               --  Apparent redeclarations in instances can occur when two
+               --  formal types get the same actual type. The subprograms in
+               --  in the instance are legal,  even if not callable from the
+               --  outside. Calls from within are disambiguated elsewhere.
+               --  For dispatching operations in the visible part, the usual
+               --  rules apply, and operations with the same profile are not
+               --  legal (B830001).
+
+               elsif (In_Instance_Visible_Part
+                       and then not Is_Dispatching_Operation (E))
+                 or else In_Instance_Not_Visible
+               then
+                  null;
+
+               --  Here we have a real error (identical profile)
+
+               else
+                  Error_Msg_Sloc := Sloc (E);
+
+                  --  Avoid cascaded errors if the entity appears in
+                  --  subsequent calls.
+
+                  Set_Scope (S, Current_Scope);
+
+                  Error_Msg_N ("& conflicts with declaration#", S);
+
+                  if Is_Generic_Instance (S)
+                    and then not Has_Completion (E)
+                  then
+                     Error_Msg_N
+                       ("\instantiation cannot provide body for it", S);
+                  end if;
+
+                  return;
+               end if;
+
+            else
+               null;
+            end if;
+
+            Prev_Vis := E;
+            E := Homonym (E);
+         end loop;
+
+         --  On exit, we know that S is a new entity
+
+         Enter_Overloaded_Entity (S);
+         Maybe_Primitive_Operation;
+
+         --  If S is a derived operation for an untagged type then
+         --  by definition it's not a dispatching operation (even
+         --  if the parent operation was dispatching), so we don't
+         --  call Check_Dispatching_Operation in that case.
+
+         if not Present (Derived_Type)
+           or else Is_Tagged_Type (Derived_Type)
+         then
+            Check_Dispatching_Operation (S, Empty);
+         end if;
+      end if;
+
+      --  If this is a  user-defined equality operator that is not
+      --  a derived subprogram, create the corresponding inequality.
+      --  If the operation is dispatching, the expansion is done
+      --  elsewhere,  and we do not create an explicit inequality
+      --  operation.
+
+      <<Check_Inequality>>
+         if Chars (S) = Name_Op_Eq
+           and then Etype (S) = Standard_Boolean
+           and then Present (Parent (S))
+           and then not Is_Dispatching_Operation (S)
+         then
+            Make_Inequality_Operator (S);
+         end if;
+
+   end New_Overloaded_Entity;
+
+   ---------------------
+   -- Process_Formals --
+   ---------------------
+
+   procedure Process_Formals
+     (S           : Entity_Id;
+      T           : List_Id;
+      Related_Nod : Node_Id)
+   is
+      Param_Spec  : Node_Id;
+      Formal      : Entity_Id;
+      Formal_Type : Entity_Id;
+      Default     : Node_Id;
+      Ptype       : Entity_Id;
+
+   begin
+      --  In order to prevent premature use of the formals in the same formal
+      --  part, the Ekind is left undefined until all default expressions are
+      --  analyzed. The Ekind is established in a separate loop at the end.
+
+      Param_Spec := First (T);
+
+      while Present (Param_Spec) loop
+
+         Formal := Defining_Identifier (Param_Spec);
+         Enter_Name (Formal);
+
+         --  Case of ordinary parameters
+
+         if Nkind (Parameter_Type (Param_Spec)) /= N_Access_Definition then
+            Find_Type (Parameter_Type (Param_Spec));
+            Ptype := Parameter_Type (Param_Spec);
+
+            if Ptype = Error then
+               goto Continue;
+            end if;
+
+            Formal_Type := Entity (Ptype);
+
+            if Ekind (Formal_Type) = E_Incomplete_Type
+              or else (Is_Class_Wide_Type (Formal_Type)
+                        and then Ekind (Root_Type (Formal_Type)) =
+                                                         E_Incomplete_Type)
+            then
+               if Nkind (Parent (T)) /= N_Access_Function_Definition
+                 and then Nkind (Parent (T)) /= N_Access_Procedure_Definition
+               then
+                  Error_Msg_N ("invalid use of incomplete type", Param_Spec);
+               end if;
+
+            elsif Ekind (Formal_Type) = E_Void then
+               Error_Msg_NE ("premature use of&",
+                 Parameter_Type (Param_Spec), Formal_Type);
+            end if;
+
+         --  An access formal type
+
+         else
+            Formal_Type :=
+              Access_Definition (Related_Nod, Parameter_Type (Param_Spec));
+         end if;
+
+         Set_Etype (Formal, Formal_Type);
+
+         Default :=  Expression (Param_Spec);
+
+         if Present (Default) then
+            if Out_Present (Param_Spec) then
+               Error_Msg_N
+                 ("default initialization only allowed for IN parameters",
+                  Param_Spec);
+            end if;
+
+            --  Do the special preanalysis of the expression (see section on
+            --  "Handling of Default Expressions" in the spec of package Sem).
+
+            Analyze_Default_Expression (Default, Formal_Type);
+
+            --  Check that the designated type of an access parameter's
+            --  default is not a class-wide type unless the parameter's
+            --  designated type is also class-wide.
+
+            if Ekind (Formal_Type) = E_Anonymous_Access_Type
+              and then Is_Class_Wide_Type (Designated_Type (Etype (Default)))
+              and then not Is_Class_Wide_Type (Designated_Type (Formal_Type))
+            then
+               Wrong_Type (Default, Formal_Type);
+            end if;
+         end if;
+
+      <<Continue>>
+         Next (Param_Spec);
+      end loop;
+
+      --  Now set the kind (mode) of each formal
+
+      Param_Spec := First (T);
+
+      while Present (Param_Spec) loop
+         Formal := Defining_Identifier (Param_Spec);
+         Set_Formal_Mode (Formal);
+
+         if Ekind (Formal) = E_In_Parameter then
+            Set_Default_Value (Formal, Expression (Param_Spec));
+
+            if Present (Expression (Param_Spec)) then
+               Default :=  Expression (Param_Spec);
+
+               if Is_Scalar_Type (Etype (Default)) then
+                  if Nkind
+                       (Parameter_Type (Param_Spec)) /= N_Access_Definition
+                  then
+                     Formal_Type := Entity (Parameter_Type (Param_Spec));
+
+                  else
+                     Formal_Type := Access_Definition
+                       (Related_Nod, Parameter_Type (Param_Spec));
+                  end if;
+
+                  Apply_Scalar_Range_Check (Default, Formal_Type);
+               end if;
+
+            end if;
+         end if;
+
+         Next (Param_Spec);
+      end loop;
+
+   end Process_Formals;
+
+   -------------------------
+   -- Set_Actual_Subtypes --
+   -------------------------
+
+   procedure Set_Actual_Subtypes (N : Node_Id; Subp : Entity_Id) is
+      Loc        : constant Source_Ptr := Sloc (N);
+      Decl       : Node_Id;
+      Formal     : Entity_Id;
+      T          : Entity_Id;
+      First_Stmt : Node_Id := Empty;
+      AS_Needed  : Boolean;
+
+   begin
+      Formal := First_Formal (Subp);
+      while Present (Formal) loop
+         T := Etype (Formal);
+
+         --  We never need an actual subtype for a constrained formal.
+
+         if Is_Constrained (T) then
+            AS_Needed := False;
+
+         --  If we have unknown discriminants, then we do not need an
+         --  actual subtype, or more accurately we cannot figure it out!
+         --  Note that all class-wide types have unknown discriminants.
+
+         elsif Has_Unknown_Discriminants (T) then
+            AS_Needed := False;
+
+         --  At this stage we have an unconstrained type that may need
+         --  an actual subtype. For sure the actual subtype is needed
+         --  if we have an unconstrained array type.
+
+         elsif Is_Array_Type (T) then
+            AS_Needed := True;
+
+         --  The only other case which needs an actual subtype is an
+         --  unconstrained record type which is an IN parameter (we
+         --  cannot generate actual subtypes for the OUT or IN OUT case,
+         --  since an assignment can change the discriminant values.
+         --  However we exclude the case of initialization procedures,
+         --  since discriminants are handled very specially in this context,
+         --  see the section entitled "Handling of Discriminants" in Einfo.
+         --  We also exclude the case of Discrim_SO_Functions (functions
+         --  used in front end layout mode for size/offset values), since
+         --  in such functions only discriminants are referenced, and not
+         --  only are such subtypes not needed, but they cannot always
+         --  be generated, because of order of elaboration issues.
+
+         elsif Is_Record_Type (T)
+           and then Ekind (Formal) = E_In_Parameter
+           and then Chars (Formal) /= Name_uInit
+           and then not Is_Discrim_SO_Function (Subp)
+         then
+            AS_Needed := True;
+
+         --  All other cases do not need an actual subtype
+
+         else
+            AS_Needed := False;
+         end if;
+
+         --  Generate actual subtypes for unconstrained arrays and
+         --  unconstrained discriminated records.
+
+         if AS_Needed then
+            Decl := Build_Actual_Subtype (T, Formal);
+
+            if Nkind (N) = N_Accept_Statement then
+               if Present (Handled_Statement_Sequence (N)) then
+                  First_Stmt :=
+                    First (Statements (Handled_Statement_Sequence (N)));
+                  Prepend (Decl, Statements (Handled_Statement_Sequence (N)));
+                  Mark_Rewrite_Insertion (Decl);
+               else
+                  --  If the accept statement has no body, there will be
+                  --  no reference to the actuals, so no need to compute
+                  --  actual subtypes.
+
+                  return;
+               end if;
+
+            else
+               Prepend (Decl, Declarations (N));
+               Mark_Rewrite_Insertion (Decl);
+            end if;
+
+            Analyze (Decl);
+
+            --  We need to freeze manually the generated type when it is
+            --  inserted anywhere else than in a declarative part.
+
+            if Present (First_Stmt) then
+               Insert_List_Before_And_Analyze (First_Stmt,
+                 Freeze_Entity (Defining_Identifier (Decl), Loc));
+            end if;
+
+            Set_Actual_Subtype (Formal, Defining_Identifier (Decl));
+         end if;
+
+         Next_Formal (Formal);
+      end loop;
+   end Set_Actual_Subtypes;
+
+   ---------------------
+   -- Set_Formal_Mode --
+   ---------------------
+
+   procedure Set_Formal_Mode (Formal_Id : Entity_Id) is
+      Spec : constant Node_Id := Parent (Formal_Id);
+
+   begin
+      --  Note: we set Is_Known_Valid for IN parameters and IN OUT parameters
+      --  since we ensure that corresponding actuals are always valid at the
+      --  point of the call.
+
+      if Out_Present (Spec) then
+
+         if Ekind (Scope (Formal_Id)) = E_Function
+           or else Ekind (Scope (Formal_Id)) = E_Generic_Function
+         then
+            Error_Msg_N ("functions can only have IN parameters", Spec);
+            Set_Ekind (Formal_Id, E_In_Parameter);
+
+         elsif In_Present (Spec) then
+            Set_Ekind (Formal_Id, E_In_Out_Parameter);
+
+         else
+            Set_Ekind (Formal_Id, E_Out_Parameter);
+            Set_Not_Source_Assigned (Formal_Id);
+         end if;
+
+      else
+         Set_Ekind (Formal_Id, E_In_Parameter);
+      end if;
+
+      Set_Mechanism (Formal_Id, Default_Mechanism);
+      Set_Formal_Validity (Formal_Id);
+   end Set_Formal_Mode;
+
+   -------------------------
+   -- Set_Formal_Validity --
+   -------------------------
+
+   procedure Set_Formal_Validity (Formal_Id : Entity_Id) is
+   begin
+      --  If in full validity checking mode, then we can assume that
+      --  an IN or IN OUT parameter is valid (see Exp_Ch5.Expand_Call)
+
+      if not Validity_Checks_On then
+         return;
+
+      elsif Ekind (Formal_Id) = E_In_Parameter
+        and then Validity_Check_In_Params
+      then
+         Set_Is_Known_Valid (Formal_Id, True);
+
+      elsif Ekind (Formal_Id) = E_In_Out_Parameter
+        and then Validity_Check_In_Out_Params
+      then
+         Set_Is_Known_Valid (Formal_Id, True);
+      end if;
+   end Set_Formal_Validity;
+
+   ------------------------
+   -- Subtype_Conformant --
+   ------------------------
+
+   function Subtype_Conformant (New_Id, Old_Id : Entity_Id) return Boolean is
+      Result : Boolean;
+
+   begin
+      Check_Conformance (New_Id, Old_Id, Subtype_Conformant, False, Result);
+      return Result;
+   end Subtype_Conformant;
+
+   ---------------------
+   -- Type_Conformant --
+   ---------------------
+
+   function Type_Conformant (New_Id, Old_Id : Entity_Id) return Boolean is
+      Result : Boolean;
+
+   begin
+      Check_Conformance (New_Id, Old_Id, Type_Conformant, False, Result);
+      return Result;
+   end Type_Conformant;
+
+   -------------------------------
+   -- Valid_Operator_Definition --
+   -------------------------------
+
+   procedure Valid_Operator_Definition (Designator : Entity_Id) is
+      N    : Integer := 0;
+      F    : Entity_Id;
+      Id   : constant Name_Id := Chars (Designator);
+      N_OK : Boolean;
+
+   begin
+      F := First_Formal (Designator);
+
+      while Present (F) loop
+         N := N + 1;
+
+         if Present (Default_Value (F)) then
+            Error_Msg_N
+              ("default values not allowed for operator parameters",
+               Parent (F));
+         end if;
+
+         Next_Formal (F);
+      end loop;
+
+      --  Verify that user-defined operators have proper number of arguments
+      --  First case of operators which can only be unary
+
+      if Id = Name_Op_Not
+        or else Id = Name_Op_Abs
+      then
+         N_OK := (N = 1);
+
+      --  Case of operators which can be unary or binary
+
+      elsif Id = Name_Op_Add
+        or Id = Name_Op_Subtract
+      then
+         N_OK := (N in 1 .. 2);
+
+      --  All other operators can only be binary
+
+      else
+         N_OK := (N = 2);
+      end if;
+
+      if not N_OK then
+         Error_Msg_N
+           ("incorrect number of arguments for operator", Designator);
+      end if;
+
+      if Id = Name_Op_Ne
+        and then Base_Type (Etype (Designator)) = Standard_Boolean
+        and then not Is_Intrinsic_Subprogram (Designator)
+      then
+         Error_Msg_N
+            ("explicit definition of inequality not allowed", Designator);
+      end if;
+   end Valid_Operator_Definition;
+
+end Sem_Ch6;
diff --git a/gcc/ada/sem_ch6.ads b/gcc/ada/sem_ch6.ads
new file mode 100644 (file)
index 0000000..beb4756
--- /dev/null
@@ -0,0 +1,170 @@
+------------------------------------------------------------------------------
+--                                                                          --
+--                         GNAT COMPILER COMPONENTS                         --
+--                                                                          --
+--                              S E M _ C H 6                               --
+--                                                                          --
+--                                 S p e c                                  --
+--                                                                          --
+--                            $Revision: 1.22 $                             --
+--                                                                          --
+--   Copyright (C) 1992,1993,1994,1995,1996 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- --
+-- ware  Foundation;  either version 2,  or (at your option) any later ver- --
+-- sion.  GNAT is distributed in the hope that it will be useful, but WITH- --
+-- OUT ANY WARRANTY;  without even the  implied warranty of MERCHANTABILITY --
+-- or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License --
+-- for  more details.  You should have  received  a copy of the GNU General --
+-- Public License  distributed with GNAT;  see file COPYING.  If not, write --
+-- to  the Free Software Foundation,  59 Temple Place - Suite 330,  Boston, --
+-- MA 02111-1307, USA.                                                      --
+--                                                                          --
+-- GNAT was originally developed  by the GNAT team at  New York University. --
+-- It is now maintained by Ada Core Technologies Inc (http://www.gnat.com). --
+--                                                                          --
+------------------------------------------------------------------------------
+
+with Types; use Types;
+package Sem_Ch6 is
+
+   procedure Analyze_Abstract_Subprogram_Declaration    (N : Node_Id);
+   procedure Analyze_Function_Call                      (N : Node_Id);
+   procedure Analyze_Operator_Symbol                    (N : Node_Id);
+   procedure Analyze_Parameter_Association              (N : Node_Id);
+   procedure Analyze_Procedure_Call                     (N : Node_Id);
+   procedure Analyze_Return_Statement                   (N : Node_Id);
+   procedure Analyze_Subprogram_Declaration             (N : Node_Id);
+   procedure Analyze_Subprogram_Body                    (N : Node_Id);
+
+   function Analyze_Spec (N : Node_Id) return Entity_Id;
+   --  Analyze subprogram specification in both subprogram declarations
+   --  and body declarations.
+
+   procedure Check_Delayed_Subprogram (Designator : Entity_Id);
+   --  Designator can be a E_Subrpgram_Type, E_Procedure or E_Function. If a
+   --  type in its profile depends on a private type without a full
+   --  declaration, indicate that the subprogram is delayed.
+
+   procedure Check_Discriminant_Conformance
+     (N        : Node_Id;
+      Prev     : Entity_Id;
+      Prev_Loc : Node_Id);
+   --  Check that the discriminants of a full type N fully conform to
+   --  the discriminants of the corresponding partial view Prev.
+   --  Prev_Loc indicates the source location of the partial view,
+   --  which may be different than Prev in the case of private types.
+
+   procedure Check_Fully_Conformant
+     (New_Id  : Entity_Id;
+      Old_Id  : Entity_Id;
+      Err_Loc : Node_Id := Empty);
+   --  Check that two callable entitites (subprograms, entries, literals)
+   --  are fully conformant, post error message if not (RM 6.3.1(17)) with
+   --  the flag being placed on the Err_Loc node if it is specified, and
+   --  on the appropriate component of the New_Id construct if not. Note:
+   --  when checking spec/body conformance, New_Id must be the body entity
+   --  and Old_Id is the spec entity (the code in the implementation relies
+   --  on this ordering, and in any case, this makes sense, since if flags
+   --  are to be placed on the construct, they clearly belong on the body.
+
+   procedure Check_Mode_Conformant
+     (New_Id   : Entity_Id;
+      Old_Id   : Entity_Id;
+      Err_Loc  : Node_Id := Empty;
+      Get_Inst : Boolean := False);
+   --  Check that two callable entitites (subprograms, entries, literals)
+   --  are mode conformant, post error message if not (RM 6.3.1(15)) with
+   --  the flag being placed on the Err_Loc node if it is specified, and
+   --  on the appropriate component of the New_Id construct if not. The
+   --  argument Get_Inst is set to True when this is a check against a
+   --  formal access-to-subprogram type, indicating that mapping of types
+   --  is needed.
+
+   procedure Check_Subtype_Conformant
+     (New_Id  : Entity_Id;
+      Old_Id  : Entity_Id;
+      Err_Loc : Node_Id := Empty);
+   --  Check that two callable entitites (subprograms, entries, literals)
+   --  are subtype conformant, post error message if not (RM 6.3.1(16))
+   --  the flag being placed on the Err_Loc node if it is specified, and
+   --  on the appropriate component of the New_Id construct if not.
+
+   procedure Check_Type_Conformant
+     (New_Id  : Entity_Id;
+      Old_Id  : Entity_Id;
+      Err_Loc : Node_Id := Empty);
+   --  Check that two callable entitites (subprograms, entries, literals)
+   --  are type conformant, post error message if not (RM 6.3.1(14)) with
+   --  the flag being placed on the Err_Loc node if it is specified, and
+   --  on the appropriate component of the New_Id construct if not.
+
+   procedure Create_Extra_Formals (E : Entity_Id);
+   --  For each parameter of a subprogram or entry that requires an additional
+   --  formal (such as for access parameters and indefinite discriminated
+   --  parameters), creates the appropriate formal and attach it to its
+   --  associated parameter. Each extra formal will also be appended to
+   --  the end of Subp's parameter list (with each subsequent extra formal
+   --  being attached to the preceding extra formal).
+
+   function Find_Corresponding_Spec (N : Node_Id) return Entity_Id;
+   --  Use the subprogram specification in the body to retrieve the previous
+   --  subprogram declaration, if any.
+
+   function Fully_Conformant (New_Id, Old_Id : Entity_Id) return Boolean;
+   --  Determine whether two callable entities (subprograms, entries,
+   --  literals) are fully conformant (RM 6.3.1(17))
+
+   function Fully_Conformant_Expressions
+     (Given_E1 : Node_Id;
+      Given_E2 : Node_Id)
+      return  Boolean;
+   --  Determines if two (non-empty) expressions are fully conformant
+   --  as defined by (RM 6.3.1(18-21))
+
+   function Mode_Conformant (New_Id, Old_Id : Entity_Id) return Boolean;
+   --  Determine whether two callable entities (subprograms, entries,
+   --  literals) are mode conformant (RM 6.3.1(15))
+
+   procedure New_Overloaded_Entity
+     (S            : Entity_Id;
+      Derived_Type : Entity_Id := Empty);
+   --  Process new overloaded entity. Overloaded entities are created
+   --  by enumeration type declarations, subprogram specifications,
+   --  entry declarations, and (implicitly) by type derivations.
+   --  If Derived_Type is not Empty, then it indicates that this
+   --  is subprogram derived for that type.
+
+   procedure Process_Formals (
+     S           : Entity_Id;
+     T           : List_Id;
+     Related_Nod : Node_Id);
+   --  Enter the formals in the scope of the subprogram or entry, and
+   --  analyze default expressions if any. The implicit types created for
+   --  access parameter are attached to the Related_Nod which comes from the
+   --  context.
+
+   procedure Set_Actual_Subtypes (N : Node_Id; Subp : Entity_Id);
+   --  If the formals of a subprogram are unconstrained, build a subtype
+   --  declaration that uses the bounds or discriminants of the actual to
+   --  construct an actual subtype for them. This is an optimization that
+   --  is done only in some cases where the actual subtype cannot change
+   --  during execution of the subprogram. By setting the actual subtype
+   --  once, we avoid recomputing it unnecessarily.
+
+   procedure Set_Formal_Mode (Formal_Id : Entity_Id);
+   --  Set proper Ekind to reflect formal mode (in, out, in out)
+
+   function Subtype_Conformant (New_Id, Old_Id : Entity_Id) return Boolean;
+   --  Determine whether two callable entities (subprograms, entries,
+   --  literals) are subtype conformant (RM6.3.1(16))
+
+   function Type_Conformant (New_Id, Old_Id : Entity_Id) return Boolean;
+   --  Determine whether two callable entities (subprograms, entries,
+   --  literals) are type conformant (RM6.3.1(14))
+
+   procedure Valid_Operator_Definition (Designator : Entity_Id);
+   --  Verify that an operator definition has the proper number of formals
+
+end Sem_Ch6;
diff --git a/gcc/ada/sem_ch7.adb b/gcc/ada/sem_ch7.adb
new file mode 100644 (file)
index 0000000..c1b0521
--- /dev/null
@@ -0,0 +1,1703 @@
+------------------------------------------------------------------------------
+--                                                                          --
+--                         GNAT COMPILER COMPONENTS                         --
+--                                                                          --
+--                              S E M . C H 7                               --
+--                                                                          --
+--                                 B o d y                                  --
+--                                                                          --
+--                            $Revision: 1.335 $
+--                                                                          --
+--          Copyright (C) 1992-2001, 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- --
+-- ware  Foundation;  either version 2,  or (at your option) any later ver- --
+-- sion.  GNAT is distributed in the hope that it will be useful, but WITH- --
+-- OUT ANY WARRANTY;  without even the  implied warranty of MERCHANTABILITY --
+-- or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License --
+-- for  more details.  You should have  received  a copy of the GNU General --
+-- Public License  distributed with GNAT;  see file COPYING.  If not, write --
+-- to  the Free Software Foundation,  59 Temple Place - Suite 330,  Boston, --
+-- MA 02111-1307, USA.                                                      --
+--                                                                          --
+-- GNAT was originally developed  by the GNAT team at  New York University. --
+-- It is now maintained by Ada Core Technologies Inc (http://www.gnat.com). --
+--                                                                          --
+------------------------------------------------------------------------------
+
+--  This package contains the routines to process package specifications and
+--  bodies. The most important semantic aspects of package processing are the
+--  handling of private and full declarations, and the construction of
+--  dispatch tables for tagged types.
+
+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_Dbug; use Exp_Dbug;
+with Lib;      use Lib;
+with Lib.Xref; use Lib.Xref;
+with Namet;    use Namet;
+with Nmake;    use Nmake;
+with Nlists;   use Nlists;
+with Opt;      use Opt;
+with Output;   use Output;
+with Sem;      use Sem;
+with Sem_Cat;  use Sem_Cat;
+with Sem_Ch3;  use Sem_Ch3;
+with Sem_Ch6;  use Sem_Ch6;
+with Sem_Ch8;  use Sem_Ch8;
+with Sem_Ch12; use Sem_Ch12;
+with Sem_Util; use Sem_Util;
+with Sem_Warn; use Sem_Warn;
+with Snames;   use Snames;
+with Stand;    use Stand;
+with Sinfo;    use Sinfo;
+with Sinput;   use Sinput;
+with Style;
+
+package body Sem_Ch7 is
+
+   -----------------------------------
+   -- Handling private declarations --
+   -----------------------------------
+
+   --  The principle that each entity has a single defining occurrence clashes
+   --  with the presence of two separate definitions for private types: the
+   --  first is the private type declaration, and the second is the full type
+   --  declaration. It is important that all references to the type point to
+   --  the same defining occurence, namely the first one. To enforce the two
+   --  separate views of the entity, the corresponding information is swapped
+   --  between the two declarations. Outside of the package, the defining
+   --  occurence only contains the private declaration information, while in
+   --  the private part and the body of the package the defining occurrence
+   --  contains the full declaration. To simplify the swap, the defining
+   --  occurrence that currently holds the private declaration points to the
+   --  full declaration. During semantic processing the defining occurence also
+   --  points to a list of private dependents, that is to say access types or
+   --  composite types whose designated types or component types are subtypes
+   --  or derived types of the private type in question. After the full decla-
+   --  ration has been seen, the private dependents are updated to indicate
+   --  that they have full definitions.
+
+   -----------------------
+   -- Local Subprograms --
+   -----------------------
+
+   procedure Install_Composite_Operations (P : Entity_Id);
+   --  Composite types declared in the current scope may depend on
+   --  types that were private at the point of declaration, and whose
+   --  full view is now in  scope. Indicate that the corresponding
+   --  operations on the composite type are available.
+
+   function Is_Private_Base_Type (E : Entity_Id) return Boolean;
+   --  True for a private type that is not a subtype.
+
+   function Is_Visible_Dependent (Dep : Entity_Id) return Boolean;
+   --  If the private dependent is a private type whose full view is
+   --  derived from the parent type, its full properties are revealed
+   --  only if we are in the immediate scope of the private dependent.
+   --  Should this predicate be tightened further???
+
+   procedure Preserve_Full_Attributes (Priv, Full : Entity_Id);
+   --  Copy to the private declaration the attributes of the full view
+   --  that need to be available for the partial view also.
+
+   procedure Declare_Inherited_Private_Subprograms (Id : Entity_Id);
+   --  Called upon entering the private part of a public child package
+   --  and the body of a nested package, to potentially declare certain
+   --  inherited subprograms that were inherited by types in the visible
+   --  part, but whose declaration was deferred because the parent
+   --  operation was private and not visible at that point. These
+   --  subprograms are located by traversing the visible part declarations
+   --  looking for nonprivate type extensions and then examining each of
+   --  the primitive operations of such types to find those that were
+   --  inherited but declared with a special internal name. Each such
+   --  operation is now declared as an operation with a normal name (using
+   --  the name of the parent operation) and replaces the previous implicit
+   --  operation in the primitive operations list of the type. If the
+   --  inherited private operation has been overridden, then it's
+   --  replaced by the overriding operation.
+
+   --------------------------
+   -- Analyze_Package_Body --
+   --------------------------
+
+   procedure Analyze_Package_Body (N : Node_Id) is
+      Loc              : constant Source_Ptr := Sloc (N);
+      HSS              : Node_Id;
+      Body_Id          : Entity_Id;
+      Spec_Id          : Entity_Id;
+      Last_Spec_Entity : Entity_Id;
+      New_N            : Node_Id;
+      Pack_Decl        : Node_Id;
+
+   begin
+      --  Find corresponding package specification, and establish the
+      --  current scope. The visible defining entity for the package is the
+      --  defining occurrence in the spec. On exit from the package body, all
+      --  body declarations are attached to the defining entity for the body,
+      --  but the later is never used for name resolution. In this fashion
+      --  there is only one visible entity that denotes the package.
+
+      if Debug_Flag_C then
+         Write_Str ("====  Compiling package body ");
+         Write_Name (Chars (Defining_Entity (N)));
+         Write_Str (" from ");
+         Write_Location (Loc);
+         Write_Eol;
+      end if;
+
+      --  Set Body_Id. Note that this wil be reset to point to the
+      --  generic copy later on in the generic case.
+
+      Body_Id := Defining_Entity (N);
+
+      if Present (Corresponding_Spec (N)) then
+
+         --  Body is body of package instantiation. Corresponding spec
+         --  has already been set.
+
+         Spec_Id := Corresponding_Spec (N);
+         Pack_Decl := Unit_Declaration_Node (Spec_Id);
+
+      else
+         Spec_Id := Current_Entity_In_Scope (Defining_Entity (N));
+
+         if Present (Spec_Id)
+           and then Is_Package (Spec_Id)
+         then
+            Pack_Decl := Unit_Declaration_Node (Spec_Id);
+
+            if Nkind (Pack_Decl) = N_Package_Renaming_Declaration then
+               Error_Msg_N ("cannot supply body for package renaming", N);
+               return;
+
+            elsif Present (Corresponding_Body (Pack_Decl)) then
+               Error_Msg_N ("redefinition of package body", N);
+               return;
+            end if;
+
+         else
+            Error_Msg_N ("missing specification for package body", N);
+            return;
+         end if;
+
+         if Is_Package (Spec_Id)
+           and then
+             (Scope (Spec_Id) = Standard_Standard
+               or else Is_Child_Unit (Spec_Id))
+           and then not Unit_Requires_Body (Spec_Id)
+         then
+            if Ada_83 then
+               Error_Msg_N
+                 ("optional package body (not allowed in Ada 95)?", N);
+            else
+               Error_Msg_N
+                 ("spec of this package does not allow a body", N);
+            end if;
+         end if;
+      end if;
+
+      Set_Is_Compilation_Unit (Body_Id, Is_Compilation_Unit (Spec_Id));
+      Style.Check_Identifier (Body_Id, Spec_Id);
+
+      if Is_Child_Unit (Spec_Id) then
+
+         if Nkind (Parent (N)) /= N_Compilation_Unit then
+            Error_Msg_NE
+              ("body of child unit& cannot be an inner package", N, Spec_Id);
+         end if;
+
+         Set_Is_Child_Unit (Body_Id);
+      end if;
+
+      --  Generic package case
+
+      if Ekind (Spec_Id) = E_Generic_Package then
+
+         --  Disable expansion and perform semantic analysis on copy.
+         --  The unannotated body will be used in all instantiations.
+
+         Body_Id := Defining_Entity (N);
+         Set_Ekind (Body_Id, E_Package_Body);
+         Set_Scope (Body_Id, Scope (Spec_Id));
+         Set_Body_Entity (Spec_Id, Body_Id);
+         Set_Spec_Entity (Body_Id, Spec_Id);
+
+         New_N := Copy_Generic_Node (N, Empty, Instantiating => False);
+         Rewrite (N, New_N);
+
+         --  Update Body_Id to point to the copied node for the remainder
+         --  of the processing.
+
+         Body_Id := Defining_Entity (N);
+         Start_Generic;
+      end if;
+
+      --  The Body_Id is that of the copied node in the generic case, the
+      --  current node otherwise. Note that N was rewritten above, so we
+      --  must be sure to get the latest Body_Id value.
+
+      Set_Ekind (Body_Id, E_Package_Body);
+      Set_Body_Entity (Spec_Id, Body_Id);
+      Set_Spec_Entity (Body_Id, Spec_Id);
+
+      --  Defining name for the package body is not a visible entity: Only
+      --  the defining name for the declaration is visible.
+
+      Set_Etype (Body_Id, Standard_Void_Type);
+      Set_Scope (Body_Id, Scope (Spec_Id));
+      Set_Corresponding_Spec (N, Spec_Id);
+      Set_Corresponding_Body (Pack_Decl, Body_Id);
+
+      --  The body entity is not used for semantics or code generation, but
+      --  it is attached to the entity list of the enclosing scope to simplify
+      --  the listing of back-annotations for the types it main contain.
+
+      if Scope (Spec_Id) /= Standard_Standard then
+         Append_Entity (Body_Id, Scope (Spec_Id));
+      end if;
+
+      --  Indicate that we are currently compiling the body of the package.
+
+      Set_In_Package_Body (Spec_Id);
+      Set_Has_Completion (Spec_Id);
+      Last_Spec_Entity := Last_Entity (Spec_Id);
+
+      New_Scope (Spec_Id);
+
+      Set_Categorization_From_Pragmas (N);
+
+      Install_Visible_Declarations (Spec_Id);
+      Install_Private_Declarations (Spec_Id);
+      Install_Composite_Operations (Spec_Id);
+
+      if Ekind (Spec_Id) = E_Generic_Package then
+         Set_Use (Generic_Formal_Declarations (Pack_Decl));
+      end if;
+
+      Set_Use (Visible_Declarations (Specification (Pack_Decl)));
+      Set_Use (Private_Declarations (Specification (Pack_Decl)));
+
+      --  This is a nested package, so it may be necessary to declare
+      --  certain inherited subprograms that are not yet visible because
+      --  the parent type's subprograms are now visible.
+
+      if Ekind (Scope (Spec_Id)) = E_Package
+        and then Scope (Spec_Id) /= Standard_Standard
+      then
+         Declare_Inherited_Private_Subprograms (Spec_Id);
+      end if;
+
+      if Present (Declarations (N)) then
+         Analyze_Declarations (Declarations (N));
+      end if;
+
+      HSS := Handled_Statement_Sequence (N);
+
+      if Present (HSS) then
+         Process_End_Label (HSS, 't');
+         Analyze (HSS);
+
+         --  Check that elaboration code in a preelaborable package body is
+         --  empty other than null statements and labels (RM 10.2.1(6)).
+
+         Validate_Null_Statement_Sequence (N);
+      end if;
+
+      Validate_Categorization_Dependency (N, Spec_Id);
+      Check_Completion (Body_Id);
+
+      --  Generate start of body reference. Note that we do this fairly late,
+      --  because the call will use In_Extended_Main_Source_Unit as a check,
+      --  and we want to make sure that Corresponding_Stub links are set
+
+      Generate_Reference (Spec_Id, Body_Id, 'b');
+
+      --  For a generic package, collect global references and mark
+      --  them on the original body so that they are not resolved
+      --  again at the point of instantiation.
+
+      if Ekind (Spec_Id) /= E_Package then
+         Save_Global_References (Original_Node (N));
+         End_Generic;
+      end if;
+
+      --  The entities of the package body have so far been chained onto
+      --  the declaration chain for the spec. That's been fine while we
+      --  were in the body, since we wanted them to be visible, but now
+      --  that we are leaving the package body, they are no longer visible,
+      --  so we remove them from the entity chain of the package spec entity,
+      --  and copy them to the entity chain of the package body entity, where
+      --  they will never again be visible.
+
+      if Present (Last_Spec_Entity) then
+         Set_First_Entity (Body_Id, Next_Entity (Last_Spec_Entity));
+         Set_Next_Entity (Last_Spec_Entity, Empty);
+         Set_Last_Entity (Body_Id, Last_Entity (Spec_Id));
+         Set_Last_Entity (Spec_Id, Last_Spec_Entity);
+
+      else
+         Set_First_Entity (Body_Id, First_Entity (Spec_Id));
+         Set_Last_Entity  (Body_Id, Last_Entity  (Spec_Id));
+         Set_First_Entity (Spec_Id, Empty);
+         Set_Last_Entity  (Spec_Id, Empty);
+      end if;
+
+      End_Package_Scope (Spec_Id);
+
+      --  All entities declared in body are not visible.
+
+      declare
+         E : Entity_Id;
+
+      begin
+         E := First_Entity (Body_Id);
+
+         while Present (E) loop
+            Set_Is_Immediately_Visible (E, False);
+            Set_Is_Potentially_Use_Visible (E, False);
+            Set_Is_Hidden (E);
+
+            --  Child units may appear on the entity list (for example if
+            --  they appear in the context of a subunit) but they are not
+            --  body entities.
+
+            if not Is_Child_Unit (E) then
+               Set_Is_Package_Body_Entity (E);
+            end if;
+
+            Next_Entity (E);
+         end loop;
+      end;
+
+      Check_References (Body_Id);
+
+      --  The processing so far has made all entities of the package body
+      --  public (i.e. externally visible to the linker). This is in general
+      --  necessary, since inlined or generic bodies, for which code is
+      --  generated in other units, may need to see these entities. The
+      --  following loop runs backwards from the end of the entities of the
+      --  package body making these entities invisible until we reach a
+      --  referencer, i.e. a declaration that could reference a previous
+      --  declaration, a generic body or an inlined body, or a stub (which
+      --  may contain either of these). This is of course an approximation,
+      --  but it is conservative and definitely correct.
+
+      --  We only do this at the outer (library) level non-generic packages.
+      --  The reason is simply to cut down on the number of external symbols
+      --  generated, so this is simply an optimization of the efficiency
+      --  of the compilation process. It has no other effect.
+
+      if (Scope (Spec_Id) = Standard_Standard or else Is_Child_Unit (Spec_Id))
+        and then not Is_Generic_Unit (Spec_Id)
+        and then Present (Declarations (N))
+      then
+         Make_Non_Public_Where_Possible : declare
+            Discard : Boolean;
+
+            function Has_Referencer
+              (L     : List_Id;
+               Outer : Boolean)
+               return  Boolean;
+            --  Traverse the given list of declarations in reverse order.
+            --  Return True as soon as a referencer is reached. Return
+            --  False if none is found. The Outer parameter is True for
+            --  the outer level call, and False for inner level calls for
+            --  nested packages. If Outer is True, then any entities up
+            --  to the point of hitting a referencer get their Is_Public
+            --  flag cleared, so that the entities will be treated as
+            --  static entities in the C sense, and need not have fully
+            --  qualified names. For inner levels, we need all names to
+            --  be fully qualified to deal with the same name appearing
+            --  in parallel packages (right now this is tied to their
+            --  being external).
+
+            --------------------
+            -- Has_Referencer --
+            --------------------
+
+            function Has_Referencer
+              (L     : List_Id;
+               Outer : Boolean)
+               return  Boolean
+            is
+               D : Node_Id;
+               E : Entity_Id;
+               K : Node_Kind;
+               S : Entity_Id;
+
+            begin
+               if No (L) then
+                  return False;
+               end if;
+
+               D := Last (L);
+
+               while Present (D) loop
+                  K := Nkind (D);
+
+                  if K in N_Body_Stub then
+                     return True;
+
+                  elsif K = N_Subprogram_Body then
+                     if Acts_As_Spec (D) then
+                        E := Defining_Entity (D);
+
+                        --  An inlined body acts as a referencer. Note also
+                        --  that we never reset Is_Public for an inlined
+                        --  subprogram. Gigi requires Is_Public to be set.
+
+                        --  Note that we test Has_Pragma_Inline here rather
+                        --  than Is_Inlined. We are compiling this for a
+                        --  client, and it is the client who will decide
+                        --  if actual inlining should occur, so we need to
+                        --  assume that the procedure could be inlined for
+                        --  the purpose of accessing global entities.
+
+                        if Has_Pragma_Inline (E) then
+                           return True;
+                        else
+                           Set_Is_Public (E, False);
+                        end if;
+
+                     else
+                        E := Corresponding_Spec (D);
+
+                        if Present (E)
+                          and then (Is_Generic_Unit (E)
+                                     or else Has_Pragma_Inline (E)
+                                     or else Is_Inlined (E))
+                        then
+                           return True;
+                        end if;
+                     end if;
+
+                  --  Processing for package bodies
+
+                  elsif K = N_Package_Body
+                    and then Present (Corresponding_Spec (D))
+                  then
+                     E := Corresponding_Spec (D);
+
+                     --  Generic package body is a referencer. It would
+                     --  seem that we only have to consider generics that
+                     --  can be exported, i.e. where the corresponding spec
+                     --  is the spec of the current package, but because of
+                     --  nested instantiations, a fully private generic
+                     --  body may export other private body entities.
+
+                     if Is_Generic_Unit (E) then
+                        return True;
+
+                     --  For non-generic package body, recurse into body
+                     --  unless this is an instance, we ignore instances
+                     --  since they cannot have references that affect
+                     --  outer entities.
+
+                     elsif not Is_Generic_Instance (E) then
+                        if Has_Referencer
+                             (Declarations (D), Outer => False)
+                        then
+                           return True;
+                        end if;
+                     end if;
+
+                  --  Processing for package specs, recurse into declarations.
+                  --  Again we skip this for the case of generic instances.
+
+                  elsif K = N_Package_Declaration then
+                     S := Specification (D);
+
+                     if not Is_Generic_Unit (Defining_Entity (S)) then
+                        if Has_Referencer
+                             (Private_Declarations (S), Outer => False)
+                        then
+                           return True;
+                        elsif Has_Referencer
+                               (Visible_Declarations (S), Outer => False)
+                        then
+                           return True;
+                        end if;
+                     end if;
+
+                  --  Objects and exceptions need not be public if we have
+                  --  not encountered a referencer so far. We only reset
+                  --  the flag for outer level entities that are not
+                  --  imported/exported, and which have no interface name.
+
+                  elsif K = N_Object_Declaration
+                    or else K = N_Exception_Declaration
+                    or else K = N_Subprogram_Declaration
+                  then
+                     E := Defining_Entity (D);
+
+                     if Outer
+                       and then not Is_Imported (E)
+                       and then not Is_Exported (E)
+                       and then No (Interface_Name (E))
+                     then
+                        Set_Is_Public (E, False);
+                     end if;
+                  end if;
+
+                  Prev (D);
+               end loop;
+
+               return False;
+            end Has_Referencer;
+
+         --  Start of processing for Make_Non_Public_Where_Possible
+
+         begin
+            Discard := Has_Referencer (Declarations (N), Outer => True);
+         end Make_Non_Public_Where_Possible;
+      end if;
+
+      --  If expander is not active, then here is where we turn off the
+      --  In_Package_Body flag, otherwise it is turned off at the end of
+      --  the corresponding expansion routine. If this is an instance body,
+      --  we need to qualify names of local entities, because the body may
+      --  have been compiled as a preliminary to another instantiation.
+
+      if not Expander_Active then
+         Set_In_Package_Body (Spec_Id, False);
+
+         if Is_Generic_Instance (Spec_Id)
+           and then Operating_Mode = Generate_Code
+         then
+            Qualify_Entity_Names (N);
+         end if;
+      end if;
+   end Analyze_Package_Body;
+
+   ---------------------------------
+   -- Analyze_Package_Declaration --
+   ---------------------------------
+
+   procedure Analyze_Package_Declaration (N : Node_Id) is
+      Id : constant Node_Id := Defining_Entity (N);
+      PF : Boolean;
+
+   begin
+      Generate_Definition (Id);
+      Enter_Name (Id);
+      Set_Ekind (Id, E_Package);
+      Set_Etype (Id, Standard_Void_Type);
+      New_Scope (Id);
+
+      PF := Is_Pure (Enclosing_Lib_Unit_Entity);
+      Set_Is_Pure (Id, PF);
+
+      Set_Categorization_From_Pragmas (N);
+
+      if Debug_Flag_C then
+         Write_Str ("====  Compiling package spec ");
+         Write_Name (Chars (Id));
+         Write_Str (" from ");
+         Write_Location (Sloc (N));
+         Write_Eol;
+      end if;
+
+      Analyze (Specification (N));
+      Validate_Categorization_Dependency (N, Id);
+      End_Package_Scope (Id);
+
+      --  For a compilation unit, indicate whether it needs a body, and
+      --  whether elaboration warnings may be meaningful on it.
+
+      if Nkind (Parent (N)) = N_Compilation_Unit then
+         Set_Body_Required (Parent (N), Unit_Requires_Body (Id));
+
+         if not Body_Required (Parent (N)) then
+            Set_Suppress_Elaboration_Warnings (Id);
+         end if;
+
+         Validate_RT_RAT_Component (N);
+      end if;
+
+      --  Clear Not_Source_Assigned on all variables in the package spec,
+      --  because at this stage some client, or the body, or a child package,
+      --  may modify variables in the declaration. Note that we wait till now
+      --  to reset these flags, because during analysis of the declaration,
+      --  the flags correctly indicated the status up to that point. We
+      --  similarly clear any Is_True_Constant indications.
+
+      declare
+         E : Entity_Id;
+
+      begin
+         E := First_Entity (Id);
+         while Present (E) loop
+            if Ekind (E) = E_Variable then
+               Set_Not_Source_Assigned (E, False);
+               Set_Is_True_Constant    (E, False);
+            end if;
+
+            Next_Entity (E);
+         end loop;
+      end;
+   end Analyze_Package_Declaration;
+
+   -----------------------------------
+   -- Analyze_Package_Specification --
+   -----------------------------------
+
+   procedure Analyze_Package_Specification (N : Node_Id) is
+      Id           : constant Entity_Id  := Defining_Entity (N);
+      Orig_Decl    : constant Node_Id    := Original_Node (Parent (N));
+      Vis_Decls    : constant List_Id    := Visible_Declarations (N);
+      Priv_Decls   : constant List_Id    := Private_Declarations (N);
+      E            : Entity_Id;
+      L            : Entity_Id;
+      Public_Child : Boolean             := False;
+
+      function Is_Public_Child (Child, Unit : Entity_Id) return Boolean;
+      --  Child and Unit are entities of compilation units. True if Child
+      --  is a public child of Parent as defined in 10.1.1
+
+      function Is_Public_Child (Child, Unit : Entity_Id) return Boolean is
+      begin
+         if not Is_Private_Descendant (Child) then
+            return True;
+         else
+            if Child = Unit then
+               return not Private_Present (
+                 Parent (Unit_Declaration_Node (Child)));
+            else
+               return Is_Public_Child (Scope (Child), Unit);
+            end if;
+         end if;
+      end Is_Public_Child;
+
+   --  Start of processing for Analyze_Package_Specification
+
+   begin
+      if Present (Vis_Decls) then
+         Analyze_Declarations (Vis_Decls);
+      end if;
+
+      --  Verify that incomplete types have received full declarations.
+
+      E := First_Entity (Id);
+
+      while Present (E) loop
+         if Ekind (E) = E_Incomplete_Type
+           and then No (Full_View (E))
+         then
+            Error_Msg_N ("no declaration in visible part for incomplete}", E);
+         end if;
+
+         Next_Entity (E);
+      end loop;
+
+      if Is_Remote_Call_Interface (Id)
+         and then Nkind (Parent (Parent (N))) = N_Compilation_Unit
+      then
+         Validate_RCI_Declarations (Id);
+      end if;
+
+      --  Save global references in the visible declarations, before
+      --  installing private declarations of parent unit if there is one,
+      --  because the privacy status of types defined in the parent will
+      --  change. This is only relevant for generic child units, but is
+      --  done in all cases for uniformity.
+
+      if Ekind (Id) = E_Generic_Package
+        and then Nkind (Orig_Decl) = N_Generic_Package_Declaration
+      then
+         declare
+            Orig_Spec : constant Node_Id    := Specification (Orig_Decl);
+            Save_Priv : constant List_Id := Private_Declarations (Orig_Spec);
+
+         begin
+            Set_Private_Declarations (Orig_Spec, Empty_List);
+            Save_Global_References   (Orig_Decl);
+            Set_Private_Declarations (Orig_Spec, Save_Priv);
+         end;
+      end if;
+
+      --  If package is a public child unit, then make the private
+      --  declarations of the parent visible.
+
+      if Present (Parent_Spec (Parent (N))) then
+         declare
+            Par       : Entity_Id := Id;
+            Pack_Decl : Node_Id;
+
+         begin
+            while Scope (Par) /= Standard_Standard
+              and then Is_Public_Child (Id, Par)
+            loop
+               Public_Child := True;
+               Par := Scope (Par);
+               Install_Private_Declarations (Par);
+               Pack_Decl := Unit_Declaration_Node (Par);
+               Set_Use (Private_Declarations (Specification (Pack_Decl)));
+            end loop;
+         end;
+      end if;
+
+      --  Analyze private part if present. The flag In_Private_Part is
+      --  reset in End_Package_Scope.
+
+      L := Last_Entity (Id);
+
+      if Present (Priv_Decls) then
+         L := Last_Entity (Id);
+         Set_In_Private_Part (Id);
+
+         --  Upon entering a public child's private part, it may be
+         --  necessary to declare subprograms that were derived in
+         --  the package visible part but not yet made visible.
+
+         if Public_Child then
+            Declare_Inherited_Private_Subprograms (Id);
+         end if;
+
+         Analyze_Declarations (Priv_Decls);
+
+         --  The first private entity is the immediate follower of the last
+         --  visible entity, if there was one.
+
+         if Present (L) then
+            Set_First_Private_Entity (Id, Next_Entity (L));
+         else
+            Set_First_Private_Entity (Id, First_Entity (Id));
+         end if;
+
+      --  There may be inherited private subprograms that need to be
+      --  declared, even in the absence of an explicit private part.
+      --  If there are any public declarations in the package and
+      --  the package is a public child unit, then an implicit private
+      --  part is assumed.
+
+      elsif Present (L) and then Public_Child then
+         Set_In_Private_Part (Id);
+         Declare_Inherited_Private_Subprograms (Id);
+         Set_First_Private_Entity (Id, Next_Entity (L));
+      end if;
+
+      --  Check rule of 3.6(11), which in general requires
+      --  waiting till all full types have been seen.
+
+      E := First_Entity (Id);
+      while Present (E) loop
+         if Ekind (E) = E_Record_Type or else Ekind (E) = E_Array_Type then
+            Check_Aliased_Component_Types (E);
+         end if;
+
+         Next_Entity (E);
+      end loop;
+
+      if Ekind (Id) = E_Generic_Package
+        and then Nkind (Orig_Decl) = N_Generic_Package_Declaration
+        and then Present (Priv_Decls)
+      then
+         --  Save global references in private declarations, ignoring the
+         --  visible declarations that were processed earlier.
+
+         declare
+            Orig_Spec : constant Node_Id := Specification (Orig_Decl);
+            Save_Vis  : constant List_Id := Visible_Declarations (Orig_Spec);
+            Save_Form : constant List_Id :=
+                          Generic_Formal_Declarations (Orig_Decl);
+
+         begin
+            Set_Visible_Declarations        (Orig_Spec, Empty_List);
+            Set_Generic_Formal_Declarations (Orig_Decl, Empty_List);
+            Save_Global_References          (Orig_Decl);
+            Set_Generic_Formal_Declarations (Orig_Decl, Save_Form);
+            Set_Visible_Declarations        (Orig_Spec, Save_Vis);
+         end;
+      end if;
+
+      Process_End_Label (N, 'e');
+   end Analyze_Package_Specification;
+
+   --------------------------------------
+   -- Analyze_Private_Type_Declaration --
+   --------------------------------------
+
+   procedure Analyze_Private_Type_Declaration (N : Node_Id) is
+      PF : constant Boolean := Is_Pure (Enclosing_Lib_Unit_Entity);
+      Id : Entity_Id := Defining_Identifier (N);
+
+   begin
+      Generate_Definition (Id);
+      Set_Is_Pure         (Id, PF);
+      Init_Size_Align     (Id);
+
+      if (Ekind (Current_Scope) /= E_Package
+          and then Ekind (Current_Scope) /= E_Generic_Package)
+        or else In_Private_Part (Current_Scope)
+      then
+         Error_Msg_N ("invalid context for private declaration", N);
+      end if;
+
+      New_Private_Type (N, Id, N);
+      Set_Depends_On_Private (Id);
+      Set_Has_Delayed_Freeze (Id);
+
+   end Analyze_Private_Type_Declaration;
+
+   -------------------------------------------
+   -- Declare_Inherited_Private_Subprograms --
+   -------------------------------------------
+
+   procedure Declare_Inherited_Private_Subprograms (Id : Entity_Id) is
+      E : Entity_Id;
+
+   begin
+      E := First_Entity (Id);
+
+      while Present (E) loop
+
+         --  If the entity is a nonprivate type extension whose parent
+         --  type is declared in an open scope, then the type may have
+         --  inherited operations that now need to be made visible.
+         --  Ditto if the entity is a formal derived type in a child unit.
+
+         if Is_Tagged_Type (E)
+           and then
+             ((Is_Derived_Type (E) and then not Is_Private_Type (E))
+               or else
+             (Nkind (Parent (E)) = N_Private_Extension_Declaration
+               and then Is_Generic_Type (E)))
+           and then In_Open_Scopes (Scope (Etype (E)))
+           and then E = Base_Type (E)
+         then
+            declare
+               Op_List        : constant Elist_Id := Primitive_Operations (E);
+               Op_Elmt        : Elmt_Id := First_Elmt (Op_List);
+               Op_Elmt_2      : Elmt_Id;
+               Prim_Op        : Entity_Id;
+               New_Op         : Entity_Id := Empty;
+               Parent_Subp    : Entity_Id;
+               Found_Explicit : Boolean;
+               Decl_Privates  : Boolean := False;
+
+            begin
+               while Present (Op_Elmt) loop
+                  Prim_Op := Node (Op_Elmt);
+
+                  --  If the primitive operation is an implicit operation
+                  --  with an internal name whose parent operation has
+                  --  a normal name, then we now need to either declare the
+                  --  operation (i.e., make it visible), or replace it
+                  --  by an overriding operation if one exists.
+
+                  if Present (Alias (Prim_Op))
+                    and then not Comes_From_Source (Prim_Op)
+                    and then Is_Internal_Name (Chars (Prim_Op))
+                    and then not Is_Internal_Name (Chars (Alias (Prim_Op)))
+                  then
+                     Parent_Subp := Alias (Prim_Op);
+
+                     Found_Explicit := False;
+                     Op_Elmt_2 := Next_Elmt (Op_Elmt);
+                     while Present (Op_Elmt_2) loop
+                        if Chars (Node (Op_Elmt_2)) = Chars (Parent_Subp)
+                          and then Type_Conformant (Prim_Op, Node (Op_Elmt_2))
+                        then
+                           --  The private inherited operation has been
+                           --  overridden by an explicit subprogram, so
+                           --  change the private op's list element to
+                           --  designate the explicit so the explicit
+                           --  one will get the right dispatching slot.
+
+                           New_Op := Node (Op_Elmt_2);
+                           Replace_Elmt (Op_Elmt, New_Op);
+                           Remove_Elmt (Op_List, Op_Elmt_2);
+                           Found_Explicit := True;
+                           Decl_Privates  := True;
+                           exit;
+                        end if;
+
+                        Next_Elmt (Op_Elmt_2);
+                     end loop;
+
+                     if not Found_Explicit then
+                        Derive_Subprogram
+                          (New_Op, Alias (Prim_Op), E, Etype (E));
+
+                        pragma Assert
+                          (Is_Dispatching_Operation (New_Op)
+                            and then Node (Last_Elmt (Op_List)) = New_Op);
+
+                        --  Substitute the new operation for the old one
+                        --  in the type's primitive operations list. Since
+                        --  the new operation was also just added to the end
+                        --  of list, the last element must be removed.
+
+                        --  (Question: is there a simpler way of declaring
+                        --  the operation, say by just replacing the name
+                        --  of the earlier operation, reentering it in the
+                        --  in the symbol table (how?), and marking it as
+                        --  private???)
+
+                        Replace_Elmt (Op_Elmt, New_Op);
+                        Remove_Last_Elmt (Op_List);
+                        Decl_Privates := True;
+                     end if;
+                  end if;
+
+                  Next_Elmt (Op_Elmt);
+               end loop;
+
+               --  The type's DT attributes need to be recalculated
+               --  in the case where private dispatching operations
+               --  have been added or overridden. Normally this action
+               --  occurs during type freezing, but we force it here
+               --  since the type may already have been frozen (e.g.,
+               --  if the type's package has an empty private part).
+               --  This can only be done if expansion is active, otherwise
+               --  Tag may not be present.
+
+               if Decl_Privates
+                 and then Expander_Active
+               then
+                  Set_All_DT_Position (E);
+               end if;
+            end;
+         end if;
+
+         Next_Entity (E);
+      end loop;
+   end Declare_Inherited_Private_Subprograms;
+
+   -----------------------
+   -- End_Package_Scope --
+   -----------------------
+
+   procedure End_Package_Scope (P : Entity_Id) is
+   begin
+      Uninstall_Declarations (P);
+      Pop_Scope;
+   end End_Package_Scope;
+
+   ---------------------------
+   -- Exchange_Declarations --
+   ---------------------------
+
+   procedure Exchange_Declarations (Id : Entity_Id) is
+      Full_Id : constant Entity_Id := Full_View (Id);
+      H1      : constant Entity_Id := Homonym (Id);
+      Next1   : constant Entity_Id := Next_Entity (Id);
+      H2      : Entity_Id;
+      Next2   : Entity_Id;
+
+   begin
+      --  If missing full declaration for type, nothing to exchange
+
+      if No (Full_Id) then
+         return;
+      end if;
+
+      --  Otherwise complete the exchange, and preserve semantic links
+
+      Next2 := Next_Entity (Full_Id);
+      H2    := Homonym (Full_Id);
+
+      --  Reset full declaration pointer to reflect the switched entities
+      --  and readjust the next entity chains.
+
+      Exchange_Entities (Id, Full_Id);
+
+      Set_Next_Entity (Id, Next1);
+      Set_Homonym     (Id, H1);
+
+      Set_Full_View   (Full_Id, Id);
+      Set_Next_Entity (Full_Id, Next2);
+      Set_Homonym     (Full_Id, H2);
+   end Exchange_Declarations;
+
+   ----------------------------------
+   -- Install_Composite_Operations --
+   ----------------------------------
+
+   procedure Install_Composite_Operations (P : Entity_Id) is
+      Id : Entity_Id;
+
+   begin
+      Id := First_Entity (P);
+
+      while Present (Id) loop
+
+         if Is_Type (Id)
+           and then (Is_Limited_Composite (Id)
+                      or else Is_Private_Composite (Id))
+           and then No (Private_Component (Id))
+         then
+            Set_Is_Limited_Composite (Id, False);
+            Set_Is_Private_Composite (Id, False);
+         end if;
+
+         Next_Entity (Id);
+      end loop;
+   end Install_Composite_Operations;
+
+   ----------------------------
+   -- Install_Package_Entity --
+   ----------------------------
+
+   procedure Install_Package_Entity (Id : Entity_Id) is
+   begin
+      if not Is_Internal (Id) then
+         if Debug_Flag_E then
+            Write_Str ("Install: ");
+            Write_Name (Chars (Id));
+            Write_Eol;
+         end if;
+
+         if not Is_Child_Unit (Id) then
+            Set_Is_Immediately_Visible (Id);
+         end if;
+
+      end if;
+   end Install_Package_Entity;
+
+   ----------------------------------
+   -- Install_Private_Declarations --
+   ----------------------------------
+
+   procedure Install_Private_Declarations (P : Entity_Id) is
+      Id        : Entity_Id;
+      Priv_Elmt : Elmt_Id;
+      Priv      : Entity_Id;
+      Full      : Entity_Id;
+
+   begin
+      --  First exchange declarations for private types, so that the
+      --  full declaration is visible. For each private type, we check
+      --  its Private_Dependents list and also exchange any subtypes of
+      --  or derived types from it. Finally, if this is a Taft amendment
+      --  type, the incomplete declaration is irrelevant, and we want to
+      --  link the eventual full declaration with the original private
+      --  one so we also skip the exchange.
+
+      Id := First_Entity (P);
+
+      while Present (Id) and then Id /= First_Private_Entity (P) loop
+
+         if Is_Private_Base_Type (Id)
+           and then Comes_From_Source (Full_View (Id))
+           and then Present (Full_View (Id))
+           and then Scope (Full_View (Id)) = Scope (Id)
+           and then Ekind (Full_View (Id)) /= E_Incomplete_Type
+         then
+            Priv_Elmt := First_Elmt (Private_Dependents (Id));
+
+            --  If there is a use-type clause on the private type, set the
+            --  full view accordingly.
+
+            Set_In_Use (Full_View (Id), In_Use (Id));
+            Full := Full_View (Id);
+
+            if Is_Private_Base_Type (Full)
+              and then Has_Private_Declaration (Full)
+              and then Nkind (Parent (Full)) = N_Full_Type_Declaration
+              and then In_Open_Scopes (Scope (Etype (Full)))
+              and then In_Package_Body (Current_Scope)
+              and then not Is_Private_Type (Etype (Full))
+            then
+               --  This is the completion of a private type by a derivation
+               --  from another private type which is not private anymore. This
+               --  can only happen in a package nested within a child package,
+               --  when the parent type is defined in the parent unit. At this
+               --  point the current type is not private either, and we have to
+               --  install the underlying full view, which is now visible.
+
+               if No (Full_View (Full))
+                 and then Present (Underlying_Full_View (Full))
+               then
+                  Set_Full_View (Id, Underlying_Full_View (Full));
+                  Set_Underlying_Full_View (Full, Empty);
+                  Set_Is_Frozen (Full_View (Id));
+               end if;
+            end if;
+
+            Exchange_Declarations (Id);
+            Set_Is_Immediately_Visible (Id);
+
+            while Present (Priv_Elmt) loop
+               Priv := Node (Priv_Elmt);
+
+               --  Before the exchange, verify that the presence of the
+               --  Full_View field. It will be empty if the entity
+               --  has already been installed due to a previous call.
+
+               if Present (Full_View (Priv))
+                 and then Is_Visible_Dependent (Priv)
+               then
+
+                  --  For each subtype that is swapped, we also swap the
+                  --  reference to it in Private_Dependents, to allow access
+                  --  to it when we swap them out in End_Package_Scope.
+
+                  Replace_Elmt (Priv_Elmt, Full_View (Priv));
+                  Exchange_Declarations (Priv);
+                  Set_Is_Immediately_Visible
+                    (Priv, In_Open_Scopes (Scope (Priv)));
+                  Set_Is_Potentially_Use_Visible
+                    (Priv, Is_Potentially_Use_Visible (Node (Priv_Elmt)));
+               end if;
+
+               Next_Elmt (Priv_Elmt);
+            end loop;
+
+            null;
+         end if;
+
+         Next_Entity (Id);
+      end loop;
+
+      --  Next make other declarations in the private part visible as well.
+
+      Id := First_Private_Entity (P);
+
+      while Present (Id) loop
+         Install_Package_Entity (Id);
+         Next_Entity (Id);
+      end loop;
+
+      --  Indicate that the private part is currently visible, so it can be
+      --  properly reset on exit.
+
+      Set_In_Private_Part (P);
+   end Install_Private_Declarations;
+
+   ----------------------------------
+   -- Install_Visible_Declarations --
+   ----------------------------------
+
+   procedure Install_Visible_Declarations (P : Entity_Id) is
+      Id : Entity_Id;
+
+   begin
+      Id := First_Entity (P);
+
+      while Present (Id) and then Id /= First_Private_Entity (P) loop
+         Install_Package_Entity (Id);
+         Next_Entity (Id);
+      end loop;
+   end Install_Visible_Declarations;
+
+   ----------------------
+   -- Is_Fully_Visible --
+   ----------------------
+
+   --  The full declaration of a private type is visible in the private
+   --  part of the package declaration, and in the package body, at which
+   --  point the full declaration must have been given.
+
+   function Is_Fully_Visible (Type_Id : Entity_Id) return Boolean is
+      S : constant Entity_Id := Scope (Type_Id);
+
+   begin
+      if Is_Generic_Type (Type_Id) then
+         return False;
+
+      elsif In_Private_Part (S) then
+         return Present (Full_View (Type_Id));
+
+      else
+         return In_Package_Body (S);
+      end if;
+   end Is_Fully_Visible;
+
+   --------------------------
+   -- Is_Private_Base_Type --
+   --------------------------
+
+   function Is_Private_Base_Type (E : Entity_Id) return Boolean is
+   begin
+      return Ekind (E) = E_Private_Type
+        or else Ekind (E) = E_Limited_Private_Type
+        or else Ekind (E) = E_Record_Type_With_Private;
+   end Is_Private_Base_Type;
+
+   --------------------------
+   -- Is_Visible_Dependent --
+   --------------------------
+
+   function Is_Visible_Dependent (Dep : Entity_Id) return Boolean
+   is
+      S : constant Entity_Id := Scope (Dep);
+
+   begin
+      --  Renamings created for actual types have the visibility of the
+      --  actual.
+
+      if Ekind (S) = E_Package
+        and then Is_Generic_Instance (S)
+        and then (Is_Generic_Actual_Type (Dep)
+                   or else Is_Generic_Actual_Type (Full_View (Dep)))
+      then
+         return True;
+
+      elsif not (Is_Derived_Type (Dep))
+        and then Is_Derived_Type (Full_View (Dep))
+      then
+         return In_Open_Scopes (S);
+      else
+         return True;
+      end if;
+   end Is_Visible_Dependent;
+
+   ----------------------------
+   -- May_Need_Implicit_Body --
+   ----------------------------
+
+   procedure May_Need_Implicit_Body (E : Entity_Id) is
+      P     : constant Node_Id := Unit_Declaration_Node (E);
+      S     : constant Node_Id := Parent (P);
+      B     : Node_Id;
+      Decls : List_Id;
+
+   begin
+      if not Has_Completion (E)
+        and then Nkind (P) = N_Package_Declaration
+        and then Present (Activation_Chain_Entity (P))
+      then
+         B :=
+           Make_Package_Body (Sloc (E),
+             Defining_Unit_Name => Make_Defining_Identifier (Sloc (E),
+               Chars => Chars (E)),
+             Declarations  => New_List);
+
+         if Nkind (S) = N_Package_Specification then
+            if Present (Private_Declarations (S)) then
+               Decls := Private_Declarations (S);
+            else
+               Decls := Visible_Declarations (S);
+            end if;
+         else
+            Decls := Declarations (S);
+         end if;
+
+         Append (B, Decls);
+         Analyze (B);
+      end if;
+   end May_Need_Implicit_Body;
+
+   ----------------------
+   -- New_Private_Type --
+   ----------------------
+
+   procedure New_Private_Type (N : Node_Id; Id : Entity_Id; Def : Node_Id) is
+   begin
+      Enter_Name (Id);
+
+      if Limited_Present (Def) then
+         Set_Ekind (Id, E_Limited_Private_Type);
+      else
+         Set_Ekind (Id, E_Private_Type);
+      end if;
+
+      Set_Etype              (Id, Id);
+      Set_Has_Delayed_Freeze (Id);
+      Set_Is_First_Subtype   (Id);
+      Init_Size_Align        (Id);
+
+      Set_Is_Constrained (Id,
+        No (Discriminant_Specifications (N))
+          and then not Unknown_Discriminants_Present (N));
+
+      Set_Discriminant_Constraint (Id, No_Elist);
+      Set_Girder_Constraint (Id, No_Elist);
+
+      if Present (Discriminant_Specifications (N)) then
+         New_Scope (Id);
+         Process_Discriminants (N);
+         End_Scope;
+
+      elsif Unknown_Discriminants_Present (N) then
+         Set_Has_Unknown_Discriminants (Id);
+      end if;
+
+      Set_Private_Dependents (Id, New_Elmt_List);
+
+      if Tagged_Present (Def) then
+         Set_Is_Tagged_Type       (Id, True);
+         Set_Ekind                (Id, E_Record_Type_With_Private);
+         Make_Class_Wide_Type     (Id);
+         Set_Primitive_Operations (Id, New_Elmt_List);
+         Set_Is_Abstract          (Id, Abstract_Present (Def));
+         Set_Is_Limited_Record    (Id, Limited_Present (Def));
+         Set_Has_Delayed_Freeze   (Id, True);
+
+      elsif Abstract_Present (Def) then
+         Error_Msg_N ("only a tagged type can be abstract", N);
+      end if;
+   end New_Private_Type;
+
+   ------------------------------
+   -- Preserve_Full_Attributes --
+   ------------------------------
+
+   procedure Preserve_Full_Attributes (Priv, Full : Entity_Id) is
+      Priv_Is_Base_Type : constant Boolean := Priv = Base_Type (Priv);
+
+   begin
+      Set_Size_Info                   (Priv,                          (Full));
+      Set_RM_Size                     (Priv, RM_Size                  (Full));
+      Set_Size_Known_At_Compile_Time  (Priv, Size_Known_At_Compile_Time
+                                                                      (Full));
+
+      if Priv_Is_Base_Type then
+         Set_Is_Controlled            (Priv, Is_Controlled (Base_Type (Full)));
+         Set_Has_Task                 (Priv, Has_Task      (Base_Type (Full)));
+         Set_Finalize_Storage_Only    (Priv, Finalize_Storage_Only
+                                                           (Base_Type (Full)));
+         Set_Has_Controlled_Component (Priv, Has_Controlled_Component
+                                                           (Base_Type (Full)));
+      end if;
+
+      Set_Freeze_Node                 (Priv, Freeze_Node              (Full));
+
+      if Is_Tagged_Type (Priv)
+        and then Is_Tagged_Type (Full)
+        and then not Error_Posted (Full)
+      then
+         if Priv_Is_Base_Type then
+            Set_Access_Disp_Table     (Priv, Access_Disp_Table
+                                                           (Base_Type (Full)));
+         end if;
+
+         Set_First_Entity             (Priv, First_Entity             (Full));
+         Set_Last_Entity              (Priv, Last_Entity              (Full));
+      end if;
+   end Preserve_Full_Attributes;
+
+   ----------------------------
+   -- Uninstall_Declarations --
+   ----------------------------
+
+   procedure Uninstall_Declarations (P : Entity_Id) is
+      Id   : Entity_Id;
+      Decl : Node_Id := Unit_Declaration_Node (P);
+      Full : Entity_Id;
+      Priv_Elmt : Elmt_Id;
+      Priv_Sub  : Entity_Id;
+
+      function Type_In_Use (T : Entity_Id) return Boolean;
+      --  Check whether type or base type appear in an active use_type clause.
+
+      function Type_In_Use (T : Entity_Id) return Boolean is
+      begin
+         return Scope (Base_Type (T)) = P
+           and then  (In_Use (T) or else In_Use (Base_Type (T)));
+      end Type_In_Use;
+
+   --  Start of processing for Uninstall_Declarations
+
+   begin
+      Id := First_Entity (P);
+
+      while Present (Id) and then Id /= First_Private_Entity (P) loop
+         if Debug_Flag_E then
+            Write_Str ("unlinking visible entity ");
+            Write_Int (Int (Id));
+            Write_Eol;
+         end if;
+
+         --  On  exit from the package scope, we must preserve the visibility
+         --  established by use clauses in the current scope. Two cases:
+
+         --  a) If the entity is an operator, it may be a primitive operator of
+         --  a type for which there is a visible use-type clause.
+
+         --  b) for other entities, their use-visibility is determined by a
+         --  visible use clause for the package itself. For a generic instance,
+         --  the instantiation of the formals appears in the visible part,
+         --  but the formals are private and remain so.
+
+         if Ekind (Id) = E_Function
+           and then  Is_Operator_Symbol_Name (Chars (Id))
+           and then not Is_Hidden (Id)
+         then
+            Set_Is_Potentially_Use_Visible (Id,
+              In_Use (P)
+              or else Type_In_Use (Etype (Id))
+              or else Type_In_Use (Etype (First_Formal (Id)))
+              or else (Present (Next_Formal (First_Formal (Id)))
+                         and then
+                           Type_In_Use
+                             (Etype (Next_Formal (First_Formal (Id))))));
+         else
+            Set_Is_Potentially_Use_Visible (Id,
+              In_Use (P) and not Is_Hidden (Id));
+         end if;
+
+         --  Local entities are not immediately visible outside of the package.
+
+         Set_Is_Immediately_Visible (Id, False);
+
+         if Is_Tagged_Type (Id) and then Ekind (Id) = E_Record_Type then
+            Check_Abstract_Overriding (Id);
+         end if;
+
+         if (Ekind (Id) = E_Private_Type
+               or else Ekind (Id) = E_Limited_Private_Type)
+           and then No (Full_View (Id))
+           and then not Is_Generic_Type (Id)
+           and then not Is_Derived_Type (Id)
+         then
+            Error_Msg_N ("missing full declaration for private type&", Id);
+
+         elsif Ekind (Id) = E_Record_Type_With_Private
+           and then not Is_Generic_Type (Id)
+           and then No (Full_View (Id))
+         then
+            if Nkind (Parent (Id)) = N_Private_Type_Declaration then
+               Error_Msg_N ("missing full declaration for private type&", Id);
+            else
+               Error_Msg_N
+                 ("missing full declaration for private extension", Id);
+            end if;
+
+         elsif Ekind (Id) = E_Constant
+           and then No (Constant_Value (Id))
+           and then No (Full_View (Id))
+           and then not Is_Imported (Id)
+           and then (Nkind (Parent (Id)) /= N_Object_Declaration
+                      or else not No_Initialization (Parent (Id)))
+         then
+            Error_Msg_N ("missing full declaration for deferred constant", Id);
+         end if;
+
+         Next_Entity (Id);
+      end loop;
+
+      --  If the specification was installed as the parent of a public child
+      --  unit, the private declarations were not installed, and there is
+      --  nothing to do.
+
+      if not In_Private_Part (P) then
+         return;
+      else
+         Set_In_Private_Part (P, False);
+      end if;
+
+      --  Make private entities invisible and exchange full and private
+      --  declarations for private types.
+
+      while Present (Id) loop
+         if Debug_Flag_E then
+            Write_Str ("unlinking private entity ");
+            Write_Int (Int (Id));
+            Write_Eol;
+         end if;
+
+         if Is_Tagged_Type (Id) and then Ekind (Id) = E_Record_Type then
+            Check_Abstract_Overriding (Id);
+         end if;
+
+         Set_Is_Immediately_Visible (Id, False);
+
+         if Is_Private_Base_Type (Id)
+           and then Present (Full_View (Id))
+         then
+            Full := Full_View (Id);
+
+            --  If the partial view is not declared in the visible part
+            --  of the package (as is the case when it is a type derived
+            --  from some other private type in the private part if the
+            --  current package), no exchange takes place.
+
+            if No (Parent (Id))
+              or else List_Containing (Parent (Id))
+                /= Visible_Declarations (Specification (Decl))
+            then
+               goto Next_Id;
+            end if;
+
+            --  The entry in the private part points to the full declaration,
+            --  which is currently visible. Exchange them so only the private
+            --  type declaration remains accessible, and link private and
+            --  full declaration in the opposite direction. Before the actual
+            --  exchange, we copy back attributes of the full view that
+            --  must be available to the partial view too.
+
+            Preserve_Full_Attributes (Id, Full);
+
+            Set_Is_Potentially_Use_Visible (Id, In_Use (P));
+
+            if  Is_Indefinite_Subtype (Full)
+              and then not Is_Indefinite_Subtype (Id)
+            then
+               Error_Msg_N
+                 ("full view of type must be definite subtype", Full);
+            end if;
+
+            Priv_Elmt := First_Elmt (Private_Dependents (Id));
+            Exchange_Declarations (Id);
+
+            --  Swap out the subtypes and derived types of Id that were
+            --  compiled in this scope, or installed previously by
+            --  Install_Private_Declarations.
+            --  Before we do the swap, we verify the presence of the
+            --  Full_View field which may be empty due to a swap by
+            --  a previous call to End_Package_Scope (e.g. from the
+            --  freezing mechanism).
+
+            while Present (Priv_Elmt) loop
+               Priv_Sub := Node (Priv_Elmt);
+
+               if Present (Full_View (Priv_Sub)) then
+
+                  if Scope (Priv_Sub) = P
+                     or else not In_Open_Scopes (Scope (Priv_Sub))
+                  then
+                     Set_Is_Immediately_Visible (Priv_Sub, False);
+                  end if;
+
+                  if Is_Visible_Dependent (Priv_Sub) then
+                     Preserve_Full_Attributes
+                       (Priv_Sub, Full_View (Priv_Sub));
+                     Replace_Elmt (Priv_Elmt, Full_View (Priv_Sub));
+                     Exchange_Declarations (Priv_Sub);
+                  end if;
+               end if;
+
+               Next_Elmt (Priv_Elmt);
+            end loop;
+
+         elsif Ekind (Id) = E_Incomplete_Type
+           and then No (Full_View (Id))
+         then
+            --  Mark Taft amendment types
+
+            Set_Has_Completion_In_Body (Id);
+
+         elsif not Is_Child_Unit (Id)
+           and then (not Is_Private_Type (Id)
+                      or else No (Full_View (Id)))
+         then
+            Set_Is_Hidden (Id);
+            Set_Is_Potentially_Use_Visible (Id, False);
+         end if;
+
+         <<Next_Id>>
+            Next_Entity (Id);
+      end loop;
+
+   end Uninstall_Declarations;
+
+   ------------------------
+   -- Unit_Requires_Body --
+   ------------------------
+
+   function Unit_Requires_Body (P : Entity_Id) return Boolean is
+      E : Entity_Id;
+
+   begin
+      --  Imported entity never requires body. Right now, only
+      --  subprograms can be imported, but perhaps in the future
+      --  we will allow import of packages.
+
+      if Is_Imported (P) then
+         return False;
+
+      --  Body required if library package with pragma Elaborate_Body
+
+      elsif Has_Pragma_Elaborate_Body (P) then
+         return True;
+
+      --  Body required if subprogram
+
+      elsif (Is_Subprogram (P)
+               or else
+             Ekind (P) = E_Generic_Function
+               or else
+             Ekind (P) = E_Generic_Procedure)
+      then
+         return True;
+
+      --  Treat a block as requiring a body
+
+      elsif Ekind (P) = E_Block then
+         return True;
+
+      elsif Ekind (P) = E_Package
+        and then Nkind (Parent (P)) = N_Package_Specification
+        and then Present (Generic_Parent (Parent (P)))
+      then
+         declare
+            G_P : Entity_Id := Generic_Parent (Parent (P));
+
+         begin
+            if Has_Pragma_Elaborate_Body (G_P) then
+               return True;
+            end if;
+         end;
+      end if;
+
+      --  Otherwise search entity chain for entity requiring completion.
+
+      E := First_Entity (P);
+      while Present (E) loop
+
+         --  Always ignore child units. Child units get added to the entity
+         --  list of a parent unit, but are not original entities of the
+         --  parent, and so do not affect whether the parent needs a body.
+
+         if Is_Child_Unit (E) then
+            null;
+
+         --  Otherwise test to see if entity requires a completion
+
+         elsif (Is_Overloadable (E)
+               and then Ekind (E) /= E_Enumeration_Literal
+               and then Ekind (E) /= E_Operator
+               and then not Is_Abstract (E)
+               and then not Has_Completion (E))
+
+           or else
+             (Ekind (E) = E_Package
+               and then E /= P
+               and then not Has_Completion (E)
+               and then Unit_Requires_Body (E))
+
+           or else
+             (Ekind (E) = E_Incomplete_Type and then No (Full_View (E)))
+
+           or else
+            ((Ekind (E) = E_Task_Type or else
+              Ekind (E) = E_Protected_Type)
+               and then not Has_Completion (E))
+
+           or else
+             (Ekind (E) = E_Generic_Package and then E /= P
+               and then not Has_Completion (E)
+               and then Unit_Requires_Body (E))
+
+           or else
+             (Ekind (E) = E_Generic_Function
+               and then not Has_Completion (E))
+
+           or else
+             (Ekind (E) = E_Generic_Procedure
+               and then not Has_Completion (E))
+
+         then
+            return True;
+
+         --  Entity that does not require completion
+
+         else
+            null;
+         end if;
+
+         Next_Entity (E);
+      end loop;
+
+      return False;
+   end Unit_Requires_Body;
+
+end Sem_Ch7;
diff --git a/gcc/ada/sem_ch7.ads b/gcc/ada/sem_ch7.ads
new file mode 100644 (file)
index 0000000..057c73c
--- /dev/null
@@ -0,0 +1,87 @@
+------------------------------------------------------------------------------
+--                                                                          --
+--                         GNAT COMPILER COMPONENTS                         --
+--                                                                          --
+--                              S E M _ C H 7                               --
+--                                                                          --
+--                                 S p e c                                  --
+--                                                                          --
+--                            $Revision: 1.19 $                             --
+--                                                                          --
+--        Copyright (C) 1992,1993,1994 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- --
+-- ware  Foundation;  either version 2,  or (at your option) any later ver- --
+-- sion.  GNAT is distributed in the hope that it will be useful, but WITH- --
+-- OUT ANY WARRANTY;  without even the  implied warranty of MERCHANTABILITY --
+-- or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License --
+-- for  more details.  You should have  received  a copy of the GNU General --
+-- Public License  distributed with GNAT;  see file COPYING.  If not, write --
+-- to  the Free Software Foundation,  59 Temple Place - Suite 330,  Boston, --
+-- MA 02111-1307, USA.                                                      --
+--                                                                          --
+-- GNAT was originally developed  by the GNAT team at  New York University. --
+-- It is now maintained by Ada Core Technologies Inc (http://www.gnat.com). --
+--                                                                          --
+------------------------------------------------------------------------------
+
+with Types; use Types;
+package Sem_Ch7  is
+
+   procedure Analyze_Package_Body                       (N : Node_Id);
+   procedure Analyze_Package_Declaration                (N : Node_Id);
+   procedure Analyze_Package_Specification              (N : Node_Id);
+   procedure Analyze_Private_Type_Declaration           (N : Node_Id);
+
+   procedure End_Package_Scope (P : Entity_Id);
+   --  Calls Uninstall_Declarations, and then pops the scope stack.
+
+   procedure Exchange_Declarations (Id : Entity_Id);
+   --  Exchange private and full declaration on entry/exit from a package
+   --  declaration or body. The semantic links of the respective nodes
+   --  are preserved in the exchange.
+
+   procedure Install_Visible_Declarations (P : Entity_Id);
+   procedure Install_Private_Declarations (P : Entity_Id);
+
+   --  On entrance to a package body, make declarations in package spec
+   --  immediately visible.
+
+   --  When compiling the body of a package,  both routines are called in
+   --  succession. When compiling the body of a child package, the call
+   --  to Install_Private_Declaration is immediate for private children,
+   --  but is deffered until the compilation of the  private part of the
+   --  child for public child packages.
+
+   procedure Install_Package_Entity (Id : Entity_Id);
+   --  Basic procedure for the previous two. Places one entity on its
+   --  visibility chain, and recurses on the visible part if the entity
+   --  is an inner package.
+
+   function Unit_Requires_Body (P : Entity_Id) return Boolean;
+   --  Check if a unit requires a body. A specification requires a body
+   --  if it contains declarations that require completion in a body.
+
+   procedure May_Need_Implicit_Body (E : Entity_Id);
+   --  If a package declaration contains tasks and does not require a
+   --  body, create an implicit body at the end of the current declarative
+   --  part to activate those tasks.
+
+   function Is_Fully_Visible (Type_Id : Entity_Id) return Boolean;
+   --  Indicates whether the Full Declaration of a private type is visible.
+
+   procedure New_Private_Type (N : Node_Id; Id : Entity_Id; Def : Node_Id);
+   --  Common processing for private type declarations and for formal
+   --  private type declarations. For private types, N and Def are the type
+   --  declaration node; for formal private types, Def is the formal type
+   --  definition.
+
+   procedure Uninstall_Declarations (P : Entity_Id);
+   --  At the end of a package declaration or body, declarations in the
+   --  visible part are no longer immediately visible, and declarations in
+   --  the private part are not visible at all. For inner packages, place
+   --  visible entities at the end of their homonym chains. For compilation
+   --  units, make all entities invisible. In both cases, exchange private
+   --  and visible declarations to restore order of elaboration.
+end Sem_Ch7;
diff --git a/gcc/ada/sem_ch8.adb b/gcc/ada/sem_ch8.adb
new file mode 100644 (file)
index 0000000..ab90a10
--- /dev/null
@@ -0,0 +1,5224 @@
+------------------------------------------------------------------------------
+--                                                                          --
+--                         GNAT COMPILER COMPONENTS                         --
+--                                                                          --
+--                              S E M . C H 8                               --
+--                                                                          --
+--                                 B o d y                                  --
+--                                                                          --
+--                            $Revision: 1.583 $
+--                                                                          --
+--          Copyright (C) 1992-2001, 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- --
+-- ware  Foundation;  either version 2,  or (at your option) any later ver- --
+-- sion.  GNAT is distributed in the hope that it will be useful, but WITH- --
+-- OUT ANY WARRANTY;  without even the  implied warranty of MERCHANTABILITY --
+-- or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License --
+-- for  more details.  You should have  received  a copy of the GNU General --
+-- Public License  distributed with GNAT;  see file COPYING.  If not, write --
+-- to  the Free Software Foundation,  59 Temple Place - Suite 330,  Boston, --
+-- MA 02111-1307, USA.                                                      --
+--                                                                          --
+-- GNAT was originally developed  by the GNAT team at  New York University. --
+-- It is now maintained by Ada Core Technologies Inc (http://www.gnat.com). --
+--                                                                          --
+------------------------------------------------------------------------------
+
+with Atree;    use Atree;
+with Debug;    use Debug;
+with Einfo;    use Einfo;
+with Elists;   use Elists;
+with Errout;   use Errout;
+with Exp_Util; use Exp_Util;
+with Fname;    use Fname;
+with Freeze;   use Freeze;
+with Lib;      use Lib;
+with Lib.Load; use Lib.Load;
+with Lib.Xref; use Lib.Xref;
+with Namet;    use Namet;
+with Nlists;   use Nlists;
+with Nmake;    use Nmake;
+with Opt;      use Opt;
+with Output;   use Output;
+with Restrict; use Restrict;
+with Rtsfind;  use Rtsfind;
+with Sem;      use Sem;
+with Sem_Ch3;  use Sem_Ch3;
+with Sem_Ch4;  use Sem_Ch4;
+with Sem_Ch6;  use Sem_Ch6;
+with Sem_Ch12; use Sem_Ch12;
+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 Style;    use Style;
+with Table;
+with Tbuild;   use Tbuild;
+with Uintp;    use Uintp;
+
+with GNAT.Spelling_Checker; use GNAT.Spelling_Checker;
+
+package body Sem_Ch8 is
+
+   ------------------------------------
+   -- Visibility and Name Resolution --
+   ------------------------------------
+
+   --  This package handles name resolution and the collection of
+   --  interpretations for overloaded names, prior to overload resolution.
+
+   --  Name resolution is the process that establishes a mapping between source
+   --  identifiers and the entities they denote at each point in the program.
+   --  Each entity is represented by a defining occurrence. Each identifier
+   --  that denotes an entity points to the corresponding defining occurrence.
+   --  This is the entity of the applied occurrence. Each occurrence holds
+   --  an index into the names table, where source identifiers are stored.
+
+   --  Each entry in the names table for an identifier or designator uses the
+   --  Info pointer to hold a link to the currently visible entity that has
+   --  this name (see subprograms Get_Name_Entity_Id and Set_Name_Entity_Id
+   --  in package Sem_Util). The visibility is initialized at the beginning of
+   --  semantic processing to make entities in package Standard immediately
+   --  visible. The visibility table is used in a more subtle way when
+   --  compiling subunits (see below).
+
+   --  Entities that have the same name (i.e. homonyms) are chained. In the
+   --  case of overloaded entities, this chain holds all the possible meanings
+   --  of a given identifier. The process of overload resolution uses type
+   --  information to select from this chain the unique meaning of a given
+   --  identifier.
+
+   --  Entities are also chained in their scope, through the Next_Entity link.
+   --  As a consequence, the name space is organized as a sparse matrix, where
+   --  each row corresponds to a scope, and each column to a source identifier.
+   --  Open scopes, that is to say scopes currently being compiled, have their
+   --  corresponding rows of entities in order, innermost scope first.
+
+   --  The scopes of packages that are mentioned in  context clauses appear in
+   --  no particular order, interspersed among open scopes. This is because
+   --  in the course of analyzing the context of a compilation, a package
+   --  declaration is first an open scope, and subsequently an element of the
+   --  context. If subunits or child units are present, a parent unit may
+   --  appear under various guises at various times in the compilation.
+
+   --  When the compilation of the innermost scope is complete, the entities
+   --  defined therein are no longer visible. If the scope is not a package
+   --  declaration, these entities are never visible subsequently, and can be
+   --  removed from visibility chains. If the scope is a package declaration,
+   --  its visible declarations may still be accessible. Therefore the entities
+   --  defined in such a scope are left on the visibility chains, and only
+   --  their visibility (immediately visibility or potential use-visibility)
+   --  is affected.
+
+   --  The ordering of homonyms on their chain does not necessarily follow
+   --  the order of their corresponding scopes on the scope stack. For
+   --  example, if package P and the enclosing scope both contain entities
+   --  named E, then when compiling the package body the chain for E will
+   --  hold the global entity first,  and the local one (corresponding to
+   --  the current inner scope) next. As a result, name resolution routines
+   --  do not assume any relative ordering of the homonym chains, either
+   --  for scope nesting or to order of appearance of context clauses.
+
+   --  When compiling a child unit, entities in the parent scope are always
+   --  immediately visible. When compiling the body of a child unit, private
+   --  entities in the parent must also be made immediately visible. There
+   --  are separate routines to make the visible and private declarations
+   --  visible at various times (see package Sem_Ch7).
+
+   --              +--------+         +-----+
+   --              | In use |-------->| EU1 |-------------------------->
+   --              +--------+         +-----+
+   --                                    |                      |
+   --      +--------+                 +-----+                +-----+
+   --      | Stand. |---------------->| ES1 |--------------->| ES2 |--->
+   --      +--------+                 +-----+                +-----+
+   --                                    |                      |
+   --              +---------+           |                   +-----+
+   --              | with'ed |------------------------------>| EW2 |--->
+   --              +---------+           |                   +-----+
+   --                                    |                      |
+   --      +--------+                 +-----+                +-----+
+   --      | Scope2 |---------------->| E12 |--------------->| E22 |--->
+   --      +--------+                 +-----+                +-----+
+   --                                    |                      |
+   --      +--------+                 +-----+                +-----+
+   --      | Scope1 |---------------->| E11 |--------------->| E12 |--->
+   --      +--------+                 +-----+                +-----+
+   --          ^                         |                      |
+   --          |                         |                      |
+   --          |   +---------+           |                      |
+   --          |   | with'ed |----------------------------------------->
+   --          |   +---------+           |                      |
+   --          |                         |                      |
+   --      Scope stack                   |                      |
+   --      (innermost first)             |                      |
+   --                                 +----------------------------+
+   --      Names  table =>            | Id1 |     |    |     | Id2 |
+   --                                 +----------------------------+
+
+   --  Name resolution must deal with several syntactic forms: simple names,
+   --  qualified names, indexed names, and various forms of calls.
+
+   --  Each identifier points to an entry in the names table. The resolution
+   --  of a simple name consists in traversing the homonym chain, starting
+   --  from the names table. If an entry is immediately visible, it is the one
+   --  designated by the identifier. If only potemtially use-visible entities
+   --  are on the chain, we must verify that they do not hide each other. If
+   --  the entity we find is overloadable, we collect all other overloadable
+   --  entities on the chain as long as they are not hidden.
+   --
+   --  To resolve expanded names, we must find the entity at the intersection
+   --  of the entity chain for the scope (the prefix) and the homonym chain
+   --  for the selector. In general, homonym chains will be much shorter than
+   --  entity chains, so it is preferable to start from the names table as
+   --  well. If the entity found is overloadable, we must collect all other
+   --  interpretations that are defined in the scope denoted by the prefix.
+
+   --  For records, protected types, and tasks, their local entities are
+   --  removed from visibility chains on exit from the corresponding scope.
+   --  From the outside, these entities are always accessed by selected
+   --  notation, and the entity chain for the record type, protected type,
+   --  etc. is traversed sequentially in  order to find the designated entity.
+
+   --  The discriminants of a type and the operations of a protected type or
+   --  task are unchained on  exit from the first view of the type, (such as
+   --  a private or incomplete type declaration, or a protected type speci-
+   --  fication) and rechained when compiling the second view.
+
+   --  In the case of operators,  we do not make operators on derived types
+   --  explicit. As a result, the notation P."+" may denote either a user-
+   --  defined function with name "+", or else an implicit declaration of the
+   --  operator "+" in package P. The resolution of expanded names always
+   --  tries to resolve an operator name as such an implicitly defined entity,
+   --  in addition to looking for explicit declarations.
+
+   --  All forms of names that denote entities (simple names, expanded names,
+   --  character literals in some cases) have a Entity attribute, which
+   --  identifies the entity denoted by the name.
+
+   ---------------------
+   -- The Scope Stack --
+   ---------------------
+
+   --  The Scope stack keeps track of the scopes currently been compiled.
+   --  Every entity that contains declarations (including records) is placed
+   --  on the scope stack while it is being processed, and removed at the end.
+   --  Whenever a non-package scope is exited, the entities defined therein
+   --  are removed from the visibility table, so that entities in outer scopes
+   --  become visible (see previous description). On entry to Sem, the scope
+   --  stack only contains the package Standard. As usual, subunits complicate
+   --  this picture ever so slightly.
+
+   --  The Rtsfind mechanism can force a call to Semantics while another
+   --  compilation is in progress. The unit retrieved by Rtsfind must be
+   --  compiled in  its own context, and has no access to the visibility of
+   --  the unit currently being compiled. The procedures Save_Scope_Stack and
+   --  Restore_Scope_Stack make entities in current open scopes invisible
+   --  before compiling the retrieved unit, and restore the compilation
+   --  environment afterwards.
+
+   ------------------------
+   -- Compiling subunits --
+   ------------------------
+
+   --  Subunits must be compiled in the environment of the corresponding
+   --  stub, that is to say with the same visibility into the parent (and its
+   --  context) that is available at the point of the stub declaration, but
+   --  with the additional visibility provided by the context clause of the
+   --  subunit itself. As a result, compilation of a subunit forces compilation
+   --  of the parent (see description in lib-). At the point of the stub
+   --  declaration, Analyze is called recursively to compile the proper body
+   --  of the subunit, but without reinitializing the names table, nor the
+   --  scope stack (i.e. standard is not pushed on the stack). In this fashion
+   --  the context of the subunit is added to the context of the parent, and
+   --  the subunit is compiled in the correct environment. Note that in the
+   --  course of processing the context of a subunit, Standard will appear
+   --  twice on the scope stack: once for the parent of the subunit, and
+   --  once for the unit in the context clause being compiled. However, the
+   --  two sets of entities are not linked by homonym chains, so that the
+   --  compilation of any context unit happens in a fresh visibility
+   --  environment.
+
+   -------------------------------
+   -- Processing of USE Clauses --
+   -------------------------------
+
+   --  Every defining occurrence has a flag indicating if it is potentially use
+   --  visible. Resolution of simple names examines this flag. The processing
+   --  of use clauses consists in setting this flag on all visible entities
+   --  defined in the corresponding package. On exit from the scope of the use
+   --  clause, the corresponding flag must be reset. However, a package may
+   --  appear in several nested use clauses (pathological but legal, alas!)
+   --  which forces us to use a slightly more involved scheme:
+
+   --    a) The defining occurrence for a package holds a flag -In_Use- to
+   --    indicate that it is currently in the scope of a use clause. If a
+   --    redundant use clause is encountered, then the corresponding occurence
+   --    of the package name is flagged -Redundant_Use-.
+
+   --    b) On exit from a scope, the use clauses in its declarative part are
+   --    scanned. The visibility flag is reset in all entities declared in
+   --    package named in a use clause, as long as the package is not flagged
+   --    as being in a redundant use clause (in which case the outer use
+   --    clause is still in effect, and the direct visibility of its entities
+   --    must be retained).
+
+   --  Note that entities are not removed from their homonym chains on exit
+   --  from the package specification. A subsequent use clause does not need
+   --  to rechain the visible entities, but only to establish their direct
+   --  visibility.
+
+   -----------------------------------
+   -- Handling private declarations --
+   -----------------------------------
+
+   --  The principle that each entity has a single defining occurrence clashes
+   --  with the presence of two separate definitions for private types: the
+   --  first is the private type declaration, and second is the full type
+   --  declaration. It is important that all references to the type point to
+   --  the same defining occurence, namely the first one. To enforce the two
+   --  separate views of the entity, the corresponding information is swapped
+   --  between the two declarations. Outside of the package, the defining
+   --  occurence only contains the private declaration information, while in
+   --  the private part and the body of the package the defining occurrence
+   --  contains the full declaration. To simplify the swap, the defining
+   --  occurrence that currently holds the private declaration points to the
+   --  full declaration. During semantic processing the defining occurence
+   --  also points to a list of private dependents, that is to say access
+   --  types or composite types whose designated types or component types are
+   --  subtypes or derived types of the private type in question. After the
+   --  full declaration has been seen, the private dependents are updated to
+   --  indicate that they have full definitions.
+
+   ------------------------------------
+   -- Handling of Undefined Messages --
+   ------------------------------------
+
+   --  In normal mode, only the first use of an undefined identifier generates
+   --  a message. The table Urefs is used to record error messages that have
+   --  been issued so that second and subsequent ones do not generate further
+   --  messages. However, the second reference causes text to be added to the
+   --  original undefined message noting "(more references follow)". The
+   --  full error list option (-gnatf) forces messages to be generated for
+   --  every reference and disconnects the use of this table.
+
+   type Uref_Entry is record
+      Node : Node_Id;
+      --  Node for identifier for which original message was posted. The
+      --  Chars field of this identifier is used to detect later references
+      --  to the same identifier.
+
+      Err : Error_Msg_Id;
+      --  Records error message Id of original undefined message. Reset to
+      --  No_Error_Msg after the second occurrence, where it is used to add
+      --  text to the original message as described above.
+
+      Nvis : Boolean;
+      --  Set if the message is not visible rather than undefined
+
+      Loc : Source_Ptr;
+      --  Records location of error message. Used to make sure that we do
+      --  not consider a, b : undefined as two separate instances, which
+      --  would otherwise happen, since the parser converts this sequence
+      --  to a : undefined; b : undefined.
+
+   end record;
+
+   package Urefs is new Table.Table (
+     Table_Component_Type => Uref_Entry,
+     Table_Index_Type     => Nat,
+     Table_Low_Bound      => 1,
+     Table_Initial        => 10,
+     Table_Increment      => 100,
+     Table_Name           => "Urefs");
+
+   Candidate_Renaming : Entity_Id;
+   --  Holds a candidate interpretation that appears in a subprogram renaming
+   --  declaration and does not match the given specification, but matches at
+   --  least on the first formal. Allows better error message when given
+   --  specification omits defaulted parameters, a common error.
+
+   -----------------------
+   -- Local Subprograms --
+   -----------------------
+
+   procedure Analyze_Generic_Renaming
+     (N : Node_Id;
+      K : Entity_Kind);
+   --  Common processing for all three kinds of generic renaming declarations.
+   --  Enter new name and indicate that it renames the generic unit.
+
+   procedure Analyze_Renamed_Character
+     (N       : Node_Id;
+      New_S   : Entity_Id;
+      Is_Body : Boolean);
+   --  Renamed entity is given by a character literal, which must belong
+   --  to the return type of the new entity. Is_Body indicates whether the
+   --  declaration is a renaming_as_body. If the original declaration has
+   --  already been frozen (because of an intervening body, e.g.) the body of
+   --  the function must be built now. The same applies to the following
+   --  various renaming procedures.
+
+   procedure Analyze_Renamed_Dereference
+     (N       : Node_Id;
+      New_S   : Entity_Id;
+      Is_Body : Boolean);
+   --  Renamed entity is given by an explicit dereference. Prefix must be a
+   --  conformant access_to_subprogram type.
+
+   procedure Analyze_Renamed_Entry
+     (N       : Node_Id;
+      New_S   : Entity_Id;
+      Is_Body : Boolean);
+   --  If the renamed entity in a subprogram renaming is an entry or protected
+   --  subprogram, build a body for the new entity whose only statement is a
+   --  call to the renamed entity.
+
+   procedure Analyze_Renamed_Family_Member
+     (N       : Node_Id;
+      New_S   : Entity_Id;
+      Is_Body : Boolean);
+   --  Used when the renamed entity is an indexed component. The prefix must
+   --  denote an entry family.
+
+   procedure Attribute_Renaming (N : Node_Id);
+   --  Analyze renaming of attribute as function. The renaming declaration N
+   --  is rewritten as a function body that returns the attribute reference
+   --  applied to the formals of the function.
+
+   procedure Check_Frozen_Renaming (N : Node_Id; Subp : Entity_Id);
+   --  A renaming_as_body may occur after the entity of the original decla-
+   --  ration has been frozen. In that case, the body of the new entity must
+   --  be built now, because the usual mechanism of building the renamed
+   --  body at the point of freezing will not work. Subp is the subprogram
+   --  for which N provides the Renaming_As_Body.
+
+   procedure Check_Library_Unit_Renaming (N : Node_Id; Old_E : Entity_Id);
+   --  Verify that the entity in a renaming declaration that is a library unit
+   --  is itself a library unit and not a nested unit or subunit. Also check
+   --  that if the renaming is a child unit of a generic parent, then the
+   --  renamed unit must also be a child unit of that parent. Finally, verify
+   --  that a renamed generic unit is not an implicit child declared within
+   --  an instance of the parent.
+
+   procedure Chain_Use_Clause (N : Node_Id);
+   --  Chain use clause onto list of uses clauses headed by First_Use_Clause
+   --  in the top scope table entry.
+
+   function Has_Implicit_Character_Literal (N : Node_Id) return Boolean;
+   --  Find a type derived from Character or Wide_Character in the prefix of N.
+   --  Used to resolved qualified names whose selector is a character literal.
+
+   function Find_Renamed_Entity
+     (N         : Node_Id;
+      Nam       : Node_Id;
+      New_S     : Entity_Id;
+      Is_Actual : Boolean := False) return Entity_Id;
+   --  Find the renamed entity that corresponds to the given parameter profile
+   --  in a subprogram renaming declaration. The renamed entity may be an
+   --  operator, a subprogram, an entry, or a protected operation. Is_Actual
+   --  indicates that the renaming is the one generated for an actual subpro-
+   --  gram in an instance, for which special visibility checks apply.
+
+   procedure Inherit_Renamed_Profile (New_S : Entity_Id; Old_S : Entity_Id);
+   --  A subprogram defined by a renaming declaration inherits the parameter
+   --  profile of the renamed entity. The subtypes given in the subprogram
+   --  specification are discarded and replaced with those of the renamed
+   --  subprogram, which are then used to recheck the default values.
+
+   procedure Premature_Usage (N : Node_Id);
+   --  Diagnose usage of an entity before it is visible.
+
+   procedure Write_Info;
+   --  Write debugging information on entities declared in current scope
+
+   procedure Write_Scopes;
+   pragma Warnings (Off, Write_Scopes);
+   --  Debugging information: dump all entities on scope stack
+
+   --------------------------------
+   -- Analyze_Exception_Renaming --
+   --------------------------------
+
+   --  The language only allows a single identifier, but the tree holds
+   --  an identifier list. The parser has already issued an error message
+   --  if there is more than one element in the list.
+
+   procedure Analyze_Exception_Renaming (N : Node_Id) is
+      Id  : constant Node_Id := Defining_Identifier (N);
+      Nam : constant Node_Id := Name (N);
+
+   begin
+      Enter_Name (Id);
+      Analyze (Nam);
+
+      Set_Ekind          (Id, E_Exception);
+      Set_Exception_Code (Id, Uint_0);
+      Set_Etype          (Id, Standard_Exception_Type);
+      Set_Is_Pure        (Id, Is_Pure (Current_Scope));
+
+      if not Is_Entity_Name (Nam) or else
+        Ekind (Entity (Nam)) /= E_Exception
+      then
+         Error_Msg_N ("invalid exception name in renaming", Nam);
+      else
+         if Present (Renamed_Object (Entity (Nam))) then
+            Set_Renamed_Object (Id, Renamed_Object (Entity (Nam)));
+         else
+            Set_Renamed_Object (Id, Entity (Nam));
+         end if;
+      end if;
+   end Analyze_Exception_Renaming;
+
+   ---------------------------
+   -- Analyze_Expanded_Name --
+   ---------------------------
+
+   procedure Analyze_Expanded_Name (N : Node_Id) is
+   begin
+      --  If the entity pointer is already set, this is an internal node, or
+      --  a node that is analyzed more than once, after a tree modification.
+      --  In such a case there is no resolution to perform, just set the type.
+      --  For completeness, analyze prefix as well.
+
+      if Present (Entity (N)) then
+         if Is_Type (Entity (N)) then
+            Set_Etype (N, Entity (N));
+         else
+            Set_Etype (N, Etype (Entity (N)));
+         end if;
+
+         Analyze (Prefix (N));
+         return;
+      else
+         Find_Expanded_Name (N);
+      end if;
+   end Analyze_Expanded_Name;
+
+   ----------------------------------------
+   --  Analyze_Generic_Function_Renaming --
+   ----------------------------------------
+
+   procedure Analyze_Generic_Function_Renaming  (N : Node_Id) is
+   begin
+      Analyze_Generic_Renaming (N, E_Generic_Function);
+   end Analyze_Generic_Function_Renaming;
+
+   ---------------------------------------
+   --  Analyze_Generic_Package_Renaming --
+   ---------------------------------------
+
+   procedure Analyze_Generic_Package_Renaming   (N : Node_Id) is
+   begin
+      --  Apply the Text_IO Kludge here, since we may be renaming
+      --  one of the subpackages of Text_IO, then join common routine.
+
+      Text_IO_Kludge (Name (N));
+
+      Analyze_Generic_Renaming (N, E_Generic_Package);
+   end Analyze_Generic_Package_Renaming;
+
+   -----------------------------------------
+   --  Analyze_Generic_Procedure_Renaming --
+   -----------------------------------------
+
+   procedure Analyze_Generic_Procedure_Renaming (N : Node_Id) is
+   begin
+      Analyze_Generic_Renaming (N, E_Generic_Procedure);
+   end Analyze_Generic_Procedure_Renaming;
+
+   ------------------------------
+   -- Analyze_Generic_Renaming --
+   ------------------------------
+
+   procedure Analyze_Generic_Renaming
+     (N : Node_Id;
+      K : Entity_Kind)
+   is
+      New_P : Entity_Id := Defining_Entity (N);
+      Old_P : Entity_Id;
+      Inst  : Boolean   := False; -- prevent junk warning
+
+   begin
+      Generate_Definition (New_P);
+
+      if Current_Scope /= Standard_Standard then
+         Set_Is_Pure (New_P, Is_Pure (Current_Scope));
+      end if;
+
+      if Nkind (Name (N)) = N_Selected_Component then
+         Check_Generic_Child_Unit (Name (N), Inst);
+      else
+         Analyze (Name (N));
+      end if;
+
+      if not Is_Entity_Name (Name (N)) then
+         Error_Msg_N ("expect entity name in renaming declaration", Name (N));
+         Old_P := Any_Id;
+      else
+         Old_P := Entity (Name (N));
+      end if;
+
+      Enter_Name (New_P);
+      Set_Ekind (New_P, K);
+
+      if Etype (Old_P) = Any_Type then
+         null;
+
+      elsif Ekind (Old_P) /= K then
+         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));
+         else
+            Set_Renamed_Object (New_P, Old_P);
+         end if;
+
+         Set_Etype (New_P, Etype (Old_P));
+         Set_Has_Completion (New_P);
+
+         if In_Open_Scopes (Old_P) then
+            Error_Msg_N ("within its scope, generic denotes its instance", N);
+         end if;
+
+         Check_Library_Unit_Renaming (N, Old_P);
+      end if;
+
+   end Analyze_Generic_Renaming;
+
+   -----------------------------
+   -- Analyze_Object_Renaming --
+   -----------------------------
+
+   procedure Analyze_Object_Renaming (N : Node_Id) is
+      Id  : constant Entity_Id := Defining_Identifier (N);
+      Dec : Node_Id;
+      Nam : constant Node_Id   := Name (N);
+      S   : constant Entity_Id := Subtype_Mark (N);
+      T   : Entity_Id;
+      T2  : Entity_Id;
+
+   begin
+      Set_Is_Pure (Id, Is_Pure (Current_Scope));
+      Enter_Name (Id);
+
+      --  The renaming of a component that depends on a discriminant
+      --  requires an actual subtype, because in subsequent use of the object
+      --  Gigi will be unable to locate the actual bounds. This explicit step
+      --  is required when the renaming is generated in removing side effects
+      --  of an already-analyzed expression.
+
+      if Nkind (Nam) = N_Selected_Component
+        and then Analyzed (Nam)
+      then
+         T := Etype (Nam);
+         Dec :=  Build_Actual_Subtype_Of_Component (Etype (Nam), Nam);
+
+         if Present (Dec) then
+            Insert_Action (N, Dec);
+            T := Defining_Identifier (Dec);
+            Set_Etype (Nam, T);
+         end if;
+
+      else
+         Find_Type (S);
+         T := Entity (S);
+         Analyze_And_Resolve (Nam, T);
+      end if;
+
+      --  An object renaming requires an exact match of the type;
+      --  class-wide matching is not allowed.
+
+      if Is_Class_Wide_Type (T)
+        and then Base_Type (Etype (Nam)) /= Base_Type (T)
+      then
+         Wrong_Type (Nam, T);
+      end if;
+
+      T2 := Etype (Nam);
+      Set_Ekind (Id, E_Variable);
+      Init_Size_Align (Id);
+
+      if T = Any_Type or else Etype (Nam) = Any_Type then
+         return;
+
+      --  Verify that the renamed entity is an object or a function call.
+      --  It may have been rewritten in several ways.
+
+      elsif Is_Object_Reference (Nam) then
+
+         if Comes_From_Source (N)
+           and then Is_Dependent_Component_Of_Mutable_Object (Nam)
+         then
+            Error_Msg_N
+              ("illegal renaming of discriminant-dependent component", Nam);
+         else
+            null;
+         end if;
+
+      --  A static function call may have been folded into a literal
+
+      elsif Nkind (Original_Node (Nam)) = N_Function_Call
+
+            --  When expansion is disabled, attribute reference is not
+            --  rewritten as function call. Otherwise it may be rewritten
+            --  as a conversion, so check original node.
+
+        or else (Nkind (Original_Node (Nam)) = N_Attribute_Reference
+                  and then Is_Function_Attribute_Name
+                    (Attribute_Name (Original_Node (Nam))))
+
+            --  Weird but legal, equivalent to renaming a function call.
+
+        or else (Is_Entity_Name (Nam)
+                  and then Ekind (Entity (Nam)) = E_Enumeration_Literal)
+
+        or else (Nkind (Nam) = N_Type_Conversion
+                    and then Is_Tagged_Type (Entity (Subtype_Mark (Nam))))
+      then
+         null;
+
+      else
+         if Nkind (Nam) = N_Type_Conversion then
+            Error_Msg_N
+              ("renaming of conversion only allowed for tagged types", Nam);
+
+         else
+            Error_Msg_N ("expect object name in renaming", Nam);
+         end if;
+
+      end if;
+
+      Set_Etype (Id, T2);
+
+      if not Is_Variable (Nam) then
+         Set_Ekind               (Id, E_Constant);
+         Set_Not_Source_Assigned (Id, True);
+         Set_Is_True_Constant    (Id, True);
+      end if;
+
+      Set_Renamed_Object (Id, Nam);
+   end Analyze_Object_Renaming;
+
+   ------------------------------
+   -- Analyze_Package_Renaming --
+   ------------------------------
+
+   procedure Analyze_Package_Renaming (N : Node_Id) is
+      New_P : constant Entity_Id := Defining_Entity (N);
+      Old_P : Entity_Id;
+      Spec  : Node_Id;
+
+   begin
+      --  Apply Text_IO kludge here, since we may be renaming one of
+      --  the children of Text_IO
+
+      Text_IO_Kludge (Name (N));
+
+      if Current_Scope /= Standard_Standard then
+         Set_Is_Pure (New_P, Is_Pure (Current_Scope));
+      end if;
+
+      Enter_Name (New_P);
+      Analyze (Name (N));
+      if Is_Entity_Name (Name (N)) then
+         Old_P := Entity (Name (N));
+      else
+         Old_P := Any_Id;
+      end if;
+
+      if Etype (Old_P) = Any_Type then
+            Error_Msg_N
+             ("expect package name in renaming", Name (N));
+
+      elsif Ekind (Old_P) /= E_Package
+        and then not (Ekind (Old_P) = E_Generic_Package
+                       and then In_Open_Scopes (Old_P))
+      then
+         if Ekind (Old_P) = E_Generic_Package then
+            Error_Msg_N
+               ("generic package cannot be renamed as a package", Name (N));
+         else
+            Error_Msg_Sloc := Sloc (Old_P);
+            Error_Msg_NE
+             ("expect package name in renaming, found& declared#",
+               Name (N), Old_P);
+         end if;
+
+         --  Set basic attributes to minimize cascaded errors.
+
+         Set_Ekind (New_P, E_Package);
+         Set_Etype (New_P, Standard_Void_Type);
+
+      elsif Ekind (Old_P) = E_Package
+        and then From_With_Type (Old_P)
+      then
+         Error_Msg_N ("imported package cannot be renamed", Name (N));
+
+      else
+         --  Entities in the old package are accessible through the
+         --  renaming entity. The simplest implementation is to have
+         --  both packages share the entity list.
+
+         Set_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));
+         else
+            Set_Renamed_Object (New_P,  Old_P);
+         end if;
+
+         Set_Has_Completion (New_P);
+
+         Set_First_Entity (New_P,  First_Entity (Old_P));
+         Set_Last_Entity  (New_P,  Last_Entity  (Old_P));
+         Set_First_Private_Entity (New_P, First_Private_Entity (Old_P));
+         Check_Library_Unit_Renaming (N, Old_P);
+         Generate_Reference (Old_P, Name (N));
+
+         --  If this is the renaming declaration of a package instantiation
+         --  within itself, it is the declaration that ends the list of actuals
+         --  for the instantiation. At this point, the subtypes that rename
+         --  the actuals are flagged as generic, to avoid spurious ambiguities
+         --  if the actuals for two distinct formals happen to coincide. If
+         --  the actual is a private type, the subtype has a private completion
+         --  that is flagged in the same fashion.
+
+         --  Resolution is identical to what is was in the original generic.
+         --  On exit from the generic instance, these are turned into regular
+         --  subtypes again, so they are compatible with types in their class.
+
+         if not Is_Generic_Instance (Old_P) then
+            return;
+         else
+            Spec := Specification (Unit_Declaration_Node (Old_P));
+         end if;
+
+         if Nkind (Spec) = N_Package_Specification
+           and then Present (Generic_Parent (Spec))
+           and then Old_P = Current_Scope
+           and then Chars (New_P) = Chars (Generic_Parent (Spec))
+         then
+            declare
+               E : Entity_Id := First_Entity (Old_P);
+            begin
+               while Present (E)
+                 and then E /= New_P
+               loop
+                  if Is_Type (E)
+                    and then Nkind (Parent (E)) = N_Subtype_Declaration
+                  then
+                     Set_Is_Generic_Actual_Type (E);
+
+                     if Is_Private_Type (E)
+                       and then Present (Full_View (E))
+                     then
+                        Set_Is_Generic_Actual_Type (Full_View (E));
+                     end if;
+                  end if;
+
+                  Next_Entity (E);
+               end loop;
+            end;
+         end if;
+      end if;
+
+   end Analyze_Package_Renaming;
+
+   -------------------------------
+   -- Analyze_Renamed_Character --
+   -------------------------------
+
+   procedure Analyze_Renamed_Character
+     (N       : Node_Id;
+      New_S   : Entity_Id;
+      Is_Body : Boolean)
+   is
+      C : constant Node_Id := Name (N);
+
+   begin
+      if Ekind (New_S) = E_Function then
+         Resolve (C, Etype (New_S));
+
+         if Is_Body then
+            Check_Frozen_Renaming (N, New_S);
+         end if;
+
+      else
+         Error_Msg_N ("character literal can only be renamed as function", N);
+      end if;
+   end Analyze_Renamed_Character;
+
+   ---------------------------------
+   -- Analyze_Renamed_Dereference --
+   ---------------------------------
+
+   procedure Analyze_Renamed_Dereference
+     (N       : Node_Id;
+      New_S   : Entity_Id;
+      Is_Body : Boolean)
+   is
+      Nam : constant Node_Id := Name (N);
+      P   : constant Node_Id := Prefix (Nam);
+      Typ : Entity_Id;
+      I   : Interp_Index;
+      It  : Interp;
+
+   begin
+      if not Is_Overloaded (P) then
+
+         if Ekind (Etype (Nam)) /= E_Subprogram_Type
+           or else not Type_Conformant (Etype (Nam), New_S) then
+            Error_Msg_N ("designated type does not match specification", P);
+         else
+            Resolve (P, Etype (P));
+         end if;
+
+         return;
+
+      else
+         Typ := Any_Type;
+         Get_First_Interp (Nam, I, It);
+
+         while Present (It.Nam) loop
+
+            if Ekind (It.Nam) = E_Subprogram_Type
+              and then Type_Conformant (It.Nam, New_S) then
+
+               if Typ /= Any_Id then
+                  Error_Msg_N ("ambiguous renaming", P);
+                  return;
+               else
+                  Typ := It.Nam;
+               end if;
+            end if;
+
+            Get_Next_Interp (I, It);
+         end loop;
+
+         if Typ = Any_Type then
+            Error_Msg_N ("designated type does not match specification", P);
+         else
+            Resolve (N, Typ);
+
+            if Is_Body then
+               Check_Frozen_Renaming (N, New_S);
+            end if;
+         end if;
+      end if;
+   end Analyze_Renamed_Dereference;
+
+   ---------------------------
+   -- Analyze_Renamed_Entry --
+   ---------------------------
+
+   procedure Analyze_Renamed_Entry
+     (N       : Node_Id;
+      New_S   : Entity_Id;
+      Is_Body : Boolean)
+   is
+      Nam   : Node_Id := Name (N);
+      Sel   : Node_Id := Selector_Name (Nam);
+      Old_S : Entity_Id;
+
+   begin
+      if Entity (Sel) = Any_Id then
+
+         --  Selector is undefined on prefix. Error emitted already.
+
+         Set_Has_Completion (New_S);
+         return;
+      end if;
+
+      --  Otherwise, find renamed entity, and build body of New_S as a call
+      --  to it.
+
+      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);
+      else
+         if Is_Body then
+            Check_Subtype_Conformant (New_S, Old_S, N);
+            Generate_Reference (New_S, Defining_Entity (N), 'b');
+            Style.Check_Identifier (Defining_Entity (N), New_S);
+         end if;
+
+         Inherit_Renamed_Profile (New_S, Old_S);
+      end if;
+
+      Set_Convention (New_S, Convention (Old_S));
+      Set_Has_Completion (New_S, Inside_A_Generic);
+
+      if Is_Body then
+         Check_Frozen_Renaming (N, New_S);
+      end if;
+   end Analyze_Renamed_Entry;
+
+   -----------------------------------
+   -- Analyze_Renamed_Family_Member --
+   -----------------------------------
+
+   procedure Analyze_Renamed_Family_Member
+     (N       : Node_Id;
+      New_S   : Entity_Id;
+      Is_Body : Boolean)
+   is
+      Nam   : Node_Id := Name (N);
+      P     : Node_Id := Prefix (Nam);
+      Old_S : Entity_Id;
+
+   begin
+      if (Is_Entity_Name (P) and then Ekind (Entity (P)) = E_Entry_Family)
+        or else (Nkind (P) = N_Selected_Component
+                   and then
+                 Ekind (Entity (Selector_Name (P))) = E_Entry_Family)
+      then
+         if Is_Entity_Name (P) then
+            Old_S := Entity (P);
+         else
+            Old_S := Entity (Selector_Name (P));
+         end if;
+
+         if not Entity_Matches_Spec (Old_S, New_S) then
+            Error_Msg_N ("entry family does not match specification", N);
+
+         elsif Is_Body then
+            Check_Subtype_Conformant (New_S, Old_S, N);
+            Generate_Reference (New_S, Defining_Entity (N), 'b');
+            Style.Check_Identifier (Defining_Entity (N), New_S);
+         end if;
+      else
+         Error_Msg_N ("no entry family matches specification", N);
+      end if;
+
+      Set_Has_Completion (New_S, Inside_A_Generic);
+
+      if Is_Body then
+         Check_Frozen_Renaming (N, New_S);
+      end if;
+   end Analyze_Renamed_Family_Member;
+
+   ---------------------------------
+   -- Analyze_Subprogram_Renaming --
+   ---------------------------------
+
+   procedure Analyze_Subprogram_Renaming (N : Node_Id) is
+      Nam         : Node_Id  := Name (N);
+      Spec        : constant Node_Id := Specification (N);
+      New_S       : Entity_Id;
+      Old_S       : Entity_Id := Empty;
+      Rename_Spec : Entity_Id;
+      Is_Actual   : Boolean := False;
+      Inst_Node   : Node_Id := Empty;
+      Save_83     : Boolean := Ada_83;
+
+   begin
+      --  We must test for the attribute renaming case before the Analyze
+      --  call because otherwise Sem_Attr will complain that the attribute
+      --  is missing an argument when it is analyzed.
+
+      if Nkind (Nam) = N_Attribute_Reference then
+         Attribute_Renaming (N);
+         return;
+      end if;
+
+      --  Check whether this declaration corresponds to the instantiation
+      --  of a formal subprogram. This is indicated by the presence of a
+      --  Corresponding_Spec that is the instantiation declaration.
+
+      --  If this is an instantiation, the corresponding actual is frozen
+      --  and error messages can be made more precise. If this is a default
+      --  subprogram, the entity is already established in the generic, and
+      --  is not retrieved by visibility. If it is a default with a box, the
+      --  candidate interpretations, if any, have been collected when building
+      --  the renaming declaration. If overloaded, the proper interpretation
+      --  is determined in Find_Renamed_Entity. If the entity is an operator,
+      --  Find_Renamed_Entity applies additional visibility checks.
+
+      if Present (Corresponding_Spec (N)) then
+         Is_Actual := True;
+         Inst_Node := Corresponding_Spec (N);
+
+         if Is_Entity_Name (Nam)
+           and then Present (Entity (Nam))
+           and then not Comes_From_Source (Nam)
+           and then not Is_Overloaded (Nam)
+         then
+            Old_S := Entity (Nam);
+            New_S := Analyze_Spec (Spec);
+
+            if Ekind (Entity (Nam)) = E_Operator
+              and then Box_Present (Corresponding_Spec (N))
+            then
+               Old_S := Find_Renamed_Entity (N, Name (N), New_S, Is_Actual);
+            end if;
+
+         else
+            Analyze (Nam);
+            New_S := Analyze_Spec (Spec);
+         end if;
+
+         Set_Corresponding_Spec (N, Empty);
+
+      else
+         --  Renamed entity must be analyzed first, to avoid being hidden by
+         --  new name (which might be the same in a generic instance).
+
+         Analyze (Nam);
+
+         --  The renaming defines a new overloaded entity, which is analyzed
+         --  like a subprogram declaration.
+
+         New_S := Analyze_Spec (Spec);
+      end if;
+
+      if Current_Scope /= Standard_Standard then
+         Set_Is_Pure (New_S, Is_Pure (Current_Scope));
+      end if;
+
+      Rename_Spec := Find_Corresponding_Spec (N);
+
+      if Present (Rename_Spec) then
+
+         --  Renaming_As_Body. Renaming declaration is the completion of
+         --  the declaration of Rename_Spec. We will build an actual body
+         --  for it at the freezing point.
+
+         Set_Corresponding_Spec (N, Rename_Spec);
+         Set_Corresponding_Body (Unit_Declaration_Node (Rename_Spec), New_S);
+
+         --  The body is created when the entity is frozen. If the context
+         --  is generic, freeze_all is not invoked, so we need to indicate
+         --  that the entity has a completion.
+
+         Set_Has_Completion (Rename_Spec, Inside_A_Generic);
+
+         if Ada_83 and then Comes_From_Source (N) then
+            Error_Msg_N ("(Ada 83) renaming cannot serve as a body", N);
+         end if;
+
+         Set_Convention (New_S,  Convention (Rename_Spec));
+         Check_Fully_Conformant (New_S, Rename_Spec);
+         Set_Public_Status (New_S);
+
+         --  Indicate that the entity in the declaration functions like
+         --  the corresponding body, and is not a new entity.
+
+         Set_Ekind (New_S, E_Subprogram_Body);
+         New_S := Rename_Spec;
+
+      else
+         Generate_Definition (New_S);
+         New_Overloaded_Entity (New_S);
+         if Is_Entity_Name (Nam)
+           and then Is_Intrinsic_Subprogram (Entity (Nam))
+         then
+            null;
+         else
+            Check_Delayed_Subprogram (New_S);
+         end if;
+      end if;
+
+      --  There is no need for elaboration checks on the new entity, which
+      --  may be called before the next freezing point where the body will
+      --  appear.
+
+      Set_Suppress_Elaboration_Checks (New_S, True);
+
+      if Etype (Nam) = Any_Type then
+         Set_Has_Completion (New_S);
+         return;
+
+      elsif Nkind (Nam) = N_Selected_Component then
+
+         --  Renamed entity is an entry or protected subprogram. For those
+         --  cases an explicit body is built (at the point of freezing of
+         --  this entity) that contains a call to the renamed entity.
+
+         Analyze_Renamed_Entry (N, New_S, Present (Rename_Spec));
+         return;
+
+      elsif Nkind (Nam) = N_Explicit_Dereference then
+
+         --  Renamed entity is designated by access_to_subprogram expression.
+         --  Must build body to encapsulate call, as in the entry case.
+
+         Analyze_Renamed_Dereference (N, New_S, Present (Rename_Spec));
+         return;
+
+      elsif Nkind (Nam) = N_Indexed_Component then
+         Analyze_Renamed_Family_Member (N, New_S, Present (Rename_Spec));
+         return;
+
+      elsif Nkind (Nam) = N_Character_Literal then
+         Analyze_Renamed_Character (N, New_S, Present (Rename_Spec));
+         return;
+
+      elsif (not Is_Entity_Name (Nam)
+              and then Nkind (Nam) /= N_Operator_Symbol)
+        or else not Is_Overloadable (Entity (Nam))
+      then
+         Error_Msg_N ("expect valid subprogram name in renaming", N);
+         return;
+
+      end if;
+
+      --  Most common case: subprogram renames subprogram. No body is
+      --  generated in this case, so we must indicate that the declaration
+      --  is complete as is.
+
+      if No (Rename_Spec) then
+         Set_Has_Completion (New_S);
+      end if;
+
+      --  Find the renamed entity that matches the given specification.
+      --  Disable Ada_83 because there is no requirement of full conformance
+      --  between renamed entity and new entity, even though the same circuit
+      --  is used.
+
+      Ada_83 := False;
+
+      if No (Old_S) then
+         Old_S := Find_Renamed_Entity (N, Name (N), New_S, Is_Actual);
+      end if;
+
+      if Old_S /= Any_Id then
+
+         if Is_Actual
+           and then Box_Present (Inst_Node)
+         then
+            --  This is an implicit reference to the default actual
+
+            Generate_Reference (Old_S, Nam, Typ => 'i', Force => True);
+         else
+            Generate_Reference (Old_S, Nam);
+         end if;
+
+         --  For a renaming-as-body, require subtype conformance,
+         --  but if the declaration being completed has not been
+         --  frozen, then inherit the convention of the renamed
+         --  subprogram prior to checking conformance (unless the
+         --  renaming has an explicit convention established; the
+         --  rule stated in the RM doesn't seem to address this ???).
+
+         if Present (Rename_Spec) then
+            Generate_Reference (Rename_Spec, Defining_Entity (Spec), 'b');
+            Style.Check_Identifier (Defining_Entity (Spec), Rename_Spec);
+
+            if not Is_Frozen (Rename_Spec)
+              and then not Has_Convention_Pragma (Rename_Spec)
+            then
+               Set_Convention (New_S, Convention (Old_S));
+            end if;
+
+            Check_Frozen_Renaming (N, Rename_Spec);
+            Check_Subtype_Conformant (New_S, Old_S, Spec);
+
+         elsif Ekind (Old_S) /= E_Operator then
+            Check_Mode_Conformant (New_S, Old_S);
+
+            if Is_Actual
+              and then Error_Posted (New_S)
+            then
+               Error_Msg_NE ("invalid actual subprogram: & #!", N, Old_S);
+            end if;
+         end if;
+
+         if No (Rename_Spec) then
+
+            --  The parameter profile of the new entity is that of the renamed
+            --  entity: the subtypes given in the specification are irrelevant.
+
+            Inherit_Renamed_Profile (New_S, Old_S);
+
+            --  A call to the subprogram is transformed into a call to the
+            --  renamed entity. This is transitive if the renamed entity is
+            --  itself a renaming.
+
+            if Present (Alias (Old_S)) then
+               Set_Alias (New_S, Alias (Old_S));
+            else
+               Set_Alias (New_S, Old_S);
+            end if;
+
+            --  Note that we do not set Is_Instrinsic_Subprogram if we have
+            --  a renaming as body, since the entity in this case is not an
+            --  intrinsic (it calls an intrinsic, but we have a real body
+            --  for this call, and it is in this body that the required
+            --  intrinsic processing will take place).
+
+            Set_Is_Intrinsic_Subprogram
+              (New_S, Is_Intrinsic_Subprogram (Old_S));
+
+            if Ekind (Alias (New_S)) = E_Operator then
+               Set_Has_Delayed_Freeze (New_S, False);
+            end if;
+
+         end if;
+
+         if not Is_Actual
+           and then (Old_S = New_S
+                      or else (Nkind (Nam) /= N_Expanded_Name
+                        and then  Chars (Old_S) = Chars (New_S)))
+         then
+            Error_Msg_N ("subprogram cannot rename itself", N);
+         end if;
+
+         Set_Convention (New_S, Convention (Old_S));
+         Set_Is_Abstract (New_S, Is_Abstract (Old_S));
+         Check_Library_Unit_Renaming (N, Old_S);
+
+         --  Pathological case: procedure renames entry in the scope of
+         --  its task. Entry is given by simple name, but body must be built
+         --  for procedure. Of course if called it will deadlock.
+
+         if Ekind (Old_S) = E_Entry then
+            Set_Has_Completion (New_S, False);
+            Set_Alias (New_S, Empty);
+         end if;
+
+         if Is_Actual then
+            Freeze_Before (N, Old_S);
+            Set_Has_Delayed_Freeze (New_S, False);
+            Freeze_Before (N, New_S);
+
+            if (Ekind (Old_S) = E_Procedure or else Ekind (Old_S) = E_Function)
+              and then Is_Abstract (Old_S)
+            then
+               Error_Msg_N
+                 ("abstract subprogram not allowed as generic actual", Nam);
+            end if;
+         end if;
+
+      else
+         --  A common error is to assume that implicit operators for types
+         --  are defined in Standard, or in the scope of a subtype. In those
+         --  cases where the renamed entity is given with an expanded name,
+         --  it is worth mentioning that operators for the type are not
+         --  declared in the scope given by the prefix.
+
+         if Nkind (Nam) = N_Expanded_Name
+           and then Nkind (Selector_Name (Nam)) = N_Operator_Symbol
+           and then Scope (Entity (Nam)) = Standard_Standard
+         then
+            declare
+               T : constant Entity_Id :=
+                     Base_Type (Etype (First_Formal (New_S)));
+
+            begin
+               Error_Msg_Node_2 := Prefix (Nam);
+               Error_Msg_NE ("\operator for type& is not declared in&",
+                 Prefix (Nam), T);
+            end;
+         else
+            Error_Msg_NE
+              ("no visible subprogram matches the specification for&",
+                Spec, New_S);
+         end if;
+
+         if Present (Candidate_Renaming) then
+            declare
+               F1 : Entity_Id;
+               F2 : Entity_Id;
+
+            begin
+               F1 := First_Formal (Candidate_Renaming);
+               F2 := First_Formal (New_S);
+
+               while Present (F1) and then Present (F2) loop
+                  Next_Formal (F1);
+                  Next_Formal (F2);
+               end loop;
+
+               if Present (F1) and then Present (Default_Value (F1)) then
+                  if Present (Next_Formal (F1)) then
+                     Error_Msg_NE
+                       ("\missing specification for &" &
+                          " and other formals with defaults", Spec, F1);
+                  else
+                     Error_Msg_NE
+                    ("\missing specification for &", Spec, F1);
+                  end if;
+               end if;
+            end;
+         end if;
+      end if;
+
+      Ada_83 := Save_83;
+   end Analyze_Subprogram_Renaming;
+
+   -------------------------
+   -- Analyze_Use_Package --
+   -------------------------
+
+   --  Resolve the package names in the use clause, and make all the visible
+   --  entities defined in the package potentially use-visible. If the package
+   --  is already in use from a previous use clause, its visible entities are
+   --  already use-visible. In that case, mark the occurrence as a redundant
+   --  use. If the package is an open scope, i.e. if the use clause occurs
+   --  within the package itself, ignore it.
+
+   procedure Analyze_Use_Package (N : Node_Id) is
+      Pack_Name : Node_Id;
+      Pack      : Entity_Id;
+
+      function In_Previous_With_Clause (P : Entity_Id) return Boolean;
+      --  For use clauses in a context clause, the indicated package may
+      --  be visible and yet illegal, if it did not appear in a previous
+      --  with clause.
+
+      -----------------------------
+      -- In_Previous_With_Clause --
+      -----------------------------
+
+      function In_Previous_With_Clause (P : Entity_Id) return Boolean is
+         Item : Node_Id;
+
+      begin
+         Item := First (Context_Items (Parent (N)));
+
+         while Present (Item)
+           and then Item /= N
+         loop
+            if Nkind (Item) = N_With_Clause
+              and then Entity (Name (Item)) = Pack
+            then
+               return True;
+            end if;
+
+            Next (Item);
+         end loop;
+
+         return False;
+      end In_Previous_With_Clause;
+
+   --  Start of processing for Analyze_Use_Package
+
+   begin
+      Set_Hidden_By_Use_Clause (N, No_Elist);
+
+      --  Use clause is not allowed in a spec of a predefined package
+      --  declaration except that packages whose file name starts a-n
+      --  are OK (these are children of Ada.Numerics, and such packages
+      --  are never loaded by Rtsfind).
+
+      if Is_Predefined_File_Name (Unit_File_Name (Current_Sem_Unit))
+        and then Name_Buffer (1 .. 3) /= "a-n"
+        and then
+          Nkind (Unit (Cunit (Current_Sem_Unit))) = N_Package_Declaration
+      then
+         Error_Msg_N ("use clause not allowed in predefined spec", N);
+      end if;
+
+      --  Chain clause to list of use clauses in current scope.
+
+      if Nkind (Parent (N)) /= N_Compilation_Unit then
+         Chain_Use_Clause (N);
+      end if;
+
+      --  Loop through package names to identify referenced packages
+
+      Pack_Name := First (Names (N));
+
+      while Present (Pack_Name) loop
+         Analyze (Pack_Name);
+
+         if Nkind (Parent (N)) = N_Compilation_Unit
+           and then Nkind (Pack_Name) = N_Expanded_Name
+         then
+            declare
+               Pref : Node_Id := Prefix (Pack_Name);
+
+            begin
+               while Nkind (Pref) = N_Expanded_Name loop
+                  Pref := Prefix (Pref);
+               end loop;
+
+               if Entity (Pref) = Standard_Standard then
+                  Error_Msg_N
+                   ("predefined package Standard cannot appear"
+                     & " in a context clause", Pref);
+               end if;
+            end;
+         end if;
+
+         Next (Pack_Name);
+      end loop;
+
+      --  Loop through package names to mark all entities as potentially
+      --  use visible.
+
+      Pack_Name := First (Names (N));
+
+      while Present (Pack_Name) loop
+
+         if Is_Entity_Name (Pack_Name) then
+            Pack := Entity (Pack_Name);
+
+            if Ekind (Pack) /= E_Package
+              and then Etype (Pack) /= Any_Type
+            then
+               if Ekind (Pack) = E_Generic_Package then
+                  Error_Msg_N
+                   ("a generic package is not allowed in a use clause",
+                      Pack_Name);
+               else
+                  Error_Msg_N ("& is not a usable package", Pack_Name);
+               end if;
+
+            elsif Nkind (Parent (N)) = N_Compilation_Unit
+              and then Nkind (Pack_Name) /= N_Expanded_Name
+              and then not In_Previous_With_Clause (Pack)
+            then
+               Error_Msg_N ("package is not directly visible", Pack_Name);
+
+            elsif Applicable_Use (Pack_Name) then
+               Use_One_Package (Pack, N);
+            end if;
+         end if;
+
+         Next (Pack_Name);
+      end loop;
+
+   end Analyze_Use_Package;
+
+   ----------------------
+   -- Analyze_Use_Type --
+   ----------------------
+
+   procedure Analyze_Use_Type (N : Node_Id) is
+      Id : Entity_Id;
+
+   begin
+      Set_Hidden_By_Use_Clause (N, No_Elist);
+
+      --  Chain clause to list of use clauses in current scope.
+
+      if Nkind (Parent (N)) /= N_Compilation_Unit then
+         Chain_Use_Clause (N);
+      end if;
+
+      Id := First (Subtype_Marks (N));
+
+      while Present (Id) loop
+         Find_Type (Id);
+
+         if Entity (Id) /= Any_Type then
+            Use_One_Type (Id, N);
+         end if;
+
+         Next (Id);
+      end loop;
+   end Analyze_Use_Type;
+
+   --------------------
+   -- Applicable_Use --
+   --------------------
+
+   function Applicable_Use (Pack_Name : Node_Id) return Boolean is
+      Pack : constant Entity_Id := Entity (Pack_Name);
+
+   begin
+      if In_Open_Scopes (Pack) then
+         return False;
+
+      elsif In_Use (Pack) then
+         Set_Redundant_Use (Pack_Name, True);
+         return False;
+
+      elsif Present (Renamed_Object (Pack))
+        and then In_Use (Renamed_Object (Pack))
+      then
+         Set_Redundant_Use (Pack_Name, True);
+         return False;
+
+      else
+         return True;
+      end if;
+   end Applicable_Use;
+
+   ------------------------
+   -- Attribute_Renaming --
+   ------------------------
+
+   procedure Attribute_Renaming (N : Node_Id) is
+      Loc        : constant Source_Ptr := Sloc (N);
+      Nam        : constant Node_Id    := Name (N);
+      Spec       : constant Node_Id    := Specification (N);
+      New_S      : constant Entity_Id  := Defining_Unit_Name (Spec);
+      Aname      : constant Name_Id    := Attribute_Name (Nam);
+
+      Form_Num   : Nat      := 0;
+      Expr_List  : List_Id  := No_List;
+
+      Attr_Node  : Node_Id;
+      Body_Node  : Node_Id;
+      Param_Spec : Node_Id;
+
+   begin
+      Generate_Definition (New_S);
+
+      --  This procedure is called in the context of subprogram renaming,
+      --  and thus the attribute must be one that is a subprogram. All of
+      --  those have at least one formal parameter, with the singular
+      --  exception of AST_Entry (which is a real oddity, it is odd that
+      --  this can be renamed at all!)
+
+      if not Is_Non_Empty_List (Parameter_Specifications (Spec)) then
+         if Aname /= Name_AST_Entry then
+            Error_Msg_N
+              ("subprogram renaming an attribute must have formals", N);
+            return;
+         end if;
+
+      else
+         Param_Spec := First (Parameter_Specifications (Spec));
+
+         while Present (Param_Spec) loop
+            Form_Num := Form_Num + 1;
+
+            if Nkind (Parameter_Type (Param_Spec)) /= N_Access_Definition then
+               Find_Type (Parameter_Type (Param_Spec));
+
+               --  The profile of the new entity denotes the base type (s) of
+               --  the types given in the specification. For access parameters
+               --  there are no subtypes involved.
+
+               Rewrite (Parameter_Type (Param_Spec),
+                New_Reference_To
+                  (Base_Type (Entity (Parameter_Type (Param_Spec))), Loc));
+            end if;
+
+            if No (Expr_List) then
+               Expr_List := New_List;
+            end if;
+
+            Append_To (Expr_List,
+              Make_Identifier (Loc,
+                Chars => Chars (Defining_Identifier (Param_Spec))));
+
+            Next (Param_Spec);
+         end loop;
+      end if;
+
+      --  Immediate error if too many formals. Other mismatches in numbers
+      --  of number of types of parameters are detected when we analyze the
+      --  body of the subprogram that we construct.
+
+      if Form_Num > 2 then
+         Error_Msg_N ("too many formals for attribute", N);
+
+      elsif
+        Aname = Name_Compose      or else
+        Aname = Name_Exponent     or else
+        Aname = Name_Leading_Part or else
+        Aname = Name_Pos          or else
+        Aname = Name_Round        or else
+        Aname = Name_Scaling      or else
+        Aname = Name_Val
+      then
+         if Nkind (N) = N_Subprogram_Renaming_Declaration
+           and then Present (Corresponding_Spec (N))
+           and then Nkind (Corresponding_Spec (N)) =
+                                   N_Formal_Subprogram_Declaration
+         then
+            Error_Msg_N
+              ("generic actual cannot be attribute involving universal type",
+               Nam);
+         else
+            Error_Msg_N
+              ("attribute involving a universal type cannot be renamed",
+               Nam);
+         end if;
+      end if;
+
+      --  AST_Entry is an odd case. It doesn't really make much sense to
+      --  allow it to be renamed, but that's the DEC rule, so we have to
+      --  do it right. The point is that the AST_Entry call should be made
+      --  now, and what the function will return is the returned value.
+
+      --  Note that there is no Expr_List in this case anyway
+
+      if Aname = Name_AST_Entry then
+
+         declare
+            Ent  : Entity_Id;
+            Decl : Node_Id;
+
+         begin
+            Ent := Make_Defining_Identifier (Loc, New_Internal_Name ('R'));
+
+            Decl :=
+              Make_Object_Declaration (Loc,
+                Defining_Identifier => Ent,
+                Object_Definition =>
+                  New_Occurrence_Of (RTE (RE_AST_Handler), Loc),
+                Expression => Nam,
+                Constant_Present => True);
+
+            Set_Assignment_OK (Decl, True);
+            Insert_Action (N, Decl);
+            Attr_Node := Make_Identifier (Loc, Chars (Ent));
+         end;
+
+      --  For all other attributes, we rewrite the attribute node to have
+      --  a list of expressions corresponding to the subprogram formals.
+      --  A renaming declaration is not a freeze point, and the analysis of
+      --  the attribute reference should not freeze the type of the prefix.
+
+      else
+         Attr_Node :=
+           Make_Attribute_Reference (Loc,
+             Prefix         => Prefix (Nam),
+             Attribute_Name => Aname,
+             Expressions    => Expr_List);
+
+         Set_Must_Not_Freeze (Attr_Node);
+         Set_Must_Not_Freeze (Prefix (Nam));
+      end if;
+
+      --  Case of renaming a function
+
+      if Nkind (Spec) = N_Function_Specification then
+
+         if Is_Procedure_Attribute_Name (Aname) then
+            Error_Msg_N ("attribute can only be renamed as procedure", Nam);
+            return;
+         end if;
+
+         Find_Type (Subtype_Mark (Spec));
+         Rewrite (Subtype_Mark (Spec),
+             New_Reference_To (Base_Type (Entity (Subtype_Mark (Spec))), Loc));
+
+         Body_Node :=
+           Make_Subprogram_Body (Loc,
+             Specification => Spec,
+             Declarations => New_List,
+             Handled_Statement_Sequence =>
+               Make_Handled_Sequence_Of_Statements (Loc,
+                   Statements => New_List (
+                     Make_Return_Statement (Loc,
+                       Expression => Attr_Node))));
+
+      --  Case of renaming a procedure
+
+      else
+         if not Is_Procedure_Attribute_Name (Aname) then
+            Error_Msg_N ("attribute can only be renamed as function", Nam);
+            return;
+         end if;
+
+         Body_Node :=
+           Make_Subprogram_Body (Loc,
+             Specification => Spec,
+             Declarations => New_List,
+             Handled_Statement_Sequence =>
+               Make_Handled_Sequence_Of_Statements (Loc,
+                   Statements => New_List (Attr_Node)));
+      end if;
+
+      Rewrite (N, Body_Node);
+      Analyze (N);
+
+      Set_Etype (New_S, Base_Type (Etype (New_S)));
+
+      --  We suppress elaboration warnings for the resulting entity, since
+      --  clearly they are not needed, and more particularly, in the case
+      --  of a generic formal subprogram, the resulting entity can appear
+      --  after the instantiation itself, and thus look like a bogus case
+      --  of access before elaboration.
+
+      Set_Suppress_Elaboration_Warnings (New_S);
+
+   end Attribute_Renaming;
+
+   ----------------------
+   -- Chain_Use_Clause --
+   ----------------------
+
+   procedure Chain_Use_Clause (N : Node_Id) is
+   begin
+      Set_Next_Use_Clause (N,
+        Scope_Stack.Table (Scope_Stack.Last).First_Use_Clause);
+      Scope_Stack.Table (Scope_Stack.Last).First_Use_Clause := N;
+   end Chain_Use_Clause;
+
+   ----------------------------
+   --  Check_Frozen_Renaming --
+   ----------------------------
+
+   procedure Check_Frozen_Renaming (N : Node_Id; Subp : Entity_Id) is
+      B_Node : Node_Id;
+      Old_S  : Entity_Id;
+
+   begin
+      if Is_Frozen (Subp)
+        and then not Has_Completion (Subp)
+      then
+         B_Node :=
+           Build_Renamed_Body
+             (Parent (Declaration_Node (Subp)), Defining_Entity (N));
+
+         if Is_Entity_Name (Name (N)) then
+            Old_S := Entity (Name (N));
+
+            if not Is_Frozen (Old_S) then
+               Ensure_Freeze_Node (Old_S);
+               if No (Actions (Freeze_Node (Old_S))) then
+                  Set_Actions (Freeze_Node (Old_S), New_List (B_Node));
+               else
+                  Append (B_Node, Actions (Freeze_Node (Old_S)));
+               end if;
+            else
+               Insert_After (N, B_Node);
+               Analyze (B_Node);
+            end if;
+
+            if Is_Intrinsic_Subprogram (Old_S)
+              and then not In_Instance
+            then
+               Error_Msg_N
+                 ("subprogram used in renaming_as_body cannot be intrinsic",
+                    Name (N));
+            end if;
+
+         else
+            Insert_After (N, B_Node);
+            Analyze (B_Node);
+         end if;
+      end if;
+   end Check_Frozen_Renaming;
+
+   ---------------------------------
+   -- Check_Library_Unit_Renaming --
+   ---------------------------------
+
+   procedure Check_Library_Unit_Renaming (N : Node_Id; Old_E : Entity_Id) is
+      New_E : Entity_Id;
+
+   begin
+      if Nkind (Parent (N)) /= N_Compilation_Unit then
+         return;
+
+      elsif Scope (Old_E) /= Standard_Standard
+        and then not Is_Child_Unit (Old_E)
+      then
+         Error_Msg_N ("renamed unit must be a library unit", Name (N));
+
+      elsif Present (Parent_Spec (N))
+        and then Nkind (Unit (Parent_Spec (N))) = N_Generic_Package_Declaration
+        and then not Is_Child_Unit (Old_E)
+      then
+         Error_Msg_N
+           ("renamed unit must be a child unit of generic parent", Name (N));
+
+      elsif Nkind (N) in N_Generic_Renaming_Declaration
+         and then  Nkind (Name (N)) = N_Expanded_Name
+         and then Is_Generic_Instance (Entity (Prefix (Name (N))))
+         and then Is_Generic_Unit (Old_E)
+      then
+         Error_Msg_N
+           ("renamed generic unit must be a library unit", Name (N));
+
+      elsif Ekind (Old_E) = E_Package
+        or else Ekind (Old_E) = E_Generic_Package
+      then
+         --  Inherit categorization flags
+
+         New_E := Defining_Entity (N);
+         Set_Is_Pure                  (New_E, Is_Pure           (Old_E));
+         Set_Is_Preelaborated         (New_E, Is_Preelaborated  (Old_E));
+         Set_Is_Remote_Call_Interface (New_E,
+                                       Is_Remote_Call_Interface (Old_E));
+         Set_Is_Remote_Types          (New_E, Is_Remote_Types   (Old_E));
+         Set_Is_Shared_Passive        (New_E, Is_Shared_Passive (Old_E));
+      end if;
+   end Check_Library_Unit_Renaming;
+
+   ---------------
+   -- End_Scope --
+   ---------------
+
+   procedure End_Scope is
+      Id    : Entity_Id;
+      Prev  : Entity_Id;
+      Outer : Entity_Id;
+
+   begin
+      Id := First_Entity (Current_Scope);
+
+      while Present (Id) loop
+         --  An entity in the current scope is not necessarily the first one
+         --  on its homonym chain. Find its predecessor if any,
+         --  If it is an internal entity, it will not be in the visibility
+         --  chain altogether,  and there is nothing to unchain.
+
+         if Id /= Current_Entity (Id) then
+            Prev := Current_Entity (Id);
+            while Present (Prev)
+              and then Present (Homonym (Prev))
+              and then Homonym (Prev) /= Id
+            loop
+               Prev := Homonym (Prev);
+            end loop;
+
+            --  Skip to end of loop if Id is not in the visibility chain
+
+            if No (Prev) or else Homonym (Prev) /= Id then
+               goto Next_Ent;
+            end if;
+
+         else
+            Prev := Empty;
+         end if;
+
+         Outer := Homonym (Id);
+         Set_Is_Immediately_Visible (Id, False);
+
+         while Present (Outer) and then Scope (Outer) = Current_Scope loop
+            Outer := Homonym (Outer);
+         end loop;
+
+         --  Reset homonym link of other entities, but do not modify link
+         --  between entities in current scope, so that the back-end can have
+         --  a proper count of local overloadings.
+
+         if No (Prev) then
+            Set_Name_Entity_Id (Chars (Id), Outer);
+
+         elsif Scope (Prev) /= Scope (Id) then
+            Set_Homonym (Prev,  Outer);
+         end if;
+
+         <<Next_Ent>>
+            Next_Entity (Id);
+      end loop;
+
+      --  If the scope generated freeze actions, place them before the
+      --  current declaration and analyze them. Type declarations and
+      --  the bodies of initialization procedures can generate such nodes.
+      --  We follow the parent chain until we reach a list node, which is
+      --  the enclosing list of declarations. If the list appears within
+      --  a protected definition, move freeze nodes outside the protected
+      --  type altogether.
+
+      if Present
+         (Scope_Stack.Table (Scope_Stack.Last).Pending_Freeze_Actions)
+      then
+         declare
+            Decl : Node_Id;
+            L    : constant List_Id := Scope_Stack.Table
+                    (Scope_Stack.Last).Pending_Freeze_Actions;
+
+         begin
+            if Is_Itype (Current_Scope) then
+               Decl := Associated_Node_For_Itype (Current_Scope);
+            else
+               Decl := Parent (Current_Scope);
+            end if;
+
+            Pop_Scope;
+
+            while not (Is_List_Member (Decl))
+              or else Nkind (Parent (Decl)) = N_Protected_Definition
+              or else Nkind (Parent (Decl)) = N_Task_Definition
+            loop
+               Decl := Parent (Decl);
+            end loop;
+
+            Insert_List_Before_And_Analyze (Decl, L);
+         end;
+
+      else
+         Pop_Scope;
+      end if;
+
+   end End_Scope;
+
+   ---------------------
+   -- End_Use_Clauses --
+   ---------------------
+
+   procedure End_Use_Clauses (Clause : Node_Id) is
+      U : Node_Id := Clause;
+
+   begin
+      while Present (U) loop
+         if Nkind (U) = N_Use_Package_Clause then
+            End_Use_Package (U);
+         elsif Nkind (U) = N_Use_Type_Clause then
+            End_Use_Type (U);
+         end if;
+
+         Next_Use_Clause (U);
+      end loop;
+   end End_Use_Clauses;
+
+   ---------------------
+   -- End_Use_Package --
+   ---------------------
+
+   procedure End_Use_Package (N : Node_Id) is
+      Pack_Name : Node_Id;
+      Pack      : Entity_Id;
+      Id        : Entity_Id;
+      Elmt      : Elmt_Id;
+
+   begin
+      Pack_Name := First (Names (N));
+
+      while Present (Pack_Name) loop
+         Pack := Entity (Pack_Name);
+
+         if Ekind (Pack) = E_Package then
+
+            if In_Open_Scopes (Pack) then
+               null;
+
+            elsif not Redundant_Use (Pack_Name) then
+               Set_In_Use (Pack, False);
+               Id := First_Entity (Pack);
+
+               while Present (Id) loop
+
+                  --  Preserve use-visibility of operators whose formals have
+                  --  a type that is use_visible thanks to a previous use_type
+                  --  clause.
+
+                  if Nkind (Id) = N_Defining_Operator_Symbol
+                       and then
+                         (In_Use (Etype (First_Formal (Id)))
+                            or else
+                              (Present (Next_Formal (First_Formal (Id)))
+                                and then In_Use (Etype (Next_Formal
+                                                        (First_Formal (Id))))))
+                  then
+                     null;
+
+                  else
+                     Set_Is_Potentially_Use_Visible (Id, False);
+                  end if;
+
+                  if Is_Private_Type (Id)
+                    and then Present (Full_View (Id))
+                  then
+                     Set_Is_Potentially_Use_Visible (Full_View (Id), False);
+                  end if;
+
+                  Next_Entity (Id);
+               end loop;
+
+               if Present (Renamed_Object (Pack)) then
+                  Set_In_Use (Renamed_Object (Pack), False);
+               end if;
+
+               if Chars (Pack) = Name_System
+                 and then Scope (Pack) = Standard_Standard
+                 and then Present_System_Aux
+               then
+                  Id := First_Entity (System_Aux_Id);
+
+                  while Present (Id) loop
+                     Set_Is_Potentially_Use_Visible (Id, False);
+
+                     if Is_Private_Type (Id)
+                       and then Present (Full_View (Id))
+                     then
+                        Set_Is_Potentially_Use_Visible (Full_View (Id), False);
+                     end if;
+
+                     Next_Entity (Id);
+                  end loop;
+
+                  Set_In_Use (System_Aux_Id, False);
+               end if;
+
+            else
+               Set_Redundant_Use (Pack_Name, False);
+            end if;
+
+         end if;
+
+         Next (Pack_Name);
+      end loop;
+
+      if Present (Hidden_By_Use_Clause (N)) then
+         Elmt := First_Elmt (Hidden_By_Use_Clause (N));
+
+         while Present (Elmt) loop
+            Set_Is_Immediately_Visible (Node (Elmt));
+            Next_Elmt (Elmt);
+         end loop;
+
+         Set_Hidden_By_Use_Clause (N, No_Elist);
+      end if;
+   end End_Use_Package;
+
+   ------------------
+   -- End_Use_Type --
+   ------------------
+
+   procedure End_Use_Type (N : Node_Id) is
+      Id      : Entity_Id;
+      Op_List : Elist_Id;
+      Elmt    : Elmt_Id;
+      T       : Entity_Id;
+
+   begin
+      Id := First (Subtype_Marks (N));
+
+      while Present (Id) loop
+         T := Entity (Id);
+
+         if T = Any_Type then
+            null;
+
+         --  Note that the use_Type clause may mention a subtype of the
+         --  type whose primitive operations have been made visible. Here
+         --  as elsewhere, it is the base type that matters for visibility.
+
+         elsif In_Open_Scopes (Scope (Base_Type (T))) then
+            null;
+
+         elsif not Redundant_Use (Id) then
+            Set_In_Use (T, False);
+            Set_In_Use (Base_Type (T), False);
+            Op_List := Collect_Primitive_Operations (T);
+            Elmt := First_Elmt (Op_List);
+
+            while Present (Elmt) loop
+
+               if Nkind (Node (Elmt)) = N_Defining_Operator_Symbol then
+                  Set_Is_Potentially_Use_Visible (Node (Elmt), False);
+               end if;
+
+               Next_Elmt (Elmt);
+            end loop;
+         end if;
+
+         Next (Id);
+      end loop;
+   end End_Use_Type;
+
+   ----------------------
+   -- Find_Direct_Name --
+   ----------------------
+
+   procedure Find_Direct_Name (N : Node_Id) is
+      E    : Entity_Id;
+      E2   : Entity_Id;
+      Msg  : Boolean;
+
+      Inst : Entity_Id := Empty;
+      --  Enclosing instance, if any.
+
+      Homonyms : Entity_Id;
+      --  Saves start of homonym chain
+
+      Nvis_Entity : Boolean;
+      --  Set True to indicate that at there is at least one entity on the
+      --  homonym chain which, while not visible, is visible enough from the
+      --  user point of view to warrant an error message of "not visible"
+      --  rather than undefined.
+
+      function From_Actual_Package (E : Entity_Id) return Boolean;
+      --  Returns true if the entity is declared in a package that is
+      --  an actual for a formal package of the current instance. Such an
+      --  entity requires special handling because it may be use-visible
+      --  but hides directly visible entities defined outside the instance.
+
+      function Known_But_Invisible (E : Entity_Id) return Boolean;
+      --  This function determines whether the entity E (which is not
+      --  visible) can reasonably be considered to be known to the writer
+      --  of the reference. This is a heuristic test, used only for the
+      --  purposes of figuring out whether we prefer to complain that an
+      --  entity is undefined or invisible (and identify the declaration
+      --  of the invisible entity in the latter case). The point here is
+      --  that we don't want to complain that something is invisible and
+      --  then point to something entirely mysterious to the writer.
+
+      procedure Nvis_Messages;
+      --  Called if there are no visible entries for N, but there is at least
+      --  one non-directly visible, or hidden declaration. This procedure
+      --  outputs an appropriate set of error messages.
+
+      procedure Undefined (Nvis : Boolean);
+      --  This function is called if the current node has no corresponding
+      --  visible entity or entities. The value set in Msg indicates whether
+      --  an error message was generated (multiple error messages for the
+      --  same variable are generally suppressed, see body for details).
+      --  Msg is True if an error message was generated, False if not. This
+      --  value is used by the caller to determine whether or not to output
+      --  additional messages where appropriate. The parameter is set False
+      --  to get the message "X is undefined", and True to get the message
+      --  "X is not visible".
+
+      -------------------------
+      -- From_Actual_Package --
+      -------------------------
+
+      function From_Actual_Package (E : Entity_Id) return Boolean is
+         Scop : constant Entity_Id := Scope (E);
+         Act  : Entity_Id;
+
+      begin
+         if not In_Instance then
+            return False;
+         else
+            Inst := Current_Scope;
+
+            while Present (Inst)
+              and then Ekind (Inst) /= E_Package
+              and then not Is_Generic_Instance (Inst)
+            loop
+               Inst := Scope (Inst);
+            end loop;
+
+            if No (Inst) then
+               return False;
+            end if;
+
+            Act := First_Entity (Inst);
+
+            while Present (Act) loop
+               if Ekind (Act) = E_Package then
+
+                  --  Check for end of actuals list
+
+                  if Renamed_Object (Act) = Inst then
+                     return False;
+
+                  elsif Present (Associated_Formal_Package (Act))
+                    and then Renamed_Object (Act) = Scop
+                  then
+                     --  Entity comes from (instance of) formal package
+
+                     return True;
+
+                  else
+                     Next_Entity (Act);
+                  end if;
+
+               else
+                  Next_Entity (Act);
+               end if;
+            end loop;
+
+            return False;
+         end if;
+      end From_Actual_Package;
+
+      -------------------------
+      -- Known_But_Invisible --
+      -------------------------
+
+      function Known_But_Invisible (E : Entity_Id) return Boolean is
+         Fname : File_Name_Type;
+
+      begin
+         --  Entities in Standard are always considered to be known
+
+         if Sloc (E) <= Standard_Location then
+            return True;
+
+         --  An entity that does not come from source is always considered
+         --  to be unknown, since it is an artifact of code expansion.
+
+         elsif not Comes_From_Source (E) then
+            return False;
+
+         --  In gnat internal mode, we consider all entities known
+
+         elsif GNAT_Mode then
+            return True;
+         end if;
+
+         --  Here we have an entity that is not from package Standard, and
+         --  which comes from Source. See if it comes from an internal file.
+
+         Fname := Unit_File_Name (Get_Source_Unit (E));
+
+         --  Case of from internal file
+
+         if Is_Internal_File_Name (Fname) then
+
+            --  Private part entities in internal files are never considered
+            --  to be known to the writer of normal application code.
+
+            if Is_Hidden (E) then
+               return False;
+            end if;
+
+            --  Entities from System packages other than System and
+            --  System.Storage_Elements are not considered to be known.
+            --  System.Auxxxx files are also considered known to the user.
+
+            --  Should refine this at some point to generally distinguish
+            --  between known and unknown internal files ???
+
+            Get_Name_String (Fname);
+
+            return
+              Name_Len < 2
+                or else
+              Name_Buffer (1 .. 2) /= "s-"
+                or else
+              Name_Buffer (3 .. 8) = "stoele"
+                or else
+              Name_Buffer (3 .. 5) = "aux";
+
+         --  If not an internal file, then entity is definitely known,
+         --  even if it is in a private part (the message generated will
+         --  note that it is in a private part)
+
+         else
+            return True;
+         end if;
+      end Known_But_Invisible;
+
+      -------------------
+      -- Nvis_Messages --
+      -------------------
+
+      procedure Nvis_Messages is
+         Ent    : Entity_Id;
+         Hidden : Boolean := False;
+
+      begin
+         Undefined (Nvis => True);
+
+         if Msg then
+
+            --  First loop does hidden declarations
+
+            Ent := Homonyms;
+            while Present (Ent) loop
+               if Is_Potentially_Use_Visible (Ent) then
+
+                  if not Hidden then
+                     Error_Msg_N ("multiple use clauses cause hiding!", N);
+                     Hidden := True;
+                  end if;
+
+                  Error_Msg_Sloc := Sloc (Ent);
+                  Error_Msg_N ("hidden declaration#!", N);
+               end if;
+
+               Ent := Homonym (Ent);
+            end loop;
+
+            --  If we found hidden declarations, then that's enough, don't
+            --  bother looking for non-visible declarations as well.
+
+            if Hidden then
+               return;
+            end if;
+
+            --  Second loop does non-directly visible declarations
+
+            Ent := Homonyms;
+            while Present (Ent) loop
+               if not Is_Potentially_Use_Visible (Ent) then
+
+                  --  Do not bother the user with unknown entities
+
+                  if not Known_But_Invisible (Ent) then
+                     goto Continue;
+                  end if;
+
+                  Error_Msg_Sloc := Sloc (Ent);
+
+                  --  Output message noting that there is a non-visible
+                  --  declaration, distinguishing the private part case.
+
+                  if Is_Hidden (Ent) then
+                     Error_Msg_N ("non-visible (private) declaration#!", N);
+                  else
+                     Error_Msg_N ("non-visible declaration#!", N);
+                  end if;
+               end if;
+
+               <<Continue>>
+               Ent := Homonym (Ent);
+            end loop;
+
+         end if;
+      end Nvis_Messages;
+
+      ---------------
+      -- Undefined --
+      ---------------
+
+      procedure Undefined (Nvis : Boolean) is
+         Emsg : Error_Msg_Id;
+
+      begin
+         --  A very specialized error check, if the undefined variable is
+         --  a case tag, and the case type is an enumeration type, check
+         --  for a possible misspelling, and if so, modify the identifier
+
+         --  Named aggregate should also be handled similarly ???
+
+         if Nkind (N) = N_Identifier
+           and then Nkind (Parent (N)) = N_Case_Statement_Alternative
+         then
+            Get_Name_String (Chars (N));
+
+            declare
+               Case_Str : constant String    := Name_Buffer (1 .. Name_Len);
+               Case_Stm : constant Node_Id   := Parent (Parent (N));
+               Case_Typ : constant Entity_Id := Etype (Expression (Case_Stm));
+
+               Lit : Node_Id;
+
+            begin
+               if Is_Enumeration_Type (Case_Typ)
+                 and then Case_Typ /= Standard_Character
+                 and then Case_Typ /= Standard_Wide_Character
+               then
+                  Lit := First_Literal (Case_Typ);
+                  Get_Name_String (Chars (Lit));
+
+                  if Chars (Lit) /= Chars (N)
+                    and then Is_Bad_Spelling_Of
+                      (Case_Str, Name_Buffer (1 .. Name_Len))
+                  then
+                     Error_Msg_Node_2 := Lit;
+                     Error_Msg_N
+                       ("& is undefined, assume misspelling of &", N);
+                     Rewrite (N, New_Occurrence_Of (Lit, Sloc (N)));
+                     return;
+                  end if;
+
+                  Lit := Next_Literal (Lit);
+               end if;
+            end;
+         end if;
+
+         --  Normal processing
+
+         Set_Entity (N, Any_Id);
+         Set_Etype  (N, Any_Type);
+
+         --  We use the table Urefs to keep track of entities for which we
+         --  have issued errors for undefined references. Multiple errors
+         --  for a single name are normally suppressed, however we modify
+         --  the error message to alert the programmer to this effect.
+
+         for J in Urefs.First .. Urefs.Last loop
+            if Chars (N) = Chars (Urefs.Table (J).Node) then
+               if Urefs.Table (J).Err /= No_Error_Msg
+                 and then Sloc (N) /= Urefs.Table (J).Loc
+               then
+                  Error_Msg_Node_1 := Urefs.Table (J).Node;
+
+                  if Urefs.Table (J).Nvis then
+                     Change_Error_Text (Urefs.Table (J).Err,
+                       "& is not visible (more references follow)");
+                  else
+                     Change_Error_Text (Urefs.Table (J).Err,
+                       "& is undefined (more references follow)");
+                  end if;
+
+                  Urefs.Table (J).Err := No_Error_Msg;
+               end if;
+
+               --  Although we will set Msg False, and thus suppress the
+               --  message, we also set Error_Posted True, to avoid any
+               --  cascaded messages resulting from the undefined reference.
+
+               Msg := False;
+               Set_Error_Posted (N, True);
+               return;
+            end if;
+         end loop;
+
+         --  If entry not found, this is first undefined occurrence
+
+         if Nvis then
+            Error_Msg_N ("& is not visible!", N);
+            Emsg := Get_Msg_Id;
+
+         else
+            Error_Msg_N ("& is undefined!", N);
+            Emsg := Get_Msg_Id;
+
+            --  A very bizarre special check, if the undefined identifier
+            --  is put or put_line, then add a special error message (since
+            --  this is a very common error for beginners to make).
+
+            if Chars (N) = Name_Put or else Chars (N) = Name_Put_Line then
+               Error_Msg_N ("\possible missing with of 'Text_'I'O!", N);
+            end if;
+
+            --  Now check for possible misspellings
+
+            Get_Name_String (Chars (N));
+
+            declare
+               E      : Entity_Id;
+               Ematch : Entity_Id := Empty;
+
+               Last_Name_Id : constant Name_Id :=
+                                Name_Id (Nat (First_Name_Id) +
+                                           Name_Entries_Count - 1);
+
+               S  : constant String (1 .. Name_Len) :=
+                      Name_Buffer (1 .. Name_Len);
+
+            begin
+               for N in First_Name_Id .. Last_Name_Id loop
+                  E := Get_Name_Entity_Id (N);
+
+                  if Present (E)
+                     and then (Is_Immediately_Visible (E)
+                                 or else
+                               Is_Potentially_Use_Visible (E))
+                  then
+                     Get_Name_String (N);
+
+                     if Is_Bad_Spelling_Of
+                          (Name_Buffer (1 .. Name_Len), S)
+                     then
+                        Ematch := E;
+                        exit;
+                     end if;
+                  end if;
+               end loop;
+
+               if Present (Ematch) then
+                  Error_Msg_NE ("\possible misspelling of&", N, Ematch);
+               end if;
+            end;
+         end if;
+
+         --  Make entry in undefined references table unless the full
+         --  errors switch is set, in which case by refraining from
+         --  generating the table entry, we guarantee that we get an
+         --  error message for every undefined reference.
+
+         if not All_Errors_Mode then
+            Urefs.Increment_Last;
+            Urefs.Table (Urefs.Last).Node := N;
+            Urefs.Table (Urefs.Last).Err  := Emsg;
+            Urefs.Table (Urefs.Last).Nvis := Nvis;
+            Urefs.Table (Urefs.Last).Loc  := Sloc (N);
+         end if;
+
+         Msg := True;
+      end Undefined;
+
+   --  Start of processing for Find_Direct_Name
+
+   begin
+      --  If the entity pointer is already set, this is an internal node, or
+      --  a node that is analyzed more than once, after a tree modification.
+      --  In such a case there is no resolution to perform, just set the type.
+
+      if Present (Entity (N)) then
+         if Is_Type (Entity (N)) then
+            Set_Etype (N, Entity (N));
+
+         else
+            declare
+               Entyp : constant Entity_Id := Etype (Entity (N));
+
+            begin
+               --  One special case here. If the Etype field is already set,
+               --  and references the packed array type corresponding to the
+               --  etype of the referenced entity, then leave it alone. This
+               --  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)
+                 and then Present (Etype (N))
+                 and then Etype (N) = Packed_Array_Type (Entyp)
+               then
+                  null;
+
+               --  If not that special case, then just reset the Etype
+
+               else
+                  Set_Etype (N, Etype (Entity (N)));
+               end if;
+            end;
+         end if;
+
+         return;
+      end if;
+
+      --  Here if Entity pointer was not set, we need full visibility analysis
+      --  First we generate debugging output if the debug E flag is set.
+
+      if Debug_Flag_E then
+         Write_Str ("Looking for ");
+         Write_Name (Chars (N));
+         Write_Eol;
+      end if;
+
+      Homonyms := Current_Entity (N);
+      Nvis_Entity := False;
+
+      E := Homonyms;
+      while Present (E) loop
+
+         --  If entity is immediately visible or potentially use
+         --  visible, then process the entity and we are done.
+
+         if Is_Immediately_Visible (E) then
+            goto Immediately_Visible_Entity;
+
+         elsif Is_Potentially_Use_Visible (E) then
+            goto Potentially_Use_Visible_Entity;
+
+         --  Note if a known but invisible entity encountered
+
+         elsif Known_But_Invisible (E) then
+            Nvis_Entity := True;
+         end if;
+
+         --  Move to next entity in chain and continue search
+
+         E := Homonym (E);
+      end loop;
+
+      --  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
+      --  explanation required!
+
+      if not Nvis_Entity then
+         Undefined (Nvis => False);
+         return;
+
+      --  Otherwise there is at least one entry on the homonym chain that
+      --  is reasonably considered as being known and non-visible.
+
+      else
+         Nvis_Messages;
+         return;
+      end if;
+
+      --  Processing for a potentially use visible entry found. We must search
+      --  the rest of the homonym chain for two reasons. First, if there is a
+      --  directly visible entry, then none of the potentially use-visible
+      --  entities are directly visible (RM 8.4(10)). Second, we need to check
+      --  for the case of multiple potentially use-visible entries hiding one
+      --  another and as a result being non-directly visible (RM 8.4(11)).
+
+      <<Potentially_Use_Visible_Entity>> declare
+         Only_One_Visible : Boolean := True;
+         All_Overloadable : Boolean := Is_Overloadable (E);
+
+      begin
+         E2 := Homonym (E);
+
+         while Present (E2) loop
+            if Is_Immediately_Visible (E2) then
+
+               --  If the use-visible entity comes from the actual for a
+               --  formal package, it hides a directly visible entity from
+               --  outside the instance.
+
+               if From_Actual_Package (E)
+                 and then Scope_Depth (E2) < Scope_Depth (Inst)
+               then
+                  goto Found;
+               else
+                  E := E2;
+                  goto Immediately_Visible_Entity;
+               end if;
+
+            elsif Is_Potentially_Use_Visible (E2) then
+               Only_One_Visible := False;
+               All_Overloadable := All_Overloadable and Is_Overloadable (E2);
+            end if;
+
+            E2 := Homonym (E2);
+         end loop;
+
+         --  On falling through this loop, we have checked that there are no
+         --  immediately visible entities. Only_One_Visible is set if exactly
+         --  one potentially use visible entity exists. All_Overloadable is
+         --  set if all the potentially use visible entities are overloadable.
+         --  The condition for legality is that either there is one potentially
+         --  use visible entity, or if there is more than one, then all of them
+         --  are overloadable.
+
+         if Only_One_Visible or All_Overloadable then
+            goto Found;
+
+         --  If there is more than one potentially use-visible entity and at
+         --  least one of them non-overloadable, we have an error (RM 8.4(11).
+         --  Note that E points to the first such entity on the homonym list.
+         --  Special case: if one of the entities is declared in an actual
+         --  package, it was visible in the generic, and takes precedence over
+         --  other entities that are potentially use-visible.
+
+         else
+            if In_Instance then
+               E2 := E;
+
+               while Present (E2) loop
+                  if Is_Generic_Instance (Scope (E2)) then
+                     E := E2;
+                     goto Found;
+                  end if;
+
+                  E2 := Homonym (E2);
+               end loop;
+
+               Nvis_Messages;
+               return;
+
+            else
+               Nvis_Messages;
+               return;
+            end if;
+         end if;
+      end;
+
+      --  Come here with E set to the first immediately visible entity on
+      --  the homonym chain. This is the one we want unless there is another
+      --  immediately visible entity further on in the chain for a more
+      --  inner scope (RM 8.3(8)).
+
+      <<Immediately_Visible_Entity>> declare
+         Level : Int;
+         Scop  : Entity_Id;
+
+      begin
+         --  Find scope level of initial entity. When compiling  through
+         --  Rtsfind, the previous context is not completely invisible, and
+         --  an outer entity may appear on the chain, whose scope is below
+         --  the entry for Standard that delimits the current scope stack.
+         --  Indicate that the level for this spurious entry is outside of
+         --  the current scope stack.
+
+         Level := Scope_Stack.Last;
+         loop
+            Scop := Scope_Stack.Table (Level).Entity;
+            exit when Scop = Scope (E);
+            Level := Level - 1;
+            exit when Scop = Standard_Standard;
+         end loop;
+
+         --  Now search remainder of homonym chain for more inner entry
+         --  If the entity is Standard itself, it has no scope, and we
+         --  compare it with the stack entry directly.
+
+         E2 := Homonym (E);
+         while Present (E2) loop
+            if Is_Immediately_Visible (E2) then
+               for J in Level + 1 .. Scope_Stack.Last loop
+                  if Scope_Stack.Table (J).Entity = Scope (E2)
+                    or else Scope_Stack.Table (J).Entity = E2
+                  then
+                     Level := J;
+                     E := E2;
+                     exit;
+                  end if;
+               end loop;
+            end if;
+
+            E2 := Homonym (E2);
+         end loop;
+
+         --  At the end of that loop, E is the innermost immediately
+         --  visible entity, so we are all set.
+      end;
+
+      --  Come here with entity found, and stored in E
+
+      <<Found>> begin
+
+         if Comes_From_Source (N)
+           and then Is_Remote_Access_To_Subprogram_Type (E)
+           and then Expander_Active
+         then
+            Rewrite (N,
+              New_Occurrence_Of (Equivalent_Type (E), Sloc (N)));
+            return;
+         end if;
+
+         Set_Entity (N, E);
+         --  Why no Style_Check here???
+
+         if Is_Type (E) then
+            Set_Etype (N, E);
+         else
+            Set_Etype (N, Get_Full_View (Etype (E)));
+         end if;
+
+         if Debug_Flag_E then
+            Write_Str (" found  ");
+            Write_Entity_Info (E, "      ");
+         end if;
+
+         --  If the Ekind of the entity is Void, it means that all homonyms
+         --  are hidden from all visibility (RM 8.3(5,14-20)). However, this
+         --  test is skipped if the current scope is a record and the name is
+         --  a pragma argument expression (case of Atomic and Volatile pragmas
+         --  and possibly other similar pragmas added later, which are allowed
+         --  to reference components in the current record).
+
+         if Ekind (E) = E_Void
+           and then
+             (not Is_Record_Type (Current_Scope)
+               or else Nkind (Parent (N)) /= N_Pragma_Argument_Association)
+         then
+            Premature_Usage (N);
+
+         --  If the entity is overloadable, collect all interpretations
+         --  of the name for subsequent overload resolution. We optimize
+         --  a bit here to do this only if we have an overloadable entity
+         --  that is not on its own on the homonym chain.
+
+         elsif Is_Overloadable (E)
+           and then (Present (Homonym (E)) or else Current_Entity (N) /= E)
+         then
+            Collect_Interps (N);
+
+            --  If no homonyms were visible, the entity is unambiguous.
+
+            if not Is_Overloaded (N) then
+               Generate_Reference (E, N);
+            end if;
+
+         --  Case of non-overloadable entity, set the entity providing that
+         --  we do not have the case of a discriminant reference within a
+         --  default expression. Such references are replaced with the
+         --  corresponding discriminal, which is the formal corresponding to
+         --  to the discriminant in the initialization procedure.
+
+         --  This replacement must not be done if we are currently processing
+         --  a generic spec or body.
+
+         --  The replacement is not done either for a task discriminant that
+         --  appears in a default expression of an entry parameter. See
+         --  Expand_Discriminant in exp_ch2 for details on their handling.
+
+         else
+            --  Entity is unambiguous, indicate that it is referenced here
+            --  One slightly odd case is that we do not want to set the
+            --  Referenced flag if the entity is a label, and the identifier
+            --  is the label in the source, since this is not a reference
+            --  from the point of view of the user
+
+            if Nkind (Parent (N)) = N_Label then
+               declare
+                  R : constant Boolean := Referenced (E);
+
+               begin
+                  Generate_Reference (E, N);
+                  Set_Referenced (E, R);
+               end;
+
+            else
+               Generate_Reference (E, N);
+            end if;
+
+            if not In_Default_Expression
+              or else Ekind (E) /= E_Discriminant
+              or else Inside_A_Generic
+            then
+               Set_Entity_With_Style_Check (N, E);
+
+            elsif Is_Concurrent_Type (Scope (E)) then
+               declare
+                  P : Node_Id := Parent (N);
+
+               begin
+                  while Present (P)
+                    and then Nkind (P) /= N_Parameter_Specification
+                    and then Nkind (P) /= N_Component_Declaration
+                  loop
+                     P := Parent (P);
+                  end loop;
+
+                  if Present (P)
+                     and then Nkind (P) = N_Parameter_Specification
+                  then
+                     null;
+                  else
+                     Set_Entity (N, Discriminal (E));
+                  end if;
+               end;
+
+            else
+               Set_Entity (N, Discriminal (E));
+            end if;
+         end if;
+      end;
+   end Find_Direct_Name;
+
+   ------------------------
+   -- Find_Expanded_Name --
+   ------------------------
+
+   --  This routine searches the homonym chain of the entity until it finds
+   --  an entity declared in the scope denoted by the prefix. If the entity
+   --  is private, it may nevertheless be immediately visible, if we are in
+   --  the scope of its declaration.
+
+   procedure Find_Expanded_Name (N : Node_Id) is
+      Candidate : Entity_Id := Empty;
+      Selector  : constant Node_Id    := Selector_Name (N);
+      P_Name    : Entity_Id;
+      O_Name    : Entity_Id;
+      Id        : Entity_Id;
+
+   begin
+      P_Name := Entity (Prefix (N));
+      O_Name := P_Name;
+
+      --  If the prefix is a renamed package, look for the entity
+      --  in the original package.
+
+      if Ekind (P_Name) = E_Package
+        and then Present (Renamed_Object (P_Name))
+      then
+         P_Name := Renamed_Object (P_Name);
+
+         --  Rewrite node with entity field pointing to renamed object
+
+         Rewrite (Prefix (N), New_Copy (Prefix (N)));
+         Set_Entity (Prefix (N), P_Name);
+
+      --  If the prefix is an object of a concurrent type, look for
+      --  the entity in the associated task or protected type.
+
+      elsif Is_Concurrent_Type (Etype (P_Name)) then
+         P_Name := Etype (P_Name);
+      end if;
+
+      Id := Current_Entity (Selector);
+
+      while Present (Id) loop
+
+         if Scope (Id) = P_Name then
+            Candidate := Id;
+
+            if Is_Child_Unit (Id) then
+               exit when
+                 (Is_Visible_Child_Unit (Id)
+                    or else Is_Immediately_Visible (Id));
+
+            else
+               exit when
+                   (not Is_Hidden (Id) or else Is_Immediately_Visible (Id));
+            end if;
+         end if;
+
+         Id := Homonym (Id);
+      end loop;
+
+      if No (Id)
+        and then (Ekind (P_Name) = E_Procedure
+                    or else
+                  Ekind (P_Name) = E_Function)
+        and then Is_Generic_Instance (P_Name)
+      then
+         --  Expanded name denotes entity in (instance of) generic subprogram.
+         --  The entity may be in the subprogram instance, or may denote one of
+         --  the formals, which is declared in the enclosing wrapper package.
+
+         P_Name := Scope (P_Name);
+         Id := Current_Entity (Selector);
+
+         while Present (Id) loop
+            exit when  Scope (Id) = P_Name;
+            Id := Homonym (Id);
+         end loop;
+      end if;
+
+      if No (Id) or else Chars (Id) /=  Chars (Selector) then
+
+         Set_Etype (N, Any_Type);
+
+         --  If we are looking for an entity defined in System, try to
+         --  find it in the child package that may have been provided as
+         --  an extension to System. The Extend_System pragma will have
+         --  supplied the name of the extension, which may have to be loaded.
+
+         if Chars (P_Name) = Name_System
+           and then Scope (P_Name) = Standard_Standard
+           and then Present (System_Extend_Pragma_Arg)
+           and then Present_System_Aux (N)
+         then
+            Set_Entity (Prefix (N), System_Aux_Id);
+            Find_Expanded_Name (N);
+            return;
+
+         elsif (Nkind (Selector) = N_Operator_Symbol
+           and then Has_Implicit_Operator (N))
+         then
+            --  There is an implicit instance of the predefined operator in
+            --  the given scope. The operator entity is defined in Standard.
+            --  Has_Implicit_Operator makes the node into an Expanded_Name.
+
+            return;
+
+         elsif Nkind (Selector) = N_Character_Literal
+           and then Has_Implicit_Character_Literal (N)
+         then
+            --  If there is no literal defined in the scope denoted by the
+            --  prefix, the literal may belong to (a type derived from)
+            --  Standard_Character, for which we have no explicit literals.
+
+            return;
+
+         else
+            --  If the prefix is a single concurrent object, use its
+            --  name in  the error message, rather than that of the
+            --  anonymous type.
+
+            if Is_Concurrent_Type (P_Name)
+              and then Is_Internal_Name (Chars (P_Name))
+            then
+               Error_Msg_Node_2 := Entity (Prefix (N));
+            else
+               Error_Msg_Node_2 := P_Name;
+            end if;
+
+            if P_Name = System_Aux_Id then
+               P_Name := Scope (P_Name);
+               Set_Entity (Prefix (N), P_Name);
+            end if;
+
+            if Present (Candidate) then
+
+               if Is_Child_Unit (Candidate) then
+                  Error_Msg_N
+                    ("missing with_clause for child unit &", Selector);
+               else
+                  Error_Msg_NE ("& is not a visible entity of&", N, Selector);
+               end if;
+
+            else
+               --  Within the instantiation of a child unit, the prefix may
+               --  denote the parent instance, but the selector has the
+               --  name of the original child. Find whether we are within
+               --  the corresponding instance, and get the proper entity, which
+               --  can only be an enclosing scope.
+
+               if O_Name /= P_Name
+                 and then In_Open_Scopes (P_Name)
+                 and then Is_Generic_Instance (P_Name)
+               then
+                  declare
+                     S : Entity_Id := Current_Scope;
+                     P : Entity_Id;
+
+                  begin
+                     for J in reverse 0 .. Scope_Stack.Last loop
+                        S := Scope_Stack.Table (J).Entity;
+
+                        exit when S = Standard_Standard;
+
+                        if Ekind (S) = E_Function
+                          or else Ekind (S) = E_Package
+                          or else Ekind (S) = E_Procedure
+                        then
+                           P := Generic_Parent (Specification
+                                  (Unit_Declaration_Node (S)));
+
+                           if Present (P)
+                             and then Chars (Scope (P)) = Chars (O_Name)
+                             and then Chars (P) = Chars (Selector)
+                           then
+                              Id := S;
+                              goto found;
+                           end if;
+                        end if;
+
+                     end loop;
+                  end;
+               end if;
+
+               if (Chars (P_Name) = Name_Ada
+                     and then Scope (P_Name) = Standard_Standard)
+               then
+                  Error_Msg_Node_2 := Selector;
+                  Error_Msg_NE
+                    ("\missing with for `&.&`", N, P_Name);
+
+               --  If this is a selection from a dummy package, then
+               --  suppress the error message, of course the entity
+               --  is missing if the package is missing!
+
+               elsif Sloc (Error_Msg_Node_2) = No_Location then
+                  null;
+
+               --  Here we have the case of an undefined component
+
+               else
+
+                  Error_Msg_NE ("& not declared in&", N, Selector);
+
+                  --  Check for misspelling of some entity in prefix.
+
+                  Id := First_Entity (P_Name);
+                  Get_Name_String (Chars (Selector));
+
+                  declare
+                     S  : constant String (1 .. Name_Len) :=
+                            Name_Buffer (1 .. Name_Len);
+                  begin
+                     while Present (Id) loop
+                        Get_Name_String (Chars (Id));
+                        if Is_Bad_Spelling_Of
+                          (Name_Buffer (1 .. Name_Len), S)
+                          and then not Is_Internal_Name (Chars (Id))
+                        then
+                           Error_Msg_NE
+                             ("possible misspelling of&", Selector, Id);
+                           exit;
+                        end if;
+
+                        Next_Entity (Id);
+                     end loop;
+                  end;
+
+                  --  Specialize the message if this may be an instantiation
+                  --  of a child unit that was not mentioned in the context.
+
+                  if Nkind (Parent (N)) = N_Package_Instantiation
+                    and then Is_Generic_Instance (Entity (Prefix (N)))
+                    and then Is_Compilation_Unit
+                     (Generic_Parent (Parent (Entity (Prefix (N)))))
+                  then
+                     Error_Msg_NE
+                      ("\possible missing with clause on child unit&",
+                        N, Selector);
+                  end if;
+               end if;
+            end if;
+
+            Id := Any_Id;
+         end if;
+      end if;
+
+      <<found>>
+      if Comes_From_Source (N)
+        and then Is_Remote_Access_To_Subprogram_Type (Id)
+      then
+         Id := Equivalent_Type (Id);
+         Set_Chars (Selector, Chars (Id));
+      end if;
+
+      if Ekind (P_Name) = E_Package
+        and then From_With_Type (P_Name)
+      then
+         if From_With_Type (Id)
+           or else (Ekind (Id) = E_Package and then From_With_Type (Id))
+         then
+            null;
+         else
+            Error_Msg_N
+              ("imported package can only be used to access imported type",
+                N);
+         end if;
+      end if;
+
+      if Is_Task_Type (P_Name)
+        and then ((Ekind (Id) = E_Entry
+                    and then Nkind (Parent (N)) /= N_Attribute_Reference)
+                    or else
+                  (Ekind (Id) = E_Entry_Family
+                    and then
+                      Nkind (Parent (Parent (N))) /= N_Attribute_Reference))
+      then
+         --  It is an entry call after all, either to the current task
+         --  (which will deadlock) or to an enclosing task.
+
+         Analyze_Selected_Component (N);
+         return;
+      end if;
+
+      Change_Selected_Component_To_Expanded_Name (N);
+      Set_Entity_With_Style_Check (N, Id);
+      Generate_Reference (Id, N);
+
+      if Is_Type (Id) then
+         Set_Etype (N, Id);
+      else
+         Set_Etype (N, Get_Full_View (Etype (Id)));
+      end if;
+
+      --  If the Ekind of the entity is Void, it means that all homonyms
+      --  are hidden from all visibility (RM 8.3(5,14-20)).
+
+      if Ekind (Id) = E_Void then
+         Premature_Usage (N);
+
+      elsif Is_Overloadable (Id)
+        and then Present (Homonym (Id))
+      then
+         declare
+            H : Entity_Id := Homonym (Id);
+
+         begin
+            while Present (H) loop
+               if Scope (H) = Scope (Id) then
+                  Collect_Interps (N);
+                  exit;
+               end if;
+
+               H := Homonym (H);
+            end loop;
+         end;
+      end if;
+
+      if Nkind (Selector_Name (N)) = N_Operator_Symbol
+        and then Scope (Id) /= Standard_Standard
+      then
+         --  In addition to user-defined operators in the given scope,
+         --  there may be an implicit instance of the predefined
+         --  operator. The operator (defined in Standard) is found
+         --  in Has_Implicit_Operator, and added to the interpretations.
+         --  Procedure Add_One_Interp will determine which hides which.
+
+         if Has_Implicit_Operator (N) then
+            null;
+         end if;
+      end if;
+   end Find_Expanded_Name;
+
+   -------------------------
+   -- Find_Renamed_Entity --
+   -------------------------
+
+   function Find_Renamed_Entity
+     (N         : Node_Id;
+      Nam       : Node_Id;
+      New_S     : Entity_Id;
+      Is_Actual : Boolean := False) return Entity_Id
+   is
+      I     : Interp_Index;
+      I1    : Interp_Index := 0; -- Suppress junk warnings
+      It    : Interp;
+      It1   : Interp;
+      Old_S : Entity_Id;
+      Inst  : Entity_Id;
+
+      function Enclosing_Instance return Entity_Id;
+      --  If the renaming determines the entity for the default of a formal
+      --  subprogram nested within another instance, choose the innermost
+      --  candidate. This is because if the formal has a box, and we are within
+      --  an enclosing instance where some candidate interpretations are local
+      --  to this enclosing instance, we know that the default was properly
+      --  resolved when analyzing the generic, so we prefer the local
+      --  candidates to those that are external. This is not always the case
+      --  but is a reasonable heuristic on the use of nested generics.
+      --  The proper solution requires a full renaming model.
+
+      function Within (Inner, Outer : Entity_Id) return Boolean;
+      --  Determine whether a candidate subprogram is defined within
+      --  the enclosing instance. If yes, it has precedence over outer
+      --  candidates.
+
+      function Is_Visible_Operation (Op : Entity_Id) return Boolean;
+      --  If the renamed entity is an implicit operator, check whether it is
+      --  visible because its operand type is properly visible. This
+      --  check applies to explicit renamed entities that appear in the
+      --  source in a renaming declaration or a formal subprogram instance,
+      --  but not to default generic actuals with a name.
+
+      ------------------------
+      -- Enclosing_Instance --
+      ------------------------
+
+      function Enclosing_Instance return Entity_Id is
+         S : Entity_Id;
+
+      begin
+         if not Is_Generic_Instance (Current_Scope)
+           and then not Is_Actual
+         then
+            return Empty;
+         end if;
+
+         S := Scope (Current_Scope);
+
+         while S /= Standard_Standard loop
+
+            if Is_Generic_Instance (S) then
+               return S;
+            end if;
+
+            S := Scope (S);
+         end loop;
+
+         return Empty;
+      end Enclosing_Instance;
+
+      --------------------------
+      -- Is_Visible_Operation --
+      --------------------------
+
+      function Is_Visible_Operation (Op : Entity_Id) return Boolean is
+         Scop : Entity_Id;
+         Typ  : Entity_Id;
+         Btyp : Entity_Id;
+
+      begin
+         if Ekind (Op) /= E_Operator
+           or else Scope (Op) /= Standard_Standard
+           or else (In_Instance
+                      and then
+                        (not Is_Actual
+                           or else Present (Enclosing_Instance)))
+         then
+            return True;
+
+         else
+            --  For a fixed point type operator, check the resulting type,
+            --  because it may be a mixed mode integer * fixed operation.
+
+            if Present (Next_Formal (First_Formal (New_S)))
+              and then Is_Fixed_Point_Type (Etype (New_S))
+            then
+               Typ := Etype (New_S);
+            else
+               Typ := Etype (First_Formal (New_S));
+            end if;
+
+            Btyp := Base_Type (Typ);
+
+            if Nkind (Nam) /= N_Expanded_Name then
+               return (In_Open_Scopes (Scope (Btyp))
+                        or else Is_Potentially_Use_Visible (Btyp)
+                        or else In_Use (Btyp)
+                        or else In_Use (Scope (Btyp)));
+
+            else
+               Scop := Entity (Prefix (Nam));
+
+               if Ekind (Scop) = E_Package
+                 and then Present (Renamed_Object (Scop))
+               then
+                  Scop := Renamed_Object (Scop);
+               end if;
+
+               --  Operator is visible if prefix of expanded name denotes
+               --  scope of type, or else type type is defined in System_Aux
+               --  and the prefix denotes System.
+
+               return Scope (Btyp) = Scop
+                 or else (Scope (Btyp) = System_Aux_Id
+                           and then Scope (Scope (Btyp)) = Scop);
+            end if;
+         end if;
+      end Is_Visible_Operation;
+
+      ------------
+      -- Within --
+      ------------
+
+      function Within (Inner, Outer : Entity_Id) return Boolean is
+         Sc : Entity_Id := Scope (Inner);
+
+      begin
+         while Sc /= Standard_Standard loop
+
+            if Sc = Outer then
+               return True;
+            else
+               Sc := Scope (Sc);
+            end if;
+         end loop;
+
+         return False;
+      end Within;
+
+   --  Start of processing for Find_Renamed_Entry
+
+   begin
+      Old_S := Any_Id;
+      Candidate_Renaming := Empty;
+
+      if not Is_Overloaded (Nam) then
+         if Entity_Matches_Spec (Entity (Nam), New_S)
+           and then Is_Visible_Operation (Entity (Nam))
+         then
+            Old_S := Entity (Nam);
+
+         elsif
+           Present (First_Formal (Entity (Nam)))
+             and then Present (First_Formal (New_S))
+             and then (Base_Type (Etype (First_Formal (Entity (Nam))))
+                        = Base_Type (Etype (First_Formal (New_S))))
+         then
+            Candidate_Renaming := Entity (Nam);
+         end if;
+
+      else
+         Get_First_Interp (Nam, I, It);
+
+         while Present (It.Nam) loop
+
+            if Entity_Matches_Spec (It.Nam, New_S)
+               and then Is_Visible_Operation (It.Nam)
+            then
+               if Old_S /= Any_Id then
+
+                  --  Note: The call to Disambiguate only happens if a
+                  --  previous interpretation was found, in which case I1
+                  --  has received a value.
+
+                  It1 := Disambiguate (Nam, I1, I, Etype (Old_S));
+
+                  if It1 = No_Interp then
+
+                     Inst := Enclosing_Instance;
+
+                     if Present (Inst) then
+
+                        if Within (It.Nam, Inst) then
+                           return (It.Nam);
+
+                        elsif Within (Old_S, Inst) then
+                           return (Old_S);
+
+                        else
+                           Error_Msg_N ("ambiguous renaming", N);
+                           return Old_S;
+                        end if;
+
+                     else
+                        Error_Msg_N ("ambiguous renaming", N);
+                        return Old_S;
+                     end if;
+
+                  else
+                     Old_S := It1.Nam;
+                     exit;
+                  end if;
+
+               else
+                  I1 := I;
+                  Old_S := It.Nam;
+               end if;
+
+            elsif
+              Present (First_Formal (It.Nam))
+                and then Present (First_Formal (New_S))
+                and then  (Base_Type (Etype (First_Formal (It.Nam)))
+                            = Base_Type (Etype (First_Formal (New_S))))
+            then
+               Candidate_Renaming := It.Nam;
+            end if;
+
+            Get_Next_Interp (I, It);
+         end loop;
+
+         Set_Entity (Nam, Old_S);
+         Set_Is_Overloaded (Nam, False);
+      end if;
+
+      return Old_S;
+   end Find_Renamed_Entity;
+
+   -----------------------------
+   -- Find_Selected_Component --
+   -----------------------------
+
+   procedure Find_Selected_Component (N : Node_Id) is
+      P : Node_Id := Prefix (N);
+
+      P_Name : Entity_Id;
+      --  Entity denoted by prefix
+
+      P_Type : Entity_Id;
+      --  and its type
+
+      Nam : Node_Id;
+
+   begin
+      Analyze (P);
+
+      if Nkind (P) = N_Error then
+         return;
+
+      --  If the selector already has an entity, the node has been
+      --  constructed in the course of expansion, and is known to be
+      --  valid. Do not verify that it is defined for the type (it may
+      --  be a private component used in the expansion of record equality).
+
+      elsif Present (Entity (Selector_Name (N))) then
+
+         if No (Etype (N))
+           or else Etype (N) = Any_Type
+         then
+            declare
+               Sel_Name : Node_Id   := Selector_Name (N);
+               Selector : Entity_Id := Entity (Sel_Name);
+               C_Etype  : Node_Id;
+
+            begin
+               Set_Etype (Sel_Name, Etype (Selector));
+
+               if not Is_Entity_Name (P) then
+                  Resolve (P, Etype (P));
+               end if;
+
+               --  Build an actual subtype except for the first parameter
+               --  of an init_proc, where this actual subtype is by
+               --  definition incorrect, since the object is uninitialized
+               --  (and does not even have defined discriminants etc.)
+
+               if Is_Entity_Name (P)
+                 and then Ekind (Entity (P)) = E_Function
+               then
+                  Nam := New_Copy (P);
+
+                  if Is_Overloaded (P) then
+                     Save_Interps (P, Nam);
+                  end if;
+
+                  Rewrite (P,
+                    Make_Function_Call (Sloc (P), Name => Nam));
+                  Analyze_Call (P);
+                  Analyze_Selected_Component (N);
+                  return;
+
+               elsif Ekind (Selector) = E_Component
+                 and then (not Is_Entity_Name (P)
+                            or else Chars (Entity (P)) /= Name_uInit)
+               then
+                  C_Etype :=
+                    Build_Actual_Subtype_Of_Component (
+                      Etype (Selector), N);
+               else
+                  C_Etype := Empty;
+               end if;
+
+               if No (C_Etype) then
+                  C_Etype := Etype (Selector);
+               else
+                  Insert_Action (N, C_Etype);
+                  C_Etype := Defining_Identifier (C_Etype);
+               end if;
+
+               Set_Etype (N, C_Etype);
+            end;
+
+            --  If this is the name of an entry or protected operation, and
+            --  the prefix is an access type, insert an explicit dereference,
+            --  so that entry calls are treated uniformly.
+
+            if Is_Access_Type (Etype (P))
+              and then Is_Concurrent_Type (Designated_Type (Etype (P)))
+            then
+               declare
+                  New_P :  Node_Id :=
+                    Make_Explicit_Dereference (Sloc (P),
+                      Prefix => Relocate_Node (P));
+               begin
+                  Rewrite (P, New_P);
+                  Set_Etype (P, Designated_Type (Etype (Prefix (P))));
+               end;
+            end if;
+
+         --  If the selected component appears within a default expression
+         --  and it has an actual subtype, the pre-analysis has not yet
+         --  completed its analysis, because Insert_Actions is disabled in
+         --  that context. Within the init_proc of the enclosing type we
+         --  must complete this analysis, if an actual subtype was created.
+
+         elsif Inside_Init_Proc then
+            declare
+               Typ  : constant Entity_Id := Etype (N);
+               Decl : constant Node_Id   := Declaration_Node (Typ);
+
+            begin
+               if Nkind (Decl) = N_Subtype_Declaration
+                 and then not Analyzed (Decl)
+                 and then Is_List_Member (Decl)
+                 and then No (Parent (Decl))
+               then
+                  Remove (Decl);
+                  Insert_Action (N, Decl);
+               end if;
+            end;
+         end if;
+
+         return;
+
+      elsif Is_Entity_Name (P) then
+         P_Name := Entity (P);
+
+         --  The prefix may denote an enclosing type which is the completion
+         --  of an incomplete type declaration.
+
+         if Is_Type (P_Name) then
+            Set_Entity (P, Get_Full_View (P_Name));
+            Set_Etype  (P, Entity (P));
+            P_Name := Entity (P);
+         end if;
+
+         P_Type := Base_Type (Etype (P));
+
+         if Debug_Flag_E then
+            Write_Str ("Found prefix type to be ");
+            Write_Entity_Info (P_Type, "      "); Write_Eol;
+         end if;
+
+         --  First check for components of a record object (not the
+         --  result of a call, which is handled below).
+
+         if Is_Appropriate_For_Record (P_Type)
+           and then not Is_Overloadable (P_Name)
+           and then not Is_Type (P_Name)
+         then
+            --  Selected component of record. Type checking will validate
+            --  name of selector.
+
+            Analyze_Selected_Component (N);
+
+         elsif Is_Appropriate_For_Entry_Prefix (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)))
+         then
+            --  Call to protected operation or entry. Type checking is
+            --  needed on the prefix.
+
+            Analyze_Selected_Component (N);
+
+         elsif (In_Open_Scopes (P_Name)
+                  and then Ekind (P_Name) /= E_Void
+                  and then not Is_Overloadable (P_Name))
+           or else (Is_Concurrent_Type (Etype (P_Name))
+                      and then In_Open_Scopes (Etype (P_Name)))
+         then
+            --  Prefix denotes an enclosing loop, block, or task, i.e. an
+            --  enclosing construct that is not a subprogram or accept.
+
+            Find_Expanded_Name (N);
+
+         elsif Ekind (P_Name) = E_Package then
+            Find_Expanded_Name (N);
+
+         elsif Is_Overloadable (P_Name) then
+
+            --  The subprogram may be a renaming (of an enclosing scope) as
+            --  in the case of the name of the generic within an instantiation.
+
+            if (Ekind (P_Name) = E_Procedure
+                 or else Ekind (P_Name) = E_Function)
+              and then Present (Alias (P_Name))
+              and then Is_Generic_Instance (Alias (P_Name))
+            then
+               P_Name := Alias (P_Name);
+            end if;
+
+            if Is_Overloaded (P) then
+
+               --  The prefix must resolve to a unique enclosing construct.
+
+               declare
+                  Found : Boolean := False;
+                  I     : Interp_Index;
+                  It    : Interp;
+
+               begin
+                  Get_First_Interp (P, I, It);
+
+                  while Present (It.Nam) loop
+
+                     if In_Open_Scopes (It.Nam) then
+                        if Found then
+                           Error_Msg_N (
+                              "prefix must be unique enclosing scope", N);
+                           Set_Entity (N, Any_Id);
+                           Set_Etype  (N, Any_Type);
+                           return;
+
+                        else
+                           Found := True;
+                           P_Name := It.Nam;
+                        end if;
+                     end if;
+
+                     Get_Next_Interp (I, It);
+                  end loop;
+               end;
+            end if;
+
+            if In_Open_Scopes (P_Name) then
+               Set_Entity (P, P_Name);
+               Set_Is_Overloaded (P, False);
+               Find_Expanded_Name (N);
+
+            else
+               --  If no interpretation as an expanded name is possible, it
+               --  must be a selected component of a record returned by a
+               --  function call. Reformat prefix as a function call, the
+               --  rest is done by type resolution. If the prefix is a
+               --  procedure or entry, as is P.X;  this is an error.
+
+               if Ekind (P_Name) /= E_Function
+                 and then (not Is_Overloaded (P)
+                             or else
+                           Nkind (Parent (N)) = N_Procedure_Call_Statement)
+               then
+
+                  --  Prefix may mention a package that is hidden by a local
+                  --  declaration: let the user know.
+
+                  if Present (Homonym (P_Name)) then
+
+                     while Present (P_Name) loop
+                        exit when Ekind (P_Name) = E_Package;
+                        P_Name := Homonym (P_Name);
+                     end loop;
+
+                     if Present (P_Name) then
+                        Error_Msg_Sloc := Sloc (Entity (Prefix (N)));
+
+                        Error_Msg_NE
+                          ("package& is hidden by declaration#",
+                            N, P_Name);
+
+                        Set_Entity (Prefix (N), P_Name);
+                        Find_Expanded_Name (N);
+                        return;
+                     else
+                        P_Name := Entity (Prefix (N));
+                     end if;
+                  end if;
+
+                  Error_Msg_NE
+                    ("invalid prefix in selected component&", N, P_Name);
+                  Change_Selected_Component_To_Expanded_Name (N);
+                  Set_Entity (N, Any_Id);
+                  Set_Etype (N, Any_Type);
+
+               else
+                  Nam := New_Copy (P);
+                  Save_Interps (P, Nam);
+                  Rewrite (P,
+                    Make_Function_Call (Sloc (P), Name => Nam));
+                  Analyze_Call (P);
+                  Analyze_Selected_Component (N);
+               end if;
+            end if;
+
+         --  Remaining cases generate various error messages
+
+         else
+            --  Format node as expanded name, to avoid cascaded errors
+
+            Change_Node (N, N_Expanded_Name);
+            Set_Prefix  (N, P);
+            Set_Entity  (N, Any_Id);
+            Set_Etype   (N, Any_Type);
+
+            --  Set_Selector_Name (N, Empty); ????
+
+            --  Issue error message, but avoid this if error issued already.
+            --  Use identifier of prefix if one is available.
+
+            if P_Name = Any_Id  then
+               null;
+
+            elsif Ekind (P_Name) = E_Void then
+               Premature_Usage (P);
+
+            elsif Nkind (P) /= N_Attribute_Reference then
+               Error_Msg_N (
+                "invalid prefix in selected component&", P);
+
+            else
+               Error_Msg_N (
+                "invalid prefix in selected component", P);
+            end if;
+         end if;
+
+      else
+         --  If prefix is not the name of an entity, it must be an expression,
+         --  whose type is appropriate for a record. This is determined by
+         --  type resolution.
+
+         Analyze_Selected_Component (N);
+      end if;
+   end Find_Selected_Component;
+
+   ---------------
+   -- Find_Type --
+   ---------------
+
+   procedure Find_Type (N : Node_Id) is
+      C      : Entity_Id;
+      Typ    : Entity_Id;
+      T      : Entity_Id;
+      T_Name : Entity_Id;
+
+   begin
+      if N = Error then
+         return;
+
+      elsif Nkind (N) = N_Attribute_Reference then
+
+         --  Class attribute. This is only valid in Ada 95 mode, but we don't
+         --  do a check, since the tagged type referenced could only exist if
+         --  we were in 95 mode when it was declared (or, if we were in Ada
+         --  83 mode, then an error message would already have been issued).
+
+         if Attribute_Name (N) = Name_Class then
+            Check_Restriction (No_Dispatch, N);
+            Find_Type (Prefix (N));
+
+            --  Propagate error from bad prefix
+
+            if Etype (Prefix (N)) = Any_Type then
+               Set_Entity (N, Any_Type);
+               Set_Etype  (N, Any_Type);
+               return;
+            end if;
+
+            T := Base_Type (Entity (Prefix (N)));
+
+            --  Case of non-tagged type
+
+            if not Is_Tagged_Type (T) then
+               if Ekind (T) = E_Incomplete_Type then
+
+                  --  It is legal to denote the class type of an incomplete
+                  --  type. The full type will have to be tagged, of course.
+
+                  Set_Is_Tagged_Type (T);
+                  Make_Class_Wide_Type (T);
+                  Set_Entity (N, Class_Wide_Type (T));
+                  Set_Etype  (N, Class_Wide_Type (T));
+
+               elsif Ekind (T) = E_Private_Type
+                 and then not Is_Generic_Type (T)
+                 and then In_Private_Part (Scope (T))
+               then
+                  --  The Class attribute can be applied to an untagged
+                  --  private type fulfilled by a tagged type prior to
+                  --  the full type declaration (but only within the
+                  --  parent package's private part). Create the class-wide
+                  --  type now and check that the full type is tagged
+                  --  later during its analysis. Note that we do not
+                  --  mark the private type as tagged, unlike the case
+                  --  of incomplete types, because the type must still
+                  --  appear untagged to outside units.
+
+                  if not Present (Class_Wide_Type (T)) then
+                     Make_Class_Wide_Type (T);
+                  end if;
+
+                  Set_Entity (N, Class_Wide_Type (T));
+                  Set_Etype  (N, Class_Wide_Type (T));
+
+               else
+                  --  Should we introduce a type Any_Tagged and use
+                  --  Wrong_Type here, it would be a bit more consistent???
+
+                  Error_Msg_NE
+                    ("tagged type required, found}",
+                     Prefix (N), First_Subtype (T));
+                  Set_Entity (N, Any_Type);
+                  return;
+               end if;
+
+            --  Case of tagged type
+
+            else
+               C := Class_Wide_Type (Entity (Prefix (N)));
+               Set_Entity_With_Style_Check (N, C);
+               Generate_Reference (C, N);
+               Set_Etype (N, C);
+
+               if From_With_Type (C)
+                 and then Nkind (Parent (N)) /= N_Access_Definition
+                 and then not Analyzed (T)
+               then
+                  Error_Msg_N
+                   ("imported class-wide type can only be used" &
+                      " for access parameters", N);
+               end if;
+            end if;
+
+         --  Base attribute, allowed in Ada 95 mode only
+
+         elsif Attribute_Name (N) = Name_Base then
+            if Ada_83 and then Comes_From_Source (N) then
+               Error_Msg_N
+                 ("(Ada 83) Base attribute not allowed in subtype mark", N);
+
+            else
+               Find_Type (Prefix (N));
+               Typ := Entity (Prefix (N));
+
+               if Sloc (Typ) = Standard_Location
+                 and then Base_Type (Typ) = Typ
+                 and then Warn_On_Redundant_Constructs
+               then
+                  Error_Msg_NE
+                    ("?redudant attribute, & is its own base type", N, Typ);
+               end if;
+
+               T := Base_Type (Typ);
+               Set_Entity (N, T);
+               Set_Etype (N, T);
+
+               --  Rewrite attribute reference with type itself (see similar
+               --  processing in Analyze_Attribute, case Base)
+
+               Rewrite (N,
+                 New_Reference_To (Entity (N), Sloc (N)));
+               Set_Etype (N, T);
+            end if;
+
+         --  All other attributes are invalid in a subtype mark
+
+         else
+            Error_Msg_N ("invalid attribute in subtype mark", N);
+         end if;
+
+      else
+         Analyze (N);
+
+         if Is_Entity_Name (N) then
+            T_Name := Entity (N);
+         else
+            Error_Msg_N ("subtype mark required in this context", N);
+            Set_Etype (N, Any_Type);
+            return;
+         end if;
+
+         if T_Name  = Any_Id or else Etype (N) = Any_Type then
+
+            --  Undefined id. Make it into a valid type
+
+            Set_Entity (N, Any_Type);
+
+         elsif not Is_Type (T_Name)
+           and then T_Name /= Standard_Void_Type
+         then
+            Error_Msg_Sloc := Sloc (T_Name);
+            Error_Msg_N ("subtype mark required in this context", N);
+            Error_Msg_NE ("\found & declared#", N, T_Name);
+            Set_Entity (N, Any_Type);
+
+         else
+            T_Name := Get_Full_View (T_Name);
+
+            if In_Open_Scopes (T_Name) then
+               if Ekind (Base_Type (T_Name)) = E_Task_Type then
+                  Error_Msg_N ("task type cannot be used as type mark " &
+                     "within its own body", N);
+               else
+                  Error_Msg_N ("type declaration cannot refer to itself", N);
+               end if;
+
+               Set_Etype (N, Any_Type);
+               Set_Entity (N, Any_Type);
+               Set_Error_Posted (T_Name);
+               return;
+            end if;
+
+            Set_Entity (N, T_Name);
+            Set_Etype  (N, T_Name);
+         end if;
+      end if;
+
+      if Present (Etype (N)) then
+         if Is_Fixed_Point_Type (Etype (N)) then
+            Check_Restriction (No_Fixed_Point, N);
+         elsif Is_Floating_Point_Type (Etype (N)) then
+            Check_Restriction (No_Floating_Point, N);
+         end if;
+      end if;
+   end Find_Type;
+
+   -------------------
+   -- Get_Full_View --
+   -------------------
+
+   function Get_Full_View (T_Name : Entity_Id) return Entity_Id is
+   begin
+      if (Ekind (T_Name) = E_Incomplete_Type
+          and then Present (Full_View (T_Name)))
+      then
+         return Full_View (T_Name);
+
+      elsif Is_Class_Wide_Type (T_Name)
+        and then Ekind (Root_Type (T_Name)) = E_Incomplete_Type
+        and then Present (Full_View (Root_Type (T_Name)))
+      then
+         return Class_Wide_Type (Full_View (Root_Type (T_Name)));
+
+      else
+         return T_Name;
+      end if;
+   end Get_Full_View;
+
+   ------------------------------------
+   -- Has_Implicit_Character_Literal --
+   ------------------------------------
+
+   function Has_Implicit_Character_Literal (N : Node_Id) return Boolean is
+      Id      : Entity_Id;
+      Found   : Boolean := False;
+      P       : constant Entity_Id := Entity (Prefix (N));
+      Priv_Id : Entity_Id := Empty;
+
+   begin
+      if Ekind (P) = E_Package
+        and then not In_Open_Scopes (P)
+      then
+         Priv_Id := First_Private_Entity (P);
+      end if;
+
+      if P = Standard_Standard then
+         Change_Selected_Component_To_Expanded_Name (N);
+         Rewrite (N, Selector_Name (N));
+         Analyze (N);
+         Set_Etype (Original_Node (N), Standard_Character);
+         return True;
+      end if;
+
+      Id := First_Entity (P);
+
+      while Present (Id)
+        and then Id /= Priv_Id
+      loop
+         if Is_Character_Type (Id)
+           and then (Root_Type (Id) = Standard_Character
+                       or else Root_Type (Id) = Standard_Wide_Character)
+           and then Id = Base_Type (Id)
+         then
+            --  We replace the node with the literal itself, resolve as a
+            --  character, and set the type correctly.
+
+            if not Found then
+               Change_Selected_Component_To_Expanded_Name (N);
+               Rewrite (N, Selector_Name (N));
+               Analyze (N);
+               Set_Etype (N, Id);
+               Set_Etype (Original_Node (N), Id);
+               Found := True;
+
+            else
+               --  More than one type derived from Character in given scope.
+               --  Collect all possible interpretations.
+
+               Add_One_Interp (N, Id, Id);
+            end if;
+         end if;
+
+         Next_Entity (Id);
+      end loop;
+
+      return Found;
+   end Has_Implicit_Character_Literal;
+
+   ---------------------------
+   -- Has_Implicit_Operator --
+   ---------------------------
+
+   function Has_Implicit_Operator (N : Node_Id) return Boolean is
+      Op_Id   : constant Name_Id   := Chars (Selector_Name (N));
+      P       : constant Entity_Id := Entity (Prefix (N));
+      Id      : Entity_Id;
+      Priv_Id : Entity_Id := Empty;
+
+      procedure Add_Implicit_Operator (T : Entity_Id);
+      --  Add implicit interpretation to node N, using the type for which
+      --  a predefined operator exists.
+
+      ---------------------------
+      -- Add_Implicit_Operator --
+      ---------------------------
+
+      procedure Add_Implicit_Operator (T : Entity_Id) is
+         Predef_Op : Entity_Id;
+
+      begin
+         Predef_Op := Current_Entity (Selector_Name (N));
+
+         while Present (Predef_Op)
+           and then Scope (Predef_Op) /= Standard_Standard
+         loop
+            Predef_Op := Homonym (Predef_Op);
+         end loop;
+
+         if Nkind (N) = N_Selected_Component then
+            Change_Selected_Component_To_Expanded_Name (N);
+         end if;
+
+         Add_One_Interp (N, Predef_Op, T);
+
+         --  For operators with unary and binary interpretations, add both
+
+         if Present (Homonym (Predef_Op)) then
+            Add_One_Interp (N, Homonym (Predef_Op), T);
+         end if;
+      end Add_Implicit_Operator;
+
+   --  Start of processing for Has_Implicit_Operator
+
+   begin
+
+      if Ekind (P) = E_Package
+        and then not In_Open_Scopes (P)
+      then
+         Priv_Id := First_Private_Entity (P);
+      end if;
+
+      Id := First_Entity (P);
+
+      case Op_Id is
+
+         --  Boolean operators: an implicit declaration exists if the scope
+         --  contains a declaration for a derived Boolean type, or for an
+         --  array of Boolean type.
+
+         when Name_Op_And | Name_Op_Not | Name_Op_Or  | Name_Op_Xor =>
+
+            while Id  /= Priv_Id loop
+
+               if Valid_Boolean_Arg (Id)
+                 and then Id = Base_Type (Id)
+               then
+                  Add_Implicit_Operator (Id);
+                  return True;
+               end if;
+
+               Next_Entity (Id);
+            end loop;
+
+         --  Equality: look for any non-limited type. Result is Boolean.
+
+         when Name_Op_Eq | Name_Op_Ne =>
+
+            while Id  /= Priv_Id loop
+
+               if Is_Type (Id)
+                 and then not Is_Limited_Type (Id)
+                 and then Id = Base_Type (Id)
+               then
+                  Add_Implicit_Operator (Standard_Boolean);
+                  return True;
+               end if;
+
+               Next_Entity (Id);
+            end loop;
+
+         --  Comparison operators: scalar type, or array of scalar.
+
+         when Name_Op_Lt | Name_Op_Le | Name_Op_Gt | Name_Op_Ge =>
+
+            while Id  /= Priv_Id loop
+               if (Is_Scalar_Type (Id)
+                 or else (Is_Array_Type (Id)
+                           and then Is_Scalar_Type (Component_Type (Id))))
+                 and then Id = Base_Type (Id)
+               then
+                  Add_Implicit_Operator (Standard_Boolean);
+                  return True;
+               end if;
+
+               Next_Entity (Id);
+            end loop;
+
+         --  Arithmetic operators: any numeric type
+
+         when Name_Op_Abs      |
+              Name_Op_Add      |
+              Name_Op_Mod      |
+              Name_Op_Rem      |
+              Name_Op_Subtract |
+              Name_Op_Multiply |
+              Name_Op_Divide   |
+              Name_Op_Expon    =>
+
+            while Id  /= Priv_Id loop
+               if Is_Numeric_Type (Id)
+                 and then Id = Base_Type (Id)
+               then
+                  Add_Implicit_Operator (Id);
+                  return True;
+               end if;
+
+               Next_Entity (Id);
+            end loop;
+
+         --  Concatenation: any one-dimensional array type
+
+         when Name_Op_Concat =>
+
+            while Id  /= Priv_Id loop
+               if Is_Array_Type (Id) and then Number_Dimensions (Id) = 1
+                 and then Id = Base_Type (Id)
+               then
+                  Add_Implicit_Operator (Id);
+                  return True;
+               end if;
+
+               Next_Entity (Id);
+            end loop;
+
+         --  What is the others condition here? Should we be using a
+         --  subtype of Name_Id that would restrict to operators ???
+
+         when others => null;
+
+      end case;
+
+      --  If we fall through, then we do not have an implicit operator
+
+      return False;
+
+   end Has_Implicit_Operator;
+
+   --------------------
+   -- In_Open_Scopes --
+   --------------------
+
+   function In_Open_Scopes (S : Entity_Id) return Boolean is
+   begin
+      --  Since there are several scope stacks maintained by Scope_Stack each
+      --  delineated by Standard (see comments by definition of Scope_Stack)
+      --  it is necessary to end the search when Standard is reached.
+
+      for J in reverse 0 .. Scope_Stack.Last loop
+         if Scope_Stack.Table (J).Entity = S then
+            return True;
+         end if;
+
+         --  We need Is_Active_Stack_Base to tell us when to stop rather
+         --  than checking for Standard_Standard because there are cases
+         --  where Standard_Standard appears in the middle of the active
+         --  set of scopes. This affects the declaration and overriding
+         --  of private inherited operations in instantiations of generic
+         --  child units.
+
+         exit when Scope_Stack.Table (J).Is_Active_Stack_Base;
+      end loop;
+
+      return False;
+   end In_Open_Scopes;
+
+   -----------------------------
+   -- Inherit_Renamed_Profile --
+   -----------------------------
+
+   procedure Inherit_Renamed_Profile (New_S : Entity_Id; Old_S : Entity_Id) is
+      New_F : Entity_Id;
+      Old_F : Entity_Id;
+      Old_T : Entity_Id;
+      New_T : Entity_Id;
+
+   begin
+      if Ekind (Old_S) = E_Operator then
+
+         New_F := First_Formal (New_S);
+
+         while Present (New_F) loop
+            Set_Etype (New_F, Base_Type (Etype (New_F)));
+            Next_Formal (New_F);
+         end loop;
+
+         Set_Etype (New_S, Base_Type (Etype (New_S)));
+
+      else
+         New_F := First_Formal (New_S);
+         Old_F := First_Formal (Old_S);
+
+         while Present (New_F) loop
+            New_T := Etype (New_F);
+            Old_T := Etype (Old_F);
+
+            --  If the new type is a renaming of the old one, as is the
+            --  case for actuals in instances, retain its name, to simplify
+            --  later disambiguation.
+
+            if Nkind (Parent (New_T)) = N_Subtype_Declaration
+              and then Is_Entity_Name (Subtype_Indication (Parent (New_T)))
+              and then Entity (Subtype_Indication (Parent (New_T))) = Old_T
+            then
+               null;
+            else
+               Set_Etype (New_F, Old_T);
+            end if;
+
+            Next_Formal (New_F);
+            Next_Formal (Old_F);
+         end loop;
+
+         if Ekind (Old_S) = E_Function
+           or else Ekind (Old_S) = E_Enumeration_Literal
+         then
+            Set_Etype (New_S, Etype (Old_S));
+         end if;
+      end if;
+   end Inherit_Renamed_Profile;
+
+   ----------------
+   -- Initialize --
+   ----------------
+
+   procedure Initialize is
+   begin
+      Urefs.Init;
+   end Initialize;
+
+   -------------------------
+   -- Install_Use_Clauses --
+   -------------------------
+
+   procedure Install_Use_Clauses (Clause : Node_Id) is
+      U  : Node_Id := Clause;
+      P  : Node_Id;
+      Id : Entity_Id;
+
+   begin
+      while Present (U) loop
+
+         --  Case of USE package
+
+         if Nkind (U) = N_Use_Package_Clause then
+            P := First (Names (U));
+
+            while Present (P) loop
+               Id := Entity (P);
+
+               if Ekind (Id) = E_Package then
+
+                  if In_Use (Id) then
+                     Set_Redundant_Use (P, True);
+
+                  elsif Present (Renamed_Object (Id))
+                    and then In_Use (Renamed_Object (Id))
+                  then
+                     Set_Redundant_Use (P, True);
+
+                  else
+                     Use_One_Package (Id, U);
+                  end if;
+               end if;
+
+               Next (P);
+            end loop;
+
+         --  case of USE TYPE
+
+         else
+            P := First (Subtype_Marks (U));
+
+            while Present (P) loop
+
+               if Entity (P) /= Any_Type then
+                  Use_One_Type (P, U);
+               end if;
+
+               Next (P);
+            end loop;
+         end if;
+
+         Next_Use_Clause (U);
+      end loop;
+   end Install_Use_Clauses;
+
+   -------------------------------------
+   -- Is_Appropriate_For_Entry_Prefix --
+   -------------------------------------
+
+   function Is_Appropriate_For_Entry_Prefix (T : Entity_Id) return Boolean is
+      P_Type : Entity_Id := T;
+
+   begin
+      if Is_Access_Type (P_Type) then
+         P_Type := Designated_Type (P_Type);
+      end if;
+
+      return Is_Task_Type (P_Type) or else Is_Protected_Type (P_Type);
+   end Is_Appropriate_For_Entry_Prefix;
+
+   -------------------------------
+   -- Is_Appropriate_For_Record --
+   -------------------------------
+
+   function Is_Appropriate_For_Record
+     (T    : Entity_Id)
+      return Boolean
+   is
+      function Has_Components (T1 : Entity_Id) return Boolean;
+      --  Determine if given type has components (i.e. is either a record
+      --  type or a type that has discriminants).
+
+      function Has_Components (T1 : Entity_Id) return Boolean is
+      begin
+         return Is_Record_Type (T1)
+           or else (Is_Private_Type (T1) and then Has_Discriminants (T1))
+           or else (Is_Task_Type (T1) and then Has_Discriminants (T1));
+      end Has_Components;
+
+   --  Start of processing for Is_Appropriate_For_Record
+
+   begin
+      return
+        Present (T)
+          and then (Has_Components (T)
+                      or else (Is_Access_Type (T)
+                                 and then
+                                   Has_Components (Designated_Type (T))));
+   end Is_Appropriate_For_Record;
+
+   ---------------
+   -- New_Scope --
+   ---------------
+
+   procedure New_Scope (S : Entity_Id) is
+      E : Entity_Id;
+
+   begin
+      if Ekind (S) = E_Void then
+         null;
+
+      --  Set scope depth if not a non-concurrent 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.
+
+      elsif (not Is_Type (S) or else Is_Concurrent_Type (S))
+        and then not Scope_Depth_Set (S)
+      then
+         if S = Standard_Standard then
+            Set_Scope_Depth_Value (S, Uint_0);
+
+         elsif Is_Child_Unit (S) then
+            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);
+            end if;
+         end if;
+      end if;
+
+      Scope_Stack.Increment_Last;
+
+      Scope_Stack.Table (Scope_Stack.Last).Entity := S;
+
+      Scope_Stack.Table (Scope_Stack.Last).Save_Scope_Suppress  :=
+        Scope_Suppress;
+
+      Scope_Stack.Table (Scope_Stack.Last).Save_Entity_Suppress :=
+        Entity_Suppress.Last;
+
+      if Scope_Stack.Last > Scope_Stack.First then
+         Scope_Stack.Table (Scope_Stack.Last).Component_Alignment_Default :=
+         Scope_Stack.Table (Scope_Stack.Last - 1).Component_Alignment_Default;
+      end if;
+
+      Scope_Stack.Table (Scope_Stack.Last).Last_Subprogram_Name   := null;
+      Scope_Stack.Table (Scope_Stack.Last).Is_Transient           := False;
+      Scope_Stack.Table (Scope_Stack.Last).Node_To_Be_Wrapped     := Empty;
+      Scope_Stack.Table (Scope_Stack.Last).Pending_Freeze_Actions := No_List;
+      Scope_Stack.Table
+        (Scope_Stack.Last).Actions_To_Be_Wrapped_Before           := No_List;
+      Scope_Stack.Table
+        (Scope_Stack.Last).Actions_To_Be_Wrapped_After            := No_List;
+      Scope_Stack.Table (Scope_Stack.Last).First_Use_Clause       := Empty;
+      Scope_Stack.Table (Scope_Stack.Last).Is_Active_Stack_Base   := False;
+
+      if Debug_Flag_W then
+         Write_Str ("--> new scope: ");
+         Write_Name (Chars (Current_Scope));
+         Write_Str (", Id=");
+         Write_Int (Int (Current_Scope));
+         Write_Str (", Depth=");
+         Write_Int (Int (Scope_Stack.Last));
+         Write_Eol;
+      end if;
+
+      --  Copy from Scope (S) the categorization flags to S, this is not
+      --  done in case Scope (S) is Standard_Standard since propagation
+      --  is from library unit entity inwards.
+
+      if S /= Standard_Standard
+        and then Scope (S) /= Standard_Standard
+        and then not Is_Child_Unit (S)
+      then
+         E := Scope (S);
+
+         if Nkind (E) not in N_Entity then
+            return;
+         end if;
+
+         --  We only propagate inwards for library level entities,
+         --  inner level subprograms do not inherit the categorization.
+
+         if Is_Library_Level_Entity (S) then
+            Set_Is_Pure (S, Is_Pure (E));
+            Set_Is_Preelaborated (S, Is_Preelaborated (E));
+            Set_Is_Remote_Call_Interface (S, Is_Remote_Call_Interface (E));
+            Set_Is_Remote_Types (S, Is_Remote_Types (E));
+            Set_Is_Shared_Passive (S, Is_Shared_Passive (E));
+         end if;
+      end if;
+   end New_Scope;
+
+   ---------------
+   -- Pop_Scope --
+   ---------------
+
+   procedure Pop_Scope is
+      E : Entity_Id;
+
+   begin
+      if Debug_Flag_E then
+         Write_Info;
+      end if;
+
+      Scope_Suppress :=
+        Scope_Stack.Table (Scope_Stack.Last).Save_Scope_Suppress;
+
+      while Entity_Suppress.Last >
+                 Scope_Stack.Table (Scope_Stack.Last).Save_Entity_Suppress
+      loop
+         E := Entity_Suppress.Table (Entity_Suppress.Last).Entity;
+
+         case Entity_Suppress.Table (Entity_Suppress.Last).Check is
+
+            when Access_Check        =>
+               Set_Suppress_Access_Checks        (E, False);
+
+            when Accessibility_Check =>
+               Set_Suppress_Accessibility_Checks (E, False);
+
+            when Discriminant_Check  =>
+               Set_Suppress_Discriminant_Checks  (E, False);
+
+            when Division_Check      =>
+               Set_Suppress_Division_Checks      (E, False);
+
+            when Elaboration_Check   =>
+               Set_Suppress_Elaboration_Checks   (E, False);
+
+            when Index_Check         =>
+               Set_Suppress_Index_Checks         (E, False);
+
+            when Length_Check        =>
+               Set_Suppress_Length_Checks        (E, False);
+
+            when Overflow_Check      =>
+               Set_Suppress_Overflow_Checks      (E, False);
+
+            when Range_Check         =>
+               Set_Suppress_Range_Checks         (E, False);
+
+            when Storage_Check       =>
+               Set_Suppress_Storage_Checks       (E, False);
+
+            when Tag_Check           =>
+               Set_Suppress_Tag_Checks           (E, False);
+
+            --  All_Checks should not appear here (since it is entered as a
+            --  series of its separate checks). Bomb if it is encountered
+
+            when All_Checks =>
+               raise Program_Error;
+         end case;
+
+         Entity_Suppress.Decrement_Last;
+      end loop;
+
+      if Debug_Flag_W then
+         Write_Str ("--> exiting scope: ");
+         Write_Name (Chars (Current_Scope));
+         Write_Str (", Depth=");
+         Write_Int (Int (Scope_Stack.Last));
+         Write_Eol;
+      end if;
+
+      End_Use_Clauses (Scope_Stack.Table (Scope_Stack.Last).First_Use_Clause);
+
+      --  If the actions to be wrapped are still there they will get lost
+      --  causing incomplete code to be generated. It is better to abort in
+      --  this case.
+
+      pragma Assert (Scope_Stack.Table
+        (Scope_Stack.Last).Actions_To_Be_Wrapped_Before = No_List);
+
+      pragma Assert (Scope_Stack.Table
+        (Scope_Stack.Last).Actions_To_Be_Wrapped_After = No_List);
+
+      --  Free last subprogram name if allocated, and pop scope
+
+      Free (Scope_Stack.Table (Scope_Stack.Last).Last_Subprogram_Name);
+      Scope_Stack.Decrement_Last;
+   end Pop_Scope;
+
+   ---------------------
+   -- Premature_Usage --
+   ---------------------
+
+   procedure Premature_Usage (N : Node_Id) is
+      Kind : Node_Kind := Nkind (Parent (Entity (N)));
+      E    : Entity_Id := Entity (N);
+
+   begin
+      --  Within an instance, the analysis of the actual for a formal object
+      --  does not see the name of the object itself. This is significant
+      --  only if the object is an aggregate, where its analysis does not do
+      --  any name resolution on component associations. (see 4717-008). In
+      --  such a case, look for the visible homonym on the chain.
+
+      if In_Instance
+        and then Present (Homonym (E))
+      then
+         E := Homonym (E);
+
+         while Present (E)
+           and then not In_Open_Scopes (Scope (E))
+         loop
+            E := Homonym (E);
+         end loop;
+
+         if Present (E) then
+            Set_Entity (N, E);
+            Set_Etype (N, Etype (E));
+            return;
+         end if;
+      end if;
+
+      if Kind  = N_Component_Declaration then
+         Error_Msg_N
+           ("component&! cannot be used before end of record declaration", N);
+
+      elsif Kind  = N_Parameter_Specification then
+         Error_Msg_N
+           ("formal parameter&! cannot be used before end of specification",
+            N);
+
+      elsif Kind  = N_Discriminant_Specification then
+         Error_Msg_N
+           ("discriminant&! cannot be used before end of discriminant part",
+            N);
+
+      elsif Kind  = N_Procedure_Specification
+        or else Kind = N_Function_Specification
+      then
+         Error_Msg_N
+           ("subprogram&! cannot be used before end of its declaration",
+            N);
+      else
+         Error_Msg_N
+           ("object& cannot be used before end of its declaration!", N);
+      end if;
+   end Premature_Usage;
+
+   ------------------------
+   -- Present_System_Aux --
+   ------------------------
+
+   function Present_System_Aux (N : Node_Id := Empty) return Boolean is
+      Loc      : Source_Ptr;
+      Aux_Name : Name_Id;
+      Unum     : Unit_Number_Type;
+      Withn    : Node_Id;
+      With_Sys : Node_Id;
+      The_Unit : Node_Id;
+
+      function Find_System (C_Unit : Node_Id) return Entity_Id;
+      --  Scan context clause of compilation unit to find a with_clause
+      --  for System.
+
+      function Find_System (C_Unit : Node_Id) return Entity_Id is
+         With_Clause : Node_Id;
+
+      begin
+         With_Clause := First (Context_Items (C_Unit));
+
+         while Present (With_Clause) loop
+            if (Nkind (With_Clause) = N_With_Clause
+              and then Chars (Name (With_Clause)) = Name_System)
+              and then Comes_From_Source (With_Clause)
+            then
+               return With_Clause;
+            end if;
+
+            Next (With_Clause);
+         end loop;
+
+         return Empty;
+      end Find_System;
+
+   --  Start of processing for Present_System_Aux
+
+   begin
+      --  The child unit may have been loaded and analyzed already.
+
+      if Present (System_Aux_Id) then
+         return True;
+
+      --  If no previous pragma for System.Aux, nothing to load
+
+      elsif No (System_Extend_Pragma_Arg) then
+         return False;
+
+      --  Use the unit name given in the pragma to retrieve the unit.
+      --  Verify that System itself appears in the context clause of the
+      --  current compilation. If System is not present, an error will
+      --  have been reported already.
+
+      else
+         With_Sys := Find_System (Cunit (Current_Sem_Unit));
+
+         The_Unit := Unit (Cunit (Current_Sem_Unit));
+
+         if No (With_Sys)
+           and then (Nkind (The_Unit) = N_Package_Body
+                      or else (Nkind (The_Unit) = N_Subprogram_Body
+                        and then not Acts_As_Spec (Cunit (Current_Sem_Unit))))
+         then
+            With_Sys := Find_System (Library_Unit (Cunit (Current_Sem_Unit)));
+         end if;
+
+         if No (With_Sys)
+           and then Present (N)
+         then
+            --  If we are compiling a subunit, we need to examine its
+            --  context as well (Current_Sem_Unit is the parent unit);
+
+            The_Unit := Parent (N);
+
+            while Nkind (The_Unit) /= N_Compilation_Unit loop
+               The_Unit := Parent (The_Unit);
+            end loop;
+
+            if Nkind (Unit (The_Unit)) = N_Subunit then
+               With_Sys := Find_System (The_Unit);
+            end if;
+         end if;
+
+         if No (With_Sys) then
+            return False;
+         end if;
+
+         Loc := Sloc (With_Sys);
+         Get_Name_String (Chars (Expression (System_Extend_Pragma_Arg)));
+         Name_Buffer (8 .. Name_Len + 7) := Name_Buffer (1 .. Name_Len);
+         Name_Buffer (1 .. 7) := "system.";
+         Name_Buffer (Name_Len + 8) := '%';
+         Name_Buffer (Name_Len + 9) := 's';
+         Name_Len := Name_Len + 9;
+         Aux_Name := Name_Find;
+
+         Unum :=
+           Load_Unit
+             (Load_Name  => Aux_Name,
+              Required   => False,
+              Subunit    => False,
+              Error_Node => With_Sys);
+
+         if Unum /= No_Unit then
+            Semantics (Cunit (Unum));
+            System_Aux_Id :=
+              Defining_Entity (Specification (Unit (Cunit (Unum))));
+
+            Withn := Make_With_Clause (Loc,
+              Name =>
+                Make_Expanded_Name (Loc,
+                  Chars  => Chars (System_Aux_Id),
+                  Prefix =>
+                    New_Reference_To (Scope (System_Aux_Id), Loc),
+                  Selector_Name =>
+                    New_Reference_To (System_Aux_Id, Loc)));
+
+            Set_Entity (Name (Withn), System_Aux_Id);
+
+            Set_Library_Unit          (Withn, Cunit (Unum));
+            Set_Corresponding_Spec    (Withn, System_Aux_Id);
+            Set_First_Name            (Withn, True);
+            Set_Implicit_With         (Withn, True);
+
+            Insert_After (With_Sys, Withn);
+            Mark_Rewrite_Insertion (Withn);
+            Set_Context_Installed (Withn);
+
+            return True;
+
+         --  Here if unit load failed
+
+         else
+            Error_Msg_Name_1 := Name_System;
+            Error_Msg_Name_2 := Chars (Expression (System_Extend_Pragma_Arg));
+            Error_Msg_N
+              ("extension package `%.%` does not exist",
+               Opt.System_Extend_Pragma_Arg);
+            return False;
+         end if;
+      end if;
+   end Present_System_Aux;
+
+   -------------------------
+   -- Restore_Scope_Stack --
+   -------------------------
+
+   procedure Restore_Scope_Stack is
+      E         : Entity_Id;
+      S         : Entity_Id;
+      Comp_Unit : Node_Id;
+      In_Child  : Boolean := False;
+      Full_Vis  : Boolean := True;
+
+   begin
+      --  Restore visibility of previous scope stack, if any.
+
+      for J in reverse 0 .. Scope_Stack.Last loop
+         exit when  Scope_Stack.Table (J).Entity = Standard_Standard
+            or else No (Scope_Stack.Table (J).Entity);
+
+         S := Scope_Stack.Table (J).Entity;
+
+         if not Is_Hidden_Open_Scope (S) then
+
+            --  If the parent scope is hidden, its entities are hidden as
+            --  well, unless the entity is the instantiation currently
+            --  being analyzed.
+
+            if not Is_Hidden_Open_Scope (Scope (S))
+              or else not Analyzed (Parent (S))
+              or else Scope (S) = Standard_Standard
+            then
+               Set_Is_Immediately_Visible (S, True);
+            end if;
+
+            E := First_Entity (S);
+
+            while Present (E) loop
+               if Is_Child_Unit (E) then
+                  Set_Is_Immediately_Visible (E,
+                    Is_Visible_Child_Unit (E) or else In_Open_Scopes (E));
+               else
+                  Set_Is_Immediately_Visible (E, True);
+               end if;
+
+               Next_Entity (E);
+
+               if not Full_Vis then
+                  exit when E = First_Private_Entity (S);
+               end if;
+            end loop;
+
+            --  The visibility of child units (siblings of current compilation)
+            --  must be restored in any case. Their declarations may appear
+            --  after the private part of the parent.
+
+            if not Full_Vis
+              and then Present (E)
+            then
+               while Present (E) loop
+                  if Is_Child_Unit (E) then
+                     Set_Is_Immediately_Visible (E,
+                       Is_Visible_Child_Unit (E) or else In_Open_Scopes (E));
+                  end if;
+
+                  Next_Entity (E);
+               end loop;
+            end if;
+         end if;
+
+         if Is_Child_Unit (S)
+            and not In_Child     --  check only for current unit.
+         then
+            In_Child := True;
+
+            --  restore visibility of parents according to whether the child
+            --  is private and whether we are in its visible part.
+
+            Comp_Unit := Parent (Unit_Declaration_Node (S));
+
+            if Nkind (Comp_Unit) = N_Compilation_Unit
+              and then Private_Present (Comp_Unit)
+            then
+               Full_Vis := True;
+
+            elsif (Ekind (S) = E_Package
+                    or else Ekind (S) = E_Generic_Package)
+              and then (In_Private_Part (S)
+                         or else In_Package_Body (S))
+            then
+               Full_Vis := True;
+
+            elsif (Ekind (S) = E_Procedure
+                    or else Ekind (S) = E_Function)
+              and then Has_Completion (S)
+            then
+               Full_Vis := True;
+            else
+               Full_Vis := False;
+            end if;
+         else
+            Full_Vis := True;
+         end if;
+      end loop;
+   end Restore_Scope_Stack;
+
+   ----------------------
+   -- Save_Scope_Stack --
+   ----------------------
+
+   procedure Save_Scope_Stack is
+      E       : Entity_Id;
+      S       : Entity_Id;
+      SS_Last : constant Int := Scope_Stack.Last;
+
+   begin
+      if SS_Last >= Scope_Stack.First
+        and then Scope_Stack.Table (SS_Last).Entity /= Standard_Standard
+      then
+
+         --  If the call is from within a compilation unit, as when
+         --  called from Rtsfind, make current entries in scope stack
+         --  invisible while we analyze the new unit.
+
+         for J in reverse 0 .. SS_Last loop
+            exit when  Scope_Stack.Table (J).Entity = Standard_Standard
+               or else No (Scope_Stack.Table (J).Entity);
+
+            S := Scope_Stack.Table (J).Entity;
+            Set_Is_Immediately_Visible (S, False);
+            E := First_Entity (S);
+
+            while Present (E) loop
+               Set_Is_Immediately_Visible (E, False);
+               Next_Entity (E);
+            end loop;
+         end loop;
+
+      end if;
+   end Save_Scope_Stack;
+
+   -------------
+   -- Set_Use --
+   -------------
+
+   procedure Set_Use (L : List_Id) is
+      Decl      : Node_Id;
+      Pack_Name : Node_Id;
+      Pack      : Entity_Id;
+      Id        : Entity_Id;
+
+   begin
+      if Present (L) then
+         Decl := First (L);
+
+         while Present (Decl) loop
+            if Nkind (Decl) = N_Use_Package_Clause then
+               Chain_Use_Clause (Decl);
+               Pack_Name := First (Names (Decl));
+
+               while Present (Pack_Name) loop
+                  Pack := Entity (Pack_Name);
+
+                  if Ekind (Pack) = E_Package
+                    and then Applicable_Use (Pack_Name)
+                  then
+                     Use_One_Package (Pack, Decl);
+                  end if;
+
+                  Next (Pack_Name);
+               end loop;
+
+            elsif Nkind (Decl) = N_Use_Type_Clause  then
+               Chain_Use_Clause (Decl);
+               Id := First (Subtype_Marks (Decl));
+
+               while Present (Id) loop
+                  if Entity (Id) /= Any_Type then
+                     Use_One_Type (Id, Decl);
+                  end if;
+
+                  Next (Id);
+               end loop;
+            end if;
+
+            Next (Decl);
+         end loop;
+      end if;
+   end Set_Use;
+
+   ---------------------
+   -- Use_One_Package --
+   ---------------------
+
+   procedure Use_One_Package (P : Entity_Id; N : Node_Id) is
+      Id               : Entity_Id;
+      Prev             : Entity_Id;
+      Current_Instance : Entity_Id := Empty;
+      Real_P           : Entity_Id;
+
+   begin
+      if Ekind (P) /= E_Package then
+         return;
+      end if;
+
+      Set_In_Use (P);
+
+      if From_With_Type (P) then
+         Error_Msg_N ("imported package cannot appear in use clause", N);
+      end if;
+
+      --  Find enclosing instance, if any.
+
+      if In_Instance then
+         Current_Instance := Current_Scope;
+
+         while not Is_Generic_Instance (Current_Instance) loop
+            Current_Instance := Scope (Current_Instance);
+         end loop;
+
+         if No (Hidden_By_Use_Clause (N)) then
+            Set_Hidden_By_Use_Clause (N, New_Elmt_List);
+         end if;
+      end if;
+
+      --  If unit is a package renaming, indicate that the renamed
+      --  package 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));
+         Real_P := Renamed_Object (P);
+      else
+         Real_P := P;
+      end if;
+
+      --  Loop through entities in one package making them potentially
+      --  use-visible.
+
+      Id := First_Entity (P);
+      while Present (Id)
+        and then Id /= First_Private_Entity (P)
+      loop
+         Prev := Current_Entity (Id);
+
+         while Present (Prev) loop
+            if Is_Immediately_Visible (Prev)
+              and then (not Is_Overloadable (Prev)
+                         or else not Is_Overloadable (Id)
+                         or else (Type_Conformant (Id, Prev)))
+            then
+               if No (Current_Instance) then
+
+                  --  Potentially use-visible entity remains hidden
+
+                  goto Next_Usable_Entity;
+
+               --  A use clause within an instance hides outer global
+               --  entities, which are not used to resolve local entities
+               --  in the instance. Note that the predefined entities in
+               --  Standard could not have been hidden in the generic by
+               --  a use clause, and therefore remain visible. Other
+               --  compilation units whose entities appear in Standard must
+               --  be hidden in an instance.
+
+               --  To determine whether an entity is external to the instance
+               --  we compare the scope depth of its scope with that of the
+               --  current instance. However, a generic actual of a subprogram
+               --  instance is declared in the wrapper package but will not be
+               --  hidden by a use-visible entity.
+
+               elsif not Is_Hidden (Id)
+                 and then not Is_Wrapper_Package (Scope (Prev))
+                 and then Scope_Depth (Scope (Prev)) <
+                          Scope_Depth (Current_Instance)
+                 and then (Scope (Prev) /= Standard_Standard
+                            or else Sloc (Prev) > Standard_Location)
+               then
+                  Set_Is_Potentially_Use_Visible (Id);
+                  Set_Is_Immediately_Visible (Prev, False);
+                  Append_Elmt (Prev, Hidden_By_Use_Clause (N));
+               end if;
+
+            --  A user-defined operator is not use-visible if the
+            --  predefined operator for the type is immediately visible,
+            --  which is the case if the type of the operand is in an open
+            --  scope. This does not apply to user-defined operators that
+            --  have operands of different types, because the predefined
+            --  mixed mode operations (multiplication and division) apply to
+            --  universal types and do not hide anything.
+
+            elsif Ekind (Prev) = E_Operator
+              and then Operator_Matches_Spec (Prev, Id)
+              and then In_Open_Scopes
+               (Scope (Base_Type (Etype (First_Formal (Id)))))
+              and then (No (Next_Formal (First_Formal (Id)))
+                         or else Etype (First_Formal (Id))
+                           = Etype (Next_Formal (First_Formal (Id)))
+                         or else Chars (Prev) = Name_Op_Expon)
+            then
+               goto Next_Usable_Entity;
+            end if;
+
+            Prev := Homonym (Prev);
+         end loop;
+
+         --  On exit, we know entity is not hidden, unless it is private.
+
+         if not Is_Hidden (Id)
+           and then ((not Is_Child_Unit (Id))
+                       or else Is_Visible_Child_Unit (Id))
+         then
+            Set_Is_Potentially_Use_Visible (Id);
+
+            if Is_Private_Type (Id)
+              and then Present (Full_View (Id))
+            then
+               Set_Is_Potentially_Use_Visible (Full_View (Id));
+            end if;
+         end if;
+
+         <<Next_Usable_Entity>>
+            Next_Entity (Id);
+      end loop;
+
+      --  Child units are also made use-visible by a use clause, but they
+      --  may appear after all visible declarations in the parent entity list.
+
+      while Present (Id) loop
+
+         if Is_Child_Unit (Id)
+           and then Is_Visible_Child_Unit (Id)
+         then
+            Set_Is_Potentially_Use_Visible (Id);
+         end if;
+
+         Next_Entity (Id);
+      end loop;
+
+      if Chars (Real_P) = Name_System
+        and then Scope (Real_P) = Standard_Standard
+        and then Present_System_Aux (N)
+      then
+         Use_One_Package (System_Aux_Id, N);
+      end if;
+
+   end Use_One_Package;
+
+   ------------------
+   -- Use_One_Type --
+   ------------------
+
+   procedure Use_One_Type (Id : Node_Id; N : Node_Id) is
+      T       : Entity_Id;
+      Op_List : Elist_Id;
+      Elmt    : Elmt_Id;
+
+   begin
+      --  It is the type determined by the subtype mark (8.4(8)) whose
+      --  operations become potentially use-visible.
+
+      T := Base_Type (Entity (Id));
+
+      --  Save current visibility status of type, before setting.
+
+      Set_Redundant_Use
+        (Id, In_Use (T) or else Is_Potentially_Use_Visible (T));
+
+      if In_Open_Scopes (Scope (T)) then
+         null;
+
+      elsif not Redundant_Use (Id) then
+         Set_In_Use (T);
+         Op_List := Collect_Primitive_Operations (T);
+         Elmt := First_Elmt (Op_List);
+
+         while Present (Elmt) loop
+
+            if (Nkind (Node (Elmt)) = N_Defining_Operator_Symbol
+                 or else Chars (Node (Elmt)) in Any_Operator_Name)
+              and then not Is_Hidden (Node (Elmt))
+            then
+               Set_Is_Potentially_Use_Visible (Node (Elmt));
+            end if;
+
+            Next_Elmt (Elmt);
+         end loop;
+      end if;
+
+   end Use_One_Type;
+
+   ----------------
+   -- Write_Info --
+   ----------------
+
+   procedure Write_Info is
+      Id : Entity_Id := First_Entity (Current_Scope);
+
+   begin
+      --  No point in dumping standard entities
+
+      if Current_Scope = Standard_Standard then
+         return;
+      end if;
+
+      Write_Str ("========================================================");
+      Write_Eol;
+      Write_Str ("        Defined Entities in ");
+      Write_Name (Chars (Current_Scope));
+      Write_Eol;
+      Write_Str ("========================================================");
+      Write_Eol;
+
+      if No (Id) then
+         Write_Str ("-- none --");
+         Write_Eol;
+
+      else
+         while Present (Id) loop
+            Write_Entity_Info (Id, " ");
+            Next_Entity (Id);
+         end loop;
+      end if;
+
+      if Scope (Current_Scope) = Standard_Standard then
+
+         --  Print information on the current unit itself
+
+         Write_Entity_Info (Current_Scope, " ");
+      end if;
+
+      Write_Eol;
+   end Write_Info;
+
+   -----------------
+   -- Write_Scopes --
+   -----------------
+
+   procedure Write_Scopes is
+      S : Entity_Id;
+
+   begin
+      for J in reverse 1 .. Scope_Stack.Last loop
+         S :=  Scope_Stack.Table (J).Entity;
+         Write_Int (Int (S));
+         Write_Str (" === ");
+         Write_Name (Chars (S));
+         Write_Eol;
+      end loop;
+   end Write_Scopes;
+
+end Sem_Ch8;
diff --git a/gcc/ada/sem_ch8.ads b/gcc/ada/sem_ch8.ads
new file mode 100644 (file)
index 0000000..c271365
--- /dev/null
@@ -0,0 +1,190 @@
+------------------------------------------------------------------------------
+--                                                                          --
+--                         GNAT COMPILER COMPONENTS                         --
+--                                                                          --
+--                              S E M _ C H 8                               --
+--                                                                          --
+--                                 S p e c                                  --
+--                                                                          --
+--                            $Revision: 1.33 $                             --
+--                                                                          --
+--          Copyright (C) 1992-2001 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- --
+-- ware  Foundation;  either version 2,  or (at your option) any later ver- --
+-- sion.  GNAT is distributed in the hope that it will be useful, but WITH- --
+-- OUT ANY WARRANTY;  without even the  implied warranty of MERCHANTABILITY --
+-- or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License --
+-- for  more details.  You should have  received  a copy of the GNU General --
+-- Public License  distributed with GNAT;  see file COPYING.  If not, write --
+-- to  the Free Software Foundation,  59 Temple Place - Suite 330,  Boston, --
+-- MA 02111-1307, USA.                                                      --
+--                                                                          --
+-- GNAT was originally developed  by the GNAT team at  New York University. --
+-- It is now maintained by Ada Core Technologies Inc (http://www.gnat.com). --
+--                                                                          --
+------------------------------------------------------------------------------
+
+with Types; use Types;
+package Sem_Ch8 is
+
+   -----------------------------------
+   -- Handling extensions of System --
+   -----------------------------------
+
+   --  For targets that define a much larger System package than given in
+   --  the RM, we use a child package containing additional declarations,
+   --  which is loaded when needed, and whose entities are conceptually
+   --  within System itself. The presence of this auxiliary package is
+   --  controlled with the pragma Extend_System. The following variable
+   --  holds the entity of the auxiliary package, to simplify the special
+   --  visibility rules that apply to it.
+
+   System_Aux_Id : Entity_Id := Empty;
+
+   -----------------
+   -- Subprograms --
+   -----------------
+
+   procedure Analyze_Exception_Renaming                 (N : Node_Id);
+   procedure Analyze_Expanded_Name                      (N : Node_Id);
+   procedure Analyze_Generic_Function_Renaming          (N : Node_Id);
+   procedure Analyze_Generic_Package_Renaming           (N : Node_Id);
+   procedure Analyze_Generic_Procedure_Renaming         (N : Node_Id);
+   procedure Analyze_Object_Renaming                    (N : Node_Id);
+   procedure Analyze_Package_Renaming                   (N : Node_Id);
+   procedure Analyze_Subprogram_Renaming                (N : Node_Id);
+   procedure Analyze_Use_Package                        (N : Node_Id);
+   procedure Analyze_Use_Type                           (N : Node_Id);
+
+   function Applicable_Use (Pack_Name : Node_Id) return Boolean;
+   --  Common code to Use_One_Package and Set_Use, to determine whether
+   --  use clause must be processed. Pack_Name is an entity name that
+   --  references the package in question.
+
+   procedure End_Scope;
+   --  Called at end of scope. On exit from blocks and bodies (subprogram,
+   --  package, task, and protected bodies), the name of the current scope
+   --  must be removed from the scope stack, and the local entities must be
+   --  removed from their homonym chains. On exit from record declarations,
+   --  from package specifications, and from tasks and protected type
+   --  specifications, more specialized procedures are invoked.
+
+   procedure End_Use_Clauses (Clause : Node_Id);
+   --  Invoked on scope exit, to undo the effect of local use clauses. U is
+   --  the first Use clause of a scope being exited. This can be the current
+   --  scope, or some enclosing scopes when building a clean environment to
+   --  compile an instance body for inlining.
+
+   procedure End_Use_Package (N : Node_Id);
+   procedure End_Use_Type    (N : Node_Id);
+   --  Subsidiaries of End_Use_Clauses.  Also called directly for use clauses
+   --  appearing in context clauses.
+
+   procedure Find_Direct_Name (N : Node_Id);
+   --  Given a direct name (Identifier or Operator_Symbol), this routine
+   --  scans the homonym chain for the name searching for corresponding
+   --  visible entities to find the referenced entity (or in the case of
+   --  overloading), entities. On return, the Entity, and Etype fields
+   --  are set. In the non-overloaded case, these are the correct final
+   --  entries. In the overloaded case, Is_Overloaded is set, Etype and
+   --  Entity refer to an arbitrary element of the overloads set, and
+   --  an appropriate list of entries has been made in the overload
+   --  interpretation table (to be disambiguated in the resolve phase).
+
+   procedure Find_Expanded_Name (N : Node_Id);
+   --  Selected component is known to be expanded name. Verify legality
+   --  of selector given the scope denoted by prefix.
+
+   procedure Find_Selected_Component (N : Node_Id);
+   --  Resolve various cases of selected components, recognize expanded names
+
+   procedure Find_Type (N : Node_Id);
+   --  Perform name resolution, and verify that the name found is that of a
+   --  type. On return the Entity and Etype fields of the node N are set
+   --  appropriately. If it is an incomplete type whose full declaration has
+   --  been seen, return the entity in the full declaration. Similarly, if
+   --  the type is private, it has receivd a full declaration, and we are
+   --  in the private part or body of the package, return the full
+   --  declaration as well. Special processing for Class types as well.
+
+   function Get_Full_View (T_Name : Entity_Id) return Entity_Id;
+   --  If T_Name is an incomplete type and the full declaration has been
+   --  seen, or is the name of a class_wide type whose root is incomplete.
+   --  return the corresponding full declaration.
+
+   function Has_Implicit_Operator (N : Node_Id) return Boolean;
+   --  N is an expanded name whose selector is an operator name (eg P."+").
+   --  A declarative part contains an implicit declaration of an operator
+   --  if it has a declaration of a type to which one of the predefined
+   --  operators apply. The existence of this routine is an artifact of
+   --  our implementation: a more straightforward but more space-consuming
+   --  choice would be to make all inherited operators explicit in the
+   --  symbol table.
+
+   procedure Initialize;
+   --  Initializes data structures used for visibility analysis. Must be
+   --  called before analyzing each new main source program.
+
+   procedure Install_Use_Clauses (Clause : Node_Id);
+   --  applies the use clauses appearing in a given declarative part,
+   --  when the corresponding scope has been placed back on the scope
+   --  stack after unstacking to compile a different context (subunit or
+   --  parent of generic body).
+
+   function In_Open_Scopes (S : Entity_Id) return Boolean;
+   --  S is the entity of a scope. This function determines if this scope
+   --  is currently open (i.e. it appears somewhere in the scope stack).
+
+   function Is_Appropriate_For_Record (T : Entity_Id) return Boolean;
+   --  Prefix is appropriate for record if it is of a record type, or
+   --  an access to such.
+
+   function Is_Appropriate_For_Entry_Prefix (T : Entity_Id) return Boolean;
+   --  True if it is of a task type, a protected type, or else an access
+   --  to one of these types.
+
+   procedure New_Scope (S : Entity_Id);
+   --  Make new scope stack entry, pushing S, the entity for a scope
+   --  onto the top of the scope table. The current setting of the scope
+   --  suppress flags is saved for restoration on exit.
+
+   procedure Pop_Scope;
+   --  Remove top entry from scope stack, restoring the saved setting
+   --  of the scope suppress flags.
+
+   function Present_System_Aux (N : Node_Id := Empty) return Boolean;
+   --  Return True if the auxiliary system file has been sucessfully loaded.
+   --  Otherwise attempt to load it, using the name supplied by a previous
+   --  Extend_System pragma, and report on the success of the load.
+   --  If N is present, it is a selected component whose prefix is System,
+   --  or else a with-clause on system. N is absent when the function is
+   --  called to find the visibility of implicit operators.
+
+   procedure Restore_Scope_Stack;
+   procedure Save_Scope_Stack;
+   --  These two procedures are called from Semantics, when a unit U1 is
+   --  to be compiled in the course of the compilation of another unit U2.
+   --  This happens whenever Rtsfind is called. U1, the unit retrieved by
+   --  Rtsfind, must be compiled in its own context, and the current scope
+   --  stack containing U2 and local scopes must be made unreachable. On
+   --  return, the contents of the scope stack must be made accessible again.
+
+   procedure Use_One_Package (P : Entity_Id; N : Node_Id);
+   --  Make visible entities declarated in package P potentially use-visible
+   --  in the current context. Also used in the analysis of subunits, when
+   --  re-installing use clauses of parent units. N is the use_clause that
+   --  names P (and possibly other packages).
+
+   procedure Use_One_Type (Id : Node_Id; N : Node_Id);
+   --  Id is the subtype mark from a use type clause. This procedure makes
+   --  the primitive operators of the type potentially use-visible.
+   --  N is the Use_Type_Clause that names Id.
+
+   procedure Set_Use (L : List_Id);
+   --  Find use clauses that are declarative items in a package declaration
+   --  and  set the potentially use-visible flags of imported entities before
+   --  analyzing the corresponding package body.
+
+end Sem_Ch8;
diff --git a/gcc/ada/sem_ch9.adb b/gcc/ada/sem_ch9.adb
new file mode 100644 (file)
index 0000000..2075e5e
--- /dev/null
@@ -0,0 +1,1705 @@
+------------------------------------------------------------------------------
+--                                                                          --
+--                         GNAT COMPILER COMPONENTS                         --
+--                                                                          --
+--                              S E M _ C H 9                               --
+--                                                                          --
+--                                 B o d y                                  --
+--                                                                          --
+--                            $Revision: 1.235 $
+--                                                                          --
+--          Copyright (C) 1992-2001, 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- --
+-- ware  Foundation;  either version 2,  or (at your option) any later ver- --
+-- sion.  GNAT is distributed in the hope that it will be useful, but WITH- --
+-- OUT ANY WARRANTY;  without even the  implied warranty of MERCHANTABILITY --
+-- or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License --
+-- for  more details.  You should have  received  a copy of the GNU General --
+-- Public License  distributed with GNAT;  see file COPYING.  If not, write --
+-- to  the Free Software Foundation,  59 Temple Place - Suite 330,  Boston, --
+-- MA 02111-1307, USA.                                                      --
+--                                                                          --
+-- GNAT was originally developed  by the GNAT team at  New York University. --
+-- It is now maintained by Ada Core Technologies Inc (http://www.gnat.com). --
+--                                                                          --
+------------------------------------------------------------------------------
+
+with Atree;    use Atree;
+with Checks;   use Checks;
+with Einfo;    use Einfo;
+with Errout;   use Errout;
+with Exp_Ch9;
+with Elists;   use Elists;
+with Itypes;   use Itypes;
+with Lib.Xref; use Lib.Xref;
+with Nlists;   use Nlists;
+with Nmake;    use Nmake;
+with Opt;      use Opt;
+with Restrict; use Restrict;
+with Rtsfind;  use Rtsfind;
+with Sem;      use Sem;
+with Sem_Ch3;  use Sem_Ch3;
+with Sem_Ch5;  use Sem_Ch5;
+with Sem_Ch6;  use Sem_Ch6;
+with Sem_Ch8;  use Sem_Ch8;
+with Sem_Eval; use Sem_Eval;
+with Sem_Res;  use Sem_Res;
+with Sem_Type; use Sem_Type;
+with Sem_Util; use Sem_Util;
+with Sem_Warn; use Sem_Warn;
+with Snames;   use Snames;
+with Stand;    use Stand;
+with Sinfo;    use Sinfo;
+with Style;
+with Tbuild;   use Tbuild;
+with Uintp;    use Uintp;
+
+package body Sem_Ch9 is
+
+   -----------------------
+   -- Local Subprograms --
+   -----------------------
+
+   procedure Check_Max_Entries (Def : Node_Id; R : Restriction_Parameter_Id);
+   --  Given either a protected definition or a task definition in Def, check
+   --  the corresponding restriction parameter identifier R, and if it is set,
+   --  count the entries (checking the static requirement), and compare with
+   --  the given maximum.
+
+   function Find_Concurrent_Spec (Body_Id : Entity_Id) return Entity_Id;
+   --  Find entity in corresponding task or protected declaration. Use full
+   --  view if first declaration was for an incomplete type.
+
+   procedure Install_Declarations (Spec : Entity_Id);
+   --  Utility to make visible in corresponding body the entities defined
+   --  in task, protected type declaration, or entry declaration.
+
+   -----------------------------
+   -- Analyze_Abort_Statement --
+   -----------------------------
+
+   procedure Analyze_Abort_Statement (N : Node_Id) is
+      T_Name : Node_Id;
+
+   begin
+      Tasking_Used := True;
+      T_Name := First (Names (N));
+      while Present (T_Name) loop
+         Analyze (T_Name);
+
+         if not Is_Task_Type (Etype (T_Name)) then
+            Error_Msg_N ("expect task name for ABORT", T_Name);
+            return;
+         else
+            Resolve (T_Name,  Etype (T_Name));
+         end if;
+
+         Next (T_Name);
+      end loop;
+
+      Check_Restriction (No_Abort_Statements, N);
+      Check_Potentially_Blocking_Operation (N);
+   end Analyze_Abort_Statement;
+
+   --------------------------------
+   -- Analyze_Accept_Alternative --
+   --------------------------------
+
+   procedure Analyze_Accept_Alternative (N : Node_Id) is
+   begin
+      Tasking_Used := True;
+
+      if Present (Pragmas_Before (N)) then
+         Analyze_List (Pragmas_Before (N));
+      end if;
+
+      Analyze (Accept_Statement (N));
+
+      if Present (Condition (N)) then
+         Analyze_And_Resolve (Condition (N), Any_Boolean);
+      end if;
+
+      if Is_Non_Empty_List (Statements (N)) then
+         Analyze_Statements (Statements (N));
+      end if;
+   end Analyze_Accept_Alternative;
+
+   ------------------------------
+   -- Analyze_Accept_Statement --
+   ------------------------------
+
+   procedure Analyze_Accept_Statement (N : Node_Id) is
+      Nam       : constant Entity_Id := Entry_Direct_Name (N);
+      Formals   : constant List_Id   := Parameter_Specifications (N);
+      Index     : constant Node_Id   := Entry_Index (N);
+      Stats     : constant Node_Id   := Handled_Statement_Sequence (N);
+      Ityp      : Entity_Id;
+      Entry_Nam : Entity_Id;
+      E         : Entity_Id;
+      Kind      : Entity_Kind;
+      Task_Nam  : Entity_Id;
+
+      -----------------------
+      -- Actual_Index_Type --
+      -----------------------
+
+      function Actual_Index_Type (E : Entity_Id) return Entity_Id;
+      --  If the bounds of an entry family depend on task discriminants,
+      --  create a new index type where a discriminant is replaced by the
+      --  local variable that renames it in the task body.
+
+      function Actual_Index_Type (E : Entity_Id) return Entity_Id is
+         Typ   : Entity_Id := Entry_Index_Type (E);
+         Lo    : Node_Id := Type_Low_Bound  (Typ);
+         Hi    : Node_Id := Type_High_Bound (Typ);
+         New_T : Entity_Id;
+
+         function Actual_Discriminant_Ref (Bound : Node_Id) return Node_Id;
+         --  If bound is discriminant reference, replace with corresponding
+         --  local variable of the same name.
+
+         function Actual_Discriminant_Ref (Bound : Node_Id) return Node_Id is
+            Typ : Entity_Id := Etype (Bound);
+            Ref : Node_Id;
+
+         begin
+            if not Is_Entity_Name (Bound)
+              or else Ekind (Entity (Bound)) /= E_Discriminant
+            then
+               return Bound;
+
+            else
+               Ref := Make_Identifier (Sloc (N), Chars (Entity (Bound)));
+               Analyze (Ref);
+               Resolve (Ref, Typ);
+               return Ref;
+            end if;
+         end Actual_Discriminant_Ref;
+
+      --  Start of processing for Actual_Index_Type
+
+      begin
+         if not Has_Discriminants (Task_Nam)
+           or else (not Is_Entity_Name (Lo)
+                     and then not Is_Entity_Name (Hi))
+         then
+            return Entry_Index_Type (E);
+         else
+            New_T := Create_Itype (Ekind (Typ), N);
+            Set_Etype        (New_T, Base_Type (Typ));
+            Set_Size_Info    (New_T, Typ);
+            Set_RM_Size      (New_T, RM_Size (Typ));
+            Set_Scalar_Range (New_T,
+              Make_Range (Sloc (N),
+                Low_Bound  => Actual_Discriminant_Ref (Lo),
+                High_Bound => Actual_Discriminant_Ref (Hi)));
+
+            return New_T;
+         end if;
+      end Actual_Index_Type;
+
+   --  Start of processing for Analyze_Accept_Statement
+
+   begin
+      Tasking_Used := True;
+
+      --  Entry name is initialized to Any_Id. It should get reset to the
+      --  matching entry entity. An error is signalled if it is not reset.
+
+      Entry_Nam := Any_Id;
+
+      for J in reverse 0 .. Scope_Stack.Last loop
+         Task_Nam := Scope_Stack.Table (J).Entity;
+         exit when Ekind (Etype (Task_Nam)) = E_Task_Type;
+         Kind :=  Ekind (Task_Nam);
+
+         if Kind /= E_Block and then Kind /= E_Loop
+           and then not Is_Entry (Task_Nam)
+         then
+            Error_Msg_N ("enclosing body of accept must be a task", N);
+            return;
+         end if;
+      end loop;
+
+      if Ekind (Etype (Task_Nam)) /= E_Task_Type then
+         Error_Msg_N ("invalid context for accept statement",  N);
+         return;
+      end if;
+
+      --  In order to process the parameters, we create a defining
+      --  identifier that can be used as the name of the scope. The
+      --  name of the accept statement itself is not a defining identifier.
+
+      if Present (Index) then
+         Ityp := New_Internal_Entity
+           (E_Entry_Family, Current_Scope, Sloc (N), 'E');
+      else
+         Ityp := New_Internal_Entity
+           (E_Entry, Current_Scope, Sloc (N), 'E');
+      end if;
+
+      Set_Etype          (Ityp, Standard_Void_Type);
+      Set_Accept_Address (Ityp, New_Elmt_List);
+
+      if Present (Formals) then
+         New_Scope (Ityp);
+         Process_Formals (Ityp, Formals, N);
+         Create_Extra_Formals (Ityp);
+         End_Scope;
+      end if;
+
+      --  We set the default expressions processed flag because we don't
+      --  need default expression functions. This is really more like a
+      --  body entity than a spec entity anyway.
+
+      Set_Default_Expressions_Processed (Ityp);
+
+      E := First_Entity (Etype (Task_Nam));
+
+      while Present (E) loop
+         if Chars (E) = Chars (Nam)
+           and then (Ekind (E) = Ekind (Ityp))
+           and then Type_Conformant (Ityp, E)
+         then
+            Entry_Nam := E;
+            exit;
+         end if;
+
+         Next_Entity (E);
+      end loop;
+
+      if Entry_Nam = Any_Id then
+         Error_Msg_N ("no entry declaration matches accept statement",  N);
+         return;
+      else
+         Set_Entity (Nam, Entry_Nam);
+         Generate_Reference (Entry_Nam, Nam, 'b');
+         Style.Check_Identifier (Nam, Entry_Nam);
+      end if;
+
+      --  Verify that the entry is not hidden by a procedure declared in
+      --  the current block (pathological but possible).
+
+      if Current_Scope /= Task_Nam then
+         declare
+            E1 : Entity_Id;
+
+         begin
+            E1 := First_Entity (Current_Scope);
+
+            while Present (E1) loop
+
+               if Ekind (E1) = E_Procedure
+                 and then Type_Conformant (E1, Entry_Nam)
+               then
+                  Error_Msg_N ("entry name is not visible", N);
+               end if;
+
+               Next_Entity (E1);
+            end loop;
+         end;
+      end if;
+
+      Set_Convention (Ityp, Convention (Entry_Nam));
+      Check_Fully_Conformant (Ityp, Entry_Nam, N);
+
+      for J in reverse 0 .. Scope_Stack.Last loop
+         exit when Task_Nam = Scope_Stack.Table (J).Entity;
+
+         if Entry_Nam = Scope_Stack.Table (J).Entity then
+            Error_Msg_N ("duplicate accept statement for same entry", N);
+         end if;
+
+      end loop;
+
+      declare
+         P : Node_Id := N;
+      begin
+         loop
+            P := Parent (P);
+            case Nkind (P) is
+               when N_Task_Body | N_Compilation_Unit =>
+                  exit;
+               when N_Asynchronous_Select =>
+                  Error_Msg_N ("accept statements are not allowed within" &
+                               " an asynchronous select inner" &
+                               " to the enclosing task body", N);
+                  exit;
+               when others =>
+                  null;
+            end case;
+         end loop;
+      end;
+
+      if Ekind (E) = E_Entry_Family then
+         if No (Index) then
+            Error_Msg_N ("missing entry index in accept for entry family", N);
+         else
+            Analyze_And_Resolve (Index, Entry_Index_Type (E));
+            Apply_Range_Check (Index, Actual_Index_Type (E));
+         end if;
+
+      elsif Present (Index) then
+         Error_Msg_N ("invalid entry index in accept for simple entry", N);
+      end if;
+
+      --  If statements are present, they must be analyzed in the context
+      --  of the entry, so that references to formals are correctly resolved.
+      --  We also have to add the declarations that are required by the
+      --  expansion of the accept statement in this case if expansion active.
+
+      --  In the case of a select alternative of a selective accept,
+      --  the expander references the address declaration even if there
+      --  is no statement list.
+
+      Exp_Ch9.Expand_Accept_Declarations (N, Entry_Nam);
+
+      --  If label declarations present, analyze them. They are declared
+      --  in the enclosing task, but their enclosing scope is the entry itself,
+      --  so that goto's to the label are recognized as local to the accept.
+
+      if Present (Declarations (N)) then
+
+         declare
+            Decl : Node_Id;
+            Id   : Entity_Id;
+
+         begin
+            Decl := First (Declarations (N));
+
+            while Present (Decl) loop
+               Analyze (Decl);
+
+               pragma Assert
+                 (Nkind (Decl) = N_Implicit_Label_Declaration);
+
+               Id := Defining_Identifier (Decl);
+               Set_Enclosing_Scope (Id, Entry_Nam);
+               Next (Decl);
+            end loop;
+         end;
+      end if;
+
+      --  Set Not_Source_Assigned flag on all entry formals
+
+      E := First_Entity (Entry_Nam);
+
+      while Present (E) loop
+         Set_Not_Source_Assigned (E, True);
+         Next_Entity (E);
+      end loop;
+
+      --  Analyze statements if present
+
+      if Present (Stats) then
+         New_Scope (Entry_Nam);
+         Install_Declarations (Entry_Nam);
+
+         Set_Actual_Subtypes (N, Current_Scope);
+         Analyze (Stats);
+         Process_End_Label (Handled_Statement_Sequence (N), 't');
+         End_Scope;
+      end if;
+
+      --  Some warning checks
+
+      Check_Potentially_Blocking_Operation (N);
+      Check_References (Entry_Nam, N);
+      Set_Entry_Accepted (Entry_Nam);
+
+   end Analyze_Accept_Statement;
+
+   ---------------------------------
+   -- Analyze_Asynchronous_Select --
+   ---------------------------------
+
+   procedure Analyze_Asynchronous_Select (N : Node_Id) is
+   begin
+      Tasking_Used := True;
+      Check_Restriction (Max_Asynchronous_Select_Nesting, N);
+      Check_Restriction (No_Select_Statements, N);
+
+      Analyze (Triggering_Alternative (N));
+
+      Analyze_Statements (Statements (Abortable_Part (N)));
+   end Analyze_Asynchronous_Select;
+
+   ------------------------------------
+   -- Analyze_Conditional_Entry_Call --
+   ------------------------------------
+
+   procedure Analyze_Conditional_Entry_Call (N : Node_Id) is
+   begin
+      Check_Restriction (No_Select_Statements, N);
+      Tasking_Used := True;
+      Analyze (Entry_Call_Alternative (N));
+      Analyze_Statements (Else_Statements (N));
+   end Analyze_Conditional_Entry_Call;
+
+   --------------------------------
+   -- Analyze_Delay_Alternative  --
+   --------------------------------
+
+   procedure Analyze_Delay_Alternative (N : Node_Id) is
+      Expr : Node_Id;
+
+   begin
+      Tasking_Used := True;
+      Check_Restriction (No_Delay, N);
+
+      if Present (Pragmas_Before (N)) then
+         Analyze_List (Pragmas_Before (N));
+      end if;
+
+      if Nkind (Parent (N)) = N_Selective_Accept
+        or else Nkind (Parent (N)) = N_Timed_Entry_Call
+      then
+         Expr := Expression (Delay_Statement (N));
+
+         --  defer full analysis until the statement is expanded, to insure
+         --  that generated code does not move past the guard. The delay
+         --  expression is only evaluated if the guard is open.
+
+         if Nkind (Delay_Statement (N)) = N_Delay_Relative_Statement then
+            Pre_Analyze_And_Resolve (Expr, Standard_Duration);
+
+         else
+            Pre_Analyze_And_Resolve (Expr);
+         end if;
+
+         Check_Restriction (No_Fixed_Point, Expr);
+      else
+         Analyze (Delay_Statement (N));
+      end if;
+
+      if Present (Condition (N)) then
+         Analyze_And_Resolve (Condition (N), Any_Boolean);
+      end if;
+
+      if Is_Non_Empty_List (Statements (N)) then
+         Analyze_Statements (Statements (N));
+      end if;
+   end Analyze_Delay_Alternative;
+
+   ----------------------------
+   -- Analyze_Delay_Relative --
+   ----------------------------
+
+   procedure Analyze_Delay_Relative (N : Node_Id) is
+      E : constant Node_Id := Expression (N);
+
+   begin
+      Check_Restriction (No_Relative_Delay, N);
+      Tasking_Used := True;
+      Check_Restriction (No_Delay, N);
+      Check_Potentially_Blocking_Operation (N);
+      Analyze_And_Resolve (E, Standard_Duration);
+      Check_Restriction (No_Fixed_Point, E);
+   end Analyze_Delay_Relative;
+
+   -------------------------
+   -- Analyze_Delay_Until --
+   -------------------------
+
+   procedure Analyze_Delay_Until (N : Node_Id) is
+      E : constant Node_Id := Expression (N);
+
+   begin
+      Tasking_Used := True;
+      Check_Restriction (No_Delay, N);
+      Check_Potentially_Blocking_Operation (N);
+      Analyze (E);
+
+      if not Is_RTE (Base_Type (Etype (E)), RO_CA_Time) and then
+         not Is_RTE (Base_Type (Etype (E)), RO_RT_Time)
+      then
+         Error_Msg_N ("expect Time types for `DELAY UNTIL`", E);
+      end if;
+   end Analyze_Delay_Until;
+
+   ------------------------
+   -- Analyze_Entry_Body --
+   ------------------------
+
+   procedure Analyze_Entry_Body (N : Node_Id) is
+      Id         : constant Entity_Id := Defining_Identifier (N);
+      Decls      : constant List_Id   := Declarations (N);
+      Stats      : constant Node_Id   := Handled_Statement_Sequence (N);
+      Formals    : constant Node_Id   := Entry_Body_Formal_Part (N);
+      P_Type     : constant Entity_Id := Current_Scope;
+      Entry_Name : Entity_Id;
+      E          : Entity_Id;
+
+   begin
+      Tasking_Used := True;
+
+      --  Entry_Name is initialized to Any_Id. It should get reset to the
+      --  matching entry entity. An error is signalled if it is not reset
+
+      Entry_Name := Any_Id;
+
+      Analyze (Formals);
+
+      if Present (Entry_Index_Specification (Formals)) then
+         Set_Ekind (Id, E_Entry_Family);
+      else
+         Set_Ekind (Id, E_Entry);
+      end if;
+
+      Set_Scope          (Id, Current_Scope);
+      Set_Etype          (Id, Standard_Void_Type);
+      Set_Accept_Address (Id, New_Elmt_List);
+
+      E := First_Entity (P_Type);
+      while Present (E) loop
+         if Chars (E) = Chars (Id)
+           and then (Ekind (E) = Ekind (Id))
+           and then Type_Conformant (Id, E)
+         then
+            Entry_Name := E;
+            Set_Convention (Id, Convention (E));
+            Check_Fully_Conformant (Id, E, N);
+            exit;
+         end if;
+
+         Next_Entity (E);
+      end loop;
+
+      if Entry_Name = Any_Id then
+         Error_Msg_N ("no entry declaration matches entry body",  N);
+         return;
+
+      elsif Has_Completion (Entry_Name) then
+         Error_Msg_N ("duplicate entry body", N);
+         return;
+
+      else
+         Set_Has_Completion (Entry_Name);
+         Generate_Reference (Entry_Name, Id, 'b');
+         Style.Check_Identifier (Id, Entry_Name);
+      end if;
+
+      Exp_Ch9.Expand_Entry_Barrier (N, Entry_Name);
+      New_Scope (Entry_Name);
+
+      Exp_Ch9.Expand_Entry_Body_Declarations (N);
+      Install_Declarations (Entry_Name);
+      Set_Actual_Subtypes (N, Current_Scope);
+
+      --  The entity for the protected subprogram corresponding to the entry
+      --  has been created. We retain the name of this entity in the entry
+      --  body, for use when the corresponding subprogram body is created.
+      --  Note that entry bodies have to corresponding_spec, and there is no
+      --  easy link back in the tree between the entry body and the entity for
+      --  the entry itself.
+
+      Set_Protected_Body_Subprogram (Id,
+        Protected_Body_Subprogram (Entry_Name));
+
+      if Present (Decls) then
+         Analyze_Declarations (Decls);
+      end if;
+
+      if Present (Stats) then
+         Analyze (Stats);
+      end if;
+
+      Check_References (Entry_Name);
+      Process_End_Label (Handled_Statement_Sequence (N), 't');
+      End_Scope;
+
+      --  If this is an entry family, remove the loop created to provide
+      --  a scope for the entry index.
+
+      if Ekind (Id) = E_Entry_Family
+        and then Present (Entry_Index_Specification (Formals))
+      then
+         End_Scope;
+      end if;
+
+   end Analyze_Entry_Body;
+
+   ------------------------------------
+   -- Analyze_Entry_Body_Formal_Part --
+   ------------------------------------
+
+   procedure Analyze_Entry_Body_Formal_Part (N : Node_Id) is
+      Id      : constant Entity_Id := Defining_Identifier (Parent (N));
+      Index   : constant Node_Id   := Entry_Index_Specification (N);
+      Formals : constant List_Id   := Parameter_Specifications (N);
+
+   begin
+      Tasking_Used := True;
+
+      if Present (Index) then
+         Analyze (Index);
+      end if;
+
+      if Present (Formals) then
+         Set_Scope (Id, Current_Scope);
+         New_Scope (Id);
+         Process_Formals (Id, Formals, Parent (N));
+         End_Scope;
+      end if;
+
+   end Analyze_Entry_Body_Formal_Part;
+
+   ------------------------------------
+   -- Analyze_Entry_Call_Alternative --
+   ------------------------------------
+
+   procedure Analyze_Entry_Call_Alternative (N : Node_Id) is
+   begin
+      Tasking_Used := True;
+
+      if Present (Pragmas_Before (N)) then
+         Analyze_List (Pragmas_Before (N));
+      end if;
+
+      Analyze (Entry_Call_Statement (N));
+
+      if Is_Non_Empty_List (Statements (N)) then
+         Analyze_Statements (Statements (N));
+      end if;
+   end Analyze_Entry_Call_Alternative;
+
+   -------------------------------
+   -- Analyze_Entry_Declaration --
+   -------------------------------
+
+   procedure Analyze_Entry_Declaration (N : Node_Id) is
+      Id      : Entity_Id := Defining_Identifier (N);
+      D_Sdef  : Node_Id   := Discrete_Subtype_Definition (N);
+      Formals : List_Id   := Parameter_Specifications (N);
+
+   begin
+      Generate_Definition (Id);
+      Tasking_Used := True;
+
+      if No (D_Sdef) then
+         Set_Ekind (Id, E_Entry);
+      else
+         Enter_Name (Id);
+         Set_Ekind (Id, E_Entry_Family);
+         Analyze (D_Sdef);
+         Make_Index (D_Sdef, N, Id);
+      end if;
+
+      Set_Etype          (Id, Standard_Void_Type);
+      Set_Convention     (Id, Convention_Entry);
+      Set_Accept_Address (Id, New_Elmt_List);
+
+      if Present (Formals) then
+         Set_Scope (Id, Current_Scope);
+         New_Scope (Id);
+         Process_Formals (Id, Formals, N);
+         Create_Extra_Formals (Id);
+         End_Scope;
+      end if;
+
+      if Ekind (Id) = E_Entry then
+         New_Overloaded_Entity (Id);
+      end if;
+
+   end Analyze_Entry_Declaration;
+
+   ---------------------------------------
+   -- Analyze_Entry_Index_Specification --
+   ---------------------------------------
+
+   --  The defining_Identifier of the entry index specification is local
+   --  to the entry body, but must be available in the entry barrier,
+   --  which is evaluated outside of the entry body. The index is eventually
+   --  renamed as a run-time object, so is visibility is strictly a front-end
+   --  concern. In order to make it available to the barrier, we create
+   --  an additional scope, as for a loop, whose only declaration is the
+   --  index name. This loop is not attached to the tree and does not appear
+   --  as an entity local to the protected type, so its existence need only
+   --  be knwown to routines that process entry families.
+
+   procedure Analyze_Entry_Index_Specification (N : Node_Id) is
+      Iden    : constant Node_Id := Defining_Identifier (N);
+      Def     : constant Node_Id := Discrete_Subtype_Definition (N);
+      Loop_Id : Entity_Id :=
+                  Make_Defining_Identifier (Sloc (N),
+                    Chars => New_Internal_Name ('L'));
+
+   begin
+      Tasking_Used := True;
+      Analyze (Def);
+      Make_Index (Def, N);
+      Set_Ekind (Loop_Id, E_Loop);
+      Set_Scope (Loop_Id, Current_Scope);
+      New_Scope (Loop_Id);
+      Enter_Name (Iden);
+      Set_Ekind (Iden, E_Entry_Index_Parameter);
+      Set_Etype (Iden, Etype (Def));
+   end Analyze_Entry_Index_Specification;
+
+   ----------------------------
+   -- Analyze_Protected_Body --
+   ----------------------------
+
+   procedure Analyze_Protected_Body (N : Node_Id) is
+      Body_Id   : constant Entity_Id := Defining_Identifier (N);
+      Spec_Id   : Entity_Id;
+      Last_E    : Entity_Id;
+
+   begin
+      Tasking_Used := True;
+      Set_Ekind (Body_Id, E_Protected_Body);
+      Spec_Id := Find_Concurrent_Spec (Body_Id);
+
+      if Present (Spec_Id)
+        and then Ekind (Spec_Id) = E_Protected_Type
+      then
+         null;
+
+      elsif Present (Spec_Id)
+        and then Ekind (Etype (Spec_Id)) = E_Protected_Type
+        and then not Comes_From_Source (Etype (Spec_Id))
+      then
+         null;
+
+      else
+         Error_Msg_N ("missing specification for protected body", Body_Id);
+         return;
+      end if;
+
+      Generate_Reference (Spec_Id, Body_Id, 'b');
+      Style.Check_Identifier (Body_Id, Spec_Id);
+
+      --  The declarations are always attached to the type
+
+      if Ekind (Spec_Id) /= E_Protected_Type then
+         Spec_Id := Etype (Spec_Id);
+      end if;
+
+      New_Scope (Spec_Id);
+      Set_Corresponding_Spec (N, Spec_Id);
+      Set_Corresponding_Body (Parent (Spec_Id), Body_Id);
+      Set_Has_Completion (Spec_Id);
+      Install_Declarations (Spec_Id);
+
+      Exp_Ch9.Expand_Protected_Body_Declarations (N, Spec_Id);
+
+      Last_E := Last_Entity (Spec_Id);
+
+      Analyze_Declarations (Declarations (N));
+
+      --  For visibility purposes, all entities in the body are private.
+      --  Set First_Private_Entity accordingly, if there was no private
+      --  part in the protected declaration.
+
+      if No (First_Private_Entity (Spec_Id)) then
+         if Present (Last_E) then
+            Set_First_Private_Entity (Spec_Id, Next_Entity (Last_E));
+         else
+            Set_First_Private_Entity (Spec_Id, First_Entity (Spec_Id));
+         end if;
+      end if;
+
+      Check_Completion (Body_Id);
+      Check_References (Spec_Id);
+      Process_End_Label (N, 't');
+      End_Scope;
+   end Analyze_Protected_Body;
+
+   ----------------------------------
+   -- Analyze_Protected_Definition --
+   ----------------------------------
+
+   procedure Analyze_Protected_Definition (N : Node_Id) is
+      E : Entity_Id;
+      L : Entity_Id;
+
+   begin
+      Tasking_Used := True;
+      Analyze_Declarations (Visible_Declarations (N));
+
+      if Present (Private_Declarations (N))
+        and then not Is_Empty_List (Private_Declarations (N))
+      then
+         L := Last_Entity (Current_Scope);
+         Analyze_Declarations (Private_Declarations (N));
+
+         if Present (L) then
+            Set_First_Private_Entity (Current_Scope, Next_Entity (L));
+
+         else
+            Set_First_Private_Entity (Current_Scope,
+              First_Entity (Current_Scope));
+         end if;
+      end if;
+
+      E := First_Entity (Current_Scope);
+
+      while Present (E) loop
+
+         if Ekind (E) = E_Function
+           or else Ekind (E) = E_Procedure
+         then
+            Set_Convention (E, Convention_Protected);
+
+         elsif Is_Task_Type (Etype (E)) then
+            Set_Has_Task (Current_Scope);
+         end if;
+
+         Next_Entity (E);
+      end loop;
+
+      Check_Max_Entries (N, Max_Protected_Entries);
+      Process_End_Label (N, 'e');
+   end Analyze_Protected_Definition;
+
+   ----------------------------
+   -- Analyze_Protected_Type --
+   ----------------------------
+
+   procedure Analyze_Protected_Type (N : Node_Id) is
+      E      : Entity_Id;
+      T      : Entity_Id;
+      Def_Id : constant Entity_Id := Defining_Identifier (N);
+
+   begin
+      Tasking_Used := True;
+      Check_Restriction (No_Protected_Types, N);
+
+      T := Find_Type_Name (N);
+
+      if Ekind (T) = E_Incomplete_Type then
+         T := Full_View (T);
+      end if;
+
+      Set_Ekind              (T, E_Protected_Type);
+      Init_Size_Align        (T);
+      Set_Etype              (T, T);
+      Set_Is_First_Subtype   (T, True);
+      Set_Has_Delayed_Freeze (T, True);
+      Set_Girder_Constraint  (T, No_Elist);
+      New_Scope (T);
+
+      if Present (Discriminant_Specifications (N)) then
+         if Has_Discriminants (T) then
+
+            --  Install discriminants. Also, verify conformance of
+            --  discriminants of previous and current view.  ???
+
+            Install_Declarations (T);
+         else
+            Process_Discriminants (N);
+         end if;
+      end if;
+
+      Analyze (Protected_Definition (N));
+
+      --  Protected types with entries are controlled (because of the
+      --  Protection component if nothing else), same for any protected type
+      --  with interrupt handlers. Note that we need to analyze the protected
+      --  definition to set Has_Entries and such.
+
+      if (Abort_Allowed or else Restrictions (No_Entry_Queue) = False
+           or else Number_Entries (T) > 1)
+        and then
+          (Has_Entries (T)
+            or else Has_Interrupt_Handler (T)
+            or else Has_Attach_Handler (T))
+      then
+         Set_Has_Controlled_Component (T, True);
+      end if;
+
+      --  The Ekind of components is E_Void during analysis to detect
+      --  illegal uses. Now it can be set correctly.
+
+      E := First_Entity (Current_Scope);
+
+      while Present (E) loop
+         if Ekind (E) = E_Void then
+            Set_Ekind (E, E_Component);
+            Init_Component_Location (E);
+         end if;
+
+         Next_Entity (E);
+      end loop;
+
+      End_Scope;
+
+      if T /= Def_Id
+        and then Is_Private_Type (Def_Id)
+        and then Has_Discriminants (Def_Id)
+        and then Expander_Active
+      then
+         Exp_Ch9.Expand_N_Protected_Type_Declaration (N);
+         Process_Full_View (N, T, Def_Id);
+      end if;
+
+   end Analyze_Protected_Type;
+
+   ---------------------
+   -- Analyze_Requeue --
+   ---------------------
+
+   procedure Analyze_Requeue (N : Node_Id) is
+      Entry_Name : Node_Id := Name (N);
+      Entry_Id   : Entity_Id;
+      Found      : Boolean;
+      I          : Interp_Index;
+      It         : Interp;
+      Enclosing  : Entity_Id;
+      Target_Obj : Node_Id := Empty;
+      Req_Scope  : Entity_Id;
+      Outer_Ent  : Entity_Id;
+
+   begin
+      Check_Restriction (No_Requeue, N);
+      Check_Unreachable_Code (N);
+      Tasking_Used := True;
+
+      Enclosing := Empty;
+      for J in reverse 0 .. Scope_Stack.Last loop
+         Enclosing := Scope_Stack.Table (J).Entity;
+         exit when Is_Entry (Enclosing);
+
+         if Ekind (Enclosing) /= E_Block
+           and then Ekind (Enclosing) /= E_Loop
+         then
+            Error_Msg_N ("requeue must appear within accept or entry body", N);
+            return;
+         end if;
+      end loop;
+
+      Analyze (Entry_Name);
+
+      if Etype (Entry_Name) = Any_Type then
+         return;
+      end if;
+
+      if Nkind (Entry_Name) = N_Selected_Component then
+         Target_Obj := Prefix (Entry_Name);
+         Entry_Name := Selector_Name (Entry_Name);
+      end if;
+
+      --  If an explicit target object is given then we have to check
+      --  the restrictions of 9.5.4(6).
+
+      if Present (Target_Obj) then
+         --  Locate containing concurrent unit and determine
+         --  enclosing entry body or outermost enclosing accept
+         --  statement within the unit.
+
+         Outer_Ent := Empty;
+         for S in reverse 0 .. Scope_Stack.Last loop
+            Req_Scope := Scope_Stack.Table (S).Entity;
+
+            exit when Ekind (Req_Scope) in Task_Kind
+              or else Ekind (Req_Scope) in Protected_Kind;
+
+            if Is_Entry (Req_Scope) then
+               Outer_Ent := Req_Scope;
+            end if;
+         end loop;
+
+         pragma Assert (Present (Outer_Ent));
+
+         --  Check that the accessibility level of the target object
+         --  is not greater or equal to the outermost enclosing accept
+         --  statement (or entry body) unless it is a parameter of the
+         --  innermost enclosing accept statement (or entry body).
+
+         if Object_Access_Level (Target_Obj) >= Scope_Depth (Outer_Ent)
+           and then
+             (not Is_Entity_Name (Target_Obj)
+               or else Ekind (Entity (Target_Obj)) not in Formal_Kind
+               or else Enclosing /= Scope (Entity (Target_Obj)))
+         then
+            Error_Msg_N
+              ("target object has invalid level for requeue", Target_Obj);
+         end if;
+      end if;
+
+      --  Overloaded case, find right interpretation
+
+      if Is_Overloaded (Entry_Name) then
+         Get_First_Interp (Entry_Name, I, It);
+         Found := False;
+         Entry_Id := Empty;
+
+         while Present (It.Nam) loop
+
+            if No (First_Formal (It.Nam))
+              or else Subtype_Conformant (Enclosing, It.Nam)
+            then
+               if not Found then
+                  Found := True;
+                  Entry_Id := It.Nam;
+               else
+                  Error_Msg_N ("ambiguous entry name in requeue", N);
+                  return;
+               end if;
+            end if;
+
+            Get_Next_Interp (I, It);
+         end loop;
+
+         if not Found then
+            Error_Msg_N ("no entry matches context",  N);
+            return;
+         else
+            Set_Entity (Entry_Name, Entry_Id);
+         end if;
+
+      --  Non-overloaded cases
+
+      --  For the case of a reference to an element of an entry family,
+      --  the Entry_Name is an indexed component.
+
+      elsif Nkind (Entry_Name) = N_Indexed_Component then
+
+         --  Requeue to an entry out of the body
+
+         if Nkind (Prefix (Entry_Name)) = N_Selected_Component then
+            Entry_Id := Entity (Selector_Name (Prefix (Entry_Name)));
+
+         --  Requeue from within the body itself
+
+         elsif Nkind (Prefix (Entry_Name)) = N_Identifier then
+            Entry_Id := Entity (Prefix (Entry_Name));
+
+         else
+            Error_Msg_N ("invalid entry_name specified",  N);
+            return;
+         end if;
+
+      --  If we had a requeue of the form REQUEUE A (B), then the parser
+      --  accepted it (because it could have been a requeue on an entry
+      --  index. If A turns out not to be an entry family, then the analysis
+      --  of A (B) turned it into a function call.
+
+      elsif Nkind (Entry_Name) = N_Function_Call then
+         Error_Msg_N
+           ("arguments not allowed in requeue statement",
+            First (Parameter_Associations (Entry_Name)));
+         return;
+
+      --  Normal case of no entry family, no argument
+
+      else
+         Entry_Id := Entity (Entry_Name);
+      end if;
+
+      --  Resolve entry, and check that it is subtype conformant with the
+      --  enclosing construct if this construct has formals (RM 9.5.4(5)).
+
+      if not Is_Entry (Entry_Id) then
+         Error_Msg_N ("expect entry name in requeue statement", Name (N));
+      elsif Ekind (Entry_Id) = E_Entry_Family
+
+        and then Nkind (Entry_Name) /= N_Indexed_Component
+      then
+         Error_Msg_N ("missing index for entry family component", Name (N));
+
+      else
+         Resolve_Entry (Name (N));
+
+         if Present (First_Formal (Entry_Id)) then
+            Check_Subtype_Conformant (Enclosing, Entry_Id, Name (N));
+
+            --  Mark any output parameters as assigned
+
+            declare
+               Ent : Entity_Id := First_Formal (Enclosing);
+
+            begin
+               while Present (Ent) loop
+                  if Ekind (Ent) = E_Out_Parameter then
+                     Set_Not_Source_Assigned (Ent, False);
+                  end if;
+
+                  Next_Formal (Ent);
+               end loop;
+            end;
+         end if;
+      end if;
+
+   end Analyze_Requeue;
+
+   ------------------------------
+   -- Analyze_Selective_Accept --
+   ------------------------------
+
+   procedure Analyze_Selective_Accept (N : Node_Id) is
+      Alts : constant List_Id := Select_Alternatives (N);
+      Alt  : Node_Id;
+
+      Accept_Present    : Boolean := False;
+      Terminate_Present : Boolean := False;
+      Delay_Present     : Boolean := False;
+      Relative_Present  : Boolean := False;
+      Alt_Count         : Uint    := Uint_0;
+
+   begin
+      Check_Restriction (No_Select_Statements, N);
+      Tasking_Used := True;
+
+      Alt := First (Alts);
+      while Present (Alt) loop
+         Alt_Count := Alt_Count + 1;
+         Analyze (Alt);
+
+         if Nkind (Alt) = N_Delay_Alternative then
+            if Delay_Present then
+
+               if (Relative_Present /=
+                 (Nkind (Delay_Statement (Alt)) = N_Delay_Relative_Statement))
+               then
+                  Error_Msg_N
+                    ("delay_until and delay_relative alternatives ", Alt);
+                  Error_Msg_N
+                    ("\cannot appear in the same selective_wait", Alt);
+               end if;
+
+            else
+               Delay_Present := True;
+               Relative_Present :=
+                 Nkind (Delay_Statement (Alt)) = N_Delay_Relative_Statement;
+            end if;
+
+         elsif Nkind (Alt) = N_Terminate_Alternative then
+            if Terminate_Present then
+               Error_Msg_N ("Only one terminate alternative allowed", N);
+            else
+               Terminate_Present := True;
+               Check_Restriction (No_Terminate_Alternatives, N);
+            end if;
+
+         elsif Nkind (Alt) = N_Accept_Alternative then
+            Accept_Present := True;
+
+            --  Check for duplicate accept
+
+            declare
+               Alt1 : Node_Id;
+               Stm  : constant Node_Id := Accept_Statement (Alt);
+               EDN  : constant Node_Id := Entry_Direct_Name (Stm);
+               Ent  : Entity_Id;
+
+            begin
+               if Nkind (EDN) = N_Identifier
+                 and then No (Condition (Alt))
+                 and then Present (Entity (EDN)) -- defend against junk
+                 and then Ekind (Entity (EDN)) = E_Entry
+               then
+                  Ent := Entity (EDN);
+
+                  Alt1 := First (Alts);
+                  while Alt1 /= Alt loop
+                     if Nkind (Alt1) = N_Accept_Alternative
+                       and then No (Condition (Alt1))
+                     then
+                        declare
+                           Stm1 : constant Node_Id := Accept_Statement (Alt1);
+                           EDN1 : constant Node_Id := Entry_Direct_Name (Stm1);
+
+                        begin
+                           if Nkind (EDN1) = N_Identifier then
+                              if Entity (EDN1) = Ent then
+                                 Error_Msg_Sloc := Sloc (Stm1);
+                                 Error_Msg_N
+                                   ("?accept duplicates one on line#", Stm);
+                                 exit;
+                              end if;
+                           end if;
+                        end;
+                     end if;
+
+                     Next (Alt1);
+                  end loop;
+               end if;
+            end;
+         end if;
+
+         Next (Alt);
+      end loop;
+
+      Check_Restriction (Max_Select_Alternatives, Alt_Count, N);
+      Check_Potentially_Blocking_Operation (N);
+
+      if Terminate_Present and Delay_Present then
+         Error_Msg_N ("at most one of terminate or delay alternative", N);
+
+      elsif not Accept_Present then
+         Error_Msg_N
+           ("select must contain at least one accept alternative", N);
+      end if;
+
+      if Present (Else_Statements (N)) then
+         if Terminate_Present or Delay_Present then
+            Error_Msg_N ("else part not allowed with other alternatives", N);
+         end if;
+
+         Analyze_Statements (Else_Statements (N));
+      end if;
+   end Analyze_Selective_Accept;
+
+   ------------------------------
+   -- Analyze_Single_Protected --
+   ------------------------------
+
+   procedure Analyze_Single_Protected (N : Node_Id) is
+      Loc    : constant Source_Ptr := Sloc (N);
+      Id     : constant Node_Id    := Defining_Identifier (N);
+      T      : Entity_Id;
+      T_Decl : Node_Id;
+      O_Decl : Node_Id;
+      O_Name : constant Entity_Id := New_Copy (Id);
+
+   begin
+      Generate_Definition (Id);
+      Tasking_Used := True;
+
+      --  The node is rewritten as a protected type declaration,
+      --  in exact analogy with what is done with single tasks.
+
+      T :=
+        Make_Defining_Identifier (Sloc (Id),
+          New_External_Name (Chars (Id), 'T'));
+
+      T_Decl :=
+        Make_Protected_Type_Declaration (Loc,
+         Defining_Identifier => T,
+         Protected_Definition => Relocate_Node (Protected_Definition (N)));
+
+      O_Decl :=
+        Make_Object_Declaration (Loc,
+          Defining_Identifier => O_Name,
+          Object_Definition   => Make_Identifier (Loc,  Chars (T)));
+
+      Rewrite (N, T_Decl);
+      Insert_After (N, O_Decl);
+      Mark_Rewrite_Insertion (O_Decl);
+
+      --  Enter names of type and object before analysis, because the name
+      --  of the object may be used in its own body.
+
+      Enter_Name (T);
+      Set_Ekind (T, E_Protected_Type);
+      Set_Etype (T, T);
+
+      Enter_Name (O_Name);
+      Set_Ekind (O_Name, E_Variable);
+      Set_Etype (O_Name, T);
+
+      --  Instead of calling Analyze on the new node,  call directly
+      --  the proper analysis procedure. Otherwise the node would be
+      --  expanded twice, with disastrous result.
+
+      Analyze_Protected_Type (N);
+
+   end Analyze_Single_Protected;
+
+   -------------------------
+   -- Analyze_Single_Task --
+   -------------------------
+
+   procedure Analyze_Single_Task (N : Node_Id) is
+      Loc    : constant Source_Ptr := Sloc (N);
+      Id     : constant Node_Id    := Defining_Identifier (N);
+      T      : Entity_Id;
+      T_Decl : Node_Id;
+      O_Decl : Node_Id;
+      O_Name : constant Entity_Id := New_Copy (Id);
+
+   begin
+      Generate_Definition (Id);
+      Tasking_Used := True;
+
+      --  The node is rewritten as a task type declaration,  followed
+      --  by an object declaration of that anonymous task type.
+
+      T :=
+        Make_Defining_Identifier (Sloc (Id),
+          New_External_Name (Chars (Id), Suffix => "TK"));
+
+      T_Decl :=
+        Make_Task_Type_Declaration (Loc,
+          Defining_Identifier => T,
+          Task_Definition     => Relocate_Node (Task_Definition (N)));
+
+      O_Decl :=
+        Make_Object_Declaration (Loc,
+          Defining_Identifier => O_Name,
+          Object_Definition   => Make_Identifier (Loc, Chars (T)));
+
+      Rewrite (N, T_Decl);
+      Insert_After (N, O_Decl);
+      Mark_Rewrite_Insertion (O_Decl);
+
+      --  Enter names of type and object before analysis, because the name
+      --  of the object may be used in its own body.
+
+      Enter_Name (T);
+      Set_Ekind (T, E_Task_Type);
+      Set_Etype (T, T);
+
+      Enter_Name (O_Name);
+      Set_Ekind (O_Name, E_Variable);
+      Set_Etype (O_Name, T);
+
+      --  Instead of calling Analyze on the new node,  call directly
+      --  the proper analysis procedure. Otherwise the node would be
+      --  expanded twice, with disastrous result.
+
+      Analyze_Task_Type (N);
+
+   end Analyze_Single_Task;
+
+   -----------------------
+   -- Analyze_Task_Body --
+   -----------------------
+
+   procedure Analyze_Task_Body (N : Node_Id) is
+      Body_Id : constant Entity_Id := Defining_Identifier (N);
+      Spec_Id : Entity_Id;
+      Last_E  : Entity_Id;
+
+   begin
+      Tasking_Used := True;
+      Set_Ekind (Body_Id, E_Task_Body);
+      Set_Scope (Body_Id, Current_Scope);
+      Spec_Id := Find_Concurrent_Spec (Body_Id);
+
+      --  The spec is either a task type declaration, or a single task
+      --  declaration for which we have created an anonymous type.
+
+      if Present (Spec_Id)
+        and then Ekind (Spec_Id) = E_Task_Type
+      then
+         null;
+
+      elsif Present (Spec_Id)
+        and then Ekind (Etype (Spec_Id)) = E_Task_Type
+        and then not Comes_From_Source (Etype (Spec_Id))
+      then
+         null;
+
+      else
+         Error_Msg_N ("missing specification for task body", Body_Id);
+         return;
+      end if;
+
+      Generate_Reference (Spec_Id, Body_Id, 'b');
+      Style.Check_Identifier (Body_Id, Spec_Id);
+
+      --  Deal with case of body of single task (anonymous type was created)
+
+      if Ekind (Spec_Id) = E_Variable then
+         Spec_Id := Etype (Spec_Id);
+      end if;
+
+      New_Scope (Spec_Id);
+      Set_Corresponding_Spec (N, Spec_Id);
+      Set_Corresponding_Body (Parent (Spec_Id), Body_Id);
+      Set_Has_Completion (Spec_Id);
+      Install_Declarations (Spec_Id);
+      Last_E := Last_Entity (Spec_Id);
+
+      Analyze_Declarations (Declarations (N));
+
+      --  For visibility purposes, all entities in the body are private.
+      --  Set First_Private_Entity accordingly, if there was no private
+      --  part in the protected declaration.
+
+      if No (First_Private_Entity (Spec_Id)) then
+         if Present (Last_E) then
+            Set_First_Private_Entity (Spec_Id, Next_Entity (Last_E));
+         else
+            Set_First_Private_Entity (Spec_Id, First_Entity (Spec_Id));
+         end if;
+      end if;
+
+      Analyze (Handled_Statement_Sequence (N));
+      Check_Completion (Body_Id);
+      Check_References (Body_Id);
+
+      --  Check for entries with no corresponding accept
+
+      declare
+         Ent : Entity_Id;
+
+      begin
+         Ent := First_Entity (Spec_Id);
+
+         while Present (Ent) loop
+            if Is_Entry (Ent)
+              and then not Entry_Accepted (Ent)
+              and then Comes_From_Source (Ent)
+            then
+               Error_Msg_NE ("no accept for entry &?", N, Ent);
+            end if;
+
+            Next_Entity (Ent);
+         end loop;
+      end;
+
+      Process_End_Label (Handled_Statement_Sequence (N), 't');
+      End_Scope;
+   end Analyze_Task_Body;
+
+   -----------------------------
+   -- Analyze_Task_Definition --
+   -----------------------------
+
+   procedure Analyze_Task_Definition (N : Node_Id) is
+      L : Entity_Id;
+
+   begin
+      Tasking_Used := True;
+
+      if Present (Visible_Declarations (N)) then
+         Analyze_Declarations (Visible_Declarations (N));
+      end if;
+
+      if Present (Private_Declarations (N)) then
+         L := Last_Entity (Current_Scope);
+         Analyze_Declarations (Private_Declarations (N));
+
+         if Present (L) then
+            Set_First_Private_Entity
+              (Current_Scope, Next_Entity (L));
+         else
+            Set_First_Private_Entity
+              (Current_Scope, First_Entity (Current_Scope));
+         end if;
+      end if;
+
+      Check_Max_Entries (N, Max_Task_Entries);
+      Process_End_Label (N, 'e');
+   end Analyze_Task_Definition;
+
+   -----------------------
+   -- Analyze_Task_Type --
+   -----------------------
+
+   procedure Analyze_Task_Type (N : Node_Id) is
+      T      : Entity_Id;
+      Def_Id : constant Entity_Id := Defining_Identifier (N);
+
+   begin
+      Tasking_Used := True;
+      Check_Restriction (Max_Tasks, N);
+      T := Find_Type_Name (N);
+      Generate_Definition (T);
+
+      if Ekind (T) = E_Incomplete_Type then
+         T := Full_View (T);
+      end if;
+
+      Set_Ekind              (T, E_Task_Type);
+      Set_Is_First_Subtype   (T, True);
+      Set_Has_Task           (T, True);
+      Init_Size_Align        (T);
+      Set_Etype              (T, T);
+      Set_Has_Delayed_Freeze (T, True);
+      Set_Girder_Constraint (T, No_Elist);
+      New_Scope (T);
+
+      if Present (Discriminant_Specifications (N)) then
+         if Ada_83 and then Comes_From_Source (N) then
+            Error_Msg_N ("(Ada 83) task discriminant not allowed!", N);
+         end if;
+
+         if Has_Discriminants (T) then
+
+            --  Install discriminants. Also, verify conformance of
+            --  discriminants of previous and current view.  ???
+
+            Install_Declarations (T);
+         else
+            Process_Discriminants (N);
+         end if;
+      end if;
+
+      if Present (Task_Definition (N)) then
+         Analyze_Task_Definition (Task_Definition (N));
+      end if;
+
+      if not Is_Library_Level_Entity (T) then
+         Check_Restriction (No_Task_Hierarchy, N);
+      end if;
+
+      End_Scope;
+
+      if T /= Def_Id
+        and then Is_Private_Type (Def_Id)
+        and then Has_Discriminants (Def_Id)
+        and then Expander_Active
+      then
+         Exp_Ch9.Expand_N_Task_Type_Declaration (N);
+         Process_Full_View (N, T, Def_Id);
+      end if;
+   end Analyze_Task_Type;
+
+   -----------------------------------
+   -- Analyze_Terminate_Alternative --
+   -----------------------------------
+
+   procedure Analyze_Terminate_Alternative (N : Node_Id) is
+   begin
+      Tasking_Used := True;
+
+      if Present (Pragmas_Before (N)) then
+         Analyze_List (Pragmas_Before (N));
+      end if;
+
+      if Present (Condition (N)) then
+         Analyze_And_Resolve (Condition (N), Any_Boolean);
+      end if;
+   end Analyze_Terminate_Alternative;
+
+   ------------------------------
+   -- Analyze_Timed_Entry_Call --
+   ------------------------------
+
+   procedure Analyze_Timed_Entry_Call (N : Node_Id) is
+   begin
+      Check_Restriction (No_Select_Statements, N);
+      Tasking_Used := True;
+      Analyze (Entry_Call_Alternative (N));
+      Analyze (Delay_Alternative (N));
+   end Analyze_Timed_Entry_Call;
+
+   ------------------------------------
+   -- Analyze_Triggering_Alternative --
+   ------------------------------------
+
+   procedure Analyze_Triggering_Alternative (N : Node_Id) is
+      Trigger : Node_Id := Triggering_Statement (N);
+   begin
+      Tasking_Used := True;
+
+      if Present (Pragmas_Before (N)) then
+         Analyze_List (Pragmas_Before (N));
+      end if;
+
+      Analyze (Trigger);
+      if Comes_From_Source (Trigger)
+        and then Nkind (Trigger) /= N_Delay_Until_Statement
+        and then Nkind (Trigger) /= N_Delay_Relative_Statement
+        and then Nkind (Trigger) /= N_Entry_Call_Statement
+      then
+         Error_Msg_N
+          ("triggering statement must be delay or entry call", Trigger);
+      end if;
+
+      if Is_Non_Empty_List (Statements (N)) then
+         Analyze_Statements (Statements (N));
+      end if;
+   end Analyze_Triggering_Alternative;
+
+   -----------------------
+   -- Check_Max_Entries --
+   -----------------------
+
+   procedure Check_Max_Entries (Def : Node_Id; R : Restriction_Parameter_Id) is
+      Ecount : Uint;
+
+      procedure Count (L : List_Id);
+      --  Count entries in given declaration list
+
+      procedure Count (L : List_Id) is
+         D : Node_Id;
+
+      begin
+         if No (L) then
+            return;
+         end if;
+
+         D := First (L);
+         while Present (D) loop
+            if Nkind (D) = N_Entry_Declaration then
+               declare
+                  DSD : constant Node_Id :=
+                          Discrete_Subtype_Definition (D);
+
+               begin
+                  if No (DSD) then
+                     Ecount := Ecount + 1;
+
+                  elsif Is_OK_Static_Subtype (Etype (DSD)) then
+                     declare
+                        Lo : constant Uint :=
+                               Expr_Value
+                                 (Type_Low_Bound (Etype (DSD)));
+                        Hi : constant Uint :=
+                               Expr_Value
+                                 (Type_High_Bound (Etype (DSD)));
+
+                     begin
+                        if Hi >= Lo then
+                           Ecount := Ecount + Hi - Lo + 1;
+                        end if;
+                     end;
+
+                  else
+                     Error_Msg_N
+                       ("static subtype required by Restriction pragma", DSD);
+                  end if;
+               end;
+            end if;
+
+            Next (D);
+         end loop;
+      end Count;
+
+   --  Start of processing for Check_Max_Entries
+
+   begin
+      if Restriction_Parameters (R) >= 0 then
+         Ecount := Uint_0;
+         Count (Visible_Declarations (Def));
+         Count (Private_Declarations (Def));
+         Check_Restriction (R, Ecount, Def);
+      end if;
+   end Check_Max_Entries;
+
+   --------------------------
+   -- Find_Concurrent_Spec --
+   --------------------------
+
+   function Find_Concurrent_Spec (Body_Id : Entity_Id) return Entity_Id is
+      Spec_Id : Entity_Id := Current_Entity_In_Scope (Body_Id);
+
+   begin
+      --  The type may have been given by an incomplete type declaration.
+      --  Find full view now.
+
+      if Present (Spec_Id) and then Ekind (Spec_Id) = E_Incomplete_Type then
+         Spec_Id := Full_View (Spec_Id);
+      end if;
+
+      return Spec_Id;
+   end Find_Concurrent_Spec;
+
+   --------------------------
+   -- Install_Declarations --
+   --------------------------
+
+   procedure Install_Declarations (Spec : Entity_Id) is
+      E    : Entity_Id;
+      Prev : Entity_Id;
+
+   begin
+      E := First_Entity (Spec);
+
+      while Present (E) loop
+         Prev := Current_Entity (E);
+         Set_Current_Entity (E);
+         Set_Is_Immediately_Visible (E);
+         Set_Homonym (E, Prev);
+         Next_Entity (E);
+      end loop;
+   end Install_Declarations;
+
+end Sem_Ch9;
diff --git a/gcc/ada/sem_ch9.ads b/gcc/ada/sem_ch9.ads
new file mode 100644 (file)
index 0000000..d4922b3
--- /dev/null
@@ -0,0 +1,58 @@
+------------------------------------------------------------------------------
+--                                                                          --
+--                         GNAT COMPILER COMPONENTS                         --
+--                                                                          --
+--                              S E M _ C H 9                               --
+--                                                                          --
+--                                 S p e c                                  --
+--                                                                          --
+--                            $Revision: 1.8 $
+--                                                                          --
+--          Copyright (C) 1992-2001 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- --
+-- ware  Foundation;  either version 2,  or (at your option) any later ver- --
+-- sion.  GNAT is distributed in the hope that it will be useful, but WITH- --
+-- OUT ANY WARRANTY;  without even the  implied warranty of MERCHANTABILITY --
+-- or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License --
+-- for  more details.  You should have  received  a copy of the GNU General --
+-- Public License  distributed with GNAT;  see file COPYING.  If not, write --
+-- to  the Free Software Foundation,  59 Temple Place - Suite 330,  Boston, --
+-- MA 02111-1307, USA.                                                      --
+--                                                                          --
+-- GNAT was originally developed  by the GNAT team at  New York University. --
+-- It is now maintained by Ada Core Technologies Inc (http://www.gnat.com). --
+--                                                                          --
+------------------------------------------------------------------------------
+
+with Types; use Types;
+
+package Sem_Ch9  is
+   procedure Analyze_Abort_Statement                    (N : Node_Id);
+   procedure Analyze_Accept_Alternative                 (N : Node_Id);
+   procedure Analyze_Accept_Statement                   (N : Node_Id);
+   procedure Analyze_Asynchronous_Select                (N : Node_Id);
+   procedure Analyze_Conditional_Entry_Call             (N : Node_Id);
+   procedure Analyze_Delay_Alternative                  (N : Node_Id);
+   procedure Analyze_Delay_Relative                     (N : Node_Id);
+   procedure Analyze_Delay_Until                        (N : Node_Id);
+   procedure Analyze_Entry_Body                         (N : Node_Id);
+   procedure Analyze_Entry_Body_Formal_Part             (N : Node_Id);
+   procedure Analyze_Entry_Call_Alternative             (N : Node_Id);
+   procedure Analyze_Entry_Declaration                  (N : Node_Id);
+   procedure Analyze_Entry_Index_Specification          (N : Node_Id);
+   procedure Analyze_Protected_Body                     (N : Node_Id);
+   procedure Analyze_Protected_Definition               (N : Node_Id);
+   procedure Analyze_Protected_Type                     (N : Node_Id);
+   procedure Analyze_Requeue                            (N : Node_Id);
+   procedure Analyze_Selective_Accept                   (N : Node_Id);
+   procedure Analyze_Single_Protected                   (N : Node_Id);
+   procedure Analyze_Single_Task                        (N : Node_Id);
+   procedure Analyze_Task_Body                          (N : Node_Id);
+   procedure Analyze_Task_Definition                    (N : Node_Id);
+   procedure Analyze_Task_Type                          (N : Node_Id);
+   procedure Analyze_Terminate_Alternative              (N : Node_Id);
+   procedure Analyze_Timed_Entry_Call                   (N : Node_Id);
+   procedure Analyze_Triggering_Alternative             (N : Node_Id);
+end Sem_Ch9;
diff --git a/gcc/ada/sem_disp.adb b/gcc/ada/sem_disp.adb
new file mode 100644 (file)
index 0000000..31dae90
--- /dev/null
@@ -0,0 +1,992 @@
+------------------------------------------------------------------------------
+--                                                                          --
+--                         GNAT COMPILER COMPONENTS                         --
+--                                                                          --
+--                             S E M _ D I S P                              --
+--                                                                          --
+--                                 B o d y                                  --
+--                                                                          --
+--                            $Revision: 1.114 $
+--                                                                          --
+--          Copyright (C) 1992-2001 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- --
+-- ware  Foundation;  either version 2,  or (at your option) any later ver- --
+-- sion.  GNAT is distributed in the hope that it will be useful, but WITH- --
+-- OUT ANY WARRANTY;  without even the  implied warranty of MERCHANTABILITY --
+-- or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License --
+-- for  more details.  You should have  received  a copy of the GNU General --
+-- Public License  distributed with GNAT;  see file COPYING.  If not, write --
+-- to  the Free Software Foundation,  59 Temple Place - Suite 330,  Boston, --
+-- MA 02111-1307, USA.                                                      --
+--                                                                          --
+-- GNAT was originally developed  by the GNAT team at  New York University. --
+-- It is now maintained by Ada Core Technologies Inc (http://www.gnat.com). --
+--                                                                          --
+------------------------------------------------------------------------------
+
+with Atree;    use Atree;
+with Debug;    use Debug;
+with Elists;   use Elists;
+with Einfo;    use Einfo;
+with Exp_Disp; use Exp_Disp;
+with Errout;   use Errout;
+with Hostparm; use Hostparm;
+with Nlists;   use Nlists;
+with Output;   use Output;
+with Sem_Ch6;  use Sem_Ch6;
+with Sem_Eval; use Sem_Eval;
+with Sem_Util; use Sem_Util;
+with Sinfo;    use Sinfo;
+with Uintp;    use Uintp;
+
+package body Sem_Disp is
+
+   -----------------------
+   -- Local Subprograms --
+   -----------------------
+
+   procedure Override_Dispatching_Operation
+     (Tagged_Type : Entity_Id;
+      Prev_Op     : Entity_Id;
+      New_Op      : Entity_Id);
+   --  Replace an implicit dispatching operation with an  explicit one.
+   --  Prev_Op is an inherited primitive operation which is overridden
+   --  by the explicit declaration of New_Op.
+
+   procedure Add_Dispatching_Operation
+     (Tagged_Type : Entity_Id;
+      New_Op      : Entity_Id);
+   --  Add New_Op in the list of primitive operations of Tagged_Type
+
+   function Check_Controlling_Type
+     (T    : Entity_Id;
+      Subp : Entity_Id)
+      return Entity_Id;
+      --  T is the type of a formal parameter of subp. Returns the tagged
+      --  if the parameter can be a controlling argument, empty otherwise
+
+   --------------------------------
+   --  Add_Dispatching_Operation --
+   --------------------------------
+
+   procedure Add_Dispatching_Operation
+     (Tagged_Type : Entity_Id;
+      New_Op      : Entity_Id)
+   is
+      List : constant Elist_Id := Primitive_Operations (Tagged_Type);
+
+   begin
+      Append_Elmt (New_Op, List);
+   end Add_Dispatching_Operation;
+
+   -------------------------------
+   -- Check_Controlling_Formals --
+   -------------------------------
+
+   procedure Check_Controlling_Formals
+     (Typ  : Entity_Id;
+      Subp : Entity_Id)
+   is
+      Formal    : Entity_Id;
+      Ctrl_Type : Entity_Id;
+      Remote    : constant Boolean :=
+                    Is_Remote_Types (Current_Scope)
+                      and then Comes_From_Source (Subp)
+                      and then Scope (Typ) = Current_Scope;
+
+   begin
+      Formal := First_Formal (Subp);
+
+      while Present (Formal) loop
+         Ctrl_Type := Check_Controlling_Type (Etype (Formal), Subp);
+
+         if Present (Ctrl_Type) then
+            if Ctrl_Type = Typ then
+               Set_Is_Controlling_Formal (Formal);
+
+               --  Check that the parameter's nominal subtype statically
+               --  matches the first subtype.
+
+               if Ekind (Etype (Formal)) = E_Anonymous_Access_Type then
+                  if not Subtypes_Statically_Match
+                           (Typ, Designated_Type (Etype (Formal)))
+                  then
+                     Error_Msg_N
+                       ("parameter subtype does not match controlling type",
+                        Formal);
+                  end if;
+
+               elsif not Subtypes_Statically_Match (Typ, Etype (Formal)) then
+                  Error_Msg_N
+                    ("parameter subtype does not match controlling type",
+                     Formal);
+               end if;
+
+               if Present (Default_Value (Formal)) then
+                  if Ekind (Etype (Formal)) = E_Anonymous_Access_Type then
+                     Error_Msg_N
+                       ("default not allowed for controlling access parameter",
+                        Default_Value (Formal));
+
+                  elsif not Is_Tag_Indeterminate (Default_Value (Formal)) then
+                     Error_Msg_N
+                       ("default expression must be a tag indeterminate" &
+                        " function call", Default_Value (Formal));
+                  end if;
+               end if;
+
+            elsif Comes_From_Source (Subp) then
+               Error_Msg_N
+                 ("operation can be dispatching in only one type", Subp);
+            end if;
+
+         --  Verify that the restriction in E.2.2 (1) is obeyed.
+
+         elsif Remote
+           and then Ekind (Etype (Formal)) = E_Anonymous_Access_Type
+         then
+            Error_Msg_N
+              ("Access parameter of a remote subprogram must be controlling",
+                Formal);
+         end if;
+
+         Next_Formal (Formal);
+      end loop;
+
+      if Present (Etype (Subp)) then
+         Ctrl_Type := Check_Controlling_Type (Etype (Subp), Subp);
+
+         if Present (Ctrl_Type) then
+            if Ctrl_Type = Typ then
+               Set_Has_Controlling_Result (Subp);
+
+               --  Check that the result subtype statically matches
+               --  the first subtype.
+
+               if not Subtypes_Statically_Match (Typ, Etype (Subp)) then
+                  Error_Msg_N
+                    ("result subtype does not match controlling type", Subp);
+               end if;
+
+            elsif Comes_From_Source (Subp) then
+               Error_Msg_N
+                 ("operation can be dispatching in only one type", Subp);
+            end if;
+
+         --  The following check is clearly required, although the RM says
+         --  nothing about return types. If the return type is a limited
+         --  class-wide type declared in the current scope, there is no way
+         --  to declare stream procedures for it, so the return cannot be
+         --  marshalled.
+
+         elsif Remote
+           and then Is_Limited_Type (Typ)
+           and then Etype (Subp) = Class_Wide_Type (Typ)
+         then
+            Error_Msg_N ("return type has no stream attributes", Subp);
+         end if;
+      end if;
+   end Check_Controlling_Formals;
+
+   ----------------------------
+   -- Check_Controlling_Type --
+   ----------------------------
+
+   function Check_Controlling_Type
+     (T    : Entity_Id;
+      Subp : Entity_Id)
+      return Entity_Id
+   is
+      Tagged_Type : Entity_Id := Empty;
+
+   begin
+      if Is_Tagged_Type (T) then
+         if Is_First_Subtype (T) then
+            Tagged_Type := T;
+         else
+            Tagged_Type := Base_Type (T);
+         end if;
+
+      elsif Ekind (T) = E_Anonymous_Access_Type
+        and then Is_Tagged_Type (Designated_Type (T))
+        and then Ekind (Designated_Type (T)) /= E_Incomplete_Type
+      then
+         if Is_First_Subtype (Designated_Type (T)) then
+            Tagged_Type := Designated_Type (T);
+         else
+            Tagged_Type := Base_Type (Designated_Type (T));
+         end if;
+      end if;
+
+      if No (Tagged_Type)
+        or else Is_Class_Wide_Type (Tagged_Type)
+      then
+         return Empty;
+
+      --  The dispatching type and the primitive operation must be defined
+      --  in the same scope except for internal operations.
+
+      elsif (Scope (Subp) = Scope (Tagged_Type)
+              or else Is_Internal (Subp))
+        and then
+            (not Is_Generic_Type (Tagged_Type)
+              or else not Comes_From_Source (Subp))
+      then
+         return Tagged_Type;
+
+      else
+         return Empty;
+      end if;
+   end Check_Controlling_Type;
+
+   ----------------------------
+   -- Check_Dispatching_Call --
+   ----------------------------
+
+   procedure Check_Dispatching_Call (N : Node_Id) is
+      Actual  : Node_Id;
+      Control : Node_Id := Empty;
+      Func    : Entity_Id;
+
+      procedure Check_Dispatching_Context;
+      --  If the call is tag-indeterminate and the entity being called is
+      --  abstract, verify that the context is a call that will eventually
+      --  provide a tag for dispatching, or has provided one already.
+
+      -------------------------------
+      -- Check_Dispatching_Context --
+      -------------------------------
+
+      procedure Check_Dispatching_Context is
+         Func : constant Entity_Id := Entity (Name (N));
+         Par  : Node_Id;
+
+      begin
+         if Is_Abstract (Func)
+           and then No (Controlling_Argument (N))
+         then
+            Par := Parent (N);
+
+            while Present (Par) loop
+
+               if Nkind (Par) = N_Function_Call            or else
+                  Nkind (Par) = N_Procedure_Call_Statement or else
+                  Nkind (Par) = N_Assignment_Statement     or else
+                  Nkind (Par) = N_Op_Eq                    or else
+                  Nkind (Par) = N_Op_Ne
+               then
+                  return;
+
+               elsif Nkind (Par) = N_Qualified_Expression
+                 or else Nkind (Par) = N_Unchecked_Type_Conversion
+               then
+                  Par := Parent (Par);
+
+               else
+                  Error_Msg_N
+                    ("call to abstract function must be dispatching", N);
+                  return;
+               end if;
+            end loop;
+         end if;
+      end Check_Dispatching_Context;
+
+   --  Start of processing for Check_Dispatching_Call
+
+   begin
+      --  Find a controlling argument, if any
+
+      if Present (Parameter_Associations (N)) then
+         Actual := First_Actual (N);
+
+         while Present (Actual) loop
+            Control := Find_Controlling_Arg (Actual);
+            exit when Present (Control);
+            Next_Actual (Actual);
+         end loop;
+
+         if Present (Control) then
+
+            --  Verify that no controlling arguments are statically tagged
+
+            if Debug_Flag_E then
+               Write_Str ("Found Dispatching call");
+               Write_Int (Int (N));
+               Write_Eol;
+            end if;
+
+            Actual := First_Actual (N);
+
+            while Present (Actual) loop
+               if Actual /= Control then
+
+                  if not Is_Controlling_Actual (Actual) then
+                     null; -- can be anything
+
+                  elsif (Is_Dynamically_Tagged (Actual)) then
+                     null; --  valid parameter
+
+                  elsif Is_Tag_Indeterminate (Actual) then
+
+                     --  The tag is inherited from the enclosing call (the
+                     --  node we are currently analyzing). Explicitly expand
+                     --  the actual, since the previous call to Expand
+                     --  (from Resolve_Call) had no way of knowing about
+                     --  the required dispatching.
+
+                     Propagate_Tag (Control, Actual);
+
+                  else
+                     Error_Msg_N
+                       ("controlling argument is not dynamically tagged",
+                        Actual);
+                     return;
+                  end if;
+               end if;
+
+               Next_Actual (Actual);
+            end loop;
+
+            --  Mark call as a dispatching call
+
+            Set_Controlling_Argument (N, Control);
+
+         else
+            --  The call is not dispatching, check that there isn't any
+            --  tag indeterminate abstract call left
+
+            Actual := First_Actual (N);
+
+            while Present (Actual) loop
+               if Is_Tag_Indeterminate (Actual) then
+
+                  --  Function call case
+
+                  if Nkind (Original_Node (Actual)) = N_Function_Call then
+                     Func := Entity (Name (Original_Node (Actual)));
+
+                  --  Only other possibility is a qualified expression whose
+                  --  consituent expression is itself a call.
+
+                  else
+                     Func :=
+                       Entity (Name
+                         (Original_Node
+                           (Expression (Original_Node (Actual)))));
+                  end if;
+
+                  if Is_Abstract (Func) then
+                     Error_Msg_N (
+                       "call to abstract function must be dispatching", N);
+                  end if;
+               end if;
+
+               Next_Actual (Actual);
+            end loop;
+
+            Check_Dispatching_Context;
+         end if;
+
+      else
+         --  If dispatching on result, the enclosing call, if any, will
+         --  determine the controlling argument. Otherwise this is the
+         --  primitive operation of the root type.
+
+         Check_Dispatching_Context;
+      end if;
+   end Check_Dispatching_Call;
+
+   ---------------------------------
+   -- Check_Dispatching_Operation --
+   ---------------------------------
+
+   procedure Check_Dispatching_Operation (Subp, Old_Subp : Entity_Id) is
+      Tagged_Seen            : Entity_Id;
+      Has_Dispatching_Parent : Boolean := False;
+      Body_Is_Last_Primitive : Boolean := False;
+
+   begin
+      if Ekind (Subp) /= E_Procedure and then Ekind (Subp) /= E_Function then
+         return;
+      end if;
+
+      Set_Is_Dispatching_Operation (Subp, False);
+      Tagged_Seen := Find_Dispatching_Type (Subp);
+
+      --  If Subp is derived from a dispatching operation then it should
+      --  always be treated as dispatching. In this case various checks
+      --  below will be bypassed. Makes sure that late declarations for
+      --  inherited private subprograms are treated as dispatching, even
+      --  if the associated tagged type is already frozen.
+
+      Has_Dispatching_Parent := Present (Alias (Subp))
+        and then Is_Dispatching_Operation (Alias (Subp));
+
+      if No (Tagged_Seen) then
+         return;
+
+      --  The subprograms build internally after the freezing point (such as
+      --  the Init procedure) are not primitives
+
+      elsif Is_Frozen (Tagged_Seen)
+        and then not Comes_From_Source (Subp)
+        and then not Has_Dispatching_Parent
+      then
+         return;
+
+      --  The operation may be a child unit, whose scope is the defining
+      --  package, but which is not a primitive operation of the type.
+
+      elsif Is_Child_Unit (Subp) then
+         return;
+
+      --  If the subprogram is not defined in a package spec, the only case
+      --  where it can be a dispatching op is when it overrides an operation
+      --  before the freezing point of the type.
+
+      elsif ((not Is_Package (Scope (Subp)))
+              or else In_Package_Body (Scope (Subp)))
+        and then not Has_Dispatching_Parent
+      then
+         if not Comes_From_Source (Subp)
+           or else (Present (Old_Subp) and then not Is_Frozen (Tagged_Seen))
+         then
+            null;
+
+         --  If the type is already frozen, the overriding is not allowed
+         --  except when Old_Subp is not a dispatching operation (which
+         --  can occur when Old_Subp was inherited by an untagged type).
+         --  However, a body with no previous spec freezes the type "after"
+         --  its declaration, and therefore is a legal overriding (unless
+         --  the type has already been frozen). Only the first such body
+         --  is legal.
+
+         elsif Present (Old_Subp)
+           and then Is_Dispatching_Operation (Old_Subp)
+         then
+            if Nkind (Unit_Declaration_Node (Subp)) = N_Subprogram_Body
+              and then Comes_From_Source (Subp)
+            then
+               declare
+                  Subp_Body : constant Node_Id := Unit_Declaration_Node (Subp);
+                  Decl_Item : Node_Id := Next (Parent (Tagged_Seen));
+
+               begin
+                  --  ??? The checks here for whether the type has been
+                  --  frozen prior to the new body are not complete. It's
+                  --  not simple to check frozenness at this point since
+                  --  the body has already caused the type to be prematurely
+                  --  frozen in Analyze_Declarations, but we're forced to
+                  --  recheck this here because of the odd rule interpretation
+                  --  that allows the overriding if the type wasn't frozen
+                  --  prior to the body. The freezing action should probably
+                  --  be delayed until after the spec is seen, but that's
+                  --  a tricky change to the delicate freezing code.
+
+                  --  Look at each declaration following the type up
+                  --  until the new subprogram body. If any of the
+                  --  declarations is a body then the type has been
+                  --  frozen already so the overriding primitive is
+                  --  illegal.
+
+                  while Present (Decl_Item)
+                    and then (Decl_Item /= Subp_Body)
+                  loop
+                     if Comes_From_Source (Decl_Item)
+                       and then (Nkind (Decl_Item) in N_Proper_Body
+                                  or else Nkind (Decl_Item) in N_Body_Stub)
+                     then
+                        Error_Msg_N ("overriding of& is too late!", Subp);
+                        Error_Msg_N
+                          ("\spec should appear immediately after the type!",
+                           Subp);
+                        exit;
+                     end if;
+
+                     Next (Decl_Item);
+                  end loop;
+
+                  --  If the subprogram doesn't follow in the list of
+                  --  declarations including the type then the type
+                  --  has definitely been frozen already and the body
+                  --  is illegal.
+
+                  if not Present (Decl_Item) then
+                     Error_Msg_N ("overriding of& is too late!", Subp);
+                     Error_Msg_N
+                       ("\spec should appear immediately after the type!",
+                        Subp);
+
+                  elsif Is_Frozen (Subp) then
+
+                     --  the subprogram body declares a primitive operation.
+                     --  if the subprogram is already frozen, we must update
+                     --  its dispatching information explicitly here. The
+                     --  information is taken from the overridden subprogram.
+
+                     Body_Is_Last_Primitive := True;
+
+                     if Present (DTC_Entity (Old_Subp)) then
+                        Set_DTC_Entity (Subp, DTC_Entity (Old_Subp));
+                        Set_DT_Position (Subp, DT_Position (Old_Subp));
+                        Insert_After (
+                          Subp_Body, Fill_DT_Entry (Sloc (Subp_Body), Subp));
+                     end if;
+                  end if;
+               end;
+
+            else
+               Error_Msg_N ("overriding of& is too late!", Subp);
+               Error_Msg_N
+                 ("\subprogram spec should appear immediately after the type!",
+                  Subp);
+            end if;
+
+         --  If the type is not frozen yet and we are not in the overridding
+         --  case it looks suspiciously like an attempt to define a primitive
+         --  operation.
+
+         elsif not Is_Frozen (Tagged_Seen) then
+            Error_Msg_N
+              ("?not dispatching (must be defined in a package spec)", Subp);
+            return;
+
+         --  When the type is frozen, it is legitimate to define a new
+         --  non-primitive operation.
+
+         else
+            return;
+         end if;
+
+      --  Now, we are sure that the scope is a package spec. If the subprogram
+      --  is declared after the freezing point ot the type that's an error
+
+      elsif Is_Frozen (Tagged_Seen) and then not Has_Dispatching_Parent then
+         Error_Msg_N ("this primitive operation is declared too late", Subp);
+         Error_Msg_NE
+           ("?no primitive operations for& after this line",
+            Freeze_Node (Tagged_Seen),
+            Tagged_Seen);
+         return;
+      end if;
+
+      Check_Controlling_Formals (Tagged_Seen, Subp);
+
+      --  Now it should be a correct primitive operation, put it in the list
+
+      if Present (Old_Subp) then
+         Check_Subtype_Conformant (Subp, Old_Subp);
+         Override_Dispatching_Operation (Tagged_Seen, Old_Subp, Subp);
+
+      else
+         Add_Dispatching_Operation (Tagged_Seen, Subp);
+      end if;
+
+      Set_Is_Dispatching_Operation (Subp, True);
+
+      if not Body_Is_Last_Primitive then
+         Set_DT_Position (Subp, No_Uint);
+      end if;
+
+   end Check_Dispatching_Operation;
+
+   ------------------------------------------
+   -- Check_Operation_From_Incomplete_Type --
+   ------------------------------------------
+
+   procedure Check_Operation_From_Incomplete_Type
+     (Subp : Entity_Id;
+      Typ  : Entity_Id)
+   is
+      Full       : constant Entity_Id := Full_View (Typ);
+      Parent_Typ : constant Entity_Id := Etype (Full);
+      Old_Prim   : constant Elist_Id  := Primitive_Operations (Parent_Typ);
+      New_Prim   : constant Elist_Id  := Primitive_Operations (Full);
+      Op1, Op2   : Elmt_Id;
+      Prev       : Elmt_Id := No_Elmt;
+
+      function Derives_From (Proc : Entity_Id) return Boolean;
+      --  Check that Subp has the signature of an operation derived from Proc.
+      --  Subp has an access parameter that designates Typ.
+
+      ------------------
+      -- Derives_From --
+      ------------------
+
+      function Derives_From (Proc : Entity_Id) return Boolean is
+         F1, F2 : Entity_Id;
+
+      begin
+         if Chars (Proc) /= Chars (Subp) then
+            return False;
+         end if;
+
+         F1 := First_Formal (Proc);
+         F2 := First_Formal (Subp);
+
+         while Present (F1) and then Present (F2) loop
+
+            if Ekind (Etype (F1)) = E_Anonymous_Access_Type then
+
+               if Ekind (Etype (F2)) /= E_Anonymous_Access_Type then
+                  return False;
+
+               elsif Designated_Type (Etype (F1)) = Parent_Typ
+                 and then Designated_Type (Etype (F2)) /= Full
+               then
+                  return False;
+               end if;
+
+            elsif Ekind (Etype (F2)) = E_Anonymous_Access_Type then
+               return False;
+
+            elsif Etype (F1) /= Etype (F2) then
+               return False;
+            end if;
+
+            Next_Formal (F1);
+            Next_Formal (F2);
+         end loop;
+
+         return No (F1) and then No (F2);
+      end Derives_From;
+
+   --  Start of processing for Check_Operation_From_Incomplete_Type
+
+   begin
+      --  The operation may override an inherited one, or may be a new one
+      --  altogether. The inherited operation will have been hidden by the
+      --  current one at the point of the type derivation, so it does not
+      --  appear in the list of primitive operations of the type. We have to
+      --  find the proper place of insertion in the list of primitive opera-
+      --  tions by iterating over the list for the parent type.
+
+      Op1 := First_Elmt (Old_Prim);
+      Op2 := First_Elmt (New_Prim);
+
+      while Present (Op1) and then Present (Op2) loop
+
+         if Derives_From (Node (Op1)) then
+
+            if No (Prev) then
+               Prepend_Elmt (Subp, New_Prim);
+            else
+               Insert_Elmt_After (Subp, Prev);
+            end if;
+
+            return;
+         end if;
+
+         Prev := Op2;
+         Next_Elmt (Op1);
+         Next_Elmt (Op2);
+      end loop;
+
+      --  Operation is a new primitive.
+
+      Append_Elmt (Subp, New_Prim);
+
+   end Check_Operation_From_Incomplete_Type;
+
+   ---------------------------------------
+   -- Check_Operation_From_Private_View --
+   ---------------------------------------
+
+   procedure Check_Operation_From_Private_View (Subp, Old_Subp : Entity_Id) is
+      Tagged_Type : Entity_Id;
+
+   begin
+      if Is_Dispatching_Operation (Alias (Subp)) then
+         Set_Scope (Subp, Current_Scope);
+         Tagged_Type := Find_Dispatching_Type (Subp);
+
+         if Present (Tagged_Type) and then Is_Tagged_Type (Tagged_Type) then
+            Append_Elmt (Old_Subp, Primitive_Operations (Tagged_Type));
+
+            --  If Old_Subp isn't already marked as dispatching then
+            --  this is the case of an operation of an untagged private
+            --  type fulfilled by a tagged type that overrides an
+            --  inherited dispatching operation, so we set the necessary
+            --  dispatching attributes here.
+
+            if not Is_Dispatching_Operation (Old_Subp) then
+               Check_Controlling_Formals (Tagged_Type, Old_Subp);
+               Set_Is_Dispatching_Operation (Old_Subp, True);
+               Set_DT_Position (Old_Subp, No_Uint);
+            end if;
+
+            --  If the old subprogram is an explicit renaming of some other
+            --  entity, it is not overridden by the inherited subprogram.
+            --  Otherwise, update its alias and other attributes.
+
+            if Present (Alias (Old_Subp))
+              and then Nkind (Unit_Declaration_Node (Old_Subp))
+                /= N_Subprogram_Renaming_Declaration
+            then
+               Set_Alias (Old_Subp, Alias (Subp));
+
+               --  The derived subprogram should inherit the abstractness
+               --  of the parent subprogram (except in the case of a function
+               --  returning the type). This sets the abstractness properly
+               --  for cases where a private extension may have inherited
+               --  an abstract operation, but the full type is derived from
+               --  a descendant type and inherits a nonabstract version.
+
+               if Etype (Subp) /= Tagged_Type then
+                  Set_Is_Abstract (Old_Subp, Is_Abstract (Alias (Subp)));
+               end if;
+            end if;
+         end if;
+      end if;
+   end Check_Operation_From_Private_View;
+
+   --------------------------
+   -- Find_Controlling_Arg --
+   --------------------------
+
+   function Find_Controlling_Arg (N : Node_Id) return Node_Id is
+      Orig_Node : constant Node_Id := Original_Node (N);
+      Typ       : Entity_Id;
+
+   begin
+      if Nkind (Orig_Node) = N_Qualified_Expression then
+         return Find_Controlling_Arg (Expression (Orig_Node));
+      end if;
+
+      --  Dispatching on result case
+
+      if Nkind (Orig_Node) = N_Function_Call
+        and then Present (Controlling_Argument (Orig_Node))
+        and then Has_Controlling_Result (Entity (Name (Orig_Node)))
+      then
+         return Controlling_Argument (Orig_Node);
+
+      --  Normal case
+
+      elsif Is_Controlling_Actual (N) then
+         Typ := Etype (N);
+
+         if Is_Access_Type (Typ) then
+            --  In the case of an Access attribute, use the type of
+            --  the prefix, since in the case of an actual for an
+            --  access parameter, the attribute's type may be of a
+            --  specific designated type, even though the prefix
+            --  type is class-wide.
+
+            if Nkind (N) = N_Attribute_Reference then
+               Typ := Etype (Prefix (N));
+            else
+               Typ := Designated_Type (Typ);
+            end if;
+         end if;
+
+         if Is_Class_Wide_Type (Typ) then
+            return N;
+         end if;
+      end if;
+
+      return Empty;
+   end Find_Controlling_Arg;
+
+   ---------------------------
+   -- Find_Dispatching_Type --
+   ---------------------------
+
+   function Find_Dispatching_Type (Subp : Entity_Id) return Entity_Id is
+      Formal    : Entity_Id;
+      Ctrl_Type : Entity_Id;
+
+   begin
+      if Present (DTC_Entity (Subp)) then
+         return Scope (DTC_Entity (Subp));
+
+      else
+         Formal := First_Formal (Subp);
+         while Present (Formal) loop
+            Ctrl_Type := Check_Controlling_Type (Etype (Formal), Subp);
+
+            if Present (Ctrl_Type) then
+               return Ctrl_Type;
+            end if;
+
+            Next_Formal (Formal);
+         end loop;
+
+      --  The subprogram may also be dispatching on result
+
+         if Present (Etype (Subp)) then
+            Ctrl_Type := Check_Controlling_Type (Etype (Subp), Subp);
+
+            if Present (Ctrl_Type) then
+               return Ctrl_Type;
+            end if;
+         end if;
+      end if;
+
+      return Empty;
+   end Find_Dispatching_Type;
+
+   ---------------------------
+   -- Is_Dynamically_Tagged --
+   ---------------------------
+
+   function Is_Dynamically_Tagged (N : Node_Id) return Boolean is
+   begin
+      return Find_Controlling_Arg (N) /= Empty;
+   end Is_Dynamically_Tagged;
+
+   --------------------------
+   -- Is_Tag_Indeterminate --
+   --------------------------
+
+   function Is_Tag_Indeterminate (N : Node_Id) return Boolean is
+      Nam       : Entity_Id;
+      Actual    : Node_Id;
+      Orig_Node : constant Node_Id := Original_Node (N);
+
+   begin
+      if Nkind (Orig_Node) = N_Function_Call
+        and then Is_Entity_Name (Name (Orig_Node))
+      then
+         Nam := Entity (Name (Orig_Node));
+
+         if not Has_Controlling_Result (Nam) then
+            return False;
+
+         --  If there are no actuals, the call is tag-indeterminate
+
+         elsif No (Parameter_Associations (Orig_Node)) then
+            return True;
+
+         else
+            Actual := First_Actual (Orig_Node);
+
+            while Present (Actual) loop
+               if Is_Controlling_Actual (Actual)
+                 and then not Is_Tag_Indeterminate (Actual)
+               then
+                  return False; -- one operand is dispatching
+               end if;
+
+               Next_Actual (Actual);
+            end loop;
+
+            return True;
+
+         end if;
+
+      elsif Nkind (Orig_Node) = N_Qualified_Expression then
+         return Is_Tag_Indeterminate (Expression (Orig_Node));
+
+      else
+         return False;
+      end if;
+   end Is_Tag_Indeterminate;
+
+   ------------------------------------
+   -- Override_Dispatching_Operation --
+   ------------------------------------
+
+   procedure Override_Dispatching_Operation
+     (Tagged_Type : Entity_Id;
+      Prev_Op     : Entity_Id;
+      New_Op      : Entity_Id)
+   is
+      Op_Elmt   : Elmt_Id := First_Elmt (Primitive_Operations (Tagged_Type));
+
+   begin
+      --  Patch the primitive operation list
+
+      while Present (Op_Elmt)
+        and then Node (Op_Elmt) /= Prev_Op
+      loop
+         Next_Elmt (Op_Elmt);
+      end loop;
+
+      --  If there is no previous operation to override, the type declaration
+      --  was malformed, and an error must have been emitted already.
+
+      if No (Op_Elmt) then
+         return;
+      end if;
+
+      Replace_Elmt (Op_Elmt, New_Op);
+
+      if (not Is_Package (Current_Scope))
+        or else not In_Private_Part (Current_Scope)
+      then
+         --  Not a private primitive
+
+         null;
+
+      else pragma Assert (Is_Inherited_Operation (Prev_Op));
+
+         --  Make the overriding operation into an alias of the implicit one.
+         --  In this fashion a call from outside ends up calling the new
+         --  body even if non-dispatching, and a call from inside calls the
+         --  overriding operation because it hides the implicit one.
+         --  To indicate that the body of Prev_Op is never called, set its
+         --  dispatch table entity to Empty.
+
+         Set_Alias (Prev_Op, New_Op);
+         Set_DTC_Entity (Prev_Op, Empty);
+         return;
+      end if;
+   end Override_Dispatching_Operation;
+
+   -------------------
+   -- Propagate_Tag --
+   -------------------
+
+   procedure Propagate_Tag (Control : Node_Id; Actual : Node_Id) is
+      Call_Node : Node_Id;
+      Arg       : Node_Id;
+
+   begin
+      if Nkind (Actual) = N_Function_Call then
+         Call_Node := Actual;
+
+      elsif Nkind (Actual) = N_Identifier
+        and then Nkind (Original_Node (Actual)) = N_Function_Call
+      then
+         --  Call rewritten as object declaration when stack-checking
+         --  is enabled. Propagate tag to expression in declaration, which
+         --  is original call.
+
+         Call_Node := Expression (Parent (Entity (Actual)));
+
+      --  Only other possibility is parenthesized or qualified expression
+
+      else
+         Call_Node := Expression (Actual);
+      end if;
+
+      --  Do not set the Controlling_Argument if already set. This happens
+      --  in the special case of _Input (see Exp_Attr, case Input).
+
+      if No (Controlling_Argument (Call_Node)) then
+         Set_Controlling_Argument (Call_Node, Control);
+      end if;
+
+      Arg := First_Actual (Call_Node);
+
+      while Present (Arg) loop
+         if Is_Tag_Indeterminate (Arg) then
+            Propagate_Tag (Control,  Arg);
+         end if;
+
+         Next_Actual (Arg);
+      end loop;
+
+      --  Expansion of dispatching calls is suppressed when Java_VM, because
+      --  the JVM back end directly handles the generation of dispatching
+      --  calls and would have to undo any expansion to an indirect call.
+
+      if not Java_VM then
+         Expand_Dispatch_Call (Call_Node);
+      end if;
+   end Propagate_Tag;
+
+end Sem_Disp;
diff --git a/gcc/ada/sem_disp.ads b/gcc/ada/sem_disp.ads
new file mode 100644 (file)
index 0000000..75f4158
--- /dev/null
@@ -0,0 +1,91 @@
+------------------------------------------------------------------------------
+--                                                                          --
+--                         GNAT COMPILER COMPONENTS                         --
+--                                                                          --
+--                             S E M _ D I S P                              --
+--                                                                          --
+--                                 S p e c                                  --
+--                                                                          --
+--                            $Revision: 1.16 $                             --
+--                                                                          --
+--          Copyright (C) 1992-1999 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- --
+-- ware  Foundation;  either version 2,  or (at your option) any later ver- --
+-- sion.  GNAT is distributed in the hope that it will be useful, but WITH- --
+-- OUT ANY WARRANTY;  without even the  implied warranty of MERCHANTABILITY --
+-- or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License --
+-- for  more details.  You should have  received  a copy of the GNU General --
+-- Public License  distributed with GNAT;  see file COPYING.  If not, write --
+-- to  the Free Software Foundation,  59 Temple Place - Suite 330,  Boston, --
+-- MA 02111-1307, USA.                                                      --
+--                                                                          --
+-- GNAT was originally developed  by the GNAT team at  New York University. --
+-- It is now maintained by Ada Core Technologies Inc (http://www.gnat.com). --
+--                                                                          --
+------------------------------------------------------------------------------
+
+--  This package contains routines involved in tagged types and dynamic
+--  dispatching.
+
+with Types; use Types;
+package Sem_Disp is
+
+   procedure Check_Controlling_Formals (Typ : Entity_Id; Subp : Entity_Id);
+   --  Check that all controlling parameters of Subp are of type Typ,
+   --  that defaults for controlling parameters are tag-indeterminate,
+   --  and that the nominal subtype of the parameters and result
+   --  statically match the first subtype of the controlling type.
+
+   procedure Check_Dispatching_Call (N : Node_Id);
+   --  Check if a call is a dispatching call. The subprogram is known to
+   --  be a dispatching operation. The call is dispatching if all the
+   --  controlling actuals are dynamically tagged. This procedure is called
+   --  after overload resolution, so the call is known to be unambiguous.
+
+   procedure Check_Dispatching_Operation (Subp, Old_Subp : Entity_Id);
+   --  Add "Subp" to the list of primitive operations of the corresponding type
+   --  if it has a parameter of this type and is defined at a proper place for
+   --  primitive operations. (new primitives are only defined in package spec,
+   --  overridden operation can be defined in any scope). If Old_Subp is not
+   --  Empty we are in the overriding case.
+
+   procedure Check_Operation_From_Incomplete_Type
+     (Subp : Entity_Id;
+      Typ  : Entity_Id);
+   --  If a primitive operation was defined for the incomplete view of the
+   --  type, and the full type declaration is a derived type definition,
+   --  the operation may override an inherited one.
+
+   procedure Check_Operation_From_Private_View (Subp, Old_Subp : Entity_Id);
+   --  Add "Old_Subp" to the list of primitive operations of the corresponding
+   --  tagged type if it is the full view of a private tagged type. The Alias
+   --  of "OldSubp" is adjusted to point to the inherited procedure of the
+   --  full view because it is always this one which has to be called.
+
+   function Find_Controlling_Arg (N : Node_Id) return Node_Id;
+   --  Returns the actual controlling argument if N is dynamically tagged,
+   --  and Empty if it is not dynamically tagged.
+
+   function Find_Dispatching_Type (Subp : Entity_Id) return Entity_Id;
+   --  Check whether a subprogram is dispatching, and find the tagged
+   --  type of the controlling argument or arguments.
+
+   function Is_Dynamically_Tagged (N : Node_Id) return Boolean;
+   --  Used to determine whether a call is dispatching, i.e. if is an
+   --  an expression of a class_Wide type, or a call to a function with
+   --  controlling result where at least one operand is dynamically tagged.
+
+   function Is_Tag_Indeterminate (N : Node_Id) return Boolean;
+   --  An expression is tag-indeterminate if it is a call that dispatches
+   --  on result, and all controlling operands are also indeterminate.
+   --  Such a function call may inherit a tag from an enclosing call.
+
+   procedure Propagate_Tag (Control : Node_Id; Actual : Node_Id);
+   --  If a function call is tag-indeterminate,  its controlling argument is
+   --  found in the context;  either an enclosing call, or the left-hand side
+   --  of the enclosing assignment statement. The tag must be propagated
+   --  recursively to the tag-indeterminate actuals of the call.
+
+end Sem_Disp;
diff --git a/gcc/ada/sem_dist.adb b/gcc/ada/sem_dist.adb
new file mode 100644 (file)
index 0000000..f2b5c6c
--- /dev/null
@@ -0,0 +1,686 @@
+------------------------------------------------------------------------------
+--                                                                          --
+--                         GNAT COMPILER COMPONENTS                         --
+--                                                                          --
+--                             S E M _ D I S T                              --
+--                                                                          --
+--                                 B o d y                                  --
+--                                                                          --
+--                            $Revision: 1.182 $
+--                                                                          --
+--          Copyright (C) 1992-2001, 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- --
+-- ware  Foundation;  either version 2,  or (at your option) any later ver- --
+-- sion.  GNAT is distributed in the hope that it will be useful, but WITH- --
+-- OUT ANY WARRANTY;  without even the  implied warranty of MERCHANTABILITY --
+-- or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License --
+-- for  more details.  You should have  received  a copy of the GNU General --
+-- Public License  distributed with GNAT;  see file COPYING.  If not, write --
+-- to  the Free Software Foundation,  59 Temple Place - Suite 330,  Boston, --
+-- MA 02111-1307, USA.                                                      --
+--                                                                          --
+-- GNAT was originally developed  by the GNAT team at  New York University. --
+-- It is now maintained by Ada Core Technologies Inc (http://www.gnat.com). --
+--                                                                          --
+------------------------------------------------------------------------------
+
+with Atree;    use Atree;
+with Casing;   use Casing;
+with Einfo;    use Einfo;
+with Errout;   use Errout;
+with Exp_Dist; use Exp_Dist;
+with Exp_Tss;  use Exp_Tss;
+with Nlists;   use Nlists;
+with Nmake;    use Nmake;
+with Namet;    use Namet;
+with Opt;      use Opt;
+with Rtsfind;  use Rtsfind;
+with Sem;      use Sem;
+with Sem_Res;  use Sem_Res;
+with Sem_Util; use Sem_Util;
+with Sinfo;    use Sinfo;
+with Snames;   use Snames;
+with Stand;    use Stand;
+with Stringt;  use Stringt;
+with Tbuild;   use Tbuild;
+with Uname;    use Uname;
+
+package body Sem_Dist is
+
+   -----------------------
+   -- Local Subprograms --
+   -----------------------
+
+   procedure RAS_E_Dereference (Pref : Node_Id);
+   --  Handles explicit dereference of Remote Access to Subprograms.
+
+   function Full_Qualified_Name (E : Entity_Id) return String_Id;
+   --  returns the full qualified name of the entity in lower case.
+
+   -------------------------
+   -- Add_Stub_Constructs --
+   -------------------------
+
+   procedure Add_Stub_Constructs (N : Node_Id) is
+      U    : constant Node_Id := Unit (N);
+      Spec : Entity_Id        := Empty;
+      Exp  : Node_Id          := U;         --  Unit that will be expanded
+
+   begin
+      pragma Assert (Distribution_Stub_Mode /= No_Stubs);
+
+      if Nkind (U) = N_Package_Declaration then
+         Spec := Defining_Entity (Specification (U));
+
+      elsif Nkind (U) = N_Package_Body then
+         Spec := Corresponding_Spec (U);
+
+      else pragma Assert (Nkind (U) = N_Package_Instantiation);
+         Exp  := Instance_Spec (U);
+         Spec := Defining_Entity (Specification (Exp));
+      end if;
+
+      pragma Assert (Is_Shared_Passive (Spec)
+        or else Is_Remote_Call_Interface (Spec));
+
+      if Distribution_Stub_Mode = Generate_Caller_Stub_Body then
+
+         if Is_Shared_Passive (Spec) then
+            null;
+         elsif Nkind (U) = N_Package_Body then
+            Error_Msg_N
+              ("Specification file expected from command line", U);
+         else
+            Expand_Calling_Stubs_Bodies (Exp);
+         end if;
+
+      else
+
+         if Is_Shared_Passive (Spec) then
+            Build_Passive_Partition_Stub (Exp);
+         else
+            Expand_Receiving_Stubs_Bodies (Exp);
+         end if;
+
+      end if;
+   end Add_Stub_Constructs;
+
+   -------------------------
+   -- Full_Qualified_Name --
+   -------------------------
+
+   function Full_Qualified_Name (E : Entity_Id) return String_Id is
+      Ent         : Entity_Id := E;
+      Parent_Name : String_Id := No_String;
+
+   begin
+      --  Deals properly with child units
+
+      if Nkind (Ent) = N_Defining_Program_Unit_Name then
+         Ent := Defining_Identifier (Ent);
+      end if;
+
+      --  Compute recursively the qualification. Only "Standard" has no scope.
+
+      if Present (Scope (Scope (Ent))) then
+         Parent_Name := Full_Qualified_Name (Scope (Ent));
+      end if;
+
+      --  Every entity should have a name except some expanded blocks
+      --  don't bother about those.
+
+      if Chars (Ent) = No_Name then
+         return Parent_Name;
+      end if;
+
+      --  Add a period between Name and qualification
+
+      if Parent_Name /= No_String then
+         Start_String (Parent_Name);
+         Store_String_Char (Get_Char_Code ('.'));
+
+      else
+         Start_String;
+      end if;
+
+      --  Generates the entity name in upper case
+
+      Get_Name_String (Chars (Ent));
+      Set_Casing (All_Lower_Case);
+      Store_String_Chars (Name_Buffer (1 .. Name_Len));
+      return End_String;
+   end Full_Qualified_Name;
+
+   -----------------------
+   -- Get_Subprogram_Id --
+   -----------------------
+
+   function Get_Subprogram_Id (E : Entity_Id) return Int is
+      Current_Declaration : Node_Id;
+      Result              : Int := 0;
+
+   begin
+      pragma Assert
+        (Is_Remote_Call_Interface (Scope (E))
+           and then
+             (Nkind (Parent (E)) = N_Procedure_Specification
+                or else
+              Nkind (Parent (E)) = N_Function_Specification));
+
+      Current_Declaration :=
+        First (Visible_Declarations
+          (Package_Specification_Of_Scope (Scope (E))));
+
+      while Current_Declaration /= Empty loop
+         if Nkind (Current_Declaration) = N_Subprogram_Declaration
+           and then Comes_From_Source (Current_Declaration)
+         then
+            if Defining_Unit_Name
+                 (Specification (Current_Declaration)) = E
+            then
+               return Result;
+            end if;
+
+            Result := Result + 1;
+         end if;
+
+         Next (Current_Declaration);
+      end loop;
+
+      --  Error if we do not find it
+
+      raise Program_Error;
+   end Get_Subprogram_Id;
+
+   ------------------------
+   -- Is_All_Remote_Call --
+   ------------------------
+
+   function Is_All_Remote_Call (N : Node_Id) return Boolean is
+      Par : Node_Id;
+
+   begin
+      if (Nkind (N) = N_Function_Call
+              or else Nkind (N) = N_Procedure_Call_Statement)
+        and then Nkind (Name (N)) in N_Has_Entity
+        and then Is_Remote_Call_Interface (Entity (Name (N)))
+        and then Has_All_Calls_Remote (Scope (Entity (Name (N))))
+        and then Comes_From_Source (N)
+      then
+         Par := Parent (Entity (Name (N)));
+
+         while Present (Par)
+           and then (Nkind (Par) /= N_Package_Specification
+                       or else Is_Wrapper_Package (Defining_Entity (Par)))
+         loop
+            Par := Parent (Par);
+         end loop;
+
+         if Present (Par) then
+            return
+              not Scope_Within_Or_Same (Current_Scope, Defining_Entity (Par));
+         else
+            return False;
+         end if;
+      else
+         return False;
+      end if;
+   end Is_All_Remote_Call;
+
+   ------------------------------------
+   -- Package_Specification_Of_Scope --
+   ------------------------------------
+
+   function Package_Specification_Of_Scope (E : Entity_Id) return Node_Id is
+      N : Node_Id := Parent (E);
+   begin
+      while Nkind (N) /= N_Package_Specification loop
+         N := Parent (N);
+      end loop;
+
+      return N;
+   end Package_Specification_Of_Scope;
+
+   --------------------------
+   -- Process_Partition_ID --
+   --------------------------
+
+   procedure Process_Partition_Id (N : Node_Id) is
+      Loc            : constant Source_Ptr := Sloc (N);
+      Ety            : Entity_Id;
+      Nd             : Node_Id;
+      Get_Pt_Id      : Node_Id;
+      Get_Pt_Id_Call : Node_Id;
+      Prefix_String  : String_Id;
+      Typ            : constant Entity_Id := Etype (N);
+
+   begin
+      Ety := Entity (Prefix (N));
+
+      --  In case prefix is not a library unit entity, get the entity
+      --  of library unit.
+
+      while (Present (Scope (Ety))
+        and then Scope (Ety) /= Standard_Standard)
+        and not Is_Child_Unit (Ety)
+      loop
+         Ety := Scope (Ety);
+      end loop;
+
+      Nd := Enclosing_Lib_Unit_Node (N);
+
+      --  Retrieve the proper function to call.
+
+      if Is_Remote_Call_Interface (Ety) then
+         Get_Pt_Id := New_Occurrence_Of
+           (RTE (RE_Get_Active_Partition_Id), Loc);
+
+      elsif Is_Shared_Passive (Ety) then
+         Get_Pt_Id := New_Occurrence_Of
+           (RTE (RE_Get_Passive_Partition_Id), Loc);
+
+      else
+         Get_Pt_Id := New_Occurrence_Of
+           (RTE (RE_Get_Local_Partition_Id), Loc);
+      end if;
+
+      --  Get and store the String_Id corresponding to the name of the
+      --  library unit whose Partition_Id is needed
+
+      Get_Unit_Name_String (Get_Unit_Name (Unit_Declaration_Node (Ety)));
+
+      --  Remove seven last character ("(spec)" or " (body)").
+      --  (this is a bit nasty, should have interface for this ???)
+
+      Name_Len := Name_Len - 7;
+
+      Start_String;
+      Store_String_Chars (Name_Buffer (1 .. Name_Len));
+      Prefix_String := End_String;
+
+      --  Build the function call which will replace the attribute
+
+      if Is_Remote_Call_Interface (Ety)
+        or else Is_Shared_Passive (Ety)
+      then
+         Get_Pt_Id_Call :=
+           Make_Function_Call (Loc,
+             Name => Get_Pt_Id,
+             Parameter_Associations =>
+               New_List (Make_String_Literal (Loc, Prefix_String)));
+
+      else
+         Get_Pt_Id_Call := Make_Function_Call (Loc, Get_Pt_Id);
+
+      end if;
+
+      --  Replace the attribute node by a conversion of the function call
+      --  to the target type.
+
+      Rewrite (N, Convert_To (Typ, Get_Pt_Id_Call));
+      Analyze_And_Resolve (N, Typ);
+
+   end Process_Partition_Id;
+
+   ----------------------------------
+   -- Process_Remote_AST_Attribute --
+   ----------------------------------
+
+   procedure Process_Remote_AST_Attribute
+     (N        : Node_Id;
+      New_Type : Entity_Id)
+   is
+      Loc                   : constant Source_Ptr := Sloc (N);
+      Remote_Subp           : Entity_Id;
+      Tick_Access_Conv_Call : Node_Id;
+      Remote_Subp_Decl      : Node_Id;
+      RAS_Decl              : Node_Id;
+      RS_Pkg_Specif         : Node_Id;
+      RS_Pkg_E              : Entity_Id;
+      RAS_Pkg_E             : Entity_Id;
+      RAS_Type              : Entity_Id;
+      RAS_Name              : Name_Id;
+      Async_E               : Entity_Id;
+      Subp_Id               : Int;
+      Attribute_Subp        : Entity_Id;
+      Parameter             : Node_Id;
+
+   begin
+      --  Check if we have to expand the access attribute
+
+      Remote_Subp := Entity (Prefix (N));
+
+      if not Expander_Active then
+         return;
+
+      elsif Ekind (New_Type) = E_Record_Type then
+         RAS_Type := New_Type;
+
+      else
+         --  If the remote type has not been constructed yet, create
+         --  it and its attributes now.
+
+         Attribute_Subp := TSS (New_Type, Name_uRAS_Access);
+
+         if No (Attribute_Subp) then
+            Add_RAST_Features (Parent (New_Type));
+         end if;
+
+         RAS_Type := Equivalent_Type (New_Type);
+      end if;
+
+      RAS_Name  := Chars (RAS_Type);
+      RAS_Decl := Parent (RAS_Type);
+      Attribute_Subp := TSS (RAS_Type, Name_uRAS_Access);
+
+      RAS_Pkg_E  := Defining_Entity (Parent (RAS_Decl));
+      Remote_Subp_Decl := Unit_Declaration_Node (Remote_Subp);
+
+      if Nkind (Remote_Subp_Decl) = N_Subprogram_Body then
+         Remote_Subp := Corresponding_Spec (Remote_Subp_Decl);
+         Remote_Subp_Decl := Unit_Declaration_Node (Remote_Subp);
+      end if;
+
+      RS_Pkg_Specif := Parent (Remote_Subp_Decl);
+      RS_Pkg_E := Defining_Entity (RS_Pkg_Specif);
+
+      Subp_Id := Get_Subprogram_Id (Remote_Subp);
+
+      if Ekind (Remote_Subp) = E_Procedure
+        and then Is_Asynchronous (Remote_Subp)
+      then
+         Async_E := Standard_True;
+      else
+         Async_E := Standard_False;
+      end if;
+
+      --  Right now, we do not call the Name_uAddress_Resolver subprogram,
+      --  which means that we end up with a Null_Address value in the ras
+      --  field: each dereference of an RAS will go through the PCS, which
+      --  is authorized but potentially not very efficient ???
+
+      Parameter := New_Occurrence_Of (RTE (RE_Null_Address), Loc);
+
+      Tick_Access_Conv_Call :=
+        Make_Function_Call (Loc,
+          Name => New_Occurrence_Of (Attribute_Subp, Loc),
+          Parameter_Associations =>
+            New_List (
+              Parameter,
+              Make_String_Literal (Loc, Full_Qualified_Name (RS_Pkg_E)),
+              Make_Integer_Literal (Loc, Subp_Id),
+              New_Occurrence_Of (Async_E, Loc)));
+
+      Rewrite (N, Tick_Access_Conv_Call);
+      Analyze_And_Resolve (N, RAS_Type);
+
+   end Process_Remote_AST_Attribute;
+
+   ------------------------------------
+   -- Process_Remote_AST_Declaration --
+   ------------------------------------
+
+   procedure Process_Remote_AST_Declaration (N : Node_Id) is
+      Loc           : constant Source_Ptr := Sloc (N);
+      User_Type     : constant Node_Id := Defining_Identifier (N);
+      Fat_Type      : constant Entity_Id :=
+                        Make_Defining_Identifier
+                          (Loc, Chars (User_Type));
+      New_Type_Decl : Node_Id;
+
+   begin
+      --  We add a record type declaration for the equivalent fat pointer type
+
+      New_Type_Decl :=
+        Make_Full_Type_Declaration (Loc,
+          Defining_Identifier => Fat_Type,
+          Type_Definition =>
+            Make_Record_Definition (Loc,
+              Component_List =>
+                Make_Component_List (Loc,
+                  Component_Items => New_List (
+
+                    Make_Component_Declaration (Loc,
+                      Defining_Identifier =>
+                        Make_Defining_Identifier (Loc,
+                          Chars => Name_Ras),
+                      Subtype_Indication =>
+                        New_Occurrence_Of
+                          (RTE (RE_Unsigned_64), Loc)),
+
+                    Make_Component_Declaration (Loc,
+                      Defining_Identifier =>
+                        Make_Defining_Identifier (Loc,
+                          Chars => Name_Origin),
+                      Subtype_Indication =>
+                        New_Reference_To
+                          (Standard_Integer,
+                           Loc)),
+
+                    Make_Component_Declaration (Loc,
+                      Defining_Identifier =>
+                        Make_Defining_Identifier (Loc,
+                          Chars => Name_Receiver),
+                      Subtype_Indication =>
+                        New_Reference_To
+                          (RTE (RE_Unsigned_64), Loc)),
+
+                    Make_Component_Declaration (Loc,
+                      Defining_Identifier =>
+                        Make_Defining_Identifier (Loc,
+                          Chars => Name_Subp_Id),
+                      Subtype_Indication =>
+                        New_Reference_To
+                          (Standard_Natural,
+                           Loc)),
+
+                    Make_Component_Declaration (Loc,
+                      Defining_Identifier =>
+                        Make_Defining_Identifier (Loc,
+                          Chars => Name_Async),
+                      Subtype_Indication =>
+                        New_Reference_To
+                          (Standard_Boolean,
+                           Loc))))));
+
+      Insert_After (N, New_Type_Decl);
+      Set_Equivalent_Type (User_Type, Fat_Type);
+      Set_Corresponding_Remote_Type (Fat_Type, User_Type);
+
+      --  The reason we suppress the initialization procedure is that we know
+      --  that no initialization is required (even if Initialize_Scalars mode
+      --  is active), and there are order of elaboration problems if we do try
+      --  to generate an Init_Proc for this created record type.
+
+      Set_Suppress_Init_Proc (Fat_Type);
+
+      if Expander_Active then
+         Add_RAST_Features (Parent (User_Type));
+      end if;
+
+   end Process_Remote_AST_Declaration;
+
+   -----------------------
+   -- RAS_E_Dereference --
+   -----------------------
+
+   procedure RAS_E_Dereference (Pref : Node_Id) is
+      Loc             : constant Source_Ptr := Sloc (Pref);
+      Call_Node       : Node_Id;
+      New_Type        : constant Entity_Id := Etype (Pref);
+      RAS             : constant Entity_Id :=
+                          Corresponding_Remote_Type (New_Type);
+      RAS_Decl        : constant Node_Id   := Parent (RAS);
+      Explicit_Deref  : constant Node_Id   := Parent (Pref);
+      Deref_Subp_Call : constant Node_Id   := Parent (Explicit_Deref);
+      Deref_Proc      : Entity_Id;
+      Params          : List_Id;
+
+   begin
+      if Nkind (Deref_Subp_Call) = N_Procedure_Call_Statement then
+         Params := Parameter_Associations (Deref_Subp_Call);
+
+         if Present (Params) then
+            Prepend (Pref, Params);
+         else
+            Params := New_List (Pref);
+         end if;
+
+      elsif Nkind (Deref_Subp_Call) = N_Indexed_Component then
+
+         Params := Expressions (Deref_Subp_Call);
+
+         if Present (Params) then
+            Prepend (Pref, Params);
+         else
+            Params := New_List (Pref);
+         end if;
+
+      else
+         --  Context is not a call.
+
+         return;
+      end if;
+
+      Deref_Proc := TSS (New_Type, Name_uRAS_Dereference);
+
+      if not Expander_Active then
+         return;
+
+      elsif No (Deref_Proc) then
+         Add_RAST_Features (RAS_Decl);
+         Deref_Proc := TSS (New_Type, Name_uRAS_Dereference);
+      end if;
+
+      if Ekind (Deref_Proc) = E_Function then
+         Call_Node :=
+           Make_Function_Call (Loc,
+              Name => New_Occurrence_Of (Deref_Proc, Loc),
+              Parameter_Associations => Params);
+
+      else
+         Call_Node :=
+           Make_Procedure_Call_Statement (Loc,
+              Name => New_Occurrence_Of (Deref_Proc, Loc),
+              Parameter_Associations => Params);
+      end if;
+
+      Rewrite (Deref_Subp_Call, Call_Node);
+      Analyze (Deref_Subp_Call);
+   end RAS_E_Dereference;
+
+   ------------------------------
+   -- Remote_AST_E_Dereference --
+   ------------------------------
+
+   function Remote_AST_E_Dereference (P : Node_Id) return Boolean
+   is
+      ET : constant Entity_Id  := Etype (P);
+
+   begin
+      --  Perform the changes only on original dereferences, and only if
+      --  we are generating code.
+
+      if Comes_From_Source (P)
+        and then Is_Record_Type (ET)
+        and then (Is_Remote_Call_Interface (ET)
+                   or else Is_Remote_Types (ET))
+        and then Present (Corresponding_Remote_Type (ET))
+        and then (Nkind (Parent (Parent (P))) = N_Procedure_Call_Statement
+                   or else Nkind (Parent (Parent (P))) = N_Indexed_Component)
+        and then Expander_Active
+      then
+         RAS_E_Dereference (P);
+         return True;
+      else
+         return False;
+      end if;
+   end Remote_AST_E_Dereference;
+
+   ------------------------------
+   -- Remote_AST_I_Dereference --
+   ------------------------------
+
+   function Remote_AST_I_Dereference (P : Node_Id) return Boolean
+   is
+      ET     : constant Entity_Id  := Etype (P);
+      Deref  : Node_Id;
+   begin
+
+      if Comes_From_Source (P)
+        and then (Is_Remote_Call_Interface (ET)
+                   or else Is_Remote_Types (ET))
+        and then Present (Corresponding_Remote_Type (ET))
+        and then Ekind (Entity (P)) /= E_Function
+      then
+         Deref :=
+           Make_Explicit_Dereference (Sloc (P),
+             Prefix => Relocate_Node (P));
+         Rewrite (P, Deref);
+         Set_Etype (P, ET);
+         RAS_E_Dereference (Prefix (P));
+         return True;
+      end if;
+
+      return False;
+   end Remote_AST_I_Dereference;
+
+   ---------------------------
+   -- Remote_AST_Null_Value --
+   ---------------------------
+
+   function Remote_AST_Null_Value
+     (N    : Node_Id;
+      Typ  : Entity_Id)
+      return Boolean
+   is
+      Loc         : constant Source_Ptr := Sloc (N);
+      Target_Type : Entity_Id;
+
+   begin
+      if not Expander_Active then
+         return False;
+
+      elsif Ekind (Typ) = E_Access_Subprogram_Type
+        and then (Is_Remote_Call_Interface (Typ)
+                    or else Is_Remote_Types (Typ))
+        and then Comes_From_Source (N)
+        and then Expander_Active
+      then
+         --  Any null that comes from source and is of the RAS type must
+         --  be expanded, except if expansion is not active (nothing
+         --  gets expanded into the equivalent record type).
+
+         Target_Type := Equivalent_Type (Typ);
+
+      elsif Ekind (Typ) = E_Record_Type
+        and then Present (Corresponding_Remote_Type (Typ))
+      then
+
+         --  This is a record type representing a RAS type, this must be
+         --  expanded.
+
+         Target_Type := Typ;
+
+      else
+         --  We do not have to handle this case
+
+         return False;
+
+      end if;
+
+      Rewrite (N,
+        Make_Aggregate (Loc,
+          Expressions => New_List (
+            Make_Integer_Literal (Loc, 0),                  -- Ras
+            Make_Integer_Literal (Loc, 0),                  -- Origin
+            Make_Integer_Literal (Loc, 0),                  -- Receiver
+            Make_Integer_Literal (Loc, 0),                  -- Subp_Id
+            New_Occurrence_Of (Standard_False, Loc))));     -- Asyn
+      Analyze_And_Resolve (N, Target_Type);
+      return True;
+   end Remote_AST_Null_Value;
+
+end Sem_Dist;
diff --git a/gcc/ada/sem_dist.ads b/gcc/ada/sem_dist.ads
new file mode 100644 (file)
index 0000000..b5c823d
--- /dev/null
@@ -0,0 +1,95 @@
+------------------------------------------------------------------------------
+--                                                                          --
+--                         GNAT COMPILER COMPONENTS                         --
+--                                                                          --
+--                             S E M _ D I S T                              --
+--                                                                          --
+--                                 S p e c                                  --
+--                                                                          --
+--                            $Revision: 1.56 $
+--                                                                          --
+--          Copyright (C) 1992-2000 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- --
+-- ware  Foundation;  either version 2,  or (at your option) any later ver- --
+-- sion.  GNAT is distributed in the hope that it will be useful, but WITH- --
+-- OUT ANY WARRANTY;  without even the  implied warranty of MERCHANTABILITY --
+-- or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License --
+-- for  more details.  You should have  received  a copy of the GNU General --
+-- Public License  distributed with GNAT;  see file COPYING.  If not, write --
+-- to  the Free Software Foundation,  59 Temple Place - Suite 330,  Boston, --
+-- MA 02111-1307, USA.                                                      --
+--                                                                          --
+-- GNAT was originally developed  by the GNAT team at  New York University. --
+-- It is now maintained by Ada Core Technologies Inc (http://www.gnat.com). --
+--                                                                          --
+------------------------------------------------------------------------------
+
+--  Semantic processing for distribution annex facilities
+
+with Types; use Types;
+
+package Sem_Dist is
+
+   procedure Add_Stub_Constructs (N : Node_Id);
+   --  Create the stubs constructs for a remote call interface package
+   --  specification or body or for a shared passive specification. For
+   --  caller stubs, expansion takes place directly in the specification and
+   --  no additional compilation unit is created.
+
+   function Is_All_Remote_Call (N : Node_Id) return Boolean;
+   --  Check whether a function or procedure call should be expanded into
+   --  a remote call, because the entity is declared in a package decl that
+   --  is not currently in scope, and the proper pragmas apply.
+
+   procedure Process_Partition_Id (N : Node_Id);
+   --  Replace attribute reference with call to runtime function. The result
+   --  is converted to the context type, because the attribute yields a
+   --  universal integer value.
+
+   procedure Process_Remote_AST_Attribute (N : Node_Id; New_Type : Entity_Id);
+   --  Given N, an access attribute reference node whose prefix is a
+   --  remote subprogram, rewrite N with a call to a conversion function
+   --  whose return type is New_Type.
+
+   procedure Process_Remote_AST_Declaration (N : Node_Id);
+   --  Given N, an access to subprogram type declaration node in RCI or
+   --  remote types unit, build a new record (fat pointer) type declaration
+   --  using the old Defining_Identifier of N and a link to the old
+   --  declaration node N whose Defining_Identifier is changed.
+   --  We also construct declarations of two subprograms in the unit
+   --  specification which handle remote access to subprogram type
+   --  (fat pointer) dereference and the unit receiver that handles
+   --  remote calls (from remote access to subprogram type values.)
+
+   function Remote_AST_E_Dereference (P : Node_Id) return Boolean;
+   --  If the prefix of an explicit dereference is a record type that
+   --  represent the fat pointer for an Remote access to subprogram, in
+   --  the context of a call, rewrite the enclosing call node into a
+   --  remote call, the first actual of which is the fat pointer. Return
+   --  true if the context is correct and the transformation took place.
+
+   function Remote_AST_I_Dereference (P : Node_Id) return Boolean;
+   --  If P is a record type that represents the fat pointer for a remote
+   --  access to subprogram, and P is the prefix of a call, insert an
+   --  explicit dereference and perform the transformation described for
+   --  the previous function.
+
+   function Remote_AST_Null_Value
+     (N    : Node_Id;
+      Typ  : Entity_Id)
+      return Boolean;
+   --  If N is a null value and Typ a remote access to subprogram type,
+   --  this function will check if null needs to be replaced with an
+   --  aggregate and will return True in this case. Otherwise, it will
+   --  return False.
+
+   function Get_Subprogram_Id (E : Entity_Id) return Int;
+   --  Given a subprogram defined in a RCI package, get its subprogram id
+   --  which will be used for remote calls.
+
+   function Package_Specification_Of_Scope (E : Entity_Id) return Node_Id;
+   --  Return the N_Package_Specification corresponding to a scope E
+
+end Sem_Dist;
diff --git a/gcc/ada/sem_elab.adb b/gcc/ada/sem_elab.adb
new file mode 100644 (file)
index 0000000..555abb8
--- /dev/null
@@ -0,0 +1,2278 @@
+------------------------------------------------------------------------------
+--                                                                          --
+--                         GNAT COMPILER COMPONENTS                         --
+--                                                                          --
+--                             S E M _ E L A B                              --
+--                                                                          --
+--                                 B o d y                                  --
+--                                                                          --
+--                            $Revision: 1.84 $
+--                                                                          --
+--          Copyright (C) 1997-2001 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- --
+-- ware  Foundation;  either version 2,  or (at your option) any later ver- --
+-- sion.  GNAT is distributed in the hope that it will be useful, but WITH- --
+-- OUT ANY WARRANTY;  without even the  implied warranty of MERCHANTABILITY --
+-- or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License --
+-- for  more details.  You should have  received  a copy of the GNU General --
+-- Public License  distributed with GNAT;  see file COPYING.  If not, write --
+-- to  the Free Software Foundation,  59 Temple Place - Suite 330,  Boston, --
+-- MA 02111-1307, USA.                                                      --
+--                                                                          --
+-- GNAT was originally developed  by the GNAT team at  New York University. --
+-- It is now maintained by Ada Core Technologies Inc (http://www.gnat.com). --
+--                                                                          --
+------------------------------------------------------------------------------
+
+with Atree;    use Atree;
+with Checks;   use Checks;
+with Debug;    use Debug;
+with Einfo;    use Einfo;
+with Elists;   use Elists;
+with Errout;   use Errout;
+with Exp_Util; use Exp_Util;
+with Expander; use Expander;
+with Fname;    use Fname;
+with Lib;      use Lib;
+with Lib.Load; use Lib.Load;
+with Namet;    use Namet;
+with Nlists;   use Nlists;
+with Nmake;    use Nmake;
+with Opt;      use Opt;
+with Output;   use Output;
+with Restrict; use Restrict;
+with Sem;      use Sem;
+with Sem_Cat;  use Sem_Cat;
+with Sem_Ch7;  use Sem_Ch7;
+with Sem_Ch8;  use Sem_Ch8;
+with Sem_Res;  use Sem_Res;
+with Sem_Util; use Sem_Util;
+with Sinfo;    use Sinfo;
+with Sinput;   use Sinput;
+with Snames;   use Snames;
+with Stand;    use Stand;
+with Table;
+with Tbuild;   use Tbuild;
+with Uname;    use Uname;
+
+package body Sem_Elab is
+
+   --  The following table records the recursive call chain for output
+   --  in the Output routine. Each entry records the call node and the
+   --  entity of the called routine. The number of entries in the table
+   --  (i.e. the value of Elab_Call.Last) indicates the current depth
+   --  of recursion and is used to identify the outer level.
+
+   type Elab_Call_Entry is record
+      Cloc : Source_Ptr;
+      Ent  : Entity_Id;
+   end record;
+
+   package Elab_Call is new Table.Table (
+     Table_Component_Type => Elab_Call_Entry,
+     Table_Index_Type     => Int,
+     Table_Low_Bound      => 1,
+     Table_Initial        => 50,
+     Table_Increment      => 100,
+     Table_Name           => "Elab_Call");
+
+   --  This table is initialized at the start of each outer level call.
+   --  It holds the entities for all subprograms that have been examined
+   --  for this particular outer level call, and is used to prevent both
+   --  infinite recursion, and useless reanalysis of bodies already seen
+
+   package Elab_Visited is new Table.Table (
+     Table_Component_Type => Entity_Id,
+     Table_Index_Type     => Int,
+     Table_Low_Bound      => 1,
+     Table_Initial        => 200,
+     Table_Increment      => 100,
+     Table_Name           => "Elab_Visited");
+
+   --  This table stores calls to Check_Internal_Call that are delayed
+   --  until all generics are instantiated, and in particular that all
+   --  generic bodies have been inserted. We need to delay, because we
+   --  need to be able to look through the inserted bodies.
+
+   type Delay_Element is record
+      N : Node_Id;
+      --  The parameter N from the call to Check_Internal_Call. Note that
+      --  this node may get rewritten over the delay period by expansion
+      --  in the call case (but not in the instantiation case).
+
+      E : Entity_Id;
+      --  The parameter E from the call to Check_Internal_Call
+
+      Orig_Ent : Entity_Id;
+      --  The parameter Orig_Ent from the call to Check_Internal_Call
+
+      Curscop : Entity_Id;
+      --  The current scope of the call. This is restored when we complete
+      --  the delayed call, so that we do this in the right scope.
+
+      From_Elab_Code : Boolean;
+      --  Save indication of whether this call is from elaboration code
+
+      Outer_Scope : Entity_Id;
+      --  Save scope of outer level call
+
+   end record;
+
+   package Delay_Check is new Table.Table (
+     Table_Component_Type => Delay_Element,
+     Table_Index_Type     => Int,
+     Table_Low_Bound      => 1,
+     Table_Initial        => 1000,
+     Table_Increment      => 100,
+     Table_Name           => "Delay_Check");
+
+   C_Scope : Entity_Id;
+   --  Top level scope of current scope. We need to compute this only
+   --  once at the outer level, i.e. for a call to Check_Elab_Call from
+   --  outside this unit.
+
+   Outer_Level_Sloc : Source_Ptr;
+   --  Save Sloc value for outer level call node for comparisons of source
+   --  locations. A body is too late if it appears after the *outer* level
+   --  call, not the particular call that is being analyzed.
+
+   From_Elab_Code : Boolean;
+   --  This flag shows whether the outer level call currently being examined
+   --  is or is not in elaboration code. We are only interested in calls to
+   --  routines in other units if this flag is True.
+
+   In_Task_Activation : Boolean := False;
+   --  This flag indicates whether we are performing elaboration checks on
+   --  task procedures, at the point of activation. If true, we do not trace
+   --  internal calls in these procedures, because all local bodies are known
+   --  to be elaborated.
+
+   Delaying_Elab_Checks : Boolean := True;
+   --  This is set True till the compilation is complete, including the
+   --  insertion of all instance bodies. Then when Check_Elab_Calls is
+   --  called, the delay table is used to make the delayed calls and
+   --  this flag is reset to False, so that the calls are processed
+
+   -----------------------
+   -- Local Subprograms --
+   -----------------------
+
+   --  Note: Outer_Scope in all these calls represents the scope of
+   --  interest of the outer level call. If it is set to Standard_Standard,
+   --  then it means the outer level call was at elaboration level, and that
+   --  thus all calls are of interest. If it was set to some other scope,
+   --  then the original call was an inner call, and we are not interested
+   --  in calls that go outside this scope.
+
+   procedure Check_A_Call
+     (N                 : Node_Id;
+      E                 : Entity_Id;
+      Outer_Scope       : Entity_Id;
+      Inter_Unit_Only   : Boolean;
+      Generate_Warnings : Boolean := True);
+   --  This is the internal recursive routine that is called to check for
+   --  a possible elaboration error. The argument N is a subprogram call
+   --  or generic instantiation to be checked, and E is the entity of
+   --  the called subprogram, or instantiated generic unit. The flag
+   --  Outer_Scope is the outer level scope for the original call.
+   --  Inter_Unit_Only is set if the call is only to be checked in the
+   --  case where it is to another unit (and skipped if within a unit).
+   --  Generate_Warnings is set to True to suppress warning messages
+   --  about missing pragma Elaborate_All's. These messages are not
+   --  wanted for inner calls in the dynamic model.
+
+   procedure Check_Bad_Instantiation (N : Node_Id);
+   --  N is a node for an instantiation (if called with any other node kind,
+   --  Check_Bad_Instantiation ignores the call). This subprogram checks for
+   --  the special case of a generic instantiation of a generic spec in the
+   --  same declarative part as the instantiation where a body is present and
+   --  has not yet been seen. This is an obvious error, but needs to be checked
+   --  specially at the time of the instantiation, since it is a case where we
+   --  cannot insert the body anywhere. If this case is detected, warnings are
+   --  generated, and a raise of Program_Error is inserted. In addition any
+   --  subprograms in the generic spec are stubbed, and the Bad_Instantiation
+   --  flag is set on the instantiation node. The caller in Sem_Ch12 uses this
+   --  flag as an indication that no attempt should be made to insert an
+   --  instance body.
+
+   procedure Check_Internal_Call
+     (N           : Node_Id;
+      E           : Entity_Id;
+      Outer_Scope : Entity_Id;
+      Orig_Ent    : Entity_Id);
+   --  N is a function call or procedure statement call node and E is
+   --  the entity of the called function, which is within the current
+   --  compilation unit (where subunits count as part of the parent).
+   --  This call checks if this call, or any call within any accessed
+   --  body could cause an ABE, and if so, outputs a warning. Orig_Ent
+   --  differs from E only in the case of renamings, and points to the
+   --  original name of the entity. This is used for error messages.
+   --  Outer_Scope is the outer level scope for the original call.
+
+   procedure Check_Internal_Call_Continue
+     (N           : Node_Id;
+      E           : Entity_Id;
+      Outer_Scope : Entity_Id;
+      Orig_Ent    : Entity_Id);
+   --  The processing for Check_Internal_Call is divided up into two phases,
+   --  and this represents the second phase. The second phase is delayed if
+   --  Delaying_Elab_Calls is set to True. In this delayed case, the first
+   --  phase makes an entry in the Delay_Check table, which is processed
+   --  when Check_Elab_Calls is called. N, E and Orig_Ent are as for the call
+   --  to Check_Internal_Call. Outer_Scope is the outer level scope for
+   --  the original call.
+
+   function Has_Generic_Body (N : Node_Id) return Boolean;
+   --  N is a generic package instantiation node, and this routine determines
+   --  if this package spec does in fact have a generic body. If so, then
+   --  True is returned, otherwise False. Note that this is not at all the
+   --  same as checking if the unit requires a body, since it deals with
+   --  the case of optional bodies accurately (i.e. if a body is optional,
+   --  then it looks to see if a body is actually present). Note: this
+   --  function can only do a fully correct job if in generating code mode
+   --  where all bodies have to be present. If we are operating in semantics
+   --  check only mode, then in some cases of optional bodies, a result of
+   --  False may incorrectly be given. In practice this simply means that
+   --  some cases of warnings for incorrect order of elaboration will only
+   --  be given when generating code, which is not a big problem (and is
+   --  inevitable, given the optional body semantics of Ada).
+
+   procedure Insert_Elab_Check (N : Node_Id; C : Node_Id := Empty);
+   --  Given code for an elaboration check (or unconditional raise if
+   --  the check is not needed), inserts the code in the appropriate
+   --  place. N is the call or instantiation node for which the check
+   --  code is required. C is the test whose failure triggers the raise.
+
+   procedure Output_Calls (N : Node_Id);
+   --  Outputs chain of calls stored in the Elab_Call table. The caller
+   --  has already generated the main warning message, so the warnings
+   --  generated are all continuation messages. The argument is the
+   --  call node at which the messages are to be placed.
+
+   function Same_Elaboration_Scope (Scop1, Scop2 : Entity_Id) return Boolean;
+   --  Given two scopes, determine whether they are the same scope from an
+   --  elaboration point of view, i.e. packages and blocks are ignored.
+
+   procedure Set_C_Scope;
+   --  On entry C_Scope is set to some scope. On return, C_Scope is reset
+   --  to be the enclosing compilation unit of this scope.
+
+   function Spec_Entity (E : Entity_Id) return Entity_Id;
+   --  Given a compilation unit entity, if it is a spec entity, it is
+   --  returned unchanged. If it is a body entity, then the spec for
+   --  the corresponding spec is returned
+
+   procedure Supply_Bodies (N : Node_Id);
+   --  Given a node, N, that is either a subprogram declaration or a package
+   --  declaration, this procedure supplies dummy bodies for the subprogram
+   --  or for all subprograms in the package. If the given node is not one
+   --  of these two possibilities, then Supply_Bodies does nothing. The
+   --  dummy body is supplied by setting the subprogram to be Imported with
+   --  convention Stubbed.
+
+   procedure Supply_Bodies (L : List_Id);
+   --  Calls Supply_Bodies for all elements of the given list L.
+
+   function Within (E1, E2 : Entity_Id) return Boolean;
+   --  Given two scopes E1 and E2, returns True if E1 is equal to E2, or
+   --  is one of its contained scopes, False otherwise.
+
+   ------------------
+   -- Check_A_Call --
+   ------------------
+
+   procedure Check_A_Call
+     (N                 : Node_Id;
+      E                 : Entity_Id;
+      Outer_Scope       : Entity_Id;
+      Inter_Unit_Only   : Boolean;
+      Generate_Warnings : Boolean := True)
+   is
+      Loc  : constant Source_Ptr := Sloc (N);
+      Ent  : Entity_Id;
+      Decl : Node_Id;
+
+      E_Scope : Entity_Id;
+      --  Top level scope of entity for called subprogram
+
+      Body_Acts_As_Spec : Boolean;
+      --  Set to true if call is to body acting as spec (no separate spec)
+
+      Inst_Case : constant Boolean := Nkind (N) in N_Generic_Instantiation;
+      --  Indicates if we have instantiation case
+
+      Caller_Unit_Internal : Boolean;
+      Callee_Unit_Internal : Boolean;
+
+      Inst_Caller : Source_Ptr;
+      Inst_Callee : Source_Ptr;
+
+      Unit_Caller : Unit_Number_Type;
+      Unit_Callee : Unit_Number_Type;
+
+      Cunit_SW : Boolean := False;
+      --  Set to suppress warnings for case of external reference where
+      --  one of the enclosing scopes has the Suppress_Elaboration_Warnings
+      --  flag set. For the internal case, we ignore this flag.
+
+      Cunit_SC : Boolean := False;
+      --  Set to suppress dynamic elaboration checks where one of the
+      --  enclosing scopes has Suppress_Elaboration_Checks set. For
+      --  the internal case, we ignore this flag.
+
+   begin
+      --  Go to parent for derived subprogram, or to original subprogram
+      --  in the case of a renaming (Alias covers both these cases)
+
+      Ent := E;
+      loop
+         if Suppress_Elaboration_Warnings (Ent) then
+            return;
+         end if;
+
+         --  Nothing to do for imported entities,
+
+         if Is_Imported (Ent) then
+            return;
+         end if;
+
+         exit when Inst_Case or else No (Alias (Ent));
+         Ent := Alias (Ent);
+      end loop;
+
+      Decl := Unit_Declaration_Node (Ent);
+
+      if Nkind (Decl) = N_Subprogram_Body then
+         Body_Acts_As_Spec := True;
+
+      elsif Nkind (Decl) = N_Subprogram_Declaration
+        or else Nkind (Decl) = N_Subprogram_Body_Stub
+        or else Inst_Case
+      then
+         Body_Acts_As_Spec := False;
+
+      --  If we have none of an instantiation, subprogram body or
+      --  subprogram declaration, then it is not a case that we want
+      --  to check. (One case is a call to a generic formal subprogram,
+      --  where we do not want the check in the template).
+
+      else
+         return;
+      end if;
+
+      E_Scope := Ent;
+      loop
+         if Suppress_Elaboration_Warnings (E_Scope) then
+            Cunit_SW := True;
+         end if;
+
+         if Suppress_Elaboration_Checks (E_Scope) then
+            Cunit_SC := True;
+         end if;
+
+         --  Exit when we get to compilation unit, not counting subunits
+
+         exit when Is_Compilation_Unit (E_Scope)
+           and then (Is_Child_Unit (E_Scope)
+                       or else Scope (E_Scope) = Standard_Standard);
+
+         --  If we did not find a compilation unit, other than standard,
+         --  then nothing to check (happens in some instantiation cases)
+
+         if E_Scope = Standard_Standard then
+            return;
+
+         --  Otherwise move up a scope looking for compilation unit
+
+         else
+            E_Scope := Scope (E_Scope);
+         end if;
+      end loop;
+
+      --  No checks needed for pure or preelaborated compilation units
+
+      if Is_Pure (E_Scope)
+        or else Is_Preelaborated (E_Scope)
+      then
+         return;
+      end if;
+
+      --  If the generic entity is within a deeper instance than we are, then
+      --  either the instantiation to which we refer itself caused an ABE, in
+      --  which case that will be handled separately. Otherwise, we know that
+      --  the body we need appears as needed at the point of the instantiation.
+      --  However, this assumption is only valid if we are in static mode.
+
+      if not Dynamic_Elaboration_Checks
+        and then Instantiation_Depth (Sloc (Ent)) >
+                 Instantiation_Depth (Sloc (N))
+      then
+         return;
+      end if;
+
+      --  Do not give a warning for a package with no body
+
+      if Ekind (Ent) = E_Generic_Package
+        and then not Has_Generic_Body (N)
+      then
+         return;
+      end if;
+
+      --  Case of entity is not in current unit (i.e. with'ed unit case)
+
+      if E_Scope /= C_Scope then
+
+         --  We are only interested in such calls if the outer call was from
+         --  elaboration code, or if we are in Dynamic_Elaboration_Checks mode.
+
+         if not From_Elab_Code and then not Dynamic_Elaboration_Checks then
+            return;
+         end if;
+
+         --  Nothing to do if some scope said to ignore warnings
+
+         if Cunit_SW then
+            return;
+         end if;
+
+         --  Nothing to do for a generic instance, because in this case
+         --  the checking was at the point of instantiation of the generic
+         --  However, this shortcut is only applicable in static mode.
+
+         if Is_Generic_Instance (Ent) and not Dynamic_Elaboration_Checks then
+            return;
+         end if;
+
+         --  Nothing to do if subprogram with no separate spec
+
+         if Body_Acts_As_Spec then
+            return;
+         end if;
+
+         --  Check cases of internal units
+
+         Callee_Unit_Internal :=
+           Is_Internal_File_Name
+             (Unit_File_Name (Get_Source_Unit (E_Scope)));
+
+         --  Do not give a warning if the with'ed unit is internal
+         --  and this is the generic instantiation case (this saves a
+         --  lot of hassle dealing with the Text_IO special child units)
+
+         if Callee_Unit_Internal and Inst_Case then
+            return;
+         end if;
+
+         if C_Scope = Standard_Standard then
+            Caller_Unit_Internal := False;
+         else
+            Caller_Unit_Internal :=
+              Is_Internal_File_Name
+                (Unit_File_Name (Get_Source_Unit (C_Scope)));
+         end if;
+
+         --  Do not give a warning if the with'ed unit is internal
+         --  and the caller is not internal (since the binder always
+         --  elaborates internal units first).
+
+         if Callee_Unit_Internal and (not Caller_Unit_Internal) then
+            return;
+         end if;
+
+         --  For now, if debug flag -gnatdE is not set, do no checking for
+         --  one internal unit withing another. This fixes the problem with
+         --  the sgi build and storage errors. To be resolved later ???
+
+         if (Callee_Unit_Internal and Caller_Unit_Internal)
+            and then not Debug_Flag_EE
+         then
+            return;
+         end if;
+
+         Ent := E;
+
+         --  If the call is in an instance, and the called entity is not
+         --  defined in the same instance, then the elaboration issue
+         --  focuses around the unit containing the template, it is
+         --  this unit which requires an Elaborate_All.
+
+         --  However, if we are doing dynamic elaboration, we need to
+         --  chase the call in the usual manner.
+
+         --  We do not handle the case of calling a generic formal correctly
+         --  in the static case. See test 4703-004 to explore this gap ???
+
+         Inst_Caller := Instantiation (Get_Source_File_Index (Sloc (N)));
+         Inst_Callee := Instantiation (Get_Source_File_Index (Sloc (Ent)));
+
+         if Inst_Caller = No_Location then
+            Unit_Caller := No_Unit;
+         else
+            Unit_Caller := Get_Source_Unit (N);
+         end if;
+
+         if Inst_Callee = No_Location then
+            Unit_Callee := No_Unit;
+         else
+            Unit_Callee := Get_Source_Unit (Ent);
+         end if;
+
+         if Unit_Caller /= No_Unit
+           and then Unit_Callee /= Unit_Caller
+           and then not Dynamic_Elaboration_Checks
+         then
+            E_Scope := Spec_Entity (Cunit_Entity (Unit_Caller));
+
+            --  If we don't get a spec entity, just ignore call. Not
+            --  quite clear why this check is necessary.
+
+            if No (E_Scope) then
+               return;
+            end if;
+
+            --  Otherwise step to enclosing compilation unit
+
+            while not Is_Compilation_Unit (E_Scope) loop
+               E_Scope := Scope (E_Scope);
+            end loop;
+
+         --  For the case of not in an instance, or call within instance
+         --  We recompute E_Scope for the error message, since we
+         --  do NOT want to go to the unit which has the ultimate
+         --  declaration in the case of renaming and derivation and
+         --  we also want to go to the generic unit in the case of
+         --  an instance, and no further.
+
+         else
+            --  Loop to carefully follow renamings and derivations
+            --  one step outside the current unit, but not further.
+
+            loop
+               E_Scope := Ent;
+               while not Is_Compilation_Unit (E_Scope) loop
+                  E_Scope := Scope (E_Scope);
+               end loop;
+
+               --  If E_Scope is the same as C_Scope, it means that there
+               --  definitely was a renaming or derivation, and we are
+               --  not yet out of the current unit.
+
+               exit when E_Scope /= C_Scope;
+               Ent := Alias (Ent);
+            end loop;
+         end if;
+
+         if not Suppress_Elaboration_Warnings (Ent)
+           and then not Suppress_Elaboration_Warnings (E_Scope)
+           and then Elab_Warnings
+           and then Generate_Warnings
+         then
+            Warn_On_Instance := True;
+
+            if Inst_Case then
+               Error_Msg_NE
+                 ("instantiation of& may raise Program_Error?", N, Ent);
+            else
+               Error_Msg_NE
+                 ("call to & may raise Program_Error?", N, Ent);
+            end if;
+
+            Error_Msg_Qual_Level := Nat'Last;
+            Error_Msg_NE
+              ("\missing pragma Elaborate_All for&?", N, E_Scope);
+            Error_Msg_Qual_Level := 0;
+            Output_Calls (N);
+            Warn_On_Instance := False;
+
+            --  Set flag to prevent further warnings for same unit
+            --  unless in All_Errors_Mode.
+
+            if not All_Errors_Mode and not Dynamic_Elaboration_Checks then
+               Set_Suppress_Elaboration_Warnings (E_Scope);
+            end if;
+         end if;
+
+         --  Check for runtime elaboration check required
+
+         if Dynamic_Elaboration_Checks then
+            if not Elaboration_Checks_Suppressed (Ent)
+              and then not Suppress_Elaboration_Checks (E_Scope)
+              and then not Cunit_SC
+            then
+               --  Runtime elaboration check required. generate check of the
+               --  elaboration Boolean for the unit containing the entity.
+
+               Insert_Elab_Check (N,
+                 Make_Attribute_Reference (Loc,
+                   Attribute_Name => Name_Elaborated,
+                   Prefix =>
+                     New_Occurrence_Of
+                       (Spec_Entity (E_Scope), Loc)));
+            end if;
+
+         --  If no dynamic check required, then ask binder to guarantee
+         --  that the necessary elaborations will be done properly!
+
+         else
+            if not Suppress_Elaboration_Warnings (E)
+              and then not Suppress_Elaboration_Warnings (E_Scope)
+              and then Elab_Warnings
+              and then Generate_Warnings
+              and then not Inst_Case
+            then
+               Error_Msg_Node_2 := E_Scope;
+               Error_Msg_NE ("call to& in elaboration code " &
+                  "requires pragma Elaborate_All on&?", N, E);
+            end if;
+
+            Set_Elaborate_All_Desirable (E_Scope);
+            Set_Suppress_Elaboration_Warnings (E_Scope);
+         end if;
+
+      --  Case of entity is in same unit as call or instantiation
+
+      elsif not Inter_Unit_Only then
+         Check_Internal_Call (N, Ent, Outer_Scope, E);
+      end if;
+
+   end Check_A_Call;
+
+   -----------------------------
+   -- Check_Bad_Instantiation --
+   -----------------------------
+
+   procedure Check_Bad_Instantiation (N : Node_Id) is
+      Nam : Node_Id;
+      Ent : Entity_Id;
+
+   begin
+      --  Nothing to do if we do not have an instantiation (happens in some
+      --  error cases, and also in the formal package declaration case)
+
+      if Nkind (N) not in N_Generic_Instantiation then
+         return;
+
+      --  Nothing to do if errors already detected (avoid cascaded errors)
+
+      elsif Errors_Detected /= 0 then
+         return;
+
+      --  Nothing to do if not in full analysis mode
+
+      elsif not Full_Analysis then
+         return;
+
+      --  Nothing to do if inside a generic template
+
+      elsif Inside_A_Generic then
+         return;
+
+      --  Nothing to do if a library level instantiation
+
+      elsif Nkind (Parent (N)) = N_Compilation_Unit then
+         return;
+
+      --  Nothing to do if we are compiling a proper body for semantic
+      --  purposes only. The generic body may be in another proper body.
+
+      elsif
+        Nkind (Parent (Unit_Declaration_Node (Main_Unit_Entity))) = N_Subunit
+      then
+         return;
+      end if;
+
+      Nam := Name (N);
+      Ent := Entity (Nam);
+
+      --  The case we are interested in is when the generic spec is in the
+      --  current declarative part
+
+      if not Same_Elaboration_Scope (Current_Scope, Scope (Ent))
+        or else not In_Same_Extended_Unit (Sloc (N), Sloc (Ent))
+      then
+         return;
+      end if;
+
+      --  If the generic entity is within a deeper instance than we are, then
+      --  either the instantiation to which we refer itself caused an ABE, in
+      --  which case that will be handled separately. Otherwise, we know that
+      --  the body we need appears as needed at the point of the instantiation.
+      --  If they are both at the same level but not within the same instance
+      --  then the body of the generic will be in the earlier instance.
+
+      declare
+         D1 : constant Int := Instantiation_Depth (Sloc (Ent));
+         D2 : constant Int := Instantiation_Depth (Sloc (N));
+
+      begin
+         if D1 > D2 then
+            return;
+
+         elsif D1 = D2
+           and then Is_Generic_Instance (Scope (Ent))
+           and then not In_Open_Scopes (Scope (Ent))
+         then
+            return;
+         end if;
+      end;
+
+      --  Now we can proceed, if the entity being called has a completion,
+      --  then we are definitely OK, since we have already seen the body.
+
+      if Has_Completion (Ent) then
+         return;
+      end if;
+
+      --  If there is no body, then nothing to do
+
+      if not Has_Generic_Body (N) then
+         return;
+      end if;
+
+      --  Here we definitely have a bad instantiation
+
+      Error_Msg_NE
+        ("?cannot instantiate& before body seen", N, Ent);
+
+      if Present (Instance_Spec (N)) then
+         Supply_Bodies (Instance_Spec (N));
+      end if;
+
+      Error_Msg_N
+        ("\?Program_Error will be raised at run time", N);
+      Insert_Elab_Check (N);
+      Set_ABE_Is_Certain (N);
+
+   end Check_Bad_Instantiation;
+
+   ---------------------
+   -- Check_Elab_Call --
+   ---------------------
+
+   procedure Check_Elab_Call
+     (N           : Node_Id;
+      Outer_Scope : Entity_Id := Empty)
+   is
+      Nam : Node_Id;
+      Ent : Entity_Id;
+      P   : Node_Id;
+
+   begin
+      --  For an entry call, check relevant restriction
+
+      if Nkind (N) = N_Entry_Call_Statement
+         and then not In_Subprogram_Or_Concurrent_Unit
+      then
+         Check_Restriction (No_Entry_Calls_In_Elaboration_Code, N);
+
+      --  Nothing to do if this is not a call (happens in some error
+      --  conditions, and in some cases where rewriting occurs).
+
+      elsif Nkind (N) /= N_Function_Call
+        and then Nkind (N) /= N_Procedure_Call_Statement
+      then
+         return;
+
+      --  Nothing to do if this is a call already rewritten for elab checking.
+
+      elsif Nkind (Parent (N)) = N_Conditional_Expression then
+         return;
+
+      --  Nothing to do if inside a generic template
+
+      elsif Inside_A_Generic
+        and then not Present (Enclosing_Generic_Body (N))
+      then
+         return;
+      end if;
+
+      --  Here we have a call at elaboration time which must be checked
+
+      if Debug_Flag_LL then
+         Write_Str ("  Check_Elab_Call: ");
+
+         if No (Name (N))
+           or else not Is_Entity_Name (Name (N))
+         then
+            Write_Str ("<<not entity name>> ");
+         else
+            Write_Name (Chars (Entity (Name (N))));
+         end if;
+
+         Write_Str ("  call at ");
+         Write_Location (Sloc (N));
+         Write_Eol;
+      end if;
+
+      --  Climb up the tree to make sure we are not inside a
+      --  default expression of a parameter specification or
+      --  a record component, since in both these cases, we
+      --  will be doing the actual call later, not now, and it
+      --  is at the time of the actual call (statically speaking)
+      --  that we must do our static check, not at the time of
+      --  its initial analysis).
+
+      P := Parent (N);
+      while Present (P) loop
+         if Nkind (P) = N_Parameter_Specification
+              or else
+            Nkind (P) = N_Component_Declaration
+         then
+            return;
+         else
+            P := Parent (P);
+         end if;
+      end loop;
+
+      --  Stuff that happens only at the outer level
+
+      if No (Outer_Scope) then
+         Elab_Visited.Set_Last (0);
+
+         --  Nothing to do if current scope is Standard (this is a bit
+         --  odd, but it happens in the case of generic instantiations).
+
+         C_Scope := Current_Scope;
+
+         if C_Scope = Standard_Standard then
+            return;
+         end if;
+
+         --  First case, we are in elaboration code
+
+         From_Elab_Code := not In_Subprogram_Or_Concurrent_Unit;
+
+         if From_Elab_Code then
+
+            --  Complain if call that comes from source in preelaborated
+            --  unit and we are not inside a subprogram (i.e. we are in
+            --  elab code)
+
+            if Comes_From_Source (N)
+              and then In_Preelaborated_Unit
+            then
+               Error_Msg_N
+                 ("non-static call not allowed in preelaborated unit", N);
+               return;
+            end if;
+
+         --  Second case, we are inside a subprogram or concurrent unit
+         --  i.e, we are not in elaboration code.
+
+         else
+            --  In this case, the issue is whether we are inside the
+            --  declarative part of the unit in which we live, or inside
+            --  its statements. In the latter case, there is no issue of
+            --  ABE calls at this level (a call from outside to the unit
+            --  in which we live might cause an ABE, but that will be
+            --  detected when we analyze that outer level call, as it
+            --  recurses into the called unit).
+
+            --  Climb up the tree, doing this test, and also testing
+            --  for being inside a default expression, which, as
+            --  discussed above, is not checked at this stage.
+
+            declare
+               P : Node_Id;
+               L : List_Id;
+
+            begin
+               P := N;
+               loop
+                  --  If we find a parentless subtree, it seems safe to
+                  --  assume that we are not in a declarative part and
+                  --  that no checking is required.
+
+                  if No (P) then
+                     return;
+                  end if;
+
+                  if Is_List_Member (P) then
+                     L := List_Containing (P);
+                     P := Parent (L);
+                  else
+                     L := No_List;
+                     P := Parent (P);
+                  end if;
+
+                  exit when Nkind (P) = N_Subunit;
+
+                  --  Filter out case of default expressions, where
+                  --  we do not do the check at this stage.
+
+                  if Nkind (P) = N_Parameter_Specification
+                       or else
+                     Nkind (P) = N_Component_Declaration
+                  then
+                     return;
+                  end if;
+
+                  if Nkind (P) = N_Subprogram_Body
+                       or else
+                     Nkind (P) = N_Protected_Body
+                       or else
+                     Nkind (P) = N_Task_Body
+                       or else
+                     Nkind (P) = N_Block_Statement
+                  then
+                     if L = Declarations (P) then
+                        exit;
+
+                     --  We are not in elaboration code, but we are doing
+                     --  dynamic elaboration checks, in this case, we still
+                     --  need to do the call, since the subprogram we are in
+                     --  could be called from another unit, also in dynamic
+                     --  elaboration check mode, at elaboration time.
+
+                     elsif Dynamic_Elaboration_Checks then
+
+                        --  This is a rather new check, going into version
+                        --  3.14a1 for the first time (V1.80 of this unit),
+                        --  so we provide a debug flag to enable it. That
+                        --  way we have an easy work around for regressions
+                        --  that are caused by this new check. This debug
+                        --  flag can be removed later.
+
+                        if Debug_Flag_DD then
+                           return;
+                        end if;
+
+                        --  Do the check in this case
+
+                        exit;
+
+                     --  Static model, call is not in elaboration code, we
+                     --  never need to worry, because in the static model
+                     --  the top level caller always takes care of things.
+
+                     else
+                        return;
+                     end if;
+                  end if;
+               end loop;
+            end;
+         end if;
+      end if;
+
+      --  Retrieve called entity. If this is a call to a protected subprogram,
+      --  the entity is a selected component.
+      --  The callable entity may be absent, in which case there is nothing
+      --  to do. This happens with non-analyzed calls in nested generics.
+
+      Nam := Name (N);
+
+      if No (Nam) then
+         return;
+
+      elsif Nkind (Nam) = N_Selected_Component then
+         Ent := Entity (Selector_Name (Nam));
+
+      elsif not Is_Entity_Name (Nam) then
+         return;
+
+      else
+         Ent := Entity (Nam);
+      end if;
+
+      if No (Ent) then
+         return;
+      end if;
+
+      --  Nothing to do if this is a recursive call (i.e. a call to
+      --  an entity that is already in the Elab_Call stack)
+
+      for J in 1 .. Elab_Visited.Last loop
+         if Ent = Elab_Visited.Table (J) then
+            return;
+         end if;
+      end loop;
+
+      --  See if we need to analyze this call. We analyze it if either of
+      --  the following conditions is met:
+
+      --    It is an inner level call (since in this case it was triggered
+      --    by an outer level call from elaboration code), but only if the
+      --    call is within the scope of the original outer level call.
+
+      --    It is an outer level call from elaboration code, or the called
+      --    entity is in the same elaboration scope.
+
+      --  And in these cases, we will check both inter-unit calls and
+      --  intra-unit (within a single unit) calls.
+
+      C_Scope := Current_Scope;
+
+      --  If not outer level call, then we follow it if it is within
+      --  the original scope of the outer call.
+
+      if Present (Outer_Scope)
+        and then Within (Scope (Ent), Outer_Scope)
+      then
+         Set_C_Scope;
+         Check_A_Call (N, Ent, Outer_Scope, Inter_Unit_Only => False);
+
+      elsif Elaboration_Checks_Suppressed (Current_Scope) then
+         null;
+
+      elsif From_Elab_Code then
+         Set_C_Scope;
+         Check_A_Call (N, Ent, Standard_Standard, Inter_Unit_Only => False);
+
+      elsif Same_Elaboration_Scope (C_Scope, Scope (Ent)) then
+         Set_C_Scope;
+         Check_A_Call (N, Ent, Scope (Ent), Inter_Unit_Only => False);
+
+      --  If none of those cases holds, but Dynamic_Elaboration_Checks mode
+      --  is set, then we will do the check, but only in the inter-unit case
+      --  (this is to accomodate unguarded elaboration calls from other units
+      --  in which this same mode is set). We don't want warnings in this case,
+      --  it would generate warnings having nothing to do with elaboration.
+
+      elsif Dynamic_Elaboration_Checks then
+         Set_C_Scope;
+         Check_A_Call
+           (N,
+            Ent,
+            Standard_Standard,
+            Inter_Unit_Only => True,
+            Generate_Warnings => False);
+
+      else
+         return;
+      end if;
+   end Check_Elab_Call;
+
+   ----------------------
+   -- Check_Elab_Calls --
+   ----------------------
+
+   procedure Check_Elab_Calls is
+   begin
+      --  If expansion is disabled, do not generate any checks. Also
+      --  skip checks if any subunits are missing because in either
+      --  case we lack the full information that we need, and no object
+      --  file will be created in any case.
+
+      if not Expander_Active or else Subunits_Missing then
+         return;
+      end if;
+
+      --  Skip delayed calls if we had any errors
+
+      if Errors_Detected = 0 then
+         Delaying_Elab_Checks := False;
+         Expander_Mode_Save_And_Set (True);
+
+         for J in Delay_Check.First .. Delay_Check.Last loop
+            New_Scope (Delay_Check.Table (J).Curscop);
+            From_Elab_Code := Delay_Check.Table (J).From_Elab_Code;
+
+            Check_Internal_Call_Continue (
+              N           => Delay_Check.Table (J).N,
+              E           => Delay_Check.Table (J).E,
+              Outer_Scope => Delay_Check.Table (J).Outer_Scope,
+              Orig_Ent    => Delay_Check.Table (J).Orig_Ent);
+
+            Pop_Scope;
+         end loop;
+
+         --  Set Delaying_Elab_Checks back on for next main compilation
+
+         Expander_Mode_Restore;
+         Delaying_Elab_Checks := True;
+      end if;
+   end Check_Elab_Calls;
+
+   ------------------------------
+   -- Check_Elab_Instantiation --
+   ------------------------------
+
+   procedure Check_Elab_Instantiation
+     (N           : Node_Id;
+      Outer_Scope : Entity_Id := Empty)
+   is
+      Nam     : Node_Id;
+      Ent     : Entity_Id;
+
+   begin
+      --  Check for and deal with bad instantiation case. There is some
+      --  duplicated code here, but we will worry about this later ???
+
+      Check_Bad_Instantiation (N);
+
+      if ABE_Is_Certain (N) then
+         return;
+      end if;
+
+      --  Nothing to do if we do not have an instantiation (happens in some
+      --  error cases, and also in the formal package declaration case)
+
+      if Nkind (N) not in N_Generic_Instantiation then
+         return;
+      end if;
+
+      --  Nothing to do if inside a generic template
+
+      if Inside_A_Generic then
+         return;
+      end if;
+
+      Nam := Name (N);
+      Ent := Entity (Nam);
+      From_Elab_Code := not In_Subprogram_Or_Concurrent_Unit;
+
+      --  See if we need to analyze this instantiation. We analyze it if
+      --  either of the following conditions is met:
+
+      --    It is an inner level instantiation (since in this case it was
+      --    triggered by an outer level call from elaboration code), but
+      --    only if the instantiation is within the scope of the original
+      --    outer level call.
+
+      --    It is an outer level instantiation from elaboration code, or the
+      --    instantiated entity is in the same elaboratoin scope.
+
+      --  And in these cases, we will check both the inter-unit case and
+      --  the intra-unit (within a single unit) case.
+
+      C_Scope := Current_Scope;
+
+      if Present (Outer_Scope)
+        and then Within (Scope (Ent), Outer_Scope)
+      then
+         Set_C_Scope;
+         Check_A_Call (N, Ent, Outer_Scope, Inter_Unit_Only => False);
+
+      elsif From_Elab_Code then
+         Set_C_Scope;
+         Check_A_Call (N, Ent, Standard_Standard, Inter_Unit_Only => False);
+
+      elsif Same_Elaboration_Scope (C_Scope, Scope (Ent)) then
+         Set_C_Scope;
+         Check_A_Call (N, Ent, Scope (Ent), Inter_Unit_Only => False);
+
+      --  If none of those cases holds, but Dynamic_Elaboration_Checks mode
+      --  is set, then we will do the check, but only in the inter-unit case
+      --  (this is to accomodate unguarded elaboration calls from other units
+      --  in which this same mode is set). We inhibit warnings in this case,
+      --  since this instantiation is not occurring in elaboration code.
+
+      elsif Dynamic_Elaboration_Checks then
+         Set_C_Scope;
+         Check_A_Call
+           (N,
+            Ent,
+            Standard_Standard,
+            Inter_Unit_Only => True,
+            Generate_Warnings => False);
+
+      else
+         return;
+      end if;
+   end Check_Elab_Instantiation;
+
+   -------------------------
+   -- Check_Internal_Call --
+   -------------------------
+
+   procedure Check_Internal_Call
+     (N           : Node_Id;
+      E           : Entity_Id;
+      Outer_Scope : Entity_Id;
+      Orig_Ent    : Entity_Id)
+   is
+      Inst_Case : constant Boolean := Nkind (N) in N_Generic_Instantiation;
+
+   begin
+      --  If not function or procedure call or instantiation, then ignore
+      --  call (this happens in some error case and rewriting cases)
+
+      if Nkind (N) /= N_Function_Call
+           and then
+         Nkind (N) /= N_Procedure_Call_Statement
+           and then
+         not Inst_Case
+      then
+         return;
+
+      --  Nothing to do if this is a call or instantiation that has
+      --  already been found to be a sure ABE
+
+      elsif ABE_Is_Certain (N) then
+         return;
+
+      --  Nothing to do if errors already detected (avoid cascaded errors)
+
+      elsif Errors_Detected /= 0 then
+         return;
+
+      --  Nothing to do if not in full analysis mode
+
+      elsif not Full_Analysis then
+         return;
+
+      --  Nothing to do if within a default expression, since the call
+      --  is not actualy being made at this time.
+
+      elsif In_Default_Expression then
+         return;
+
+      --  Nothing to do for call to intrinsic subprogram
+
+      elsif Is_Intrinsic_Subprogram (E) then
+         return;
+
+      --  No need to trace local calls if checking task activation, because
+      --  other local bodies are elaborated already.
+
+      elsif In_Task_Activation then
+         return;
+      end if;
+
+      --  Delay this call if we are still delaying calls
+
+      if Delaying_Elab_Checks then
+         Delay_Check.Increment_Last;
+         Delay_Check.Table (Delay_Check.Last) :=
+           (N              => N,
+            E              => E,
+            Orig_Ent       => Orig_Ent,
+            Curscop        => Current_Scope,
+            Outer_Scope    => Outer_Scope,
+            From_Elab_Code => From_Elab_Code);
+         return;
+
+      --  Otherwise, call phase 2 continuation right now
+
+      else
+         Check_Internal_Call_Continue (N, E, Outer_Scope, Orig_Ent);
+      end if;
+
+   end Check_Internal_Call;
+
+   ----------------------------------
+   -- Check_Internal_Call_Continue --
+   ----------------------------------
+
+   procedure Check_Internal_Call_Continue
+     (N           : Node_Id;
+      E           : Entity_Id;
+      Outer_Scope : Entity_Id;
+      Orig_Ent    : Entity_Id)
+   is
+      Loc       : constant Source_Ptr := Sloc (N);
+      Inst_Case : constant Boolean := Is_Generic_Unit (E);
+
+      Sbody : Node_Id;
+      Ebody : Entity_Id;
+
+      function Process (N : Node_Id) return Traverse_Result;
+      --  Function applied to each node as we traverse the body.
+      --  Checks for call that needs checking, and if so checks
+      --  it. Always returns OK, so entire tree is traversed.
+
+      function Process (N : Node_Id) return Traverse_Result is
+      begin
+         --  If user has specified that there are no entry calls in elaboration
+         --  code, do not trace past an accept statement, because the rendez-
+         --  vous will happen after elaboration.
+
+         if (Nkind (Original_Node (N)) = N_Accept_Statement
+              or else Nkind (Original_Node (N)) = N_Selective_Accept)
+           and then Restrictions (No_Entry_Calls_In_Elaboration_Code)
+         then
+            return Abandon;
+
+         --  If we have a subprogram call, check it
+
+         elsif Nkind (N) = N_Function_Call
+           or else Nkind (N) = N_Procedure_Call_Statement
+         then
+            Check_Elab_Call (N, Outer_Scope);
+            return OK;
+
+         --  If we have a generic instantiation, check it
+
+         elsif Nkind (N) in N_Generic_Instantiation then
+            Check_Elab_Instantiation (N, Outer_Scope);
+            return OK;
+
+         --  Skip subprogram bodies that come from source (wait for
+         --  call to analyze these). The reason for the come from
+         --  source test is to avoid catching task bodies.
+
+         --  For task bodies, we should really avoid these too, waiting
+         --  for the task activation, but that's too much trouble to
+         --  catch for now, so we go in unconditionally. This is not
+         --  so terrible, it means the error backtrace is not quite
+         --  complete, and we are too eager to scan bodies of tasks
+         --  that are unused, but this is hardly very significant!
+
+         elsif Nkind (N) = N_Subprogram_Body
+           and then Comes_From_Source (N)
+         then
+            return Skip;
+
+         else
+            return OK;
+         end if;
+      end Process;
+
+      procedure Traverse is new Atree.Traverse_Proc;
+      --  Traverse procedure using above Process function
+
+   --  Start of processing for Check_Internal_Call_Continue
+
+   begin
+      --  Save outer level call if at outer level
+
+      if Elab_Call.Last = 0 then
+         Outer_Level_Sloc := Loc;
+      end if;
+
+      Elab_Visited.Increment_Last;
+      Elab_Visited.Table (Elab_Visited.Last) := E;
+
+      --  If the call is to a function that renames a literal, no check
+      --  is needed.
+
+      if Ekind (E) = E_Enumeration_Literal then
+         return;
+      end if;
+
+      Sbody := Unit_Declaration_Node (E);
+
+      if Nkind (Sbody) /= N_Subprogram_Body
+           and then
+         Nkind (Sbody) /= N_Package_Body
+      then
+         Ebody := Corresponding_Body (Sbody);
+
+         if No (Ebody) then
+            return;
+         else
+            Sbody := Unit_Declaration_Node (Ebody);
+         end if;
+      end if;
+
+      --  If the body appears after the outer level call or
+      --  instantiation then we have an error case handled below.
+
+      if Earlier_In_Extended_Unit (Outer_Level_Sloc, Sloc (Sbody))
+        and then not In_Task_Activation
+      then
+         null;
+
+      --  If we have the instantiation case we are done, since we now
+      --  know that the body of the generic appeared earlier.
+
+      elsif Inst_Case then
+         return;
+
+      --  Otherwise we have a call, so we trace through the called
+      --  body to see if it has any problems ..
+
+      else
+         pragma Assert (Nkind (Sbody) = N_Subprogram_Body);
+
+         Elab_Call.Increment_Last;
+         Elab_Call.Table (Elab_Call.Last).Cloc := Loc;
+         Elab_Call.Table (Elab_Call.Last).Ent  := E;
+
+         if Debug_Flag_LL then
+            Write_Str ("Elab_Call.Last = ");
+            Write_Int (Int (Elab_Call.Last));
+            Write_Str ("   Ent = ");
+            Write_Name (Chars (E));
+            Write_Str ("   at ");
+            Write_Location (Sloc (N));
+            Write_Eol;
+         end if;
+
+         --  Now traverse declarations and statements of subprogram body.
+         --  Note that we cannot simply Traverse (Sbody), since traverse
+         --  does not normally visit subprogram bodies.
+
+         declare
+            Decl : Node_Id := First (Declarations (Sbody));
+
+         begin
+            while Present (Decl) loop
+               Traverse (Decl);
+               Next (Decl);
+            end loop;
+         end;
+
+         Traverse (Handled_Statement_Sequence (Sbody));
+
+         Elab_Call.Decrement_Last;
+         return;
+      end if;
+
+      --  Here is the case of calling a subprogram where the body has
+      --  not yet been encountered, a warning message is needed.
+
+      Warn_On_Instance := True;
+
+      --  If we have nothing in the call stack, then this is at the
+      --  outer level, and the ABE is bound to occur.
+
+      if Elab_Call.Last = 0 then
+
+         if Inst_Case then
+            Error_Msg_NE
+              ("?cannot instantiate& before body seen", N, Orig_Ent);
+         else
+            Error_Msg_NE
+              ("?cannot call& before body seen", N, Orig_Ent);
+         end if;
+
+         Error_Msg_N
+           ("\?Program_Error will be raised at run time", N);
+         Insert_Elab_Check (N);
+
+      --  Call is not at outer level
+
+      else
+         --  Deal with dynamic elaboration check
+
+         if not Elaboration_Checks_Suppressed (E) then
+            Set_Elaboration_Entity_Required (E);
+
+            --  Case of no elaboration entity allocated yet
+
+            if No (Elaboration_Entity (E)) then
+
+               --  Create object declaration for elaboration entity, and put it
+               --  just in front of the spec of the subprogram or generic unit,
+               --  in the same scope as this unit.
+
+               declare
+                  Loce : constant Source_Ptr := Sloc (E);
+                  Ent  : constant Entity_Id  :=
+                           Make_Defining_Identifier (Loc,
+                             Chars => New_External_Name (Chars (E), 'E'));
+
+               begin
+                  Set_Elaboration_Entity (E, Ent);
+                  New_Scope (Scope (E));
+
+                  Insert_Action (Declaration_Node (E),
+                    Make_Object_Declaration (Loce,
+                      Defining_Identifier => Ent,
+                      Object_Definition =>
+                        New_Occurrence_Of (Standard_Boolean, Loce),
+                      Expression => New_Occurrence_Of (Standard_False, Loce)));
+
+                  --  Set elaboration flag at the point of the body
+
+                  Set_Elaboration_Flag (Sbody, E);
+
+                  Pop_Scope;
+               end;
+            end if;
+
+            --  Generate check of the elaboration Boolean
+
+            Insert_Elab_Check (N,
+              New_Occurrence_Of (Elaboration_Entity (E), Loc));
+         end if;
+
+         --  Generate the warning
+
+         if not Suppress_Elaboration_Warnings (E) then
+            if Inst_Case then
+               Error_Msg_NE
+                 ("instantiation of& may occur before body is seen?",
+                  N, Orig_Ent);
+            else
+               Error_Msg_NE
+                 ("call to& may occur before body is seen?", N, Orig_Ent);
+            end if;
+
+            Error_Msg_N
+              ("\Program_Error may be raised at run time?", N);
+
+            Output_Calls (N);
+         end if;
+      end if;
+
+      Warn_On_Instance := False;
+
+      --  Set flag to suppress further warnings on same subprogram
+      --  unless in all errors mode
+
+      if not All_Errors_Mode then
+         Set_Suppress_Elaboration_Warnings (E);
+      end if;
+   end Check_Internal_Call_Continue;
+
+   ----------------------------
+   --  Check_Task_Activation --
+   ----------------------------
+
+   procedure Check_Task_Activation (N : Node_Id) is
+      Loc         : constant Source_Ptr := Sloc (N);
+      Ent         : Entity_Id;
+      P           : Entity_Id;
+      Task_Scope  : Entity_Id;
+      Cunit_SC    : Boolean := False;
+      Decl        : Node_Id;
+      Elmt        : Elmt_Id;
+      Inter_Procs : Elist_Id := New_Elmt_List;
+      Intra_Procs : Elist_Id := New_Elmt_List;
+      Enclosing   : Entity_Id;
+
+      procedure Add_Task_Proc (Typ : Entity_Id);
+      --  Add to Task_Procs the task body procedure(s) of task types in Typ.
+      --  For record types, this procedure recurses over component types.
+
+      procedure Collect_Tasks (Decls : List_Id);
+      --  Collect the types of the tasks that are to be activated in the given
+      --  list of declarations, in order to perform elaboration checks on the
+      --  corresponding task procedures which are called implicitly here.
+
+      function Outer_Unit (E : Entity_Id) return Entity_Id;
+      --  find enclosing compilation unit of Entity, ignoring subunits, or
+      --  else enclosing subprogram. If E is not a package, there is no need
+      --  for inter-unit elaboration checks.
+
+      -------------------
+      -- Add_Task_Proc --
+      -------------------
+
+      procedure Add_Task_Proc (Typ : Entity_Id) is
+         Comp : Entity_Id;
+         Proc : Entity_Id := Empty;
+
+      begin
+         if Is_Task_Type (Typ) then
+            Proc := Get_Task_Body_Procedure (Typ);
+
+         elsif Is_Array_Type (Typ)
+           and then Has_Task (Base_Type (Typ))
+         then
+            Add_Task_Proc (Component_Type (Typ));
+
+         elsif Is_Record_Type (Typ)
+           and then Has_Task (Base_Type (Typ))
+         then
+            Comp := First_Component (Typ);
+
+            while Present (Comp) loop
+               Add_Task_Proc (Etype (Comp));
+               Comp := Next_Component (Comp);
+            end loop;
+         end if;
+
+         --  If the task type is another unit, we will perform the usual
+         --  elaboration check on its enclosing unit. If the type is in the
+         --  same unit, we can trace the task body as for an internal call,
+         --  but we only need to examine other external calls, because at
+         --  the point the task is activated, internal subprogram bodies
+         --  will have been elaborated already. We keep separate lists for
+         --  each kind of task.
+
+         if Present (Proc) then
+            if Outer_Unit (Scope (Proc)) = Enclosing then
+
+               if No (Corresponding_Body (Unit_Declaration_Node (Proc)))
+                 and then
+                   (not Is_Generic_Instance (Scope (Proc))
+                      or else
+                    Scope (Proc) = Scope (Defining_Identifier (Decl)))
+               then
+                  Error_Msg_N
+                    ("task will be activated before elaboration of its body?",
+                      Decl);
+                  Error_Msg_N
+                    ("Program_Error will be raised at run-time?", Decl);
+
+               elsif
+                 Present (Corresponding_Body (Unit_Declaration_Node (Proc)))
+               then
+                  Append_Elmt (Proc, Intra_Procs);
+               end if;
+
+            else
+               Elmt := First_Elmt (Inter_Procs);
+
+               --  No need for multiple entries of the same type.
+
+               while Present (Elmt) loop
+                  if Node (Elmt) = Proc then
+                     return;
+                  end if;
+
+                  Next_Elmt (Elmt);
+               end loop;
+
+               Append_Elmt (Proc, Inter_Procs);
+            end if;
+         end if;
+      end Add_Task_Proc;
+
+      -------------------
+      -- Collect_Tasks --
+      -------------------
+
+      procedure Collect_Tasks (Decls : List_Id) is
+      begin
+         if Present (Decls) then
+            Decl := First (Decls);
+
+            while Present (Decl) loop
+
+               if Nkind (Decl) = N_Object_Declaration
+                 and then Has_Task (Etype (Defining_Identifier (Decl)))
+               then
+                  Add_Task_Proc (Etype (Defining_Identifier (Decl)));
+               end if;
+
+               Next (Decl);
+            end loop;
+         end if;
+      end Collect_Tasks;
+
+      ----------------
+      -- Outer_Unit --
+      ----------------
+
+      function Outer_Unit (E : Entity_Id) return Entity_Id is
+         Outer : Entity_Id := E;
+
+      begin
+         while Present (Outer) loop
+            if Suppress_Elaboration_Checks (Outer) then
+               Cunit_SC := True;
+            end if;
+
+            exit when Is_Child_Unit (Outer)
+              or else Scope (Outer) = Standard_Standard
+              or else Ekind (Outer) /= E_Package;
+            Outer := Scope (Outer);
+         end loop;
+
+         return Outer;
+      end Outer_Unit;
+
+   --  Start of processing for Check_Task_Activation
+
+   begin
+      Enclosing := Outer_Unit (Current_Scope);
+
+      --  Find all tasks declared in the current unit.
+
+      if Nkind (N) = N_Package_Body then
+         P := Unit_Declaration_Node (Corresponding_Spec (N));
+
+         Collect_Tasks (Declarations (N));
+         Collect_Tasks (Visible_Declarations (Specification (P)));
+         Collect_Tasks (Private_Declarations (Specification (P)));
+
+      elsif Nkind (N) = N_Package_Declaration then
+         Collect_Tasks (Visible_Declarations (Specification (N)));
+         Collect_Tasks (Private_Declarations (Specification (N)));
+
+      else
+         Collect_Tasks (Declarations (N));
+      end if;
+
+      --  We only perform detailed checks in all tasks are library level
+      --  entities. If the master is a subprogram or task, activation will
+      --  depend on the activation of the master itself.
+      --  Should dynamic checks be added in the more general case???
+
+      if Ekind (Enclosing) /= E_Package then
+         return;
+      end if;
+
+      --  For task types defined in other units, we want the unit containing
+      --  the task body to be elaborated before the current one.
+
+      Elmt := First_Elmt (Inter_Procs);
+
+      while Present (Elmt) loop
+         Ent := Node (Elmt);
+         Task_Scope := Outer_Unit (Scope (Ent));
+
+         if not Is_Compilation_Unit (Task_Scope) then
+            null;
+
+         elsif Suppress_Elaboration_Warnings (Task_Scope) then
+            null;
+
+         elsif Dynamic_Elaboration_Checks then
+            if not Elaboration_Checks_Suppressed (Ent)
+              and then not Cunit_SC
+              and then not Restrictions (No_Entry_Calls_In_Elaboration_Code)
+            then
+               --  Runtime elaboration check required. generate check of the
+               --  elaboration Boolean for the unit containing the entity.
+
+               Insert_Elab_Check (N,
+                 Make_Attribute_Reference (Loc,
+                   Attribute_Name => Name_Elaborated,
+                   Prefix =>
+                     New_Occurrence_Of
+                       (Spec_Entity (Task_Scope), Loc)));
+            end if;
+
+         else
+            --  Force the binder to elaborate other unit first.
+
+            if not Suppress_Elaboration_Warnings (Ent)
+              and then Elab_Warnings
+              and then not Suppress_Elaboration_Warnings (Task_Scope)
+            then
+               Error_Msg_Node_2 := Task_Scope;
+               Error_Msg_NE ("activation of an instance of task type&" &
+                  " requires pragma Elaborate_All on &?", N, Ent);
+            end if;
+
+            Set_Elaborate_All_Desirable (Task_Scope);
+            Set_Suppress_Elaboration_Warnings (Task_Scope);
+         end if;
+
+         Next_Elmt (Elmt);
+      end loop;
+
+      --  For tasks declared in the current unit, trace other calls within
+      --  the task procedure bodies, which are available.
+
+      In_Task_Activation := True;
+      Elmt := First_Elmt (Intra_Procs);
+
+      while Present (Elmt) loop
+         Ent := Node (Elmt);
+         Check_Internal_Call_Continue (N, Ent, Enclosing, Ent);
+         Next_Elmt (Elmt);
+      end loop;
+
+      In_Task_Activation := False;
+   end Check_Task_Activation;
+
+   ----------------------
+   -- Has_Generic_Body --
+   ----------------------
+
+   function Has_Generic_Body (N : Node_Id) return Boolean is
+      Ent  : constant Entity_Id := Entity (Name (N));
+      Decl : constant Node_Id   := Unit_Declaration_Node (Ent);
+      Scop : Entity_Id;
+
+      function Find_Body_In (E : Entity_Id; N : Node_Id) return Node_Id;
+      --  Determine if the list of nodes headed by N and linked by Next
+      --  contains a package body for the package spec entity E, and if
+      --  so return the package body. If not, then returns Empty.
+
+      function Load_Package_Body (Nam : Unit_Name_Type) return Node_Id;
+      --  This procedure is called load the unit whose name is given by Nam.
+      --  This unit is being loaded to see whether it contains an optional
+      --  generic body. The returned value is the loaded unit, which is
+      --  always a package body (only package bodies can contain other
+      --  entities in the sense in which Has_Generic_Body is interested).
+      --  We only attempt to load bodies if we are generating code. If we
+      --  are in semantics check only mode, then it would be wrong to load
+      --  bodies that are not required from a semantic point of view, so
+      --  in this case we return Empty. The result is that the caller may
+      --  incorrectly decide that a generic spec does not have a body when
+      --  in fact it does, but the only harm in this is that some warnings
+      --  on elaboration problems may be lost in semantic checks only mode,
+      --  which is not big loss. We also return Empty if we go for a body
+      --  and it is not there.
+
+      function Locate_Corresponding_Body (PE : Entity_Id) return Node_Id;
+      --  PE is the entity for a package spec. This function locates the
+      --  corresponding package body, returning Empty if none is found.
+      --  The package body returned is fully parsed but may not yet be
+      --  analyzed, so only syntactic fields should be referenced.
+
+      ------------------
+      -- Find_Body_In --
+      ------------------
+
+      function Find_Body_In (E : Entity_Id; N : Node_Id) return Node_Id is
+         Nod : Node_Id;
+
+      begin
+         Nod := N;
+         while Present (Nod) loop
+
+            --  If we found the package body we are looking for, return it
+
+            if Nkind (Nod) = N_Package_Body
+              and then Chars (Defining_Unit_Name (Nod)) = Chars (E)
+            then
+               return Nod;
+
+            --  If we found the stub for the body, go after the subunit,
+            --  loading it if necessary.
+
+            elsif Nkind (Nod) = N_Package_Body_Stub
+              and then Chars (Defining_Identifier (Nod)) = Chars (E)
+            then
+               if Present (Library_Unit (Nod)) then
+                  return Unit (Library_Unit (Nod));
+
+               else
+                  return Load_Package_Body (Get_Unit_Name (Nod));
+               end if;
+
+            --  If neither package body nor stub, keep looking on chain
+
+            else
+               Next (Nod);
+            end if;
+         end loop;
+
+         return Empty;
+      end Find_Body_In;
+
+      -----------------------
+      -- Load_Package_Body --
+      -----------------------
+
+      function Load_Package_Body (Nam : Unit_Name_Type) return Node_Id is
+         U : Unit_Number_Type;
+
+      begin
+         if Operating_Mode /= Generate_Code then
+            return Empty;
+         else
+            U :=
+              Load_Unit
+                (Load_Name  => Nam,
+                 Required   => False,
+                 Subunit    => False,
+                 Error_Node => N);
+
+            if U = No_Unit then
+               return Empty;
+            else
+               return Unit (Cunit (U));
+            end if;
+         end if;
+      end Load_Package_Body;
+
+      -------------------------------
+      -- Locate_Corresponding_Body --
+      -------------------------------
+
+      function Locate_Corresponding_Body (PE : Entity_Id) return Node_Id is
+         Spec  : constant Node_Id   := Declaration_Node (PE);
+         Decl  : constant Node_Id   := Parent (Spec);
+         Scop  : constant Entity_Id := Scope (PE);
+         PBody : Node_Id;
+
+      begin
+         if Is_Library_Level_Entity (PE) then
+
+            --  If package is a library unit that requires a body, we have
+            --  no choice but to go after that body because it might contain
+            --  an optional body for the original generic package.
+
+            if Unit_Requires_Body (PE) then
+
+               --  Load the body. Note that we are a little careful here to
+               --  use Spec to get the unit number, rather than PE or Decl,
+               --  since in the case where the package is itself a library
+               --  level instantiation, Spec will properly reference the
+               --  generic template, which is what we really want.
+
+               return
+                 Load_Package_Body
+                   (Get_Body_Name (Unit_Name (Get_Source_Unit (Spec))));
+
+            --  But if the package is a library unit that does NOT require
+            --  a body, then no body is permitted, so we are sure that there
+            --  is no body for the original generic package.
+
+            else
+               return Empty;
+            end if;
+
+         --  Otherwise look and see if we are embedded in a further package
+
+         elsif Is_Package (Scop) then
+
+            --  If so, get the body of the enclosing package, and look in
+            --  its package body for the package body we are looking for.
+
+            PBody := Locate_Corresponding_Body (Scop);
+
+            if No (PBody) then
+               return Empty;
+            else
+               return Find_Body_In (PE, First (Declarations (PBody)));
+            end if;
+
+         --  If we are not embedded in a further package, then the body
+         --  must be in the same declarative part as we are.
+
+         else
+            return Find_Body_In (PE, Next (Decl));
+         end if;
+      end Locate_Corresponding_Body;
+
+   --  Start of processing for Has_Generic_Body
+
+   begin
+      if Present (Corresponding_Body (Decl)) then
+         return True;
+
+      elsif Unit_Requires_Body (Ent) then
+         return True;
+
+      --  Compilation units cannot have optional bodies
+
+      elsif Is_Compilation_Unit (Ent) then
+         return False;
+
+      --  Otherwise look at what scope we are in
+
+      else
+         Scop := Scope (Ent);
+
+         --  Case of entity is in other than a package spec, in this case
+         --  the body, if present, must be in the same declarative part.
+
+         if not Is_Package (Scop) then
+            declare
+               P : Node_Id;
+
+            begin
+               P := Declaration_Node (Ent);
+
+               --  Declaration node may get us a spec, so if so, go to
+               --  the parent declaration.
+
+               while not Is_List_Member (P) loop
+                  P := Parent (P);
+               end loop;
+
+               return Present (Find_Body_In (Ent, Next (P)));
+            end;
+
+         --  If the entity is in a package spec, then we have to locate
+         --  the corresponding package body, and look there.
+
+         else
+            declare
+               PBody : constant Node_Id := Locate_Corresponding_Body (Scop);
+
+            begin
+               if No (PBody) then
+                  return False;
+               else
+                  return
+                    Present
+                      (Find_Body_In (Ent, (First (Declarations (PBody)))));
+               end if;
+            end;
+         end if;
+      end if;
+   end Has_Generic_Body;
+
+   -----------------------
+   -- Insert_Elab_Check --
+   -----------------------
+
+   procedure Insert_Elab_Check (N : Node_Id; C : Node_Id := Empty) is
+      Nod : Node_Id;
+      Loc : constant Source_Ptr := Sloc (N);
+
+   begin
+      --  If expansion is disabled, do not generate any checks. Also
+      --  skip checks if any subunits are missing because in either
+      --  case we lack the full information that we need, and no object
+      --  file will be created in any case.
+
+      if not Expander_Active or else Subunits_Missing then
+         return;
+      end if;
+
+      --  If we have a generic instantiation, where Instance_Spec is set,
+      --  then this field points to a generic instance spec that has
+      --  been inserted before the instantiation node itself, so that
+      --  is where we want to insert a check.
+
+      if Nkind (N) in N_Generic_Instantiation
+        and then Present (Instance_Spec (N))
+      then
+         Nod := Instance_Spec (N);
+      else
+         Nod := N;
+      end if;
+
+      --  If we are inserting at the top level, insert in Aux_Decls
+
+      if Nkind (Parent (Nod)) = N_Compilation_Unit then
+         declare
+            ADN : constant Node_Id := Aux_Decls_Node (Parent (Nod));
+            R   : Node_Id;
+
+         begin
+            if No (C) then
+               R :=  Make_Raise_Program_Error (Loc);
+            else
+               R := Make_Raise_Program_Error (Loc, Make_Op_Not (Loc, C));
+            end if;
+
+            if No (Declarations (ADN)) then
+               Set_Declarations (ADN, New_List (R));
+            else
+               Append_To (Declarations (ADN), R);
+            end if;
+
+            Analyze (R);
+         end;
+
+      --  Otherwise just insert before the node in question. However, if
+      --  the context of the call has already been analyzed, an insertion
+      --  will not work if it depends on subsequent expansion (e.g. a call in
+      --  a branch of a short-circuit). In that case we replace the call with
+      --  a conditional expression, or with a Raise if it is unconditional.
+      --  Unfortunately this does not work if the call has a dynamic size,
+      --  because gigi regards it as a dynamic-sized temporary. If such a call
+      --  appears in a short-circuit expression, the elaboration check will be
+      --  missed (rare enough ???).
+
+      else
+         if Nkind (N) = N_Function_Call
+           and then Analyzed (Parent (N))
+           and then Size_Known_At_Compile_Time (Etype (N))
+         then
+            declare
+               Typ : constant Entity_Id := Etype (N);
+               R   : constant Node_Id   := Make_Raise_Program_Error (Loc);
+               Chk : constant Boolean   := Do_Range_Check (N);
+
+            begin
+               Set_Etype (R, Typ);
+
+               if No (C) then
+                  Rewrite (N, R);
+
+               else
+                  Rewrite (N,
+                    Make_Conditional_Expression (Loc,
+                      Expressions => New_List (C, Relocate_Node (N), R)));
+               end if;
+
+               Analyze_And_Resolve (N, Typ);
+
+               --  If the original call requires a range check, so does the
+               --  conditional expression.
+
+               if Chk then
+                  Enable_Range_Check (N);
+               else
+                  Set_Do_Range_Check (N, False);
+               end if;
+            end;
+
+         else
+            if No (C) then
+               Insert_Action (Nod,
+                  Make_Raise_Program_Error (Loc));
+            else
+               Insert_Action (Nod,
+                  Make_Raise_Program_Error (Loc,
+                    Condition =>
+                      Make_Op_Not (Loc,
+                        Right_Opnd => C)));
+            end if;
+         end if;
+      end if;
+   end Insert_Elab_Check;
+
+   ------------------
+   -- Output_Calls --
+   ------------------
+
+   procedure Output_Calls (N : Node_Id) is
+      Ent : Entity_Id;
+
+      function Is_Printable_Error_Name (Nm : Name_Id) return Boolean;
+      --  An internal function, used to determine if a name, Nm, is either
+      --  a non-internal name, or is an internal name that is printable
+      --  by the error message circuits (i.e. it has a single upper
+      --  case letter at the end).
+
+      function Is_Printable_Error_Name (Nm : Name_Id) return Boolean is
+      begin
+         if not Is_Internal_Name (Nm) then
+            return True;
+
+         elsif Name_Len = 1 then
+            return False;
+
+         else
+            Name_Len := Name_Len - 1;
+            return not Is_Internal_Name;
+         end if;
+      end Is_Printable_Error_Name;
+
+   --  Start of processing for Output_Calls
+
+   begin
+      for J in reverse 1 .. Elab_Call.Last loop
+         Error_Msg_Sloc := Elab_Call.Table (J).Cloc;
+
+         Ent := Elab_Call.Table (J).Ent;
+
+         if Is_Generic_Unit (Ent) then
+            Error_Msg_NE ("\?& instantiated #", N, Ent);
+
+         elsif Chars (Ent) = Name_uInit_Proc then
+            Error_Msg_N ("\?initialization procedure called #", N);
+
+         elsif Is_Printable_Error_Name (Chars (Ent)) then
+            Error_Msg_NE ("\?& called #", N, Ent);
+
+         else
+            Error_Msg_N ("\? called #", N);
+         end if;
+      end loop;
+   end Output_Calls;
+
+   ----------------------------
+   -- Same_Elaboration_Scope --
+   ----------------------------
+
+   function Same_Elaboration_Scope (Scop1, Scop2 : Entity_Id) return Boolean is
+      S1 : Entity_Id := Scop1;
+      S2 : Entity_Id := Scop2;
+
+   begin
+      while S1 /= Standard_Standard
+        and then (Ekind (S1) = E_Package
+                    or else
+                  Ekind (S1) = E_Block)
+      loop
+         S1 := Scope (S1);
+      end loop;
+
+      while S2 /= Standard_Standard
+        and then (Ekind (S2) = E_Package
+                    or else
+                  Ekind (S2) = E_Protected_Type
+                    or else
+                  Ekind (S2) = E_Block)
+      loop
+         S2 := Scope (S2);
+      end loop;
+
+      return S1 = S2;
+   end Same_Elaboration_Scope;
+
+   -----------------
+   -- Set_C_Scope --
+   -----------------
+
+   procedure Set_C_Scope is
+   begin
+      while not Is_Compilation_Unit (C_Scope) loop
+         C_Scope := Scope (C_Scope);
+      end loop;
+   end Set_C_Scope;
+
+   -----------------
+   -- Spec_Entity --
+   -----------------
+
+   function Spec_Entity (E : Entity_Id) return Entity_Id is
+      Decl : Node_Id;
+
+   begin
+      --  Check for case of body entity
+      --  Why is the check for E_Void needed???
+
+      if Ekind (E) = E_Void
+        or else Ekind (E) = E_Subprogram_Body
+        or else Ekind (E) = E_Package_Body
+      then
+         Decl := E;
+
+         loop
+            Decl := Parent (Decl);
+            exit when Nkind (Decl) in N_Proper_Body;
+         end loop;
+
+         return Corresponding_Spec (Decl);
+
+      else
+         return E;
+      end if;
+   end Spec_Entity;
+
+   -------------------
+   -- Supply_Bodies --
+   -------------------
+
+   procedure Supply_Bodies (N : Node_Id) is
+   begin
+      if Nkind (N) = N_Subprogram_Declaration then
+         declare
+            Ent : constant Entity_Id := Defining_Unit_Name (Specification (N));
+
+         begin
+            Set_Is_Imported (Ent);
+            Set_Convention  (Ent, Convention_Stubbed);
+         end;
+
+      elsif Nkind (N) = N_Package_Declaration then
+         declare
+            Spec : constant Node_Id := Specification (N);
+
+         begin
+            New_Scope (Defining_Unit_Name (Spec));
+            Supply_Bodies (Visible_Declarations (Spec));
+            Supply_Bodies (Private_Declarations (Spec));
+            Pop_Scope;
+         end;
+      end if;
+   end Supply_Bodies;
+
+   procedure Supply_Bodies (L : List_Id) is
+      Elmt : Node_Id;
+
+   begin
+      if Present (L) then
+         Elmt := First (L);
+         while Present (Elmt) loop
+            Supply_Bodies (Elmt);
+            Next (Elmt);
+         end loop;
+      end if;
+   end Supply_Bodies;
+
+   ------------
+   -- Within --
+   ------------
+
+   function Within (E1, E2 : Entity_Id) return Boolean is
+      Scop : Entity_Id;
+
+   begin
+      Scop := E1;
+
+      loop
+         if Scop = E2 then
+            return True;
+
+         elsif Scop = Standard_Standard then
+            return False;
+
+         else
+            Scop := Scope (Scop);
+         end if;
+      end loop;
+
+      raise Program_Error;
+   end Within;
+
+end Sem_Elab;
diff --git a/gcc/ada/sem_elab.ads b/gcc/ada/sem_elab.ads
new file mode 100644 (file)
index 0000000..87071c2
--- /dev/null
@@ -0,0 +1,156 @@
+------------------------------------------------------------------------------
+--                                                                          --
+--                         GNAT COMPILER COMPONENTS                         --
+--                                                                          --
+--                             S E M _ E L A B                              --
+--                                                                          --
+--                                 S p e c                                  --
+--                                                                          --
+--                            $Revision: 1.8 $
+--                                                                          --
+--          Copyright (C) 1997-2001 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- --
+-- ware  Foundation;  either version 2,  or (at your option) any later ver- --
+-- sion.  GNAT is distributed in the hope that it will be useful, but WITH- --
+-- OUT ANY WARRANTY;  without even the  implied warranty of MERCHANTABILITY --
+-- or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License --
+-- for  more details.  You should have  received  a copy of the GNU General --
+-- Public License  distributed with GNAT;  see file COPYING.  If not, write --
+-- to  the Free Software Foundation,  59 Temple Place - Suite 330,  Boston, --
+-- MA 02111-1307, USA.                                                      --
+--                                                                          --
+-- GNAT was originally developed  by the GNAT team at  New York University. --
+-- It is now maintained by Ada Core Technologies Inc (http://www.gnat.com). --
+--                                                                          --
+------------------------------------------------------------------------------
+
+--  This package contains the routines used to deal with issuing warnings
+--  for cases of calls that may require warnings about possible access
+--  before elaboration.
+
+with Types; use Types;
+
+package Sem_Elab is
+
+   -----------------------------
+   -- Description of Approach --
+   -----------------------------
+
+   --  Every non-static call that is encountered by Sem_Res results in
+   --  a call to Check_Elab_Call, with N being the call node, and Outer
+   --  set to its default value of True.
+
+   --  The goal of Check_Elab_Call is to determine whether or not the
+   --  call in question can generate an access before elaboration
+   --  error (raising Program_Error) either by directly calling a
+   --  subprogram whose body has not yet been elaborated, or indirectly,
+   --  by calling a subprogram whose body has been elaborated, but which
+   --  contains a call to such a subprogram.
+
+   --  The only calls that we need to look at at the outer level are
+   --  calls that occur in elaboration code. There are two cases. The
+   --  call can be at the outer level of elaboration code, or it can
+   --  be within another unit, e.g. the elaboration code of a subprogram.
+
+   --  In the case of an elaboration call at the outer level, we must
+   --  trace all calls to outer level routines either within the current
+   --  unit or to other units that are with'ed. For calls within the
+   --  current unit, we can determine if the body has been elaborated
+   --  or not, and if it has not, then a warning is generated.
+
+   --  Note that there are two subcases. If the original call directly
+   --  calls a subprogram whose body has not been elaborated, then we
+   --  know that an ABE will take place, and we replace the call by
+   --  a raise of Program_Error. If the call is indirect, then we don't
+   --  know that the PE will be raised, since the call might be guarded
+   --  by a conditional. In this case we set Do_Elab_Check on the call
+   --  so that a dynamic check is generated, and output a warning.
+
+   --  For calls to a subprogram in a with'ed unit, we require that
+   --  a pragma Elaborate_All or pragma Elaborate be present, or that
+   --  the referenced unit have a pragma Preelaborate, pragma Pure, or
+   --  pragma Elaborate_Body. If none of these conditions is met, then
+   --  a warning is generated that a pragma Elaborate_All may be needed.
+
+   --  For the case of an elaboration call at some inner level, we are
+   --  interested in tracing only calls to subprograms at the same level,
+   --  i.e. those that can be called during elaboration. Any calls to
+   --  outer level routines cannot cause ABE's as a result of the original
+   --  call (there might be an outer level call to the subprogram from
+   --  outside that causes the ABE, but that gets analyzed separately).
+
+   --  Note that we never trace calls to inner level subprograms, since
+   --  these cannot result in ABE's unless there is an elaboration problem
+   --  at a lower level, which will be separately detected.
+
+   --  Note on pragma Elaborate. The checking here assumes that a pragma
+   --  Elaborate on a with'ed unit guarantees that subprograms within the
+   --  unit can be called without causing an ABE. This is not in fact the
+   --  case since pragma Elaborate does not guarantee the transititive
+   --  coverage guaranteed by Elaborate_All. However, we leave this issue
+   --  up to the binder, which has generates warnings if there are possible
+   --  problems in the use of pragma Elaborate.
+
+   --------------------------------------
+   -- Instantiation Elaboration Errors --
+   --------------------------------------
+
+   --  A special case arises when an instantiation appears in a context
+   --  that is known to be before the body is elaborated, e.g.
+
+   --       generic package x is ...
+   --       ...
+   --       package xx is new x;
+   --       ...
+   --       package body x is ...
+
+   --  In this situation it is certain that an elaboration error will
+   --  occur, and an unconditional raise Program_Error statement is
+   --  inserted before the instantiation, and a warning generated.
+
+   --  The problem is that in this case we have no place to put the
+   --  body of the instantiation. We can't put it in the normal place,
+   --  because it is too early, and will cause errors to occur as a
+   --  result of referencing entities before they are declared.
+
+   --  Our approach in this case is simply to avoid creating the body
+   --  of the instantiation in such a case. The instantiation spec is
+   --  modified to include dummy bodies for all subprograms, so that
+   --  the resulting code does not contain subprogram specs with no
+   --  corresponding bodies.
+
+   procedure Check_Elab_Call (N : Node_Id; Outer_Scope : Entity_Id := Empty);
+   --  Check a call for possible elaboration problems. N is either an
+   --  N_Function_Call or N_Procedure_Call_Statement node, and Outer
+   --  indicates whether this is an outer level call from Sem_Res
+   --  (Outer_Scope set to Empty), or an internal recursive call
+   --  (Outer_Scope set to entity of outermost call, see body).
+
+   procedure Check_Elab_Calls;
+   --  Not all the processing for Check_Elab_Call can be done at the time
+   --  of calls to Check_Elab_Call. This is because for internal calls, we
+   --  need to wait to complete the check until all generic bodies have been
+   --  instantiated. The Check_Elab_Calls procedure cleans up these waiting
+   --  checks. It is called once after the completion of instantiation.
+
+   procedure Check_Elab_Instantiation
+     (N           : Node_Id;
+      Outer_Scope : Entity_Id := Empty);
+   --  Check an instantiation for possible elaboration problems. N is an
+   --  instantiation node (N_Package_Instantiation, N_Function_Instantiation,
+   --  or N_Procedure_Instantiation), and Outer_Scope indicates if this is
+   --  an outer level call from Sem_Ch12 (Outer_Scope set to Empty), or an
+   --  internal recursive call (Outer_Scope set to scope of outermost call,
+   --  see body for further details). The returned value is relevant only
+   --  for an outer level call, and is set to False if an elaboration error
+   --  is bound to occur on the instantiation, and True otherwise. This is
+   --  used by the caller to signal that the body of the instance should
+   --  not be generated (see detailed description in body).
+
+   procedure Check_Task_Activation (N : Node_Id);
+   --  at the point at which tasks are activated in a package body, check
+   --  that the bodies of the tasks are elaborated.
+
+end Sem_Elab;
diff --git a/gcc/ada/sem_elim.adb b/gcc/ada/sem_elim.adb
new file mode 100644 (file)
index 0000000..e418657
--- /dev/null
@@ -0,0 +1,557 @@
+------------------------------------------------------------------------------
+--                                                                          --
+--                         GNAT COMPILER COMPONENTS                         --
+--                                                                          --
+--                             S E M _ E L I M                              --
+--                                                                          --
+--                                 B o d y                                  --
+--                                                                          --
+--                            $Revision: 1.13 $
+--                                                                          --
+--          Copyright (C) 1997-2001 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- --
+-- ware  Foundation;  either version 2,  or (at your option) any later ver- --
+-- sion.  GNAT is distributed in the hope that it will be useful, but WITH- --
+-- OUT ANY WARRANTY;  without even the  implied warranty of MERCHANTABILITY --
+-- or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License --
+-- for  more details.  You should have  received  a copy of the GNU General --
+-- Public License  distributed with GNAT;  see file COPYING.  If not, write --
+-- to  the Free Software Foundation,  59 Temple Place - Suite 330,  Boston, --
+-- MA 02111-1307, USA.                                                      --
+--                                                                          --
+-- GNAT was originally developed  by the GNAT team at  New York University. --
+-- It is now maintained by Ada Core Technologies Inc (http://www.gnat.com). --
+--                                                                          --
+------------------------------------------------------------------------------
+
+with Atree;   use Atree;
+with Einfo;   use Einfo;
+with Errout;  use Errout;
+with Namet;   use Namet;
+with Nlists;  use Nlists;
+with Sinfo;   use Sinfo;
+with Snames;  use Snames;
+with Stand;   use Stand;
+with Stringt; use Stringt;
+
+with GNAT.HTable; use GNAT.HTable;
+package body Sem_Elim is
+
+   No_Elimination : Boolean;
+   --  Set True if no Eliminate pragmas active
+
+   ---------------------
+   -- Data Structures --
+   ---------------------
+
+   --  A single pragma Eliminate is represented by the following record
+
+   type Elim_Data;
+   type Access_Elim_Data is access Elim_Data;
+
+   type Names is array (Nat range <>) of Name_Id;
+   --  Type used to represent set of names. Used for names in Unit_Name
+   --  and also the set of names in Argument_Types.
+
+   type Access_Names is access Names;
+
+   type Elim_Data is record
+
+      Unit_Name : Access_Names;
+      --  Unit name, broken down into a set of names (e.g. A.B.C is
+      --  represented as Name_Id values for A, B, C in sequence).
+
+      Entity_Name : Name_Id;
+      --  Entity name if Entity parameter if present. If no Entity parameter
+      --  was supplied, then Entity_Node is set to Empty, and the Entity_Name
+      --  field contains the last identifier name in the Unit_Name.
+
+      Entity_Scope : Access_Names;
+      --  Static scope of the entity within the compilation unit represented by
+      --  Unit_Name.
+
+      Entity_Node : Node_Id;
+      --  Save node of entity argument, for posting error messages. Set
+      --  to Empty if there is no entity argument.
+
+      Parameter_Types : Access_Names;
+      --  Set to set of names given for parameter types. If no parameter
+      --  types argument is present, this argument is set to null.
+
+      Result_Type : Name_Id;
+      --  Result type name if Result_Types parameter present, No_Name if not
+
+      Hash_Link : Access_Elim_Data;
+      --  Link for hash table use
+
+      Homonym : Access_Elim_Data;
+      --  Pointer to next entry with same key
+
+   end record;
+
+   ----------------
+   -- Hash_Table --
+   ----------------
+
+   --  Setup hash table using the Entity_Name field as the hash key
+
+   subtype Element is Elim_Data;
+   subtype Elmt_Ptr is Access_Elim_Data;
+
+   subtype Key is Name_Id;
+
+   type Header_Num is range 0 .. 1023;
+
+   Null_Ptr : constant Elmt_Ptr := null;
+
+   ----------------------
+   -- Hash_Subprograms --
+   ----------------------
+
+   package Hash_Subprograms is
+
+      function Equal (F1, F2 : Key) return Boolean;
+      pragma Inline (Equal);
+
+      function Get_Key (E : Elmt_Ptr) return Key;
+      pragma Inline (Get_Key);
+
+      function Hash (F : Key) return Header_Num;
+      pragma Inline (Hash);
+
+      function Next (E : Elmt_Ptr) return Elmt_Ptr;
+      pragma Inline (Next);
+
+      procedure Set_Next (E : Elmt_Ptr; Next : Elmt_Ptr);
+      pragma Inline (Set_Next);
+
+   end Hash_Subprograms;
+
+   package body Hash_Subprograms is
+
+      -----------
+      -- Equal --
+      -----------
+
+      function Equal (F1, F2 : Key) return Boolean is
+      begin
+         return F1 = F2;
+      end Equal;
+
+      -------------
+      -- Get_Key --
+      -------------
+
+      function Get_Key (E : Elmt_Ptr) return Key is
+      begin
+         return E.Entity_Name;
+      end Get_Key;
+
+      ----------
+      -- Hash --
+      ----------
+
+      function Hash (F : Key) return Header_Num is
+      begin
+         return Header_Num (Int (F) mod 1024);
+      end Hash;
+
+      ----------
+      -- Next --
+      ----------
+
+      function Next (E : Elmt_Ptr) return Elmt_Ptr is
+      begin
+         return E.Hash_Link;
+      end Next;
+
+      --------------
+      -- Set_Next --
+      --------------
+
+      procedure Set_Next (E : Elmt_Ptr; Next : Elmt_Ptr) is
+      begin
+         E.Hash_Link := Next;
+      end Set_Next;
+   end Hash_Subprograms;
+
+   package Elim_Hash_Table is new Static_HTable (
+      Header_Num => Header_Num,
+      Element    => Element,
+      Elmt_Ptr   => Elmt_Ptr,
+      Null_Ptr   => Null_Ptr,
+      Set_Next   => Hash_Subprograms.Set_Next,
+      Next       => Hash_Subprograms.Next,
+      Key        => Key,
+      Get_Key    => Hash_Subprograms.Get_Key,
+      Hash       => Hash_Subprograms.Hash,
+      Equal      => Hash_Subprograms.Equal);
+
+   ----------------------
+   -- Check_Eliminated --
+   ----------------------
+
+   procedure Check_Eliminated (E : Entity_Id) is
+      Elmt : Access_Elim_Data;
+      Scop : Entity_Id;
+      Form : Entity_Id;
+
+   begin
+      if No_Elimination then
+         return;
+
+      --  Elimination of objects and types is not implemented yet.
+
+      elsif Ekind (E) not in Subprogram_Kind then
+         return;
+      end if;
+
+      Elmt := Elim_Hash_Table.Get (Chars (E));
+
+      --  Loop through homonyms for this key
+
+      while Elmt /= null loop
+
+         --  First we check that the name of the entity matches
+
+         if Elmt.Entity_Name /= Chars (E) then
+            goto Continue;
+         end if;
+
+         --  Then we need to see if the static scope matches within the
+         --  compilation unit.
+
+         Scop := Scope (E);
+         if Elmt.Entity_Scope /= null then
+            for J in reverse Elmt.Entity_Scope'Range loop
+               if Elmt.Entity_Scope (J) /= Chars (Scop) then
+                  goto Continue;
+               end if;
+
+               Scop := Scope (Scop);
+
+               if not Is_Compilation_Unit (Scop) and then J = 1 then
+                  goto Continue;
+               end if;
+            end loop;
+         end if;
+
+         --  Now see if compilation unit matches
+
+         for J in reverse Elmt.Unit_Name'Range loop
+            if Elmt.Unit_Name (J) /= Chars (Scop) then
+               goto Continue;
+            end if;
+
+            Scop := Scope (Scop);
+
+            if Scop /= Standard_Standard and then J = 1 then
+               goto Continue;
+            end if;
+         end loop;
+
+         if Scop /= Standard_Standard then
+            goto Continue;
+         end if;
+
+         --  Check for case of given entity is a library level subprogram
+         --  and we have the single parameter Eliminate case, a match!
+
+         if Is_Compilation_Unit (E)
+           and then Is_Subprogram (E)
+           and then No (Elmt.Entity_Node)
+         then
+            Set_Is_Eliminated (E);
+            return;
+
+         --  Check for case of type or object with two parameter case
+
+         elsif (Is_Type (E) or else Is_Object (E))
+           and then Elmt.Result_Type = No_Name
+           and then Elmt.Parameter_Types = null
+         then
+            Set_Is_Eliminated (E);
+            return;
+
+         --  Check for case of subprogram
+
+         elsif Ekind (E) = E_Function
+           or else Ekind (E) = E_Procedure
+         then
+            --  Two parameter case always matches
+
+            if Elmt.Result_Type = No_Name
+              and then Elmt.Parameter_Types = null
+            then
+               Set_Is_Eliminated (E);
+               return;
+
+            --  Here we have a profile, so see if it matches
+
+            else
+               if Ekind (E) = E_Function then
+                  if Chars (Etype (E)) /= Elmt.Result_Type then
+                     goto Continue;
+                  end if;
+               end if;
+
+               Form := First_Formal (E);
+
+               if No (Form) and then Elmt.Parameter_Types = null then
+                  Set_Is_Eliminated (E);
+                  return;
+
+               elsif Elmt.Parameter_Types = null then
+                  goto Continue;
+
+               else
+                  for J in Elmt.Parameter_Types'Range loop
+                     if No (Form)
+                       or else Chars (Etype (Form)) /= Elmt.Parameter_Types (J)
+                     then
+                        goto Continue;
+                     else
+                        Next_Formal (Form);
+                     end if;
+                  end loop;
+
+                  if Present (Form) then
+                     goto Continue;
+                  else
+                     Set_Is_Eliminated (E);
+                     return;
+                  end if;
+               end if;
+            end if;
+         end if;
+
+         <<Continue>> Elmt := Elmt.Homonym;
+      end loop;
+
+      return;
+   end Check_Eliminated;
+
+   ----------------
+   -- Initialize --
+   ----------------
+
+   procedure Initialize is
+   begin
+      Elim_Hash_Table.Reset;
+      No_Elimination := True;
+   end Initialize;
+
+   ------------------------------
+   -- Process_Eliminate_Pragma --
+   ------------------------------
+
+   procedure Process_Eliminate_Pragma
+     (Arg_Unit_Name       : Node_Id;
+      Arg_Entity          : Node_Id;
+      Arg_Parameter_Types : Node_Id;
+      Arg_Result_Type     : Node_Id)
+   is
+      Argx_Unit_Name       : Node_Id;
+      Argx_Entity          : Node_Id;
+      Argx_Parameter_Types : Node_Id;
+      Argx_Result_Type     : Node_Id;
+
+      Data : constant Access_Elim_Data := new Elim_Data;
+      --  Build result data here
+
+      Elmt : Access_Elim_Data;
+
+      Num_Names : Nat := 0;
+      --  Number of names in unit name
+
+      Lit : Node_Id;
+
+      function OK_Selected_Component (N : Node_Id) return Boolean;
+      --  Test if N is a selected component with all identifiers, or a
+      --  selected component whose selector is an operator symbol. As a
+      --  side effect if result is True, sets Num_Names to the number
+      --  of names present (identifiers and operator if any).
+
+      ---------------------------
+      -- OK_Selected_Component --
+      ---------------------------
+
+      function OK_Selected_Component (N : Node_Id) return Boolean is
+      begin
+         if Nkind (N) = N_Identifier
+           or else Nkind (N) = N_Operator_Symbol
+         then
+            Num_Names := Num_Names + 1;
+            return True;
+
+         elsif Nkind (N) = N_Selected_Component then
+            return OK_Selected_Component (Prefix (N))
+              and then OK_Selected_Component (Selector_Name (N));
+
+         else
+            return False;
+         end if;
+      end OK_Selected_Component;
+
+   --  Start of processing for Process_Eliminate_Pragma
+
+   begin
+      Error_Msg_Name_1 := Name_Eliminate;
+
+      --  Process Unit_Name argument
+
+      Argx_Unit_Name := Expression (Arg_Unit_Name);
+
+      if Nkind (Argx_Unit_Name) = N_Identifier then
+         Data.Unit_Name := new Names'(1 => Chars (Argx_Unit_Name));
+         Num_Names := 1;
+
+      elsif OK_Selected_Component (Argx_Unit_Name) then
+         Data.Unit_Name := new Names (1 .. Num_Names);
+
+         for J in reverse 2 .. Num_Names loop
+            Data.Unit_Name (J) := Chars (Selector_Name (Argx_Unit_Name));
+            Argx_Unit_Name := Prefix (Argx_Unit_Name);
+         end loop;
+
+         Data.Unit_Name (1) := Chars (Argx_Unit_Name);
+
+      else
+         Error_Msg_N
+           ("wrong form for Unit_Name parameter of pragma%",
+            Argx_Unit_Name);
+         return;
+      end if;
+
+      --  Process Entity argument
+
+      if Present (Arg_Entity) then
+         Argx_Entity := Expression (Arg_Entity);
+         Num_Names := 0;
+
+         if Nkind (Argx_Entity) = N_Identifier
+           or else Nkind (Argx_Entity) = N_Operator_Symbol
+         then
+            Data.Entity_Name  := Chars (Argx_Entity);
+            Data.Entity_Node  := Argx_Entity;
+            Data.Entity_Scope := null;
+
+         elsif OK_Selected_Component (Argx_Entity) then
+            Data.Entity_Scope := new Names (1 .. Num_Names - 1);
+            Data.Entity_Name  := Chars (Selector_Name (Argx_Entity));
+            Data.Entity_Node  := Argx_Entity;
+
+            Argx_Entity := Prefix (Argx_Entity);
+            for J in reverse 2 .. Num_Names - 1 loop
+               Data.Entity_Scope (J) := Chars (Selector_Name (Argx_Entity));
+               Argx_Entity := Prefix (Argx_Entity);
+            end loop;
+
+            Data.Entity_Scope (1) := Chars (Argx_Entity);
+
+         elsif Nkind (Argx_Entity) = N_String_Literal then
+            String_To_Name_Buffer (Strval (Argx_Entity));
+            Data.Entity_Name := Name_Find;
+            Data.Entity_Node := Argx_Entity;
+
+         else
+            Error_Msg_N
+              ("wrong form for Entity_Argument parameter of pragma%",
+              Argx_Unit_Name);
+            return;
+         end if;
+      else
+         Data.Entity_Node := Empty;
+         Data.Entity_Name := Data.Unit_Name (Num_Names);
+      end if;
+
+      --  Process Parameter_Types argument
+
+      if Present (Arg_Parameter_Types) then
+         Argx_Parameter_Types := Expression (Arg_Parameter_Types);
+
+         --  Case of one name, which looks like a parenthesized literal
+         --  rather than an aggregate.
+
+         if Nkind (Argx_Parameter_Types) = N_String_Literal
+           and then Paren_Count (Argx_Parameter_Types) = 1
+         then
+            String_To_Name_Buffer (Strval (Argx_Parameter_Types));
+            Data.Parameter_Types := new Names'(1 => Name_Find);
+
+         --  Otherwise must be an aggregate
+
+         elsif Nkind (Argx_Parameter_Types) /= N_Aggregate
+           or else Present (Component_Associations (Argx_Parameter_Types))
+           or else No (Expressions (Argx_Parameter_Types))
+         then
+            Error_Msg_N
+              ("Parameter_Types for pragma% must be list of string literals",
+               Argx_Parameter_Types);
+            return;
+
+         --  Here for aggregate case
+
+         else
+            Data.Parameter_Types :=
+              new Names
+                (1 .. List_Length (Expressions (Argx_Parameter_Types)));
+
+            Lit := First (Expressions (Argx_Parameter_Types));
+            for J in Data.Parameter_Types'Range loop
+               if Nkind (Lit) /= N_String_Literal then
+                  Error_Msg_N
+                    ("parameter types for pragma% must be string literals",
+                     Lit);
+                  return;
+               end if;
+
+               String_To_Name_Buffer (Strval (Lit));
+               Data.Parameter_Types (J) := Name_Find;
+               Next (Lit);
+            end loop;
+         end if;
+      end if;
+
+      --  Process Result_Types argument
+
+      if Present (Arg_Result_Type) then
+         Argx_Result_Type := Expression (Arg_Result_Type);
+
+         if Nkind (Argx_Result_Type) /= N_String_Literal then
+            Error_Msg_N
+              ("Result_Type argument for pragma% must be string literal",
+               Argx_Result_Type);
+            return;
+         end if;
+
+         String_To_Name_Buffer (Strval (Argx_Result_Type));
+         Data.Result_Type := Name_Find;
+
+      else
+         Data.Result_Type := No_Name;
+      end if;
+
+      --  Now link this new entry into the hash table
+
+      Elmt := Elim_Hash_Table.Get (Hash_Subprograms.Get_Key (Data));
+
+      --  If we already have an entry with this same key, then link
+      --  it into the chain of entries for this key.
+
+      if Elmt /= null then
+         Data.Homonym := Elmt.Homonym;
+         Elmt.Homonym := Data;
+
+      --  Otherwise create a new entry
+
+      else
+         Elim_Hash_Table.Set (Data);
+      end if;
+
+      No_Elimination := False;
+   end Process_Eliminate_Pragma;
+
+end Sem_Elim;
diff --git a/gcc/ada/sem_elim.ads b/gcc/ada/sem_elim.ads
new file mode 100644 (file)
index 0000000..861ffc9
--- /dev/null
@@ -0,0 +1,54 @@
+------------------------------------------------------------------------------
+--                                                                          --
+--                         GNAT COMPILER COMPONENTS                         --
+--                                                                          --
+--                             S E M _ E L I M                              --
+--                                                                          --
+--                                 S p e c                                  --
+--                                                                          --
+--                            $Revision: 1.1 $                              --
+--                                                                          --
+--             Copyright (C) 1997 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- --
+-- ware  Foundation;  either version 2,  or (at your option) any later ver- --
+-- sion.  GNAT is distributed in the hope that it will be useful, but WITH- --
+-- OUT ANY WARRANTY;  without even the  implied warranty of MERCHANTABILITY --
+-- or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License --
+-- for  more details.  You should have  received  a copy of the GNU General --
+-- Public License  distributed with GNAT;  see file COPYING.  If not, write --
+-- to  the Free Software Foundation,  59 Temple Place - Suite 330,  Boston, --
+-- MA 02111-1307, USA.                                                      --
+--                                                                          --
+-- GNAT was originally developed  by the GNAT team at  New York University. --
+-- It is now maintained by Ada Core Technologies Inc (http://www.gnat.com). --
+--                                                                          --
+------------------------------------------------------------------------------
+
+--  This package contains the routines used to process the Eliminate pragma
+
+with Types; use Types;
+
+package Sem_Elim is
+
+   procedure Initialize;
+   --  Initialize for new main souce program
+
+   procedure Process_Eliminate_Pragma
+     (Arg_Unit_Name       : Node_Id;
+      Arg_Entity          : Node_Id;
+      Arg_Parameter_Types : Node_Id;
+      Arg_Result_Type     : Node_Id);
+   --  Process eliminate pragma. The number of arguments has been checked,
+   --  as well as possible optional identifiers, but no other checks have
+   --  been made. This subprogram completes the checking, and then if the
+   --  pragma is well formed, makes appropriate entries in the internal
+   --  tables used to keep track of Eliminate pragmas. The four arguments
+   --  are the possible pragma arguments (set to Empty if not present).
+
+   procedure Check_Eliminated (E : Entity_Id);
+   --  Checks if entity E is eliminated, and if so sets the Is_Eliminated
+   --  flag on the given entity.
+
+end Sem_Elim;
diff --git a/gcc/ada/sem_eval.adb b/gcc/ada/sem_eval.adb
new file mode 100644 (file)
index 0000000..dde46a4
--- /dev/null
@@ -0,0 +1,3663 @@
+------------------------------------------------------------------------------
+--                                                                          --
+--                         GNAT COMPILER COMPONENTS                         --
+--                                                                          --
+--                             S E M _ E V A L                              --
+--                                                                          --
+--                                 B o d y                                  --
+--                                                                          --
+--                            $Revision: 1.291 $
+--                                                                          --
+--          Copyright (C) 1992-2001 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- --
+-- ware  Foundation;  either version 2,  or (at your option) any later ver- --
+-- sion.  GNAT is distributed in the hope that it will be useful, but WITH- --
+-- OUT ANY WARRANTY;  without even the  implied warranty of MERCHANTABILITY --
+-- or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License --
+-- for  more details.  You should have  received  a copy of the GNU General --
+-- Public License  distributed with GNAT;  see file COPYING.  If not, write --
+-- to  the Free Software Foundation,  59 Temple Place - Suite 330,  Boston, --
+-- MA 02111-1307, USA.                                                      --
+--                                                                          --
+-- GNAT was originally developed  by the GNAT team at  New York University. --
+-- It is now maintained by Ada Core Technologies Inc (http://www.gnat.com). --
+--                                                                          --
+------------------------------------------------------------------------------
+
+with Atree;    use Atree;
+with Checks;   use Checks;
+with Debug;    use Debug;
+with Einfo;    use Einfo;
+with Elists;   use Elists;
+with Errout;   use Errout;
+with Eval_Fat; use Eval_Fat;
+with Nmake;    use Nmake;
+with Nlists;   use Nlists;
+with Opt;      use Opt;
+with Sem;      use Sem;
+with Sem_Cat;  use Sem_Cat;
+with Sem_Ch8;  use Sem_Ch8;
+with Sem_Res;  use Sem_Res;
+with Sem_Util; use Sem_Util;
+with Sem_Type; use Sem_Type;
+with Sem_Warn; use Sem_Warn;
+with Sinfo;    use Sinfo;
+with Snames;   use Snames;
+with Stand;    use Stand;
+with Stringt;  use Stringt;
+
+package body Sem_Eval is
+
+   -----------------------------------------
+   -- Handling of Compile Time Evaluation --
+   -----------------------------------------
+
+   --  The compile time evaluation of expressions is distributed over several
+   --  Eval_xxx procedures. These procedures are called immediatedly after
+   --  a subexpression is resolved and is therefore accomplished in a bottom
+   --  up fashion. The flags are synthesized using the following approach.
+
+   --    Is_Static_Expression is determined by following the detailed rules
+   --    in RM 4.9(4-14). This involves testing the Is_Static_Expression
+   --    flag of the operands in many cases.
+
+   --    Raises_Constraint_Error is set if any of the operands have the flag
+   --    set or if an attempt to compute the value of the current expression
+   --    results in detection of a runtime constraint error.
+
+   --  As described in the spec, the requirement is that Is_Static_Expression
+   --  be accurately set, and in addition for nodes for which this flag is set,
+   --  Raises_Constraint_Error must also be set. Furthermore a node which has
+   --  Is_Static_Expression set, and Raises_Constraint_Error clear, then the
+   --  requirement is that the expression value must be precomputed, and the
+   --  node is either a literal, or the name of a constant entity whose value
+   --  is a static expression.
+
+   --  The general approach is as follows. First compute Is_Static_Expression.
+   --  If the node is not static, then the flag is left off in the node and
+   --  we are all done. Otherwise for a static node, we test if any of the
+   --  operands will raise constraint error, and if so, propagate the flag
+   --  Raises_Constraint_Error to the result node and we are done (since the
+   --  error was already posted at a lower level).
+
+   --  For the case of a static node whose operands do not raise constraint
+   --  error, we attempt to evaluate the node. If this evaluation succeeds,
+   --  then the node is replaced by the result of this computation. If the
+   --  evaluation raises constraint error, then we rewrite the node with
+   --  Apply_Compile_Time_Constraint_Error to raise the exception and also
+   --  to post appropriate error messages.
+
+   ----------------
+   -- Local Data --
+   ----------------
+
+   type Bits is array (Nat range <>) of Boolean;
+   --  Used to convert unsigned (modular) values for folding logical ops
+
+   -----------------------
+   -- Local Subprograms --
+   -----------------------
+
+   function OK_Bits (N : Node_Id; Bits : Uint) return Boolean;
+   --  Bits represents the number of bits in an integer value to be computed
+   --  (but the value has not been computed yet). If this value in Bits is
+   --  reasonable, a result of True is returned, with the implication that
+   --  the caller should go ahead and complete the calculation. If the value
+   --  in Bits is unreasonably large, then an error is posted on node N, and
+   --  False is returned (and the caller skips the proposed calculation).
+
+   function From_Bits (B : Bits; T : Entity_Id) return Uint;
+   --  Converts a bit string of length B'Length to a Uint value to be used
+   --  for a target of type T, which is a modular type. This procedure
+   --  includes the necessary reduction by the modulus in the case of a
+   --  non-binary modulus (for a binary modulus, the bit string is the
+   --  right length any way so all is well).
+
+   function Get_String_Val (N : Node_Id) return Node_Id;
+   --  Given a tree node for a folded string or character value, returns
+   --  the corresponding string literal or character literal (one of the
+   --  two must be available, or the operand would not have been marked
+   --  as foldable in the earlier analysis of the operation).
+
+   procedure Out_Of_Range (N : Node_Id);
+   --  This procedure is called if it is determined that node N, which
+   --  appears in a non-static context, is a compile time known value
+   --  which is outside its range, i.e. the range of Etype. This is used
+   --  in contexts where this is an illegality if N is static, and should
+   --  generate a warning otherwise.
+
+   procedure Rewrite_In_Raise_CE (N : Node_Id; Exp : Node_Id);
+   --  N and Exp are nodes representing an expression, Exp is known
+   --  to raise CE. N is rewritten in term of Exp in the optimal way.
+
+   function String_Type_Len (Stype : Entity_Id) return Uint;
+   --  Given a string type, determines the length of the index type, or,
+   --  if this index type is non-static, the length of the base type of
+   --  this index type. Note that if the string type is itself static,
+   --  then the index type is static, so the second case applies only
+   --  if the string type passed is non-static.
+
+   function Test (Cond : Boolean) return Uint;
+   pragma Inline (Test);
+   --  This function simply returns the appropriate Boolean'Pos value
+   --  corresponding to the value of Cond as a universal integer. It is
+   --  used for producing the result of the static evaluation of the
+   --  logical operators
+
+   procedure Test_Expression_Is_Foldable
+     (N    : Node_Id;
+      Op1  : Node_Id;
+      Stat : out Boolean;
+      Fold : out Boolean);
+   --  Tests to see if expression N whose single operand is Op1 is foldable,
+   --  i.e. the operand value is known at compile time. If the operation is
+   --  foldable, then Fold is True on return, and Stat indicates whether
+   --  the result is static (i.e. both operands were static). Note that it
+   --  is quite possible for Fold to be True, and Stat to be False, since
+   --  there are cases in which we know the value of an operand even though
+   --  it is not technically static (e.g. the static lower bound of a range
+   --  whose upper bound is non-static).
+   --
+   --  If Stat is set False on return, then Expression_Is_Foldable makes a
+   --  call to Check_Non_Static_Context on the operand. If Fold is False on
+   --  return, then all processing is complete, and the caller should
+   --  return, since there is nothing else to do.
+
+   procedure Test_Expression_Is_Foldable
+     (N    : Node_Id;
+      Op1  : Node_Id;
+      Op2  : Node_Id;
+      Stat : out Boolean;
+      Fold : out Boolean);
+   --  Same processing, except applies to an expression N with two operands
+   --  Op1 and Op2.
+
+   procedure To_Bits (U : Uint; B : out Bits);
+   --  Converts a Uint value to a bit string of length B'Length
+
+   ------------------------------
+   -- Check_Non_Static_Context --
+   ------------------------------
+
+   procedure Check_Non_Static_Context (N : Node_Id) is
+      T         : Entity_Id := Etype (N);
+      Checks_On : constant Boolean :=
+                    not Index_Checks_Suppressed (T)
+                      and not Range_Checks_Suppressed (T);
+
+   begin
+      --  We need the check only for static expressions not raising CE
+      --  We can also ignore cases in which the type is Any_Type
+
+      if not Is_OK_Static_Expression (N)
+        or else Etype (N) = Any_Type
+      then
+         return;
+
+      --  Skip this check for non-scalar expressions
+
+      elsif not Is_Scalar_Type (T) then
+         return;
+      end if;
+
+      --  Here we have the case of outer level static expression of
+      --  scalar type, where the processing of this procedure is needed.
+
+      --  For real types, this is where we convert the value to a machine
+      --  number (see RM 4.9(38)). Also see ACVC test C490001. We should
+      --  only need to do this if the parent is a constant declaration,
+      --  since in other cases, gigi should do the necessary conversion
+      --  correctly, but experimentation shows that this is not the case
+      --  on all machines, in particular if we do not convert all literals
+      --  to machine values in non-static contexts, then ACVC test C490001
+      --  fails on Sparc/Solaris and SGI/Irix.
+
+      if Nkind (N) = N_Real_Literal
+        and then not Is_Machine_Number (N)
+        and then not Is_Generic_Type (Etype (N))
+        and then Etype (N) /= Universal_Real
+        and then not Debug_Flag_S
+        and then (not Debug_Flag_T
+                    or else
+                      (Nkind (Parent (N)) = N_Object_Declaration
+                        and then Constant_Present (Parent (N))))
+      then
+         --  Check that value is in bounds before converting to machine
+         --  number, so as not to lose case where value overflows in the
+         --  least significant bit or less. See B490001.
+
+         if Is_Out_Of_Range (N, Base_Type (T)) then
+            Out_Of_Range (N);
+            return;
+         end if;
+
+         --  Note: we have to copy the node, to avoid problems with conformance
+         --  of very similar numbers (see ACVC tests B4A010C and B63103A).
+
+         Rewrite (N, New_Copy (N));
+
+         if not Is_Floating_Point_Type (T) then
+            Set_Realval
+              (N, Corresponding_Integer_Value (N) * Small_Value (T));
+
+         elsif not UR_Is_Zero (Realval (N)) then
+            declare
+               RT : constant Entity_Id := Base_Type (T);
+               X  : constant Ureal := Machine (RT, Realval (N), Round);
+
+            begin
+               --  Warn if result of static rounding actually differs from
+               --  runtime evaluation, which uses round to even.
+
+               if Warn_On_Biased_Rounding and Rounding_Was_Biased then
+                  Error_Msg_N ("static expression does not round to even"
+                    & " ('R'M 4.9(38))?", N);
+               end if;
+
+               Set_Realval (N, X);
+            end;
+         end if;
+
+         Set_Is_Machine_Number (N);
+      end if;
+
+      --  Check for out of range universal integer. This is a non-static
+      --  context, so the integer value must be in range of the runtime
+      --  representation of universal integers.
+
+      --  We do this only within an expression, because that is the only
+      --  case in which non-static universal integer values can occur, and
+      --  furthermore, Check_Non_Static_Context is currently (incorrectly???)
+      --  called in contexts like the expression of a number declaration where
+      --  we certainly want to allow out of range values.
+
+      if Etype (N) = Universal_Integer
+        and then Nkind (N) = N_Integer_Literal
+        and then Nkind (Parent (N)) in N_Subexpr
+        and then
+          (Intval (N) < Expr_Value (Type_Low_Bound (Universal_Integer))
+            or else
+           Intval (N) > Expr_Value (Type_High_Bound (Universal_Integer)))
+      then
+         Apply_Compile_Time_Constraint_Error
+           (N, "non-static universal integer value out of range?");
+
+      --  Check out of range of base type
+
+      elsif Is_Out_Of_Range (N, Base_Type (T)) then
+         Out_Of_Range (N);
+
+      --  Give warning if outside subtype (where one or both of the
+      --  bounds of the subtype is static). This warning is omitted
+      --  if the expression appears in a range that could be null
+      --  (warnings are handled elsewhere for this case).
+
+      elsif T /= Base_Type (T)
+        and then Nkind (Parent (N)) /= N_Range
+      then
+         if Is_In_Range (N, T) then
+            null;
+
+         elsif Is_Out_Of_Range (N, T) then
+            Apply_Compile_Time_Constraint_Error
+              (N, "value not in range of}?");
+
+         elsif Checks_On then
+            Enable_Range_Check (N);
+
+         else
+            Set_Do_Range_Check (N, False);
+         end if;
+      end if;
+   end Check_Non_Static_Context;
+
+   ---------------------------------
+   -- Check_String_Literal_Length --
+   ---------------------------------
+
+   procedure Check_String_Literal_Length (N : Node_Id; Ttype : Entity_Id) is
+   begin
+      if not Raises_Constraint_Error (N)
+        and then Is_Constrained (Ttype)
+      then
+         if
+           UI_From_Int (String_Length (Strval (N))) /= String_Type_Len (Ttype)
+         then
+            Apply_Compile_Time_Constraint_Error
+              (N, "string length wrong for}?",
+               Ent => Ttype,
+               Typ => Ttype);
+         end if;
+      end if;
+   end Check_String_Literal_Length;
+
+   --------------------------
+   -- Compile_Time_Compare --
+   --------------------------
+
+   function Compile_Time_Compare (L, R : Node_Id) return Compare_Result is
+      Ltyp : constant Entity_Id := Etype (L);
+      Rtyp : constant Entity_Id := Etype (R);
+
+      procedure Compare_Decompose
+        (N : Node_Id;
+         R : out Node_Id;
+         V : out Uint);
+      --  This procedure decomposes the node N into an expression node
+      --  and a signed offset, so that the value of N is equal to the
+      --  value of R plus the value V (which may be negative). If no
+      --  such decomposition is possible, then on return R is a copy
+      --  of N, and V is set to zero.
+
+      function Compare_Fixup (N : Node_Id) return Node_Id;
+      --  This function deals with replacing 'Last and 'First references
+      --  with their corresponding type bounds, which we then can compare.
+      --  The argument is the original node, the result is the identity,
+      --  unless we have a 'Last/'First reference in which case the value
+      --  returned is the appropriate type bound.
+
+      function Is_Same_Value (L, R : Node_Id) return Boolean;
+      --  Returns True iff L and R represent expressions that definitely
+      --  have identical (but not necessarily compile time known) values
+      --  Indeed the caller is expected to have already dealt with the
+      --  cases of compile time known values, so these are not tested here.
+
+      -----------------------
+      -- Compare_Decompose --
+      -----------------------
+
+      procedure Compare_Decompose
+        (N : Node_Id;
+         R : out Node_Id;
+         V : out Uint)
+      is
+      begin
+         if Nkind (N) = N_Op_Add
+           and then Nkind (Right_Opnd (N)) = N_Integer_Literal
+         then
+            R := Left_Opnd (N);
+            V := Intval (Right_Opnd (N));
+            return;
+
+         elsif Nkind (N) = N_Op_Subtract
+           and then Nkind (Right_Opnd (N)) = N_Integer_Literal
+         then
+            R := Left_Opnd (N);
+            V := UI_Negate (Intval (Right_Opnd (N)));
+            return;
+
+         elsif Nkind (N) = N_Attribute_Reference  then
+
+            if Attribute_Name (N) = Name_Succ then
+               R := First (Expressions (N));
+               V := Uint_1;
+               return;
+
+            elsif Attribute_Name (N) = Name_Pred then
+               R := First (Expressions (N));
+               V := Uint_Minus_1;
+               return;
+            end if;
+         end if;
+
+         R := N;
+         V := Uint_0;
+      end Compare_Decompose;
+
+      -------------------
+      -- Compare_Fixup --
+      -------------------
+
+      function Compare_Fixup (N : Node_Id) return Node_Id is
+         Indx : Node_Id;
+         Xtyp : Entity_Id;
+         Subs : Nat;
+
+      begin
+         if Nkind (N) = N_Attribute_Reference
+           and then (Attribute_Name (N) = Name_First
+                       or else
+                     Attribute_Name (N) = Name_Last)
+         then
+            Xtyp := Etype (Prefix (N));
+
+            --  If we have no type, then just abandon the attempt to do
+            --  a fixup, this is probably the result of some other error.
+
+            if No (Xtyp) then
+               return N;
+            end if;
+
+            --  Dereference an access type
+
+            if Is_Access_Type (Xtyp) then
+               Xtyp := Designated_Type (Xtyp);
+            end if;
+
+            --  If we don't have an array type at this stage, something
+            --  is peculiar, e.g. another error, and we abandon the attempt
+            --  at a fixup.
+
+            if not Is_Array_Type (Xtyp) then
+               return N;
+            end if;
+
+            --  Ignore unconstrained array, since bounds are not meaningful
+
+            if not Is_Constrained (Xtyp) then
+               return N;
+            end if;
+
+            --  Find correct index type
+
+            Indx := First_Index (Xtyp);
+
+            if Present (Expressions (N)) then
+               Subs := UI_To_Int (Expr_Value (First (Expressions (N))));
+
+               for J in 2 .. Subs loop
+                  Indx := Next_Index (Indx);
+               end loop;
+            end if;
+
+            Xtyp := Etype (Indx);
+
+            if Attribute_Name (N) = Name_First then
+               return Type_Low_Bound (Xtyp);
+
+            else -- Attribute_Name (N) = Name_Last
+               return Type_High_Bound (Xtyp);
+            end if;
+         end if;
+
+         return N;
+      end Compare_Fixup;
+
+      -------------------
+      -- Is_Same_Value --
+      -------------------
+
+      function Is_Same_Value (L, R : Node_Id) return Boolean is
+         Lf : constant Node_Id := Compare_Fixup (L);
+         Rf : constant Node_Id := Compare_Fixup (R);
+
+      begin
+         --  Values are the same if they are the same identifier and the
+         --  identifier refers to a constant object (E_Constant)
+
+         if Nkind (Lf) = N_Identifier and then Nkind (Rf) = N_Identifier
+           and then Entity (Lf) = Entity (Rf)
+           and then (Ekind (Entity (Lf)) = E_Constant     or else
+                     Ekind (Entity (Lf)) = E_In_Parameter or else
+                     Ekind (Entity (Lf)) = E_Loop_Parameter)
+         then
+            return True;
+
+         --  Or if they are compile time known and identical
+
+         elsif Compile_Time_Known_Value (Lf)
+                 and then
+               Compile_Time_Known_Value (Rf)
+           and then Expr_Value (Lf) = Expr_Value (Rf)
+         then
+            return True;
+
+         --  Or if they are both 'First or 'Last values applying to the
+         --  same entity (first and last don't change even if value does)
+
+         elsif Nkind (Lf) = N_Attribute_Reference
+                 and then
+               Nkind (Rf) = N_Attribute_Reference
+           and then Attribute_Name (Lf) = Attribute_Name (Rf)
+           and then (Attribute_Name (Lf) = Name_First
+                       or else
+                     Attribute_Name (Lf) = Name_Last)
+           and then Is_Entity_Name (Prefix (Lf))
+           and then Is_Entity_Name (Prefix (Rf))
+           and then Entity (Prefix (Lf)) = Entity (Prefix (Rf))
+         then
+            return True;
+
+         --  All other cases, we can't tell
+
+         else
+            return False;
+         end if;
+      end Is_Same_Value;
+
+   --  Start of processing for Compile_Time_Compare
+
+   begin
+      if L = R then
+         return EQ;
+
+      --  If expressions have no types, then do not attempt to determine
+      --  if they are the same, since something funny is going on. One
+      --  case in which this happens is during generic template analysis,
+      --  when bounds are not fully analyzed.
+
+      elsif No (Ltyp) or else No (Rtyp) then
+         return Unknown;
+
+      --  We only attempt compile time analysis for scalar values
+
+      elsif not Is_Scalar_Type (Ltyp)
+        or else Is_Packed_Array_Type (Ltyp)
+      then
+         return Unknown;
+
+      --  Case where comparison involves two compile time known values
+
+      elsif Compile_Time_Known_Value (L)
+        and then Compile_Time_Known_Value (R)
+      then
+         --  For the floating-point case, we have to be a little careful, since
+         --  at compile time we are dealing with universal exact values, but at
+         --  runtime, these will be in non-exact target form. That's why the
+         --  returned results are LE and GE below instead of LT and GT.
+
+         if Is_Floating_Point_Type (Ltyp)
+              or else
+            Is_Floating_Point_Type (Rtyp)
+         then
+            declare
+               Lo : constant Ureal := Expr_Value_R (L);
+               Hi : constant Ureal := Expr_Value_R (R);
+
+            begin
+               if Lo < Hi then
+                  return LE;
+               elsif Lo = Hi then
+                  return EQ;
+               else
+                  return GE;
+               end if;
+            end;
+
+         --  For the integer case we know exactly (note that this includes the
+         --  fixed-point case, where we know the run time integer values now)
+
+         else
+            declare
+               Lo : constant Uint := Expr_Value (L);
+               Hi : constant Uint := Expr_Value (R);
+
+            begin
+               if Lo < Hi then
+                  return LT;
+               elsif Lo = Hi then
+                  return EQ;
+               else
+                  return GT;
+               end if;
+            end;
+         end if;
+
+      --  Cases where at least one operand is not known at compile time
+
+      else
+         --  Here is where we check for comparisons against maximum bounds of
+         --  types, where we know that no value can be outside the bounds of
+         --  the subtype. Note that this routine is allowed to assume that all
+         --  expressions are within their subtype bounds. Callers wishing to
+         --  deal with possibly invalid values must in any case take special
+         --  steps (e.g. conversions to larger types) to avoid this kind of
+         --  optimization, which is always considered to be valid. We do not
+         --  attempt this optimization with generic types, since the type
+         --  bounds may not be meaningful in this case.
+
+         if Is_Discrete_Type (Ltyp)
+           and then not Is_Generic_Type (Ltyp)
+           and then not Is_Generic_Type (Rtyp)
+         then
+            if Is_Same_Value (R, Type_High_Bound (Ltyp)) then
+               return LE;
+
+            elsif Is_Same_Value (R, Type_Low_Bound (Ltyp)) then
+               return GE;
+
+            elsif Is_Same_Value (L, Type_High_Bound (Rtyp)) then
+               return GE;
+
+            elsif Is_Same_Value (L, Type_Low_Bound (Ltyp)) then
+               return LE;
+            end if;
+         end if;
+
+         --  Next attempt is to decompose the expressions to extract
+         --  a constant offset resulting from the use of any of the forms:
+
+         --     expr + literal
+         --     expr - literal
+         --     typ'Succ (expr)
+         --     typ'Pred (expr)
+
+         --  Then we see if the two expressions are the same value, and if so
+         --  the result is obtained by comparing the offsets.
+
+         declare
+            Lnode : Node_Id;
+            Loffs : Uint;
+            Rnode : Node_Id;
+            Roffs : Uint;
+
+         begin
+            Compare_Decompose (L, Lnode, Loffs);
+            Compare_Decompose (R, Rnode, Roffs);
+
+            if Is_Same_Value (Lnode, Rnode) then
+               if Loffs = Roffs then
+                  return EQ;
+
+               elsif Loffs < Roffs then
+                  return LT;
+
+               else
+                  return GT;
+               end if;
+
+            --  If the expressions are different, we cannot say at compile
+            --  time how they compare, so we return the Unknown indication.
+
+            else
+               return Unknown;
+            end if;
+         end;
+      end if;
+   end Compile_Time_Compare;
+
+   ------------------------------
+   -- Compile_Time_Known_Value --
+   ------------------------------
+
+   function Compile_Time_Known_Value (Op : Node_Id) return Boolean is
+      K : constant Node_Kind := Nkind (Op);
+
+   begin
+      --  Never known at compile time if bad type or raises constraint error
+      --  or empty (latter case occurs only as a result of a previous error)
+
+      if No (Op)
+        or else Op = Error
+        or else Etype (Op) = Any_Type
+        or else Raises_Constraint_Error (Op)
+      then
+         return False;
+      end if;
+
+      --  If we have an entity name, then see if it is the name of a constant
+      --  and if so, test the corresponding constant value, or the name of
+      --  an enumeration literal, which is always a constant.
+
+      if Present (Etype (Op)) and then Is_Entity_Name (Op) then
+         declare
+            E : constant Entity_Id := Entity (Op);
+            V : Node_Id;
+
+         begin
+            --  Never known at compile time if it is a packed array value.
+            --  We might want to try to evaluate these at compile time one
+            --  day, but we do not make that attempt now.
+
+            if Is_Packed_Array_Type (Etype (Op)) then
+               return False;
+            end if;
+
+            if Ekind (E) = E_Enumeration_Literal then
+               return True;
+
+            elsif Ekind (E) /= E_Constant then
+               return False;
+
+            else
+               V := Constant_Value (E);
+               return Present (V) and then Compile_Time_Known_Value (V);
+            end if;
+         end;
+
+      --  We have a value, see if it is compile time known
+
+      else
+         --  Literals and NULL are known at compile time
+
+         if K = N_Integer_Literal
+              or else
+            K = N_Character_Literal
+              or else
+            K = N_Real_Literal
+              or else
+            K = N_String_Literal
+              or else
+            K = N_Null
+         then
+            return True;
+
+         --  Any reference to Null_Parameter is known at compile time. No
+         --  other attribute references (that have not already been folded)
+         --  are known at compile time.
+
+         elsif K = N_Attribute_Reference then
+            return Attribute_Name (Op) = Name_Null_Parameter;
+
+         --  All other types of values are not known at compile time
+
+         else
+            return False;
+         end if;
+
+      end if;
+   end Compile_Time_Known_Value;
+
+   --------------------------------------
+   -- Compile_Time_Known_Value_Or_Aggr --
+   --------------------------------------
+
+   function Compile_Time_Known_Value_Or_Aggr (Op : Node_Id) return Boolean is
+   begin
+      --  If we have an entity name, then see if it is the name of a constant
+      --  and if so, test the corresponding constant value, or the name of
+      --  an enumeration literal, which is always a constant.
+
+      if Is_Entity_Name (Op) then
+         declare
+            E : constant Entity_Id := Entity (Op);
+            V : Node_Id;
+
+         begin
+            if Ekind (E) = E_Enumeration_Literal then
+               return True;
+
+            elsif Ekind (E) /= E_Constant then
+               return False;
+
+            else
+               V := Constant_Value (E);
+               return Present (V)
+                 and then Compile_Time_Known_Value_Or_Aggr (V);
+            end if;
+         end;
+
+      --  We have a value, see if it is compile time known
+
+      else
+         if Compile_Time_Known_Value (Op) then
+            return True;
+
+         elsif Nkind (Op) = N_Aggregate then
+
+            if Present (Expressions (Op)) then
+               declare
+                  Expr : Node_Id;
+
+               begin
+                  Expr := First (Expressions (Op));
+                  while Present (Expr) loop
+                     if not Compile_Time_Known_Value_Or_Aggr (Expr) then
+                        return False;
+                     end if;
+
+                     Next (Expr);
+                  end loop;
+               end;
+            end if;
+
+            if Present (Component_Associations (Op)) then
+               declare
+                  Cass : Node_Id;
+
+               begin
+                  Cass := First (Component_Associations (Op));
+                  while Present (Cass) loop
+                     if not
+                       Compile_Time_Known_Value_Or_Aggr (Expression (Cass))
+                     then
+                        return False;
+                     end if;
+
+                     Next (Cass);
+                  end loop;
+               end;
+            end if;
+
+            return True;
+
+         --  All other types of values are not known at compile time
+
+         else
+            return False;
+         end if;
+
+      end if;
+   end Compile_Time_Known_Value_Or_Aggr;
+
+   -----------------
+   -- Eval_Actual --
+   -----------------
+
+   --  This is only called for actuals of functions that are not predefined
+   --  operators (which have already been rewritten as operators at this
+   --  stage), so the call can never be folded, and all that needs doing for
+   --  the actual is to do the check for a non-static context.
+
+   procedure Eval_Actual (N : Node_Id) is
+   begin
+      Check_Non_Static_Context (N);
+   end Eval_Actual;
+
+   --------------------
+   -- Eval_Allocator --
+   --------------------
+
+   --  Allocators are never static, so all we have to do is to do the
+   --  check for a non-static context if an expression is present.
+
+   procedure Eval_Allocator (N : Node_Id) is
+      Expr : constant Node_Id := Expression (N);
+
+   begin
+      if Nkind (Expr) = N_Qualified_Expression then
+         Check_Non_Static_Context (Expression (Expr));
+      end if;
+   end Eval_Allocator;
+
+   ------------------------
+   -- Eval_Arithmetic_Op --
+   ------------------------
+
+   --  Arithmetic operations are static functions, so the result is static
+   --  if both operands are static (RM 4.9(7), 4.9(20)).
+
+   procedure Eval_Arithmetic_Op (N : Node_Id) is
+      Left  : constant Node_Id   := Left_Opnd (N);
+      Right : constant Node_Id   := Right_Opnd (N);
+      Ltype : constant Entity_Id := Etype (Left);
+      Rtype : constant Entity_Id := Etype (Right);
+      Stat  : Boolean;
+      Fold  : Boolean;
+
+   begin
+      --  If not foldable we are done
+
+      Test_Expression_Is_Foldable (N, Left, Right, Stat, Fold);
+
+      if not Fold then
+         return;
+      end if;
+
+      --  Fold for cases where both operands are of integer type
+
+      if Is_Integer_Type (Ltype) and then Is_Integer_Type (Rtype) then
+         declare
+            Left_Int  : constant Uint := Expr_Value (Left);
+            Right_Int : constant Uint := Expr_Value (Right);
+            Result    : Uint;
+
+         begin
+            case Nkind (N) is
+
+               when N_Op_Add =>
+                  Result := Left_Int + Right_Int;
+
+               when N_Op_Subtract =>
+                  Result := Left_Int - Right_Int;
+
+               when N_Op_Multiply =>
+                  if OK_Bits
+                       (N, UI_From_Int
+                             (Num_Bits (Left_Int) + Num_Bits (Right_Int)))
+                  then
+                     Result := Left_Int * Right_Int;
+                  else
+                     Result := Left_Int;
+                  end if;
+
+               when N_Op_Divide =>
+
+                  --  The exception Constraint_Error is raised by integer
+                  --  division, rem and mod if the right operand is zero.
+
+                  if Right_Int = 0 then
+                     Apply_Compile_Time_Constraint_Error
+                       (N, "division by zero");
+                     return;
+                  else
+                     Result := Left_Int / Right_Int;
+                  end if;
+
+               when N_Op_Mod =>
+
+                  --  The exception Constraint_Error is raised by integer
+                  --  division, rem and mod if the right operand is zero.
+
+                  if Right_Int = 0 then
+                     Apply_Compile_Time_Constraint_Error
+                       (N, "mod with zero divisor");
+                     return;
+                  else
+                     Result := Left_Int mod Right_Int;
+                  end if;
+
+               when N_Op_Rem =>
+
+                  --  The exception Constraint_Error is raised by integer
+                  --  division, rem and mod if the right operand is zero.
+
+                  if Right_Int = 0 then
+                     Apply_Compile_Time_Constraint_Error
+                       (N, "rem with zero divisor");
+                     return;
+                  else
+                     Result := Left_Int rem Right_Int;
+                  end if;
+
+               when others =>
+                  raise Program_Error;
+            end case;
+
+            --  Adjust the result by the modulus if the type is a modular type
+
+            if Is_Modular_Integer_Type (Ltype) then
+               Result := Result mod Modulus (Ltype);
+            end if;
+
+            Fold_Uint (N, Result);
+         end;
+
+      --  Cases where at least one operand is a real. We handle the cases
+      --  of both reals, or mixed/real integer cases (the latter happen
+      --  only for divide and multiply, and the result is always real).
+
+      elsif Is_Real_Type (Ltype) or else Is_Real_Type (Rtype) then
+         declare
+            Left_Real  : Ureal;
+            Right_Real : Ureal;
+            Result     : Ureal;
+
+         begin
+            if Is_Real_Type (Ltype) then
+               Left_Real := Expr_Value_R (Left);
+            else
+               Left_Real := UR_From_Uint (Expr_Value (Left));
+            end if;
+
+            if Is_Real_Type (Rtype) then
+               Right_Real := Expr_Value_R (Right);
+            else
+               Right_Real := UR_From_Uint (Expr_Value (Right));
+            end if;
+
+            if Nkind (N) = N_Op_Add then
+               Result := Left_Real + Right_Real;
+
+            elsif Nkind (N) = N_Op_Subtract then
+               Result := Left_Real - Right_Real;
+
+            elsif Nkind (N) = N_Op_Multiply then
+               Result := Left_Real * Right_Real;
+
+            else pragma Assert (Nkind (N) = N_Op_Divide);
+               if UR_Is_Zero (Right_Real) then
+                  Apply_Compile_Time_Constraint_Error
+                    (N, "division by zero");
+                  return;
+               end if;
+
+               Result := Left_Real / Right_Real;
+            end if;
+
+            Fold_Ureal (N, Result);
+         end;
+      end if;
+
+      Set_Is_Static_Expression (N, Stat);
+
+   end Eval_Arithmetic_Op;
+
+   ----------------------------
+   -- Eval_Character_Literal --
+   ----------------------------
+
+   --  Nothing to be done!
+
+   procedure Eval_Character_Literal (N : Node_Id) is
+   begin
+      null;
+   end Eval_Character_Literal;
+
+   ------------------------
+   -- Eval_Concatenation --
+   ------------------------
+
+   --  Concatenation is a static function, so the result is static if
+   --  both operands are static (RM 4.9(7), 4.9(21)).
+
+   procedure Eval_Concatenation (N : Node_Id) is
+      Left  : constant Node_Id := Left_Opnd (N);
+      Right : constant Node_Id := Right_Opnd (N);
+      Stat  : Boolean;
+      Fold  : Boolean;
+      C_Typ : constant Entity_Id := Root_Type (Component_Type (Etype (N)));
+
+   begin
+      --  Concatenation is never static in Ada 83, so if Ada 83
+      --  check operand non-static context
+
+      if Ada_83
+        and then Comes_From_Source (N)
+      then
+         Check_Non_Static_Context (Left);
+         Check_Non_Static_Context (Right);
+         return;
+      end if;
+
+      --  If not foldable we are done. In principle concatenation that yields
+      --  any string type is static (i.e. an array type of character types).
+      --  However, character types can include enumeration literals, and
+      --  concatenation in that case cannot be described by a literal, so we
+      --  only consider the operation static if the result is an array of
+      --  (a descendant of) a predefined character type.
+
+      Test_Expression_Is_Foldable (N, Left, Right, Stat, Fold);
+
+      if (C_Typ = Standard_Character
+            or else  C_Typ = Standard_Wide_Character)
+        and then Fold
+      then
+         null;
+      else
+         Set_Is_Static_Expression (N, False);
+         return;
+      end if;
+
+      --  Compile time string concatenation.
+
+      --  ??? Note that operands that are aggregates can be marked as
+      --  static, so we should attempt at a later stage to fold
+      --  concatenations with such aggregates.
+
+      declare
+         Left_Str  : constant Node_Id := Get_String_Val (Left);
+         Right_Str : constant Node_Id := Get_String_Val (Right);
+
+      begin
+         --  Establish new string literal, and store left operand. We make
+         --  sure to use the special Start_String that takes an operand if
+         --  the left operand is a string literal. Since this is optimized
+         --  in the case where that is the most recently created string
+         --  literal, we ensure efficient time/space behavior for the
+         --  case of a concatenation of a series of string literals.
+
+         if Nkind (Left_Str) = N_String_Literal then
+            Start_String (Strval (Left_Str));
+         else
+            Start_String;
+            Store_String_Char (Char_Literal_Value (Left_Str));
+         end if;
+
+         --  Now append the characters of the right operand
+
+         if Nkind (Right_Str) = N_String_Literal then
+            declare
+               S : constant String_Id := Strval (Right_Str);
+
+            begin
+               for J in 1 .. String_Length (S) loop
+                  Store_String_Char (Get_String_Char (S, J));
+               end loop;
+            end;
+         else
+            Store_String_Char (Char_Literal_Value (Right_Str));
+         end if;
+
+         Set_Is_Static_Expression (N, Stat);
+
+         if Stat then
+            Fold_Str (N, End_String);
+         end if;
+      end;
+   end Eval_Concatenation;
+
+   ---------------------------------
+   -- Eval_Conditional_Expression --
+   ---------------------------------
+
+   --  This GNAT internal construct can never be statically folded, so the
+   --  only required processing is to do the check for non-static context
+   --  for the two expression operands.
+
+   procedure Eval_Conditional_Expression (N : Node_Id) is
+      Condition : constant Node_Id := First (Expressions (N));
+      Then_Expr : constant Node_Id := Next (Condition);
+      Else_Expr : constant Node_Id := Next (Then_Expr);
+
+   begin
+      Check_Non_Static_Context (Then_Expr);
+      Check_Non_Static_Context (Else_Expr);
+   end Eval_Conditional_Expression;
+
+   ----------------------
+   -- Eval_Entity_Name --
+   ----------------------
+
+   --  This procedure is used for identifiers and expanded names other than
+   --  named numbers (see Eval_Named_Integer, Eval_Named_Real. These are
+   --  static if they denote a static constant (RM 4.9(6)) or if the name
+   --  denotes an enumeration literal (RM 4.9(22)).
+
+   procedure Eval_Entity_Name (N : Node_Id) is
+      Def_Id : constant Entity_Id := Entity (N);
+      Val    : Node_Id;
+
+   begin
+      --  Enumeration literals are always considered to be constants
+      --  and cannot raise constraint error (RM 4.9(22)).
+
+      if Ekind (Def_Id) = E_Enumeration_Literal then
+         Set_Is_Static_Expression (N);
+         return;
+
+      --  A name is static if it denotes a static constant (RM 4.9(5)), and
+      --  we also copy Raise_Constraint_Error. Notice that even if non-static,
+      --  it does not violate 10.2.1(8) here, since this is not a variable.
+
+      elsif Ekind (Def_Id) = E_Constant then
+
+         --  Deferred constants must always be treated as nonstatic
+         --  outside the scope of their full view.
+
+         if Present (Full_View (Def_Id))
+           and then not In_Open_Scopes (Scope (Def_Id))
+         then
+            Val := Empty;
+         else
+            Val := Constant_Value (Def_Id);
+         end if;
+
+         if Present (Val) then
+            Set_Is_Static_Expression
+              (N, Is_Static_Expression (Val)
+                    and then Is_Static_Subtype (Etype (Def_Id)));
+            Set_Raises_Constraint_Error (N, Raises_Constraint_Error (Val));
+
+            if not Is_Static_Expression (N)
+              and then not Is_Generic_Type (Etype (N))
+            then
+               Validate_Static_Object_Name (N);
+            end if;
+
+            return;
+         end if;
+      end if;
+
+      --  Fall through if the name is not static.
+
+      Validate_Static_Object_Name (N);
+   end Eval_Entity_Name;
+
+   ----------------------------
+   -- Eval_Indexed_Component --
+   ----------------------------
+
+   --  Indexed components are never static, so the only required processing
+   --  is to perform the check for non-static context on the index values.
+
+   procedure Eval_Indexed_Component (N : Node_Id) is
+      Expr : Node_Id;
+
+   begin
+      Expr := First (Expressions (N));
+      while Present (Expr) loop
+         Check_Non_Static_Context (Expr);
+         Next (Expr);
+      end loop;
+
+   end Eval_Indexed_Component;
+
+   --------------------------
+   -- Eval_Integer_Literal --
+   --------------------------
+
+   --  Numeric literals are static (RM 4.9(1)), and have already been marked
+   --  as static by the analyzer. The reason we did it that early is to allow
+   --  the possibility of turning off the Is_Static_Expression flag after
+   --  analysis, but before resolution, when integer literals are generated
+   --  in the expander that do not correspond to static expressions.
+
+   procedure Eval_Integer_Literal (N : Node_Id) is
+      T : constant Entity_Id := Etype (N);
+
+   begin
+      --  If the literal appears in a non-expression context, then it is
+      --  certainly appearing in a non-static context, so check it. This
+      --  is actually a redundant check, since Check_Non_Static_Context
+      --  would check it, but it seems worth while avoiding the call.
+
+      if Nkind (Parent (N)) not in N_Subexpr then
+         Check_Non_Static_Context (N);
+      end if;
+
+      --  Modular integer literals must be in their base range
+
+      if Is_Modular_Integer_Type (T)
+        and then Is_Out_Of_Range (N, Base_Type (T))
+      then
+         Out_Of_Range (N);
+      end if;
+   end Eval_Integer_Literal;
+
+   ---------------------
+   -- Eval_Logical_Op --
+   ---------------------
+
+   --  Logical operations are static functions, so the result is potentially
+   --  static if both operands are potentially static (RM 4.9(7), 4.9(20)).
+
+   procedure Eval_Logical_Op (N : Node_Id) is
+      Left  : constant Node_Id := Left_Opnd (N);
+      Right : constant Node_Id := Right_Opnd (N);
+      Stat  : Boolean;
+      Fold  : Boolean;
+
+   begin
+      --  If not foldable we are done
+
+      Test_Expression_Is_Foldable (N, Left, Right, Stat, Fold);
+
+      if not Fold then
+         return;
+      end if;
+
+      --  Compile time evaluation of logical operation
+
+      declare
+         Left_Int  : constant Uint := Expr_Value (Left);
+         Right_Int : constant Uint := Expr_Value (Right);
+
+      begin
+         if Is_Modular_Integer_Type (Etype (N)) then
+            declare
+               Left_Bits  : Bits (0 .. UI_To_Int (Esize (Etype (N))) - 1);
+               Right_Bits : Bits (0 .. UI_To_Int (Esize (Etype (N))) - 1);
+
+            begin
+               To_Bits (Left_Int, Left_Bits);
+               To_Bits (Right_Int, Right_Bits);
+
+               --  Note: should really be able to use array ops instead of
+               --  these loops, but they weren't working at the time ???
+
+               if Nkind (N) = N_Op_And then
+                  for J in Left_Bits'Range loop
+                     Left_Bits (J) := Left_Bits (J) and Right_Bits (J);
+                  end loop;
+
+               elsif Nkind (N) = N_Op_Or then
+                  for J in Left_Bits'Range loop
+                     Left_Bits (J) := Left_Bits (J) or Right_Bits (J);
+                  end loop;
+
+               else
+                  pragma Assert (Nkind (N) = N_Op_Xor);
+
+                  for J in Left_Bits'Range loop
+                     Left_Bits (J) := Left_Bits (J) xor Right_Bits (J);
+                  end loop;
+               end if;
+
+               Fold_Uint (N, From_Bits (Left_Bits, Etype (N)));
+            end;
+
+         else
+            pragma Assert (Is_Boolean_Type (Etype (N)));
+
+            if Nkind (N) = N_Op_And then
+               Fold_Uint (N,
+                 Test (Is_True (Left_Int) and then Is_True (Right_Int)));
+
+            elsif Nkind (N) = N_Op_Or then
+               Fold_Uint (N,
+                 Test (Is_True (Left_Int) or else Is_True (Right_Int)));
+
+            else
+               pragma Assert (Nkind (N) = N_Op_Xor);
+               Fold_Uint (N,
+                 Test (Is_True (Left_Int) xor Is_True (Right_Int)));
+            end if;
+         end if;
+
+         Set_Is_Static_Expression (N, Stat);
+      end;
+   end Eval_Logical_Op;
+
+   ------------------------
+   -- Eval_Membership_Op --
+   ------------------------
+
+   --  A membership test is potentially static if the expression is static,
+   --  and the range is a potentially static range, or is a subtype mark
+   --  denoting a static subtype (RM 4.9(12)).
+
+   procedure Eval_Membership_Op (N : Node_Id) is
+      Left   : constant Node_Id := Left_Opnd (N);
+      Right  : constant Node_Id := Right_Opnd (N);
+      Def_Id : Entity_Id;
+      Lo     : Node_Id;
+      Hi     : Node_Id;
+      Result : Boolean;
+      Stat   : Boolean;
+      Fold   : Boolean;
+
+   begin
+      --  Ignore if error in either operand, except to make sure that
+      --  Any_Type is properly propagated to avoid junk cascaded errors.
+
+      if Etype (Left) = Any_Type
+        or else Etype (Right) = Any_Type
+      then
+         Set_Etype (N, Any_Type);
+         return;
+      end if;
+
+      --  Case of right operand is a subtype name
+
+      if Is_Entity_Name (Right) then
+         Def_Id := Entity (Right);
+
+         if (Is_Scalar_Type (Def_Id) or else Is_String_Type (Def_Id))
+           and then Is_OK_Static_Subtype (Def_Id)
+         then
+            Test_Expression_Is_Foldable (N, Left, Stat, Fold);
+
+            if not Fold or else not Stat then
+               return;
+            end if;
+         else
+            Check_Non_Static_Context (Left);
+            return;
+         end if;
+
+         --  For string membership tests we will check the length
+         --  further below.
+
+         if not Is_String_Type (Def_Id) then
+            Lo := Type_Low_Bound (Def_Id);
+            Hi := Type_High_Bound (Def_Id);
+
+         else
+            Lo := Empty;
+            Hi := Empty;
+         end if;
+
+      --  Case of right operand is a range
+
+      else
+         if Is_Static_Range (Right) then
+            Test_Expression_Is_Foldable (N, Left, Stat, Fold);
+
+            if not Fold or else not Stat then
+               return;
+
+            --  If one bound of range raises CE, then don't try to fold
+
+            elsif not Is_OK_Static_Range (Right) then
+               Check_Non_Static_Context (Left);
+               return;
+            end if;
+
+         else
+            Check_Non_Static_Context (Left);
+            return;
+         end if;
+
+         --  Here we know range is an OK static range
+
+         Lo := Low_Bound (Right);
+         Hi := High_Bound (Right);
+      end if;
+
+      --  For strings we check that the length of the string expression is
+      --  compatible with the string subtype if the subtype is constrained,
+      --  or if unconstrained then the test is always true.
+
+      if Is_String_Type (Etype (Right)) then
+         if not Is_Constrained (Etype (Right)) then
+            Result := True;
+
+         else
+            declare
+               Typlen : constant Uint := String_Type_Len (Etype (Right));
+               Strlen : constant Uint :=
+                 UI_From_Int (String_Length (Strval (Get_String_Val (Left))));
+            begin
+               Result := (Typlen = Strlen);
+            end;
+         end if;
+
+      --  Fold the membership test. We know we have a static range and Lo
+      --  and Hi are set to the expressions for the end points of this range.
+
+      elsif Is_Real_Type (Etype (Right)) then
+         declare
+            Leftval : constant Ureal := Expr_Value_R (Left);
+
+         begin
+            Result := Expr_Value_R (Lo) <= Leftval
+                        and then Leftval <= Expr_Value_R (Hi);
+         end;
+
+      else
+         declare
+            Leftval : constant Uint := Expr_Value (Left);
+
+         begin
+            Result := Expr_Value (Lo) <= Leftval
+                        and then Leftval <= Expr_Value (Hi);
+         end;
+      end if;
+
+      if Nkind (N) = N_Not_In then
+         Result := not Result;
+      end if;
+
+      Fold_Uint (N, Test (Result));
+      Warn_On_Known_Condition (N);
+
+   end Eval_Membership_Op;
+
+   ------------------------
+   -- Eval_Named_Integer --
+   ------------------------
+
+   procedure Eval_Named_Integer (N : Node_Id) is
+   begin
+      Fold_Uint (N,
+        Expr_Value (Expression (Declaration_Node (Entity (N)))));
+   end Eval_Named_Integer;
+
+   ---------------------
+   -- Eval_Named_Real --
+   ---------------------
+
+   procedure Eval_Named_Real (N : Node_Id) is
+   begin
+      Fold_Ureal (N,
+        Expr_Value_R (Expression (Declaration_Node (Entity (N)))));
+   end Eval_Named_Real;
+
+   -------------------
+   -- Eval_Op_Expon --
+   -------------------
+
+   --  Exponentiation is a static functions, so the result is potentially
+   --  static if both operands are potentially static (RM 4.9(7), 4.9(20)).
+
+   procedure Eval_Op_Expon (N : Node_Id) is
+      Left  : constant Node_Id := Left_Opnd (N);
+      Right : constant Node_Id := Right_Opnd (N);
+      Stat  : Boolean;
+      Fold  : Boolean;
+
+   begin
+      --  If not foldable we are done
+
+      Test_Expression_Is_Foldable (N, Left, Right, Stat, Fold);
+
+      if not Fold then
+         return;
+      end if;
+
+      --  Fold exponentiation operation
+
+      declare
+         Right_Int : constant Uint := Expr_Value (Right);
+
+      begin
+         --  Integer case
+
+         if Is_Integer_Type (Etype (Left)) then
+            declare
+               Left_Int : constant Uint := Expr_Value (Left);
+               Result   : Uint;
+
+            begin
+               --  Exponentiation of an integer raises the exception
+               --  Constraint_Error for a negative exponent (RM 4.5.6)
+
+               if Right_Int < 0 then
+                  Apply_Compile_Time_Constraint_Error
+                    (N, "integer exponent negative");
+                  return;
+
+               else
+                  if OK_Bits (N, Num_Bits (Left_Int) * Right_Int) then
+                     Result := Left_Int ** Right_Int;
+                  else
+                     Result := Left_Int;
+                  end if;
+
+                  if Is_Modular_Integer_Type (Etype (N)) then
+                     Result := Result mod Modulus (Etype (N));
+                  end if;
+
+                  Fold_Uint (N, Result);
+               end if;
+            end;
+
+         --  Real case
+
+         else
+            declare
+               Left_Real : constant Ureal := Expr_Value_R (Left);
+
+            begin
+               --  Cannot have a zero base with a negative exponent
+
+               if UR_Is_Zero (Left_Real) then
+
+                  if Right_Int < 0 then
+                     Apply_Compile_Time_Constraint_Error
+                       (N, "zero ** negative integer");
+                     return;
+                  else
+                     Fold_Ureal (N, Ureal_0);
+                  end if;
+
+               else
+                  Fold_Ureal (N, Left_Real ** Right_Int);
+               end if;
+            end;
+         end if;
+
+         Set_Is_Static_Expression (N, Stat);
+      end;
+   end Eval_Op_Expon;
+
+   -----------------
+   -- Eval_Op_Not --
+   -----------------
+
+   --  The not operation is a  static functions, so the result is potentially
+   --  static if the operand is potentially static (RM 4.9(7), 4.9(20)).
+
+   procedure Eval_Op_Not (N : Node_Id) is
+      Right : constant Node_Id := Right_Opnd (N);
+      Stat  : Boolean;
+      Fold  : Boolean;
+
+   begin
+      --  If not foldable we are done
+
+      Test_Expression_Is_Foldable (N, Right, Stat, Fold);
+
+      if not Fold then
+         return;
+      end if;
+
+      --  Fold not operation
+
+      declare
+         Rint : constant Uint      := Expr_Value (Right);
+         Typ  : constant Entity_Id := Etype (N);
+
+      begin
+         --  Negation is equivalent to subtracting from the modulus minus
+         --  one. For a binary modulus this is equivalent to the ones-
+         --  component of the original value. For non-binary modulus this
+         --  is an arbitrary but consistent definition.
+
+         if Is_Modular_Integer_Type (Typ) then
+            Fold_Uint (N, Modulus (Typ) - 1 - Rint);
+
+         else
+            pragma Assert (Is_Boolean_Type (Typ));
+            Fold_Uint (N, Test (not Is_True (Rint)));
+         end if;
+
+         Set_Is_Static_Expression (N, Stat);
+      end;
+   end Eval_Op_Not;
+
+   -------------------------------
+   -- Eval_Qualified_Expression --
+   -------------------------------
+
+   --  A qualified expression is potentially static if its subtype mark denotes
+   --  a static subtype and its expression is potentially static (RM 4.9 (11)).
+
+   procedure Eval_Qualified_Expression (N : Node_Id) is
+      Operand     : constant Node_Id   := Expression (N);
+      Target_Type : constant Entity_Id := Entity (Subtype_Mark (N));
+
+      Stat  : Boolean;
+      Fold  : Boolean;
+
+   begin
+      --  Can only fold if target is string or scalar and subtype is static
+      --  Also, do not fold if our parent is an allocator (this is because
+      --  the qualified expression is really part of the syntactic structure
+      --  of an allocator, and we do not want to end up with something that
+      --  corresponds to "new 1" where the 1 is the result of folding a
+      --  qualified expression).
+
+      if not Is_Static_Subtype (Target_Type)
+        or else Nkind (Parent (N)) = N_Allocator
+      then
+         Check_Non_Static_Context (Operand);
+         return;
+      end if;
+
+      --  If not foldable we are done
+
+      Test_Expression_Is_Foldable (N, Operand, Stat, Fold);
+
+      if not Fold then
+         return;
+
+      --  Don't try fold if target type has constraint error bounds
+
+      elsif not Is_OK_Static_Subtype (Target_Type) then
+         Set_Raises_Constraint_Error (N);
+         return;
+      end if;
+
+      --  Fold the result of qualification
+
+      if Is_Discrete_Type (Target_Type) then
+         Fold_Uint (N, Expr_Value (Operand));
+         Set_Is_Static_Expression (N, Stat);
+
+      elsif Is_Real_Type (Target_Type) then
+         Fold_Ureal (N, Expr_Value_R (Operand));
+         Set_Is_Static_Expression (N, Stat);
+
+      else
+         Fold_Str (N, Strval (Get_String_Val (Operand)));
+
+         if not Stat then
+            Set_Is_Static_Expression (N, False);
+         else
+            Check_String_Literal_Length (N, Target_Type);
+         end if;
+
+         return;
+      end if;
+
+      if Is_Out_Of_Range (N, Etype (N)) then
+         Out_Of_Range (N);
+      end if;
+
+   end Eval_Qualified_Expression;
+
+   -----------------------
+   -- Eval_Real_Literal --
+   -----------------------
+
+   --  Numeric literals are static (RM 4.9(1)), and have already been marked
+   --  as static by the analyzer. The reason we did it that early is to allow
+   --  the possibility of turning off the Is_Static_Expression flag after
+   --  analysis, but before resolution, when integer literals are generated
+   --  in the expander that do not correspond to static expressions.
+
+   procedure Eval_Real_Literal (N : Node_Id) is
+   begin
+      --  If the literal appears in a non-expression context, then it is
+      --  certainly appearing in a non-static context, so check it.
+
+      if Nkind (Parent (N)) not in N_Subexpr then
+         Check_Non_Static_Context (N);
+      end if;
+
+   end Eval_Real_Literal;
+
+   ------------------------
+   -- Eval_Relational_Op --
+   ------------------------
+
+   --  Relational operations are static functions, so the result is static
+   --  if both operands are static (RM 4.9(7), 4.9(20)).
+
+   procedure Eval_Relational_Op (N : Node_Id) is
+      Left   : constant Node_Id   := Left_Opnd (N);
+      Right  : constant Node_Id   := Right_Opnd (N);
+      Typ    : constant Entity_Id := Etype (Left);
+      Result : Boolean;
+      Stat   : Boolean;
+      Fold   : Boolean;
+
+   begin
+      --  One special case to deal with first. If we can tell that
+      --  the result will be false because the lengths of one or
+      --  more index subtypes are compile time known and different,
+      --  then we can replace the entire result by False. We only
+      --  do this for one dimensional arrays, because the case of
+      --  multi-dimensional arrays is rare and too much trouble!
+
+      if Is_Array_Type (Typ)
+        and then Number_Dimensions (Typ) = 1
+        and then (Nkind (N) = N_Op_Eq
+                    or else Nkind (N) = N_Op_Ne)
+      then
+         if Raises_Constraint_Error (Left)
+           or else Raises_Constraint_Error (Right)
+         then
+            return;
+         end if;
+
+         declare
+            procedure Get_Static_Length (Op : Node_Id; Len : out Uint);
+            --  If Op is an expression for a constrained array with a
+            --  known at compile time length, then Len is set to this
+            --  (non-negative length). Otherwise Len is set to minus 1.
+
+            procedure Get_Static_Length (Op : Node_Id; Len : out Uint) is
+               T : Entity_Id;
+
+            begin
+               if Nkind (Op) = N_String_Literal then
+                  Len := UI_From_Int (String_Length (Strval (Op)));
+
+               elsif not Is_Constrained (Etype (Op)) then
+                  Len := Uint_Minus_1;
+
+               else
+                  T := Etype (First_Index (Etype (Op)));
+
+                  if Is_Discrete_Type (T)
+                    and then
+                      Compile_Time_Known_Value (Type_Low_Bound (T))
+                    and then
+                      Compile_Time_Known_Value (Type_High_Bound (T))
+                  then
+                     Len := UI_Max (Uint_0,
+                                     Expr_Value (Type_High_Bound (T)) -
+                                     Expr_Value (Type_Low_Bound  (T)) + 1);
+                  else
+                     Len := Uint_Minus_1;
+                  end if;
+               end if;
+            end Get_Static_Length;
+
+            Len_L : Uint;
+            Len_R : Uint;
+
+         begin
+            Get_Static_Length (Left,  Len_L);
+            Get_Static_Length (Right, Len_R);
+
+            if Len_L /= Uint_Minus_1
+              and then Len_R /= Uint_Minus_1
+              and then Len_L /= Len_R
+            then
+               Fold_Uint (N, Test (Nkind (N) = N_Op_Ne));
+               Set_Is_Static_Expression (N, False);
+               Warn_On_Known_Condition (N);
+               return;
+            end if;
+         end;
+      end if;
+
+      --  Can only fold if type is scalar (don't fold string ops)
+
+      if not Is_Scalar_Type (Typ) then
+         Check_Non_Static_Context (Left);
+         Check_Non_Static_Context (Right);
+         return;
+      end if;
+
+      --  If not foldable we are done
+
+      Test_Expression_Is_Foldable (N, Left, Right, Stat, Fold);
+
+      if not Fold then
+         return;
+      end if;
+
+      --  Integer and Enumeration (discrete) type cases
+
+      if Is_Discrete_Type (Typ) then
+         declare
+            Left_Int  : constant Uint := Expr_Value (Left);
+            Right_Int : constant Uint := Expr_Value (Right);
+
+         begin
+            case Nkind (N) is
+               when N_Op_Eq => Result := Left_Int =  Right_Int;
+               when N_Op_Ne => Result := Left_Int /= Right_Int;
+               when N_Op_Lt => Result := Left_Int <  Right_Int;
+               when N_Op_Le => Result := Left_Int <= Right_Int;
+               when N_Op_Gt => Result := Left_Int >  Right_Int;
+               when N_Op_Ge => Result := Left_Int >= Right_Int;
+
+               when others =>
+                  raise Program_Error;
+            end case;
+
+            Fold_Uint (N, Test (Result));
+         end;
+
+      --  Real type case
+
+      else
+         pragma Assert (Is_Real_Type (Typ));
+
+         declare
+            Left_Real  : constant Ureal := Expr_Value_R (Left);
+            Right_Real : constant Ureal := Expr_Value_R (Right);
+
+         begin
+            case Nkind (N) is
+               when N_Op_Eq => Result := (Left_Real =  Right_Real);
+               when N_Op_Ne => Result := (Left_Real /= Right_Real);
+               when N_Op_Lt => Result := (Left_Real <  Right_Real);
+               when N_Op_Le => Result := (Left_Real <= Right_Real);
+               when N_Op_Gt => Result := (Left_Real >  Right_Real);
+               when N_Op_Ge => Result := (Left_Real >= Right_Real);
+
+               when others =>
+                  raise Program_Error;
+            end case;
+
+            Fold_Uint (N, Test (Result));
+         end;
+      end if;
+
+      Set_Is_Static_Expression (N, Stat);
+      Warn_On_Known_Condition (N);
+   end Eval_Relational_Op;
+
+   ----------------
+   -- Eval_Shift --
+   ----------------
+
+   --  Shift operations are intrinsic operations that can never be static,
+   --  so the only processing required is to perform the required check for
+   --  a non static context for the two operands.
+
+   --  Actually we could do some compile time evaluation here some time ???
+
+   procedure Eval_Shift (N : Node_Id) is
+   begin
+      Check_Non_Static_Context (Left_Opnd (N));
+      Check_Non_Static_Context (Right_Opnd (N));
+   end Eval_Shift;
+
+   ------------------------
+   -- Eval_Short_Circuit --
+   ------------------------
+
+   --  A short circuit operation is potentially static if both operands
+   --  are potentially static (RM 4.9 (13))
+
+   procedure Eval_Short_Circuit (N : Node_Id) is
+      Kind     : constant Node_Kind := Nkind (N);
+      Left     : constant Node_Id   := Left_Opnd (N);
+      Right    : constant Node_Id   := Right_Opnd (N);
+      Left_Int : Uint;
+      Rstat    : constant Boolean   :=
+                   Is_Static_Expression (Left)
+                     and then Is_Static_Expression (Right);
+
+   begin
+      --  Short circuit operations are never static in Ada 83
+
+      if Ada_83
+        and then Comes_From_Source (N)
+      then
+         Check_Non_Static_Context (Left);
+         Check_Non_Static_Context (Right);
+         return;
+      end if;
+
+      --  Now look at the operands, we can't quite use the normal call to
+      --  Test_Expression_Is_Foldable here because short circuit operations
+      --  are a special case, they can still be foldable, even if the right
+      --  operand raises constraint error.
+
+      --  If either operand is Any_Type, just propagate to result and
+      --  do not try to fold, this prevents cascaded errors.
+
+      if Etype (Left) = Any_Type or else Etype (Right) = Any_Type then
+         Set_Etype (N, Any_Type);
+         return;
+
+      --  If left operand raises constraint error, then replace node N with
+      --  the raise constraint error node, and we are obviously not foldable.
+      --  Is_Static_Expression is set from the two operands in the normal way,
+      --  and we check the right operand if it is in a non-static context.
+
+      elsif Raises_Constraint_Error (Left) then
+         if not Rstat then
+            Check_Non_Static_Context (Right);
+         end if;
+
+         Rewrite_In_Raise_CE (N, Left);
+         Set_Is_Static_Expression (N, Rstat);
+         return;
+
+      --  If the result is not static, then we won't in any case fold
+
+      elsif not Rstat then
+         Check_Non_Static_Context (Left);
+         Check_Non_Static_Context (Right);
+         return;
+      end if;
+
+      --  Here the result is static, note that, unlike the normal processing
+      --  in Test_Expression_Is_Foldable, we did *not* check above to see if
+      --  the right operand raises constraint error, that's because it is not
+      --  significant if the left operand is decisive.
+
+      Set_Is_Static_Expression (N);
+
+      --  It does not matter if the right operand raises constraint error if
+      --  it will not be evaluated. So deal specially with the cases where
+      --  the right operand is not evaluated. Note that we will fold these
+      --  cases even if the right operand is non-static, which is fine, but
+      --  of course in these cases the result is not potentially static.
+
+      Left_Int := Expr_Value (Left);
+
+      if (Kind = N_And_Then and then Is_False (Left_Int))
+        or else (Kind = N_Or_Else and Is_True (Left_Int))
+      then
+         Fold_Uint (N, Left_Int);
+         return;
+      end if;
+
+      --  If first operand not decisive, then it does matter if the right
+      --  operand raises constraint error, since it will be evaluated, so
+      --  we simply replace the node with the right operand. Note that this
+      --  properly propagates Is_Static_Expression and Raises_Constraint_Error
+      --  (both are set to True in Right).
+
+      if Raises_Constraint_Error (Right) then
+         Rewrite_In_Raise_CE (N, Right);
+         Check_Non_Static_Context (Left);
+         return;
+      end if;
+
+      --  Otherwise the result depends on the right operand
+
+      Fold_Uint (N, Expr_Value (Right));
+      return;
+
+   end Eval_Short_Circuit;
+
+   ----------------
+   -- Eval_Slice --
+   ----------------
+
+   --  Slices can never be static, so the only processing required is to
+   --  check for non-static context if an explicit range is given.
+
+   procedure Eval_Slice (N : Node_Id) is
+      Drange : constant Node_Id := Discrete_Range (N);
+
+   begin
+      if Nkind (Drange) = N_Range then
+         Check_Non_Static_Context (Low_Bound (Drange));
+         Check_Non_Static_Context (High_Bound (Drange));
+      end if;
+   end Eval_Slice;
+
+   -------------------------
+   -- Eval_String_Literal --
+   -------------------------
+
+   procedure Eval_String_Literal (N : Node_Id) is
+      T : constant Entity_Id := Etype (N);
+      B : constant Entity_Id := Base_Type (T);
+      I : Entity_Id;
+
+   begin
+      --  Nothing to do if error type (handles cases like default expressions
+      --  or generics where we have not yet fully resolved the type)
+
+      if B = Any_Type or else B = Any_String then
+         return;
+
+      --  String literals are static if the subtype is static (RM 4.9(2)), so
+      --  reset the static expression flag (it was set unconditionally in
+      --  Analyze_String_Literal) if the subtype is non-static. We tell if
+      --  the subtype is static by looking at the lower bound.
+
+      elsif not Is_OK_Static_Expression (String_Literal_Low_Bound (T)) then
+         Set_Is_Static_Expression (N, False);
+
+      elsif Nkind (Original_Node (N)) = N_Type_Conversion then
+         Set_Is_Static_Expression (N, False);
+
+      --  Test for illegal Ada 95 cases. A string literal is illegal in
+      --  Ada 95 if its bounds are outside the index base type and this
+      --  index type is static. This can hapen in only two ways. Either
+      --  the string literal is too long, or it is null, and the lower
+      --  bound is type'First. In either case it is the upper bound that
+      --  is out of range of the index type.
+
+      elsif Ada_95 then
+         if Root_Type (B) = Standard_String
+           or else Root_Type (B) = Standard_Wide_String
+         then
+            I := Standard_Positive;
+         else
+            I := Etype (First_Index (B));
+         end if;
+
+         if String_Literal_Length (T) > String_Type_Len (B) then
+            Apply_Compile_Time_Constraint_Error
+              (N, "string literal too long for}",
+               Ent => B,
+               Typ => First_Subtype (B));
+
+         elsif String_Literal_Length (T) = 0
+            and then not Is_Generic_Type (I)
+            and then Expr_Value (String_Literal_Low_Bound (T)) =
+                     Expr_Value (Type_Low_Bound (Base_Type (I)))
+         then
+            Apply_Compile_Time_Constraint_Error
+              (N, "null string literal not allowed for}",
+               Ent => B,
+               Typ => First_Subtype (B));
+         end if;
+      end if;
+
+   end Eval_String_Literal;
+
+   --------------------------
+   -- Eval_Type_Conversion --
+   --------------------------
+
+   --  A type conversion is potentially static if its subtype mark is for a
+   --  static scalar subtype, and its operand expression is potentially static
+   --  (RM 4.9 (10))
+
+   procedure Eval_Type_Conversion (N : Node_Id) is
+      Operand     : constant Node_Id   := Expression (N);
+      Source_Type : constant Entity_Id := Etype (Operand);
+      Target_Type : constant Entity_Id := Etype (N);
+
+      Stat   : Boolean;
+      Fold   : Boolean;
+
+      function To_Be_Treated_As_Integer (T : Entity_Id) return Boolean;
+      --  Returns true if type T is an integer type, or if it is a
+      --  fixed-point type to be treated as an integer (i.e. the flag
+      --  Conversion_OK is set on the conversion node).
+
+      function To_Be_Treated_As_Real (T : Entity_Id) return Boolean;
+      --  Returns true if type T is a floating-point type, or if it is a
+      --  fixed-point type that is not to be treated as an integer (i.e. the
+      --  flag Conversion_OK is not set on the conversion node).
+
+      function To_Be_Treated_As_Integer (T : Entity_Id) return Boolean is
+      begin
+         return
+           Is_Integer_Type (T)
+             or else (Is_Fixed_Point_Type (T) and then Conversion_OK (N));
+      end To_Be_Treated_As_Integer;
+
+      function To_Be_Treated_As_Real (T : Entity_Id) return Boolean is
+      begin
+         return
+           Is_Floating_Point_Type (T)
+             or else (Is_Fixed_Point_Type (T) and then not Conversion_OK (N));
+      end To_Be_Treated_As_Real;
+
+   --  Start of processing for Eval_Type_Conversion
+
+   begin
+      --  Cannot fold if target type is non-static or if semantic error.
+
+      if not Is_Static_Subtype (Target_Type) then
+         Check_Non_Static_Context (Operand);
+         return;
+
+      elsif Error_Posted (N) then
+         return;
+      end if;
+
+      --  If not foldable we are done
+
+      Test_Expression_Is_Foldable (N, Operand, Stat, Fold);
+
+      if not Fold then
+         return;
+
+      --  Don't try fold if target type has constraint error bounds
+
+      elsif not Is_OK_Static_Subtype (Target_Type) then
+         Set_Raises_Constraint_Error (N);
+         return;
+      end if;
+
+      --  Remaining processing depends on operand types. Note that in the
+      --  following type test, fixed-point counts as real unless the flag
+      --  Conversion_OK is set, in which case it counts as integer.
+
+      --  Fold conversion, case of string type. The result is not static.
+
+      if Is_String_Type (Target_Type) then
+         Fold_Str (N, Strval (Get_String_Val (Operand)));
+         Set_Is_Static_Expression (N, False);
+
+         return;
+
+      --  Fold conversion, case of integer target type
+
+      elsif To_Be_Treated_As_Integer (Target_Type) then
+         declare
+            Result : Uint;
+
+         begin
+            --  Integer to integer conversion
+
+            if To_Be_Treated_As_Integer (Source_Type) then
+               Result := Expr_Value (Operand);
+
+            --  Real to integer conversion
+
+            else
+               Result := UR_To_Uint (Expr_Value_R (Operand));
+            end if;
+
+            --  If fixed-point type (Conversion_OK must be set), then the
+            --  result is logically an integer, but we must replace the
+            --  conversion with the corresponding real literal, since the
+            --  type from a semantic point of view is still fixed-point.
+
+            if Is_Fixed_Point_Type (Target_Type) then
+               Fold_Ureal
+                 (N, UR_From_Uint (Result) * Small_Value (Target_Type));
+
+            --  Otherwise result is integer literal
+
+            else
+               Fold_Uint (N, Result);
+            end if;
+         end;
+
+      --  Fold conversion, case of real target type
+
+      elsif To_Be_Treated_As_Real (Target_Type) then
+         declare
+            Result : Ureal;
+
+         begin
+            if To_Be_Treated_As_Real (Source_Type) then
+               Result := Expr_Value_R (Operand);
+            else
+               Result := UR_From_Uint (Expr_Value (Operand));
+            end if;
+
+            Fold_Ureal (N, Result);
+         end;
+
+      --  Enumeration types
+
+      else
+         Fold_Uint (N, Expr_Value (Operand));
+      end if;
+
+      Set_Is_Static_Expression (N, Stat);
+
+      if Is_Out_Of_Range (N, Etype (N)) then
+         Out_Of_Range (N);
+      end if;
+
+   end Eval_Type_Conversion;
+
+   -------------------
+   -- Eval_Unary_Op --
+   -------------------
+
+   --  Predefined unary operators are static functions (RM 4.9(20)) and thus
+   --  are potentially static if the operand is potentially static (RM 4.9(7))
+
+   procedure Eval_Unary_Op (N : Node_Id) is
+      Right : constant Node_Id := Right_Opnd (N);
+      Stat  : Boolean;
+      Fold  : Boolean;
+
+   begin
+      --  If not foldable we are done
+
+      Test_Expression_Is_Foldable (N, Right, Stat, Fold);
+
+      if not Fold then
+         return;
+      end if;
+
+      --  Fold for integer case
+
+      if Is_Integer_Type (Etype (N)) then
+         declare
+            Rint   : constant Uint := Expr_Value (Right);
+            Result : Uint;
+
+         begin
+            --  In the case of modular unary plus and abs there is no need
+            --  to adjust the result of the operation since if the original
+            --  operand was in bounds the result will be in the bounds of the
+            --  modular type. However, in the case of modular unary minus the
+            --  result may go out of the bounds of the modular type and needs
+            --  adjustment.
+
+            if Nkind (N) = N_Op_Plus then
+               Result := Rint;
+
+            elsif Nkind (N) = N_Op_Minus then
+               if Is_Modular_Integer_Type (Etype (N)) then
+                  Result := (-Rint) mod Modulus (Etype (N));
+               else
+                  Result := (-Rint);
+               end if;
+
+            else
+               pragma Assert (Nkind (N) = N_Op_Abs);
+               Result := abs Rint;
+            end if;
+
+            Fold_Uint (N, Result);
+         end;
+
+      --  Fold for real case
+
+      elsif Is_Real_Type (Etype (N)) then
+         declare
+            Rreal  : constant Ureal := Expr_Value_R (Right);
+            Result : Ureal;
+
+         begin
+            if Nkind (N) = N_Op_Plus then
+               Result := Rreal;
+
+            elsif Nkind (N) = N_Op_Minus then
+               Result := UR_Negate (Rreal);
+
+            else
+               pragma Assert (Nkind (N) = N_Op_Abs);
+               Result := abs Rreal;
+            end if;
+
+            Fold_Ureal (N, Result);
+         end;
+      end if;
+
+      Set_Is_Static_Expression (N, Stat);
+
+   end Eval_Unary_Op;
+
+   -------------------------------
+   -- Eval_Unchecked_Conversion --
+   -------------------------------
+
+   --  Unchecked conversions can never be static, so the only required
+   --  processing is to check for a non-static context for the operand.
+
+   procedure Eval_Unchecked_Conversion (N : Node_Id) is
+   begin
+      Check_Non_Static_Context (Expression (N));
+   end Eval_Unchecked_Conversion;
+
+   --------------------
+   -- Expr_Rep_Value --
+   --------------------
+
+   function Expr_Rep_Value (N : Node_Id) return Uint is
+      Kind   : constant Node_Kind := Nkind (N);
+      Ent    : Entity_Id;
+
+   begin
+      if Is_Entity_Name (N) then
+         Ent := Entity (N);
+
+         --  An enumeration literal that was either in the source or
+         --  created as a result of static evaluation.
+
+         if Ekind (Ent) = E_Enumeration_Literal then
+            return Enumeration_Rep (Ent);
+
+         --  A user defined static constant
+
+         else
+            pragma Assert (Ekind (Ent) = E_Constant);
+            return Expr_Rep_Value (Constant_Value (Ent));
+         end if;
+
+      --  An integer literal that was either in the source or created
+      --  as a result of static evaluation.
+
+      elsif Kind = N_Integer_Literal then
+         return Intval (N);
+
+      --  A real literal for a fixed-point type. This must be the fixed-point
+      --  case, either the literal is of a fixed-point type, or it is a bound
+      --  of a fixed-point type, with type universal real. In either case we
+      --  obtain the desired value from Corresponding_Integer_Value.
+
+      elsif Kind = N_Real_Literal then
+
+         --  Apply the assertion to the Underlying_Type of the literal for
+         --  the benefit of calls to this function in the JGNAT back end,
+         --  where literal types can reflect private views.
+
+         pragma Assert (Is_Fixed_Point_Type (Underlying_Type (Etype (N))));
+         return Corresponding_Integer_Value (N);
+
+      else
+         pragma Assert (Kind = N_Character_Literal);
+         Ent := Entity (N);
+
+         --  Since Character literals of type Standard.Character don't
+         --  have any defining character literals built for them, they
+         --  do not have their Entity set, so just use their Char
+         --  code. Otherwise for user-defined character literals use
+         --  their Pos value as usual which is the same as the Rep value.
+
+         if No (Ent) then
+            return UI_From_Int (Int (Char_Literal_Value (N)));
+         else
+            return Enumeration_Rep (Ent);
+         end if;
+      end if;
+   end Expr_Rep_Value;
+
+   ----------------
+   -- Expr_Value --
+   ----------------
+
+   function Expr_Value (N : Node_Id) return Uint is
+      Kind : constant Node_Kind := Nkind (N);
+      Ent  : Entity_Id;
+
+   begin
+      if Is_Entity_Name (N) then
+         Ent := Entity (N);
+
+         --  An enumeration literal that was either in the source or
+         --  created as a result of static evaluation.
+
+         if Ekind (Ent) = E_Enumeration_Literal then
+            return Enumeration_Pos (Ent);
+
+         --  A user defined static constant
+
+         else
+            pragma Assert (Ekind (Ent) = E_Constant);
+            return Expr_Value (Constant_Value (Ent));
+         end if;
+
+      --  An integer literal that was either in the source or created
+      --  as a result of static evaluation.
+
+      elsif Kind = N_Integer_Literal then
+         return Intval (N);
+
+      --  A real literal for a fixed-point type. This must be the fixed-point
+      --  case, either the literal is of a fixed-point type, or it is a bound
+      --  of a fixed-point type, with type universal real. In either case we
+      --  obtain the desired value from Corresponding_Integer_Value.
+
+      elsif Kind = N_Real_Literal then
+
+         --  Apply the assertion to the Underlying_Type of the literal for
+         --  the benefit of calls to this function in the JGNAT back end,
+         --  where literal types can reflect private views.
+
+         pragma Assert (Is_Fixed_Point_Type (Underlying_Type (Etype (N))));
+         return Corresponding_Integer_Value (N);
+
+      --  Peculiar VMS case, if we have xxx'Null_Parameter, return zero
+
+      elsif Kind = N_Attribute_Reference
+        and then Attribute_Name (N) = Name_Null_Parameter
+      then
+         return Uint_0;
+
+      --  Otherwise must be character literal
+
+      else
+         pragma Assert (Kind = N_Character_Literal);
+         Ent := Entity (N);
+
+         --  Since Character literals of type Standard.Character don't
+         --  have any defining character literals built for them, they
+         --  do not have their Entity set, so just use their Char
+         --  code. Otherwise for user-defined character literals use
+         --  their Pos value as usual.
+
+         if No (Ent) then
+            return UI_From_Int (Int (Char_Literal_Value (N)));
+         else
+            return Enumeration_Pos (Ent);
+         end if;
+      end if;
+
+   end Expr_Value;
+
+   ------------------
+   -- Expr_Value_E --
+   ------------------
+
+   function Expr_Value_E (N : Node_Id) return Entity_Id is
+      Ent  : constant Entity_Id := Entity (N);
+
+   begin
+      if Ekind (Ent) = E_Enumeration_Literal then
+         return Ent;
+      else
+         pragma Assert (Ekind (Ent) = E_Constant);
+         return Expr_Value_E (Constant_Value (Ent));
+      end if;
+   end Expr_Value_E;
+
+   ------------------
+   -- Expr_Value_R --
+   ------------------
+
+   function Expr_Value_R (N : Node_Id) return Ureal is
+      Kind : constant Node_Kind := Nkind (N);
+      Ent  : Entity_Id;
+      Expr : Node_Id;
+
+   begin
+      if Kind = N_Real_Literal then
+         return Realval (N);
+
+      elsif Kind = N_Identifier or else Kind = N_Expanded_Name then
+         Ent := Entity (N);
+         pragma Assert (Ekind (Ent) = E_Constant);
+         return Expr_Value_R (Constant_Value (Ent));
+
+      elsif Kind = N_Integer_Literal then
+         return UR_From_Uint (Expr_Value (N));
+
+      --  Strange case of VAX literals, which are at this stage transformed
+      --  into Vax_Type!x_To_y(IEEE_Literal). See Expand_N_Real_Literal in
+      --  Exp_Vfpt for further details.
+
+      elsif Vax_Float (Etype (N))
+        and then Nkind (N) = N_Unchecked_Type_Conversion
+      then
+         Expr := Expression (N);
+
+         if Nkind (Expr) = N_Function_Call
+           and then Present (Parameter_Associations (Expr))
+         then
+            Expr := First (Parameter_Associations (Expr));
+
+            if Nkind (Expr) = N_Real_Literal then
+               return Realval (Expr);
+            end if;
+         end if;
+
+      --  Peculiar VMS case, if we have xxx'Null_Parameter, return 0.0
+
+      elsif Kind = N_Attribute_Reference
+        and then Attribute_Name (N) = Name_Null_Parameter
+      then
+         return Ureal_0;
+      end if;
+
+      --  If we fall through, we have a node that cannot be interepreted
+      --  as a compile time constant. That is definitely an error.
+
+      raise Program_Error;
+   end Expr_Value_R;
+
+   ------------------
+   -- Expr_Value_S --
+   ------------------
+
+   function Expr_Value_S (N : Node_Id) return Node_Id is
+   begin
+      if Nkind (N) = N_String_Literal then
+         return N;
+      else
+         pragma Assert (Ekind (Entity (N)) = E_Constant);
+         return Expr_Value_S (Constant_Value (Entity (N)));
+      end if;
+   end Expr_Value_S;
+
+   --------------
+   -- Fold_Str --
+   --------------
+
+   procedure Fold_Str (N : Node_Id; Val : String_Id) is
+      Loc : constant Source_Ptr := Sloc (N);
+      Typ : constant Entity_Id  := Etype (N);
+
+   begin
+      Rewrite (N, Make_String_Literal (Loc, Strval => Val));
+      Analyze_And_Resolve (N, Typ);
+   end Fold_Str;
+
+   ---------------
+   -- Fold_Uint --
+   ---------------
+
+   procedure Fold_Uint (N : Node_Id; Val : Uint) is
+      Loc : constant Source_Ptr := Sloc (N);
+      Typ : constant Entity_Id  := Etype (N);
+
+   begin
+      --  For a result of type integer, subsitute an N_Integer_Literal node
+      --  for the result of the compile time evaluation of the expression.
+
+      if Is_Integer_Type (Etype (N)) then
+         Rewrite (N, Make_Integer_Literal (Loc, Val));
+
+      --  Otherwise we have an enumeration type, and we substitute either
+      --  an N_Identifier or N_Character_Literal to represent the enumeration
+      --  literal corresponding to the given value, which must always be in
+      --  range, because appropriate tests have already been made for this.
+
+      else pragma Assert (Is_Enumeration_Type (Etype (N)));
+         Rewrite (N, Get_Enum_Lit_From_Pos (Etype (N), Val, Loc));
+      end if;
+
+      --  We now have the literal with the right value, both the actual type
+      --  and the expected type of this literal are taken from the expression
+      --  that was evaluated.
+
+      Analyze (N);
+      Set_Etype (N, Typ);
+      Resolve (N, Typ);
+   end Fold_Uint;
+
+   ----------------
+   -- Fold_Ureal --
+   ----------------
+
+   procedure Fold_Ureal (N : Node_Id; Val : Ureal) is
+      Loc : constant Source_Ptr := Sloc (N);
+      Typ : constant Entity_Id  := Etype (N);
+
+   begin
+      Rewrite (N, Make_Real_Literal (Loc, Realval => Val));
+      Analyze (N);
+
+      --  Both the actual and expected type comes from the original expression
+
+      Set_Etype (N, Typ);
+      Resolve (N, Typ);
+   end Fold_Ureal;
+
+   ---------------
+   -- From_Bits --
+   ---------------
+
+   function From_Bits (B : Bits; T : Entity_Id) return Uint is
+      V : Uint := Uint_0;
+
+   begin
+      for J in 0 .. B'Last loop
+         if B (J) then
+            V := V + 2 ** J;
+         end if;
+      end loop;
+
+      if Non_Binary_Modulus (T) then
+         V := V mod Modulus (T);
+      end if;
+
+      return V;
+   end From_Bits;
+
+   --------------------
+   -- Get_String_Val --
+   --------------------
+
+   function Get_String_Val (N : Node_Id) return Node_Id is
+   begin
+      if Nkind (N) = N_String_Literal then
+         return N;
+
+      elsif Nkind (N) = N_Character_Literal then
+         return N;
+
+      else
+         pragma Assert (Is_Entity_Name (N));
+         return Get_String_Val (Constant_Value (Entity (N)));
+      end if;
+   end Get_String_Val;
+
+   --------------------
+   -- In_Subrange_Of --
+   --------------------
+
+   function In_Subrange_Of
+     (T1        : Entity_Id;
+      T2        : Entity_Id;
+      Fixed_Int : Boolean := False)
+      return      Boolean
+   is
+      L1 : Node_Id;
+      H1 : Node_Id;
+
+      L2 : Node_Id;
+      H2 : Node_Id;
+
+   begin
+      if T1 = T2 or else Is_Subtype_Of (T1, T2) then
+         return True;
+
+      --  Never in range if both types are not scalar. Don't know if this can
+      --  actually happen, but just in case.
+
+      elsif not Is_Scalar_Type (T1) or else not Is_Scalar_Type (T1) then
+         return False;
+
+      else
+         L1 := Type_Low_Bound  (T1);
+         H1 := Type_High_Bound (T1);
+
+         L2 := Type_Low_Bound  (T2);
+         H2 := Type_High_Bound (T2);
+
+         --  Check bounds to see if comparison possible at compile time
+
+         if Compile_Time_Compare (L1, L2) in Compare_GE
+              and then
+            Compile_Time_Compare (H1, H2) in Compare_LE
+         then
+            return True;
+         end if;
+
+         --  If bounds not comparable at compile time, then the bounds of T2
+         --  must be compile time known or we cannot answer the query.
+
+         if not Compile_Time_Known_Value (L2)
+           or else not Compile_Time_Known_Value (H2)
+         then
+            return False;
+         end if;
+
+         --  If the bounds of T1 are know at compile time then use these
+         --  ones, otherwise use the bounds of the base type (which are of
+         --  course always static).
+
+         if not Compile_Time_Known_Value (L1) then
+            L1 := Type_Low_Bound (Base_Type (T1));
+         end if;
+
+         if not Compile_Time_Known_Value (H1) then
+            H1 := Type_High_Bound (Base_Type (T1));
+         end if;
+
+         --  Fixed point types should be considered as such only if
+         --  flag Fixed_Int is set to False.
+
+         if Is_Floating_Point_Type (T1) or else Is_Floating_Point_Type (T2)
+           or else (Is_Fixed_Point_Type (T1) and then not Fixed_Int)
+           or else (Is_Fixed_Point_Type (T2) and then not Fixed_Int)
+         then
+            return
+              Expr_Value_R (L2) <= Expr_Value_R (L1)
+                and then
+              Expr_Value_R (H2) >= Expr_Value_R (H1);
+
+         else
+            return
+              Expr_Value (L2) <= Expr_Value (L1)
+                and then
+              Expr_Value (H2) >= Expr_Value (H1);
+
+         end if;
+      end if;
+
+   --  If any exception occurs, it means that we have some bug in the compiler
+   --  possibly triggered by a previous error, or by some unforseen peculiar
+   --  occurrence. However, this is only an optimization attempt, so there is
+   --  really no point in crashing the compiler. Instead we just decide, too
+   --  bad, we can't figure out the answer in this case after all.
+
+   exception
+      when others =>
+
+         --  Debug flag K disables this behavior (useful for debugging)
+
+         if Debug_Flag_K then
+            raise;
+         else
+            return False;
+         end if;
+   end In_Subrange_Of;
+
+   -----------------
+   -- Is_In_Range --
+   -----------------
+
+   function Is_In_Range
+     (N         : Node_Id;
+      Typ       : Entity_Id;
+      Fixed_Int : Boolean := False;
+      Int_Real  : Boolean := False)
+      return      Boolean
+   is
+      Val  : Uint;
+      Valr : Ureal;
+
+   begin
+      --  Universal types have no range limits, so always in range.
+
+      if Typ = Universal_Integer or else Typ = Universal_Real then
+         return True;
+
+      --  Never in range if not scalar type. Don't know if this can
+      --  actually happen, but our spec allows it, so we must check!
+
+      elsif not Is_Scalar_Type (Typ) then
+         return False;
+
+      --  Never in range unless we have a compile time known value.
+
+      elsif not Compile_Time_Known_Value (N) then
+         return False;
+
+      else
+         declare
+            Lo       : constant Node_Id := Type_Low_Bound  (Typ);
+            Hi       : constant Node_Id := Type_High_Bound (Typ);
+            LB_Known : constant Boolean := Compile_Time_Known_Value (Lo);
+            UB_Known : constant Boolean := Compile_Time_Known_Value (Hi);
+
+         begin
+            --  Fixed point types should be considered as such only in
+            --  flag Fixed_Int is set to False.
+
+            if Is_Floating_Point_Type (Typ)
+              or else (Is_Fixed_Point_Type (Typ) and then not Fixed_Int)
+              or else Int_Real
+            then
+               Valr := Expr_Value_R (N);
+
+               if LB_Known and then Valr >= Expr_Value_R (Lo)
+                 and then UB_Known and then Valr <= Expr_Value_R (Hi)
+               then
+                  return True;
+               else
+                  return False;
+               end if;
+
+            else
+               Val := Expr_Value (N);
+
+               if         LB_Known and then Val >= Expr_Value (Lo)
+                 and then UB_Known and then Val <= Expr_Value (Hi)
+               then
+                  return True;
+               else
+                  return False;
+               end if;
+            end if;
+         end;
+      end if;
+   end Is_In_Range;
+
+   -------------------
+   -- Is_Null_Range --
+   -------------------
+
+   function Is_Null_Range (Lo : Node_Id; Hi : Node_Id) return Boolean is
+      Typ : constant Entity_Id := Etype (Lo);
+
+   begin
+      if not Compile_Time_Known_Value (Lo)
+        or else not Compile_Time_Known_Value (Hi)
+      then
+         return False;
+      end if;
+
+      if Is_Discrete_Type (Typ) then
+         return Expr_Value (Lo) > Expr_Value (Hi);
+
+      else
+         pragma Assert (Is_Real_Type (Typ));
+         return Expr_Value_R (Lo) > Expr_Value_R (Hi);
+      end if;
+   end Is_Null_Range;
+
+   -----------------------------
+   -- Is_OK_Static_Expression --
+   -----------------------------
+
+   function Is_OK_Static_Expression (N : Node_Id) return Boolean is
+   begin
+      return Is_Static_Expression (N)
+        and then not Raises_Constraint_Error (N);
+   end Is_OK_Static_Expression;
+
+   ------------------------
+   -- Is_OK_Static_Range --
+   ------------------------
+
+   --  A static range is a range whose bounds are static expressions, or a
+   --  Range_Attribute_Reference equivalent to such a range (RM 4.9(26)).
+   --  We have already converted range attribute references, so we get the
+   --  "or" part of this rule without needing a special test.
+
+   function Is_OK_Static_Range (N : Node_Id) return Boolean is
+   begin
+      return Is_OK_Static_Expression (Low_Bound (N))
+        and then Is_OK_Static_Expression (High_Bound (N));
+   end Is_OK_Static_Range;
+
+   --------------------------
+   -- Is_OK_Static_Subtype --
+   --------------------------
+
+   --  Determines if Typ is a static subtype as defined in (RM 4.9(26))
+   --  where neither bound raises constraint error when evaluated.
+
+   function Is_OK_Static_Subtype (Typ : Entity_Id) return Boolean is
+      Base_T   : constant Entity_Id := Base_Type (Typ);
+      Anc_Subt : Entity_Id;
+
+   begin
+      --  First a quick check on the non static subtype flag. As described
+      --  in further detail in Einfo, this flag is not decisive in all cases,
+      --  but if it is set, then the subtype is definitely non-static.
+
+      if Is_Non_Static_Subtype (Typ) then
+         return False;
+      end if;
+
+      Anc_Subt := Ancestor_Subtype (Typ);
+
+      if Anc_Subt = Empty then
+         Anc_Subt := Base_T;
+      end if;
+
+      if Is_Generic_Type (Root_Type (Base_T))
+        or else Is_Generic_Actual_Type (Base_T)
+      then
+         return False;
+
+      --  String types
+
+      elsif Is_String_Type (Typ) then
+         return
+           Ekind (Typ) = E_String_Literal_Subtype
+             or else
+           (Is_OK_Static_Subtype (Component_Type (Typ))
+              and then Is_OK_Static_Subtype (Etype (First_Index (Typ))));
+
+      --  Scalar types
+
+      elsif Is_Scalar_Type (Typ) then
+         if Base_T = Typ then
+            return True;
+
+         else
+            --  Scalar_Range (Typ) might be an N_Subtype_Indication, so
+            --  use Get_Type_Low,High_Bound.
+
+            return     Is_OK_Static_Subtype (Anc_Subt)
+              and then Is_OK_Static_Expression (Type_Low_Bound (Typ))
+              and then Is_OK_Static_Expression (Type_High_Bound (Typ));
+         end if;
+
+      --  Types other than string and scalar types are never static
+
+      else
+         return False;
+      end if;
+   end Is_OK_Static_Subtype;
+
+   ---------------------
+   -- Is_Out_Of_Range --
+   ---------------------
+
+   function Is_Out_Of_Range
+     (N         : Node_Id;
+      Typ       : Entity_Id;
+      Fixed_Int : Boolean := False;
+      Int_Real  : Boolean := False)
+      return      Boolean
+   is
+      Val  : Uint;
+      Valr : Ureal;
+
+   begin
+      --  Universal types have no range limits, so always in range.
+
+      if Typ = Universal_Integer or else Typ = Universal_Real then
+         return False;
+
+      --  Never out of range if not scalar type. Don't know if this can
+      --  actually happen, but our spec allows it, so we must check!
+
+      elsif not Is_Scalar_Type (Typ) then
+         return False;
+
+      --  Never out of range if this is a generic type, since the bounds
+      --  of generic types are junk. Note that if we only checked for
+      --  static expressions (instead of compile time known values) below,
+      --  we would not need this check, because values of a generic type
+      --  can never be static, but they can be known at compile time.
+
+      elsif Is_Generic_Type (Typ) then
+         return False;
+
+      --  Never out of range unless we have a compile time known value.
+
+      elsif not Compile_Time_Known_Value (N) then
+         return False;
+
+      else
+         declare
+            Lo       : constant Node_Id := Type_Low_Bound  (Typ);
+            Hi       : constant Node_Id := Type_High_Bound (Typ);
+            LB_Known : constant Boolean := Compile_Time_Known_Value (Lo);
+            UB_Known : constant Boolean := Compile_Time_Known_Value (Hi);
+
+         begin
+            --  Real types (note that fixed-point types are not treated
+            --  as being of a real type if the flag Fixed_Int is set,
+            --  since in that case they are regarded as integer types).
+
+            if Is_Floating_Point_Type (Typ)
+              or else (Is_Fixed_Point_Type (Typ) and then not Fixed_Int)
+              or else Int_Real
+            then
+               Valr := Expr_Value_R (N);
+
+               if LB_Known and then Valr < Expr_Value_R (Lo) then
+                  return True;
+
+               elsif UB_Known and then Expr_Value_R (Hi) < Valr then
+                  return True;
+
+               else
+                  return False;
+               end if;
+
+            else
+               Val := Expr_Value (N);
+
+               if LB_Known and then Val < Expr_Value (Lo) then
+                  return True;
+
+               elsif UB_Known and then Expr_Value (Hi) < Val then
+                  return True;
+
+               else
+                  return False;
+               end if;
+            end if;
+         end;
+      end if;
+   end Is_Out_Of_Range;
+
+   ---------------------
+   -- Is_Static_Range --
+   ---------------------
+
+   --  A static range is a range whose bounds are static expressions, or a
+   --  Range_Attribute_Reference equivalent to such a range (RM 4.9(26)).
+   --  We have already converted range attribute references, so we get the
+   --  "or" part of this rule without needing a special test.
+
+   function Is_Static_Range (N : Node_Id) return Boolean is
+   begin
+      return Is_Static_Expression (Low_Bound (N))
+        and then Is_Static_Expression (High_Bound (N));
+   end Is_Static_Range;
+
+   -----------------------
+   -- Is_Static_Subtype --
+   -----------------------
+
+   --  Determines if Typ is a static subtype as defined in (RM 4.9(26)).
+
+   function Is_Static_Subtype (Typ : Entity_Id) return Boolean is
+      Base_T   : constant Entity_Id := Base_Type (Typ);
+      Anc_Subt : Entity_Id;
+
+   begin
+      --  First a quick check on the non static subtype flag. As described
+      --  in further detail in Einfo, this flag is not decisive in all cases,
+      --  but if it is set, then the subtype is definitely non-static.
+
+      if Is_Non_Static_Subtype (Typ) then
+         return False;
+      end if;
+
+      Anc_Subt := Ancestor_Subtype (Typ);
+
+      if Anc_Subt = Empty then
+         Anc_Subt := Base_T;
+      end if;
+
+      if Is_Generic_Type (Root_Type (Base_T))
+        or else Is_Generic_Actual_Type (Base_T)
+      then
+         return False;
+
+      --  String types
+
+      elsif Is_String_Type (Typ) then
+         return
+           Ekind (Typ) = E_String_Literal_Subtype
+             or else
+           (Is_Static_Subtype (Component_Type (Typ))
+              and then Is_Static_Subtype (Etype (First_Index (Typ))));
+
+      --  Scalar types
+
+      elsif Is_Scalar_Type (Typ) then
+         if Base_T = Typ then
+            return True;
+
+         else
+            return     Is_Static_Subtype (Anc_Subt)
+              and then Is_Static_Expression (Type_Low_Bound (Typ))
+              and then Is_Static_Expression (Type_High_Bound (Typ));
+         end if;
+
+      --  Types other than string and scalar types are never static
+
+      else
+         return False;
+      end if;
+   end Is_Static_Subtype;
+
+   --------------------
+   -- Not_Null_Range --
+   --------------------
+
+   function Not_Null_Range (Lo : Node_Id; Hi : Node_Id) return Boolean is
+      Typ : constant Entity_Id := Etype (Lo);
+
+   begin
+      if not Compile_Time_Known_Value (Lo)
+        or else not Compile_Time_Known_Value (Hi)
+      then
+         return False;
+      end if;
+
+      if Is_Discrete_Type (Typ) then
+         return Expr_Value (Lo) <= Expr_Value (Hi);
+
+      else
+         pragma Assert (Is_Real_Type (Typ));
+
+         return Expr_Value_R (Lo) <= Expr_Value_R (Hi);
+      end if;
+   end Not_Null_Range;
+
+   -------------
+   -- OK_Bits --
+   -------------
+
+   function OK_Bits (N : Node_Id; Bits : Uint) return Boolean is
+   begin
+      --  We allow a maximum of 500,000 bits which seems a reasonable limit
+
+      if Bits < 500_000 then
+         return True;
+
+      else
+         Error_Msg_N ("static value too large, capacity exceeded", N);
+         return False;
+      end if;
+   end OK_Bits;
+
+   ------------------
+   -- Out_Of_Range --
+   ------------------
+
+   procedure Out_Of_Range (N : Node_Id) is
+   begin
+      --  If we have the static expression case, then this is an illegality
+      --  in Ada 95 mode, except that in an instance, we never generate an
+      --  error (if the error is legitimate, it was already diagnosed in
+      --  the template). The expression to compute the length of a packed
+      --  array is attached to the array type itself, and deserves a separate
+      --  message.
+
+      if Is_Static_Expression (N)
+        and then not In_Instance
+        and then Ada_95
+      then
+
+         if Nkind (Parent (N)) = N_Defining_Identifier
+           and then Is_Array_Type (Parent (N))
+           and then Present (Packed_Array_Type (Parent (N)))
+           and then Present (First_Rep_Item (Parent (N)))
+         then
+            Error_Msg_N
+             ("length of packed array must not exceed Integer''Last",
+              First_Rep_Item (Parent (N)));
+            Rewrite (N, Make_Integer_Literal (Sloc (N), Uint_1));
+
+         else
+            Apply_Compile_Time_Constraint_Error
+              (N, "value not in range of}");
+         end if;
+
+      --  Here we generate a warning for the Ada 83 case, or when we are
+      --  in an instance, or when we have a non-static expression case.
+
+      else
+         Warn_On_Instance := True;
+         Apply_Compile_Time_Constraint_Error
+           (N, "value not in range of}?");
+         Warn_On_Instance := False;
+      end if;
+   end Out_Of_Range;
+
+   -------------------------
+   -- Rewrite_In_Raise_CE --
+   -------------------------
+
+   procedure Rewrite_In_Raise_CE (N : Node_Id; Exp : Node_Id) is
+      Typ : constant Entity_Id := Etype (N);
+
+   begin
+      --  If we want to raise CE in the condition of a raise_CE node
+      --  we may as well get rid of the condition
+
+      if Present (Parent (N))
+        and then Nkind (Parent (N)) = N_Raise_Constraint_Error
+      then
+         Set_Condition (Parent (N), Empty);
+
+      --  If the expression raising CE is a N_Raise_CE node, we can use
+      --  that one. We just preserve the type of the context
+
+      elsif Nkind (Exp) = N_Raise_Constraint_Error then
+         Rewrite (N, Exp);
+         Set_Etype (N, Typ);
+
+      --  We have to build an explicit raise_ce node
+
+      else
+         Rewrite (N, Make_Raise_Constraint_Error (Sloc (Exp)));
+         Set_Raises_Constraint_Error (N);
+         Set_Etype (N, Typ);
+      end if;
+   end Rewrite_In_Raise_CE;
+
+   ---------------------
+   -- String_Type_Len --
+   ---------------------
+
+   function String_Type_Len (Stype : Entity_Id) return Uint is
+      NT : constant Entity_Id := Etype (First_Index (Stype));
+      T  : Entity_Id;
+
+   begin
+      if Is_OK_Static_Subtype (NT) then
+         T := NT;
+      else
+         T := Base_Type (NT);
+      end if;
+
+      return Expr_Value (Type_High_Bound (T)) -
+             Expr_Value (Type_Low_Bound (T)) + 1;
+   end String_Type_Len;
+
+   ------------------------------------
+   -- Subtypes_Statically_Compatible --
+   ------------------------------------
+
+   function Subtypes_Statically_Compatible
+     (T1   : Entity_Id;
+      T2   : Entity_Id)
+      return Boolean
+   is
+   begin
+      if Is_Scalar_Type (T1) then
+
+         --  Definitely compatible if we match
+
+         if Subtypes_Statically_Match (T1, T2) then
+            return True;
+
+         --  If either subtype is nonstatic then they're not compatible
+
+         elsif not Is_Static_Subtype (T1)
+           or else not Is_Static_Subtype (T2)
+         then
+            return False;
+
+         --  If either type has constraint error bounds, then consider that
+         --  they match to avoid junk cascaded errors here.
+
+         elsif not Is_OK_Static_Subtype (T1)
+           or else not Is_OK_Static_Subtype (T2)
+         then
+            return True;
+
+         --  Base types must match, but we don't check that (should
+         --  we???) but we do at least check that both types are
+         --  real, or both types are not real.
+
+         elsif (Is_Real_Type (T1) /= Is_Real_Type (T2)) then
+            return False;
+
+         --  Here we check the bounds
+
+         else
+            declare
+               LB1 : constant Node_Id := Type_Low_Bound  (T1);
+               HB1 : constant Node_Id := Type_High_Bound (T1);
+               LB2 : constant Node_Id := Type_Low_Bound  (T2);
+               HB2 : constant Node_Id := Type_High_Bound (T2);
+
+            begin
+               if Is_Real_Type (T1) then
+                  return
+                    (Expr_Value_R (LB1) > Expr_Value_R (HB1))
+                      or else
+                    (Expr_Value_R (LB2) <= Expr_Value_R (LB1)
+                       and then
+                     Expr_Value_R (HB1) <= Expr_Value_R (HB2));
+
+               else
+                  return
+                    (Expr_Value (LB1) > Expr_Value (HB1))
+                      or else
+                    (Expr_Value (LB2) <= Expr_Value (LB1)
+                       and then
+                     Expr_Value (HB1) <= Expr_Value (HB2));
+               end if;
+            end;
+         end if;
+
+      elsif Is_Access_Type (T1) then
+         return not Is_Constrained (T2)
+           or else Subtypes_Statically_Match
+                     (Designated_Type (T1), Designated_Type (T2));
+
+      else
+         return (Is_Composite_Type (T1) and then not Is_Constrained (T2))
+           or else Subtypes_Statically_Match (T1, T2);
+      end if;
+   end Subtypes_Statically_Compatible;
+
+   -------------------------------
+   -- Subtypes_Statically_Match --
+   -------------------------------
+
+   --  Subtypes statically match if they have statically matching constraints
+   --  (RM 4.9.1(2)). Constraints statically match if there are none, or if
+   --  they are the same identical constraint, or if they are static and the
+   --  values match (RM 4.9.1(1)).
+
+   function Subtypes_Statically_Match (T1, T2 : Entity_Id) return Boolean is
+   begin
+      --  A type always statically matches itself
+
+      if T1 = T2 then
+         return True;
+
+      --  Scalar types
+
+      elsif Is_Scalar_Type (T1) then
+
+         --  Base types must be the same
+
+         if Base_Type (T1) /= Base_Type (T2) then
+            return False;
+         end if;
+
+         --  A constrained numeric subtype never matches an unconstrained
+         --  subtype, i.e. both types must be constrained or unconstrained.
+
+         --  To understand the requirement for this test, see RM 4.9.1(1).
+         --  As is made clear in RM 3.5.4(11), type Integer, for example
+         --  is a constrained subtype with constraint bounds matching the
+         --  bounds of its corresponding uncontrained base type. In this
+         --  situation, Integer and Integer'Base do not statically match,
+         --  even though they have the same bounds.
+
+         --  We only apply this test to types in Standard and types that
+         --  appear in user programs. That way, we do not have to be
+         --  too careful about setting Is_Constrained right for itypes.
+
+         if Is_Numeric_Type (T1)
+           and then (Is_Constrained (T1) /= Is_Constrained (T2))
+           and then (Scope (T1) = Standard_Standard
+                      or else Comes_From_Source (T1))
+           and then (Scope (T2) = Standard_Standard
+                      or else Comes_From_Source (T2))
+         then
+            return False;
+         end if;
+
+         --  If there was an error in either range, then just assume
+         --  the types statically match to avoid further junk errors
+
+         if Error_Posted (Scalar_Range (T1))
+              or else
+            Error_Posted (Scalar_Range (T2))
+         then
+            return True;
+         end if;
+
+         --  Otherwise both types have bound that can be compared
+
+         declare
+            LB1 : constant Node_Id := Type_Low_Bound  (T1);
+            HB1 : constant Node_Id := Type_High_Bound (T1);
+            LB2 : constant Node_Id := Type_Low_Bound  (T2);
+            HB2 : constant Node_Id := Type_High_Bound (T2);
+
+         begin
+            --  If the bounds are the same tree node, then match
+
+            if LB1 = LB2 and then HB1 = HB2 then
+               return True;
+
+            --  Otherwise bounds must be static and identical value
+
+            else
+               if not Is_Static_Subtype (T1)
+                 or else not Is_Static_Subtype (T2)
+               then
+                  return False;
+
+               --  If either type has constraint error bounds, then say
+               --  that they match to avoid junk cascaded errors here.
+
+               elsif not Is_OK_Static_Subtype (T1)
+                 or else not Is_OK_Static_Subtype (T2)
+               then
+                  return True;
+
+               elsif Is_Real_Type (T1) then
+                  return
+                    (Expr_Value_R (LB1) = Expr_Value_R (LB2))
+                      and then
+                    (Expr_Value_R (HB1) = Expr_Value_R (HB2));
+
+               else
+                  return
+                    Expr_Value (LB1) = Expr_Value (LB2)
+                      and then
+                    Expr_Value (HB1) = Expr_Value (HB2);
+               end if;
+            end if;
+         end;
+
+      --  Type with discriminants
+
+      elsif Has_Discriminants (T1) or else Has_Discriminants (T2) then
+         if Has_Discriminants (T1) /= Has_Discriminants (T2) then
+            return False;
+         end if;
+
+         declare
+            DL1 : constant Elist_Id := Discriminant_Constraint (T1);
+            DL2 : constant Elist_Id := Discriminant_Constraint (T2);
+
+            DA1 : Elmt_Id := First_Elmt (DL1);
+            DA2 : Elmt_Id := First_Elmt (DL2);
+
+         begin
+            if DL1 = DL2 then
+               return True;
+
+            elsif Is_Constrained (T1) /= Is_Constrained (T2) then
+               return False;
+            end if;
+
+            while Present (DA1) loop
+               declare
+                  Expr1 : constant Node_Id := Node (DA1);
+                  Expr2 : constant Node_Id := Node (DA2);
+
+               begin
+                  if not Is_Static_Expression (Expr1)
+                    or else not Is_Static_Expression (Expr2)
+                  then
+                     return False;
+
+                  --  If either expression raised a constraint error,
+                  --  consider the expressions as matching, since this
+                  --  helps to prevent cascading errors.
+
+                  elsif Raises_Constraint_Error (Expr1)
+                    or else Raises_Constraint_Error (Expr2)
+                  then
+                     null;
+
+                  elsif Expr_Value (Expr1) /= Expr_Value (Expr2) then
+                     return False;
+                  end if;
+               end;
+
+               Next_Elmt (DA1);
+               Next_Elmt (DA2);
+            end loop;
+         end;
+
+         return True;
+
+      --  A definite type does not match an indefinite or classwide type.
+
+      elsif
+         Has_Unknown_Discriminants (T1) /= Has_Unknown_Discriminants (T2)
+      then
+         return False;
+
+      --  Array type
+
+      elsif Is_Array_Type (T1) then
+
+         --  If either subtype is unconstrained then both must be,
+         --  and if both are unconstrained then no further checking
+         --  is needed.
+
+         if not Is_Constrained (T1) or else not Is_Constrained (T2) then
+            return not (Is_Constrained (T1) or else Is_Constrained (T2));
+         end if;
+
+         --  Both subtypes are constrained, so check that the index
+         --  subtypes statically match.
+
+         declare
+            Index1 : Node_Id := First_Index (T1);
+            Index2 : Node_Id := First_Index (T2);
+
+         begin
+            while Present (Index1) loop
+               if not
+                 Subtypes_Statically_Match (Etype (Index1), Etype (Index2))
+               then
+                  return False;
+               end if;
+
+               Next_Index (Index1);
+               Next_Index (Index2);
+            end loop;
+
+            return True;
+         end;
+
+      elsif Is_Access_Type (T1) then
+         return Subtypes_Statically_Match
+                  (Designated_Type (T1),
+                   Designated_Type (T2));
+
+      --  All other types definitely match
+
+      else
+         return True;
+      end if;
+   end Subtypes_Statically_Match;
+
+   ----------
+   -- Test --
+   ----------
+
+   function Test (Cond : Boolean) return Uint is
+   begin
+      if Cond then
+         return Uint_1;
+      else
+         return Uint_0;
+      end if;
+   end Test;
+
+   ---------------------------------
+   -- Test_Expression_Is_Foldable --
+   ---------------------------------
+
+   --  One operand case
+
+   procedure Test_Expression_Is_Foldable
+     (N    : Node_Id;
+      Op1  : Node_Id;
+      Stat : out Boolean;
+      Fold : out Boolean)
+   is
+   begin
+      Stat := False;
+
+      --  If operand is Any_Type, just propagate to result and do not
+      --  try to fold, this prevents cascaded errors.
+
+      if Etype (Op1) = Any_Type then
+         Set_Etype (N, Any_Type);
+         Fold := False;
+         return;
+
+      --  If operand raises constraint error, then replace node N with the
+      --  raise constraint error node, and we are obviously not foldable.
+      --  Note that this replacement inherits the Is_Static_Expression flag
+      --  from the operand.
+
+      elsif Raises_Constraint_Error (Op1) then
+         Rewrite_In_Raise_CE (N, Op1);
+         Fold := False;
+         return;
+
+      --  If the operand is not static, then the result is not static, and
+      --  all we have to do is to check the operand since it is now known
+      --  to appear in a non-static context.
+
+      elsif not Is_Static_Expression (Op1) then
+         Check_Non_Static_Context (Op1);
+         Fold := Compile_Time_Known_Value (Op1);
+         return;
+
+      --   An expression of a formal modular type is not foldable because
+      --   the modulus is unknown.
+
+      elsif Is_Modular_Integer_Type (Etype (Op1))
+        and then Is_Generic_Type (Etype (Op1))
+      then
+         Check_Non_Static_Context (Op1);
+         Fold := False;
+         return;
+
+      --  Here we have the case of an operand whose type is OK, which is
+      --  static, and which does not raise constraint error, we can fold.
+
+      else
+         Set_Is_Static_Expression (N);
+         Fold := True;
+         Stat := True;
+      end if;
+   end Test_Expression_Is_Foldable;
+
+   --  Two operand case
+
+   procedure Test_Expression_Is_Foldable
+     (N    : Node_Id;
+      Op1  : Node_Id;
+      Op2  : Node_Id;
+      Stat : out Boolean;
+      Fold : out Boolean)
+   is
+      Rstat : constant Boolean := Is_Static_Expression (Op1)
+                                    and then Is_Static_Expression (Op2);
+
+   begin
+      Stat := False;
+
+      --  If either operand is Any_Type, just propagate to result and
+      --  do not try to fold, this prevents cascaded errors.
+
+      if Etype (Op1) = Any_Type or else Etype (Op2) = Any_Type then
+         Set_Etype (N, Any_Type);
+         Fold := False;
+         return;
+
+      --  If left operand raises constraint error, then replace node N with
+      --  the raise constraint error node, and we are obviously not foldable.
+      --  Is_Static_Expression is set from the two operands in the normal way,
+      --  and we check the right operand if it is in a non-static context.
+
+      elsif Raises_Constraint_Error (Op1) then
+         if not Rstat then
+            Check_Non_Static_Context (Op2);
+         end if;
+
+         Rewrite_In_Raise_CE (N, Op1);
+         Set_Is_Static_Expression (N, Rstat);
+         Fold := False;
+         return;
+
+      --  Similar processing for the case of the right operand. Note that
+      --  we don't use this routine for the short-circuit case, so we do
+      --  not have to worry about that special case here.
+
+      elsif Raises_Constraint_Error (Op2) then
+         if not Rstat then
+            Check_Non_Static_Context (Op1);
+         end if;
+
+         Rewrite_In_Raise_CE (N, Op2);
+         Set_Is_Static_Expression (N, Rstat);
+         Fold := False;
+         return;
+
+      --  Exclude expressions of a generic modular type, as above.
+
+      elsif Is_Modular_Integer_Type (Etype (Op1))
+        and then Is_Generic_Type (Etype (Op1))
+      then
+         Check_Non_Static_Context (Op1);
+         Fold := False;
+         return;
+
+      --  If result is not static, then check non-static contexts on operands
+      --  since one of them may be static and the other one may not be static
+
+      elsif not Rstat then
+         Check_Non_Static_Context (Op1);
+         Check_Non_Static_Context (Op2);
+         Fold := Compile_Time_Known_Value (Op1)
+                   and then Compile_Time_Known_Value (Op2);
+         return;
+
+      --  Else result is static and foldable. Both operands are static,
+      --  and neither raises constraint error, so we can definitely fold.
+
+      else
+         Set_Is_Static_Expression (N);
+         Fold := True;
+         Stat := True;
+         return;
+      end if;
+   end Test_Expression_Is_Foldable;
+
+   --------------
+   -- To_Bits --
+   --------------
+
+   procedure To_Bits (U : Uint; B : out Bits) is
+   begin
+      for J in 0 .. B'Last loop
+         B (J) := (U / (2 ** J)) mod 2 /= 0;
+      end loop;
+   end To_Bits;
+
+end Sem_Eval;
diff --git a/gcc/ada/sem_eval.ads b/gcc/ada/sem_eval.ads
new file mode 100644 (file)
index 0000000..b693ffd
--- /dev/null
@@ -0,0 +1,377 @@
+------------------------------------------------------------------------------
+--                                                                          --
+--                         GNAT COMPILER COMPONENTS                         --
+--                                                                          --
+--                             S E M _ E V A L                              --
+--                                                                          --
+--                                 S p e c                                  --
+--                                                                          --
+--                            $Revision: 1.53 $
+--                                                                          --
+--          Copyright (C) 1992-2001 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- --
+-- ware  Foundation;  either version 2,  or (at your option) any later ver- --
+-- sion.  GNAT is distributed in the hope that it will be useful, but WITH- --
+-- OUT ANY WARRANTY;  without even the  implied warranty of MERCHANTABILITY --
+-- or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License --
+-- for  more details.  You should have  received  a copy of the GNU General --
+-- Public License  distributed with GNAT;  see file COPYING.  If not, write --
+-- to  the Free Software Foundation,  59 Temple Place - Suite 330,  Boston, --
+-- MA 02111-1307, USA.                                                      --
+--                                                                          --
+-- GNAT was originally developed  by the GNAT team at  New York University. --
+-- It is now maintained by Ada Core Technologies Inc (http://www.gnat.com). --
+--                                                                          --
+------------------------------------------------------------------------------
+
+--  This package contains various subprograms involved in compile time
+--  evaluation of expressions and checks for staticness of expressions
+--  and types. It also contains the circuitry for checking for violations
+--  of pure and preelaborated conditions (this naturally goes here, since
+--  these rules involve consideration of staticness).
+
+--  Note: the static evaluation for attributes is found in Sem_Attr even
+--  though logically it belongs here. We have done this so that it is easier
+--  to add new attributes to GNAT.
+
+with Types;  use Types;
+with Uintp;  use Uintp;
+with Urealp; use Urealp;
+
+package Sem_Eval is
+
+   ------------------------------------
+   -- Handling of Static Expressions --
+   ------------------------------------
+
+   --  This package contains a set of routine that process individual
+   --  subexpression nodes with the objective of folding (precomputing)
+   --  the value of static expressions that are known at compile time and
+   --  properly computing the setting of two flags that appear in every
+   --  subexpression node:
+
+   --    Is_Static_Expression
+
+   --      This flag is set on any expression that is static according
+   --      to the rules in (RM 4.9(3-32)).
+
+   --    Raises_Constraint_Error
+
+   --      This flag indicatest that it is known at compile time that the
+   --      evaluation of an expression raises constraint error. If the
+   --      expression is static, and this flag is off, then it is also known
+   --      at compile time that the expression does not raise constraint error
+   --      (i.e. the flag is accurate for static expressions, and conservative
+   --      for non-static expressions.
+
+   --  If a static expression does not raise constraint error, then the
+   --  Raises_Constraint_Error flag is off, and the expression must be
+   --  computed at compile time, which means that it has the form of either
+   --  a literal, or a constant that is itself (recursively) either a literal
+   --  or a constant.
+
+   --  The above rules must be followed exactly in order for legality
+   --  checks to be accurate. For subexpressions that are not static
+   --  according to the RM definition, they are sometimes folded anyway,
+   --  but of course in this case Is_Static_Expression is not set.
+
+   -------------------------------
+   -- Compile-Time Known Values --
+   -------------------------------
+
+   --  For most legality checking purposes the flag Is_Static_Expression
+   --  defined in Sinfo should be used. This package also provides
+   --  a routine called Is_OK_Static_Expression which in addition of
+   --  checking that an expression is static in the RM 4.9 sense, it
+   --  checks that the expression does not raise constraint error. In
+   --  fact for certain legality checks not only do we need to ascertain
+   --  that the expression is static, but we must also ensure that it
+   --  does not raise constraint error.
+   --
+   --  Neither of Is_Static_Expression and Is_OK_Static_Expression should
+   --  be used for compile time evaluation purposes. In fact certain
+   --  expression whose value is known at compile time are not static
+   --  in the RM 4.9 sense. A typical example is:
+   --
+   --     C : constant Integer := Record_Type'Size;
+   --
+   --  The expression 'C' is not static in the technical RM sense, but for
+   --  many simple record types, the size is in fact known at compile time.
+   --  When we are trying to perform compile time constant folding (for
+   --  instance for expressions such as 'C + 1', Is_Static_Expression or
+   --  Is_OK_Static_Expression are not the right functions to test to see
+   --  if folding is possible. Instead, we use Compile_Time_Know_Value.
+   --  All static expressions that do not raise constraint error (i.e.
+   --  those for which Is_OK_Static_Expression is true) are known at
+   --  compile time, but as shown by the above example, there are cases
+   --  of non-static expressions which are known at compile time.
+
+   -----------------
+   -- Subprograms --
+   -----------------
+
+   procedure Check_Non_Static_Context (N : Node_Id);
+   --  Deals with the special check required for a static expression that
+   --  appears in a non-static context, i.e. is not part of a larger static
+   --  expression (see RM 4.9(35)), i.e. the value of the expression must be
+   --  within the base range of the base type of its expected type. A check
+   --  is also made for expressions that are inside the base range, but
+   --  outside the range of the expected subtype (this is a warning message
+   --  rather than an illegality).
+   --
+   --  Note: most cases of non-static context checks are handled within
+   --  Sem_Eval itself, including all cases of expressions at the outer
+   --  level (i.e. those that are not a subexpression). Currently the only
+   --  outside customer for this procedure is Sem_Attr (because Eval_Attribute
+   --  is there). There is also one special case arising from ranges (see body
+   --  of Resolve_Range).
+
+   procedure Check_String_Literal_Length (N : Node_Id; Ttype : Entity_Id);
+   --  N is either a string literal, or a constraint error node. In the latter
+   --  case, the situation is already dealt with, and the call has no effect.
+   --  In the former case, if the target type, Ttyp is constrained, then a
+   --  check is made to see if the string literal is of appropriate length.
+
+   type Compare_Result is (LT, LE, EQ, GT, GE, NE, Unknown);
+   subtype Compare_GE is Compare_Result range EQ .. GE;
+   subtype Compare_LE is Compare_Result range LT .. EQ;
+   function Compile_Time_Compare (L, R : Node_Id) return Compare_Result;
+   --  Given two expression nodes, finds out whether it can be determined
+   --  at compile time how the runtime values will compare. An Unknown
+   --  result means that the result of a comparison cannot be determined at
+   --  compile time, otherwise the returned result indicates the known result
+   --  of the comparison, given as tightly as possible (i.e. EQ or LT is a
+   --  preferred returned value to LE).
+
+   function Is_OK_Static_Expression (N : Node_Id) return Boolean;
+   --  An OK static expression is one that is static in the RM definition
+   --  sense and which does not raise constraint error. For most legality
+   --  checking purposes you should use Is_Static_Expression. For those
+   --  legality checks where the expression N should not raise constaint
+   --  error use this routine. This routine is *not* to be used in contexts
+   --  where the test is for compile time evaluation purposes. Use routine
+   --  Compile_Time_Known_Value instead (see section on "Compile-Time Known
+   --  Values" above).
+
+   function Is_Static_Range (N : Node_Id) return Boolean;
+   --  Determine if range is static, as defined in RM 4.9(26). The only
+   --  allowed argument is an N_Range node (but note that the semantic
+   --  analysis of equivalent range attribute references already turned
+   --  them into the equivalent range).
+
+   function Is_OK_Static_Range (N : Node_Id) return Boolean;
+   --  Like Is_Static_Range, but also makes sure that the bounds of the
+   --  range are compile-time evaluable (i.e. do not raise constraint error).
+   --  A result of true means that the bounds are compile time evaluable.
+   --  A result of false means they are not (either because the range is
+   --  not static, or because one or the other bound raises CE).
+
+   function Is_Static_Subtype (Typ : Entity_Id) return Boolean;
+   --  Determines whether a subtype fits the definition of an Ada static
+   --  subtype as given in (RM 4.9(26)).
+
+   function Is_OK_Static_Subtype (Typ : Entity_Id) return Boolean;
+   --  Like Is_Static_Subtype but also makes sure that the bounds of the
+   --  subtype are compile-time evaluable (i.e. do not raise constraint
+   --  error). A result of true means that the bounds are compile time
+   --  evaluable. A result of false means they are not (either because the
+   --  range is not static, or because one or the other bound raises CE).
+
+   function Subtypes_Statically_Compatible
+     (T1   : Entity_Id;
+      T2   : Entity_Id)
+      return Boolean;
+   --  Returns true if the subtypes are unconstrained or the constraint on
+   --  on T1 is statically compatible with T2 (as defined by 4.9.1(4)).
+   --  Otherwise returns false.
+
+   function Subtypes_Statically_Match (T1, T2 : Entity_Id) return Boolean;
+   --  Determine whether two types T1, T2, which have the same base type,
+   --  are statically matching subtypes (RM 4.9.1(1-2)).
+
+   function Compile_Time_Known_Value (Op : Node_Id) return Boolean;
+   --  Returns true if Op is an expression not raising constraint error
+   --  whose value is known at compile time. This is true if Op is a static
+   --  expression, but can also be true for expressions which are
+   --  technically non-static but which are in fact known at compile time,
+   --  such as the static lower bound of a non-static range or the value
+   --  of a constant object whose initial value is static. Note that this
+   --  routine is defended against unanalyzed expressions. Such expressions
+   --  will not cause a blowup, they may cause pessimistic (i.e. False)
+   --  results to be returned.
+
+   function Compile_Time_Known_Value_Or_Aggr (Op : Node_Id) return Boolean;
+   --  Similar to Compile_Time_Known_Value, but also returns True if the
+   --  value is a compile time known aggregate, i.e. an aggregate all of
+   --  whose constituent expressions are either compile time known values
+   --  or compile time known aggregates.
+
+   function Expr_Value (N : Node_Id) return Uint;
+   --  Returns the folded value of the expression N. This function is called
+   --  in instances where it has already been determined that the expression
+   --  is static or its value is known at compile time (ie the call to
+   --  Compile_Time_Known_Value (N) returns True). This version is used for
+   --  integer values, and enumeration or character literals. In the latter
+   --  two cases, the value returned is the Pos value in the relevant
+   --  enumeration type. It can also be used for fixed-point values, in
+   --  which case it returns the corresponding integer value. It cannot be
+   --  used for floating-point values.
+
+   function Expr_Value_E (N : Node_Id) return Entity_Id;
+   --  Returns the folded value of the expression. This function is called
+   --  in instances where it has already been determined that the expression
+   --  is static or its value known at compile time. This version is used
+   --  for enumeration types and returns the corresponding enumeration
+   --  literal.
+
+   function Expr_Value_R (N : Node_Id) return Ureal;
+   --  Returns the folded value of the expression. This function is called
+   --  in instances where it has already been determined that the expression
+   --  is static or its value known at compile time. This version is used
+   --  for real values (including both the floating-point and fixed-point
+   --  cases). In the case of a fixed-point type, the real value is returned
+   --  (cf above version returning Uint).
+
+   function Expr_Value_S (N : Node_Id) return Node_Id;
+   --  Returns the folded value of the expression. This function is called
+   --  in instances where it has already been determined that the expression
+   --  is static or its value is known at compile time. This version is used
+   --  for string types and returns the corresponding N_String_Literal node.
+
+   function Expr_Rep_Value (N : Node_Id) return Uint;
+   --  This is identical to Expr_Value, except in the case of enumeration
+   --  literals of types for which an enumeration representation clause has
+   --  been given, in which case it returns the representation value rather
+   --  than the pos value. This is the value that is needed for generating
+   --  code sequences, while the Expr_Value value is appropriate for compile
+   --  time constraint errors or getting the logical value. Note that this
+   --  function does NOT concern itself with biased values, if the caller
+   --  needs a properly biased value, the subtraction of the bias must be
+   --  handled explicitly.
+
+   procedure Eval_Actual                 (N : Node_Id);
+   procedure Eval_Allocator              (N : Node_Id);
+   procedure Eval_Arithmetic_Op          (N : Node_Id);
+   procedure Eval_Character_Literal      (N : Node_Id);
+   procedure Eval_Concatenation          (N : Node_Id);
+   procedure Eval_Conditional_Expression (N : Node_Id);
+   procedure Eval_Entity_Name            (N : Node_Id);
+   procedure Eval_Indexed_Component      (N : Node_Id);
+   procedure Eval_Integer_Literal        (N : Node_Id);
+   procedure Eval_Logical_Op             (N : Node_Id);
+   procedure Eval_Membership_Op          (N : Node_Id);
+   procedure Eval_Named_Integer          (N : Node_Id);
+   procedure Eval_Named_Real             (N : Node_Id);
+   procedure Eval_Op_Expon               (N : Node_Id);
+   procedure Eval_Op_Not                 (N : Node_Id);
+   procedure Eval_Real_Literal           (N : Node_Id);
+   procedure Eval_Relational_Op          (N : Node_Id);
+   procedure Eval_Shift                  (N : Node_Id);
+   procedure Eval_Short_Circuit          (N : Node_Id);
+   procedure Eval_Slice                  (N : Node_Id);
+   procedure Eval_String_Literal         (N : Node_Id);
+   procedure Eval_Qualified_Expression   (N : Node_Id);
+   procedure Eval_Type_Conversion        (N : Node_Id);
+   procedure Eval_Unary_Op               (N : Node_Id);
+   procedure Eval_Unchecked_Conversion   (N : Node_Id);
+
+   procedure Fold_Str (N : Node_Id; Val : String_Id);
+   --  Rewrite N with a new N_String_Literal node as the result of the
+   --  compile time evaluation of the node N. Val is the resulting string
+   --  value from the folding operation. The Is_Static_Expression flag is
+   --  set in the result node. The result is fully analyzed and resolved.
+
+   procedure Fold_Uint (N : Node_Id; Val : Uint);
+   --  Rewrite N with a (N_Integer_Literal, N_Identifier, N_Character_Literal)
+   --  node as the result of the compile time evaluation of the node N. Val
+   --  is the result in the integer case and is the position of the literal
+   --  in the literals list for the enumeration case. Is_Static_Expression
+   --  is set True in the result node. The result is fully analyzed/resolved.
+
+   procedure Fold_Ureal (N : Node_Id; Val : Ureal);
+   --  Rewrite N with a new N_Real_Literal node as the result of the compile
+   --  time evaluation of the node N. Val is the resulting real value from
+   --  the folding operation. The Is_Static_Expression flag is set in the
+   --  result node. The result is fully analyzed and result.
+
+   function Is_In_Range
+     (N         : Node_Id;
+      Typ       : Entity_Id;
+      Fixed_Int : Boolean := False;
+      Int_Real  : Boolean := False)
+      return      Boolean;
+   --  Returns True if it can be guaranteed at compile time that expression
+   --  N is known to be in range of the subtype Typ. If the values of N or
+   --  of either bouds of Type are unknown at compile time, False will
+   --  always be returned. A result of False does not mean that the
+   --  expression is out of range, merely that it cannot be determined at
+   --  compile time that it is in range. If Typ is a floating point type or
+   --  Int_Real is set, any integer value is treated as though it was a real
+   --  value (i.e. the underlying real value is used).  In this case we use
+   --  the corresponding real value, both for the bounds of Typ, and for the
+   --  value of the expression N. If Typ is a fixed type or a discrete type
+   --  and Int_Real is False but flag Fixed_Int is True then any fixed-point
+   --  value is treated as though it was a discrete value (i.e. the
+   --  underlying integer value is used).  In this case we use the
+   --  corresponding integer value, both for the bounds of Typ, and for the
+   --  value of the expression N. If Typ is a discret type and Fixed_Int as
+   --  well as Int_Real are false, intere values are used throughout.
+
+   function Is_Out_Of_Range
+     (N         : Node_Id;
+      Typ       : Entity_Id;
+      Fixed_Int : Boolean := False;
+      Int_Real  : Boolean := False)
+      return      Boolean;
+   --  Returns True if it can be guaranteed at compile time that expression
+   --  N is known to be out of range of the subtype Typ.  True is returned
+   --  if Typ is a scalar type, at least one of whose bounds is known at
+   --  compile time, and N is a compile time known expression which can be
+   --  determined to be outside a compile_time known bound of Typ. A result
+   --  of False does not mean that the expression is in range, merely that
+   --  it cannot be determined at compile time that it is out of range. Flags
+   --  Int_Real and Fixed_Int are used like in routine Is_In_Range above.
+
+   function In_Subrange_Of
+     (T1        : Entity_Id;
+      T2        : Entity_Id;
+      Fixed_Int : Boolean := False)
+      return      Boolean;
+   --  Returns True if it can be guaranteed at compile time that the range
+   --  of values for scalar type T1 are always in the range of scalar type
+   --  T2.  A result of False does not mean that T1 is not in T2's subrange,
+   --  only that it cannot be determined at compile time. Flag Fixed_Int is
+   --  used is like in routine Is_In_Range_Above.
+
+   function Is_Null_Range (Lo : Node_Id; Hi : Node_Id) return Boolean;
+   --  Returns True if it can guarantee that Lo .. Hi is a null range.
+   --  If it cannot (because the value of Lo or Hi is not known at compile
+   --  time) then it returns False.
+
+   function Not_Null_Range (Lo : Node_Id; Hi : Node_Id) return Boolean;
+   --  Returns True if it can guarantee that Lo .. Hi is not a null range.
+   --  If it cannot (because the value of Lo or Hi is not known at compile
+   --  time) then it returns False.
+
+private
+   --  The Eval routines are all marked inline, since they are called once
+
+   pragma Inline (Eval_Actual);
+   pragma Inline (Eval_Allocator);
+   pragma Inline (Eval_Character_Literal);
+   pragma Inline (Eval_Conditional_Expression);
+   pragma Inline (Eval_Indexed_Component);
+   pragma Inline (Eval_Integer_Literal);
+   pragma Inline (Eval_Named_Integer);
+   pragma Inline (Eval_Named_Real);
+   pragma Inline (Eval_Real_Literal);
+   pragma Inline (Eval_Shift);
+   pragma Inline (Eval_Slice);
+   pragma Inline (Eval_String_Literal);
+   pragma Inline (Eval_Unchecked_Conversion);
+
+   pragma Inline (Is_OK_Static_Expression);
+
+end Sem_Eval;
diff --git a/gcc/ada/sem_intr.adb b/gcc/ada/sem_intr.adb
new file mode 100644 (file)
index 0000000..20b1918
--- /dev/null
@@ -0,0 +1,352 @@
+------------------------------------------------------------------------------
+--                                                                          --
+--                         GNAT COMPILER COMPONENTS                         --
+--                                                                          --
+--                             S E M _ I N T R                              --
+--                                                                          --
+--                                 B o d y                                  --
+--                                                                          --
+--                            $Revision: 1.25 $
+--                                                                          --
+--          Copyright (C) 1992-2001 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- --
+-- ware  Foundation;  either version 2,  or (at your option) any later ver- --
+-- sion.  GNAT is distributed in the hope that it will be useful, but WITH- --
+-- OUT ANY WARRANTY;  without even the  implied warranty of MERCHANTABILITY --
+-- or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License --
+-- for  more details.  You should have  received  a copy of the GNU General --
+-- Public License  distributed with GNAT;  see file COPYING.  If not, write --
+-- to  the Free Software Foundation,  59 Temple Place - Suite 330,  Boston, --
+-- MA 02111-1307, USA.                                                      --
+--                                                                          --
+-- GNAT was originally developed  by the GNAT team at  New York University. --
+-- It is now maintained by Ada Core Technologies Inc (http://www.gnat.com). --
+--                                                                          --
+------------------------------------------------------------------------------
+
+--  Processing for intrinsic subprogram declarations
+
+with Atree;    use Atree;
+with Einfo;    use Einfo;
+with Errout;   use Errout;
+with Fname;    use Fname;
+with Lib;      use Lib;
+with Namet;    use Namet;
+with Sem_Eval; use Sem_Eval;
+with Sem_Util; use Sem_Util;
+with Sinfo;    use Sinfo;
+with Snames;   use Snames;
+with Stand;    use Stand;
+with Stringt;  use Stringt;
+with Targparm; use Targparm;
+with Uintp;    use Uintp;
+
+package body Sem_Intr is
+
+   -----------------------
+   -- Local Subprograms --
+   -----------------------
+
+   procedure Check_Exception_Function (E : Entity_Id; N : Node_Id);
+   --  Check use of intrinsic Exception_Message, Exception_Info or
+   --  Exception_Name, as used in the DEC compatible Current_Exceptions
+   --  package. In each case we must have a parameterless function that
+   --  returns type String.
+
+   procedure Check_Intrinsic_Operator (E : Entity_Id; N : Node_Id);
+   --  Check that operator is one of the binary arithmetic operators, and
+   --  that the types involved have the same size.
+
+   procedure Check_Shift (E : Entity_Id; N : Node_Id);
+   --  Check intrinsic shift subprogram, the two arguments are the same
+   --  as for Check_Intrinsic_Subprogram (i.e. the entity of the subprogram
+   --  declaration, and the node for the pragma argument, used for messages)
+
+   procedure Errint (Msg : String; S : Node_Id; N : Node_Id);
+   --  Post error message for bad intrinsic, the message itself is posted
+   --  on the appropriate spec node and another message is placed on the
+   --  pragma itself, referring to the spec. S is the node in the spec on
+   --  which the message is to be placed, and N is the pragma argument node.
+
+   ------------------------------
+   -- Check_Exception_Function --
+   ------------------------------
+
+   procedure Check_Exception_Function (E : Entity_Id; N : Node_Id) is
+   begin
+      if Ekind (E) /= E_Function
+        and then Ekind (E) /= E_Generic_Function
+      then
+         Errint
+           ("intrinsic exception subprogram must be a function", E, N);
+
+      elsif Present (First_Formal (E)) then
+         Errint
+           ("intrinsic exception subprogram may not have parameters",
+            E, First_Formal (E));
+         return;
+
+      elsif Etype (E) /= Standard_String then
+         Errint
+           ("return type of exception subprogram must be String", E, N);
+         return;
+      end if;
+   end Check_Exception_Function;
+
+   --------------------------
+   -- Check_Intrinsic_Call --
+   --------------------------
+
+   procedure Check_Intrinsic_Call (N : Node_Id) is
+      Nam  : constant Entity_Id := Entity (Name (N));
+      Cnam : constant Name_Id   := Chars (Nam);
+      Arg1 : constant Node_Id   := First_Actual (N);
+
+   begin
+      --  For Import_xxx calls, argument must be static string
+
+      if Cnam = Name_Import_Address
+           or else
+         Cnam = Name_Import_Largest_Value
+           or else
+         Cnam = Name_Import_Value
+      then
+         if Etype (Arg1) = Any_Type
+           or else Raises_Constraint_Error (Arg1)
+         then
+            null;
+
+         elsif not Is_Static_Expression (Arg1) then
+            Error_Msg_NE
+              ("call to & requires static string argument", N, Nam);
+
+         elsif String_Length (Strval (Expr_Value_S (Arg1))) = 0 then
+            Error_Msg_NE
+              ("call to & does not permit null string", N, Nam);
+
+         elsif OpenVMS_On_Target
+           and then String_Length (Strval (Expr_Value_S (Arg1))) > 31
+         then
+            Error_Msg_NE
+              ("argument in call to & must be 31 characters or less", N, Nam);
+         end if;
+
+      --  For now, no other special checks are required
+
+      else
+         return;
+      end if;
+   end Check_Intrinsic_Call;
+
+   ------------------------------
+   -- Check_Intrinsic_Operator --
+   ------------------------------
+
+   procedure Check_Intrinsic_Operator (E : Entity_Id; N : Node_Id) is
+      Nam : Name_Id := Chars (E);
+      T1  : Entity_Id;
+      T2  : Entity_Id;
+      Ret : constant Entity_Id := Etype (E);
+
+   begin
+      if Nam = Name_Op_Add
+        or else Nam = Name_Op_Subtract
+        or else Nam = Name_Op_Multiply
+        or else Nam = Name_Op_Divide
+      then
+         T1 := Etype (First_Formal (E));
+
+         if No (Next_Formal (First_Formal (E))) then
+
+            --  previous error in declaration.
+            return;
+
+         else
+            T2 := Etype (Next_Formal (First_Formal (E)));
+         end if;
+
+         if Root_Type (T1) /= Root_Type (T2)
+           or else Root_Type (T1) /= Root_Type (Ret)
+         then
+            Errint (
+              "types of intrinsic operator must have the same size", E, N);
+
+         elsif not Is_Numeric_Type (T1) then
+            Errint (
+              " intrinsic operator can only apply to numeric types", E, N);
+         end if;
+
+      else
+         Errint ("incorrect context for ""Intrinsic"" convention", E, N);
+      end if;
+   end Check_Intrinsic_Operator;
+
+   --------------------------------
+   -- Check_Intrinsic_Subprogram --
+   --------------------------------
+
+   procedure Check_Intrinsic_Subprogram (E : Entity_Id; N : Node_Id) is
+      Spec : constant Node_Id := Specification (Unit_Declaration_Node (E));
+      Nam  : Name_Id;
+
+   begin
+      if Present (Spec)
+        and then Present (Generic_Parent (Spec))
+      then
+         Nam := Chars (Generic_Parent (Spec));
+      else
+         Nam := Chars (E);
+      end if;
+
+      --  Check name is valid intrinsic name
+
+      Get_Name_String (Nam);
+
+      if Name_Buffer (1) /= 'O'
+        and then Nam /= Name_Asm
+        and then Nam not in First_Intrinsic_Name .. Last_Intrinsic_Name
+      then
+         Errint ("unrecognized intrinsic subprogram", E, N);
+
+      --  We always allow intrinsic specifications in language defined units
+      --  and in expanded code. We assume that the GNAT implemetors know what
+      --  they are doing, and do not write or generate junk use of intrinsic!
+
+      elsif not Comes_From_Source (E)
+        or else not Comes_From_Source (N)
+        or else Is_Predefined_File_Name
+                  (Unit_File_Name (Get_Source_Unit (N)))
+      then
+         null;
+
+      --  Shift cases. We allow user specification of intrinsic shift
+      --  operators for any numeric types.
+
+      elsif
+        Nam = Name_Rotate_Left
+          or else
+        Nam = Name_Rotate_Right
+          or else
+        Nam = Name_Shift_Left
+          or else
+        Nam = Name_Shift_Right
+          or else
+        Nam = Name_Shift_Right_Arithmetic
+      then
+         Check_Shift (E, N);
+
+      elsif
+        Nam = Name_Exception_Information
+          or else
+        Nam = Name_Exception_Message
+          or else
+        Nam = Name_Exception_Name
+      then
+         Check_Exception_Function (E, N);
+
+      elsif Nkind (E) = N_Defining_Operator_Symbol then
+         Check_Intrinsic_Operator (E, N);
+
+      elsif Nam = Name_File
+        or else Nam = Name_Line
+        or else Nam = Name_Source_Location
+        or else Nam = Name_Enclosing_Entity
+      then
+         null;
+
+      --  For now, no other intrinsic subprograms are recognized in user code
+
+      else
+         Errint ("incorrect context for ""Intrinsic"" convention", E, N);
+      end if;
+   end Check_Intrinsic_Subprogram;
+
+   -----------------
+   -- Check_Shift --
+   -----------------
+
+   procedure Check_Shift (E : Entity_Id; N : Node_Id) is
+      Arg1  : Node_Id;
+      Arg2  : Node_Id;
+      Size  : Nat;
+      Typ1  : Entity_Id;
+      Typ2  : Entity_Id;
+      Ptyp1 : Node_Id;
+      Ptyp2 : Node_Id;
+
+   begin
+      if Ekind (E) /= E_Function
+        and then Ekind (E) /= E_Generic_Function
+      then
+         Errint ("intrinsic shift subprogram must be a function", E, N);
+         return;
+      end if;
+
+      Arg1 := First_Formal (E);
+
+      if Present (Arg1) then
+         Arg2 := Next_Formal (Arg1);
+      else
+         Arg2 := Empty;
+      end if;
+
+      if Arg1 = Empty or else Arg2 = Empty then
+         Errint ("intrinsic shift function must have two arguments", E, N);
+         return;
+      end if;
+
+      Typ1 := Etype (Arg1);
+      Typ2 := Etype (Arg2);
+
+      Ptyp1 := Parameter_Type (Parent (Arg1));
+      Ptyp2 := Parameter_Type (Parent (Arg2));
+
+      if not Is_Integer_Type (Typ1) then
+         Errint ("first argument to shift must be integer type", Ptyp1, N);
+         return;
+      end if;
+
+      if Typ2 /= Standard_Natural then
+         Errint ("second argument to shift must be type Natural", Ptyp2, N);
+         return;
+      end if;
+
+      Size := UI_To_Int (Esize (Typ1));
+
+      if Size /= 8
+        and then Size /= 16
+        and then Size /= 32
+        and then Size /= 64
+      then
+         Errint
+           ("first argument for shift must have size 8, 16, 32 or 64",
+             Ptyp1, N);
+         return;
+
+      elsif Is_Modular_Integer_Type (Typ1)
+        and then Non_Binary_Modulus (Typ1)
+      then
+         Errint
+           ("shifts not allowed for non-binary modular types",
+            Ptyp1, N);
+
+      elsif Etype (Arg1) /= Etype (E) then
+         Errint
+           ("first argument of shift must match return type", Ptyp1, N);
+         return;
+      end if;
+   end Check_Shift;
+
+   ------------
+   -- Errint --
+   ------------
+
+   procedure Errint (Msg : String; S : Node_Id; N : Node_Id) is
+   begin
+      Error_Msg_N (Msg, S);
+      Error_Msg_N ("incorrect intrinsic subprogram, see spec", N);
+   end Errint;
+
+end Sem_Intr;
diff --git a/gcc/ada/sem_intr.ads b/gcc/ada/sem_intr.ads
new file mode 100644 (file)
index 0000000..3576ffb
--- /dev/null
@@ -0,0 +1,49 @@
+------------------------------------------------------------------------------
+--                                                                          --
+--                         GNAT COMPILER COMPONENTS                         --
+--                                                                          --
+--                             S E M _ I N T R                              --
+--                                                                          --
+--                                 S p e c                                  --
+--                                                                          --
+--                            $Revision: 1.4 $                              --
+--                                                                          --
+--        Copyright (C) 1992,1993,1994 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- --
+-- ware  Foundation;  either version 2,  or (at your option) any later ver- --
+-- sion.  GNAT is distributed in the hope that it will be useful, but WITH- --
+-- OUT ANY WARRANTY;  without even the  implied warranty of MERCHANTABILITY --
+-- or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License --
+-- for  more details.  You should have  received  a copy of the GNU General --
+-- Public License  distributed with GNAT;  see file COPYING.  If not, write --
+-- to  the Free Software Foundation,  59 Temple Place - Suite 330,  Boston, --
+-- MA 02111-1307, USA.                                                      --
+--                                                                          --
+-- GNAT was originally developed  by the GNAT team at  New York University. --
+-- It is now maintained by Ada Core Technologies Inc (http://www.gnat.com). --
+--                                                                          --
+------------------------------------------------------------------------------
+
+--  Processing for intrinsic subprogram declarations
+
+with Types; use Types;
+
+package Sem_Intr is
+
+   procedure Check_Intrinsic_Call (N : Node_Id);
+   --  Perform legality check for intrinsic call N (which is either function
+   --  call or a procedure call node). All the normal semantic checks have
+   --  been performed already. Check_Intrinsic_Call applies any additional
+   --  checks required by the fact that an intrinsic subprogram is involved.
+
+   procedure Check_Intrinsic_Subprogram (E : Entity_Id; N : Node_Id);
+   --  Special processing for pragma Import or pragma Interface when the
+   --  convention is Intrinsic. E is the Entity_Id of the spec of the
+   --  subprogram, and N is the second (subprogram) argument of the pragma.
+   --  Check_Intrinsic_Subprogram checks that the referenced subprogram is
+   --  known as an intrinsic and has an appropriate profile. If so the flag
+   --  Is_Intrinsic_Subprogram is set, otherwise an error message is posted.
+
+end Sem_Intr;
diff --git a/gcc/ada/sem_maps.adb b/gcc/ada/sem_maps.adb
new file mode 100644 (file)
index 0000000..a876156
--- /dev/null
@@ -0,0 +1,376 @@
+------------------------------------------------------------------------------
+--                                                                          --
+--                         GNAT COMPILER COMPONENTS                         --
+--                                                                          --
+--                             S E M _ M A P S                              --
+--                                                                          --
+--                                 B o d y                                  --
+--                                                                          --
+--                             $Revision: 1.3 $                             --
+--                                                                          --
+--          Copyright (C) 1996-1998 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- --
+-- ware  Foundation;  either version 2,  or (at your option) any later ver- --
+-- sion.  GNAT is distributed in the hope that it will be useful, but WITH- --
+-- OUT ANY WARRANTY;  without even the  implied warranty of MERCHANTABILITY --
+-- or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License --
+-- for  more details.  You should have  received  a copy of the GNU General --
+-- Public License  distributed with GNAT;  see file COPYING.  If not, write --
+-- to  the Free Software Foundation,  59 Temple Place - Suite 330,  Boston, --
+-- MA 02111-1307, USA.                                                      --
+--                                                                          --
+-- GNAT was originally developed  by the GNAT team at  New York University. --
+-- It is now maintained by Ada Core Technologies Inc (http://www.gnat.com). --
+--                                                                          --
+------------------------------------------------------------------------------
+
+with Atree;  use Atree;
+with Einfo;  use Einfo;
+with Namet;  use Namet;
+with Output; use Output;
+with Sinfo;  use Sinfo;
+with Uintp;  use Uintp;
+
+package body Sem_Maps is
+
+   -----------------------
+   -- Local Subprograms --
+   -----------------------
+
+   function Find_Assoc (M : Map; E : Entity_Id) return Assoc_Index;
+   --  Standard hash table search. M is the map to be searched, E is the
+   --  entity to be searched for, and Assoc_Index is the resulting
+   --  association, or is set to No_Assoc if there is no association.
+
+   function Find_Header_Size (N : Int) return Header_Index;
+   --  Find largest power of two smaller than the number of entries in
+   --  the table. This load factor of 2 may be adjusted later if needed.
+
+   procedure Write_Map (E : Entity_Id);
+   pragma Warnings (Off, Write_Map);
+   --  For debugging purposes.
+
+   ---------------------
+   -- Add_Association --
+   ---------------------
+
+   procedure Add_Association
+     (M    : in out Map;
+      O_Id : Entity_Id;
+      N_Id : Entity_Id;
+      Kind : Scope_Kind := S_Local)
+   is
+      Info : constant Map_Info      := Maps_Table.Table (M);
+      Offh : constant Header_Index  := Info.Header_Offset;
+      Offs : constant Header_Index  := Info.Header_Num;
+      J    : constant Header_Index  := Header_Index (O_Id) mod Offs;
+      K    : constant Assoc_Index   := Info.Assoc_Next;
+
+   begin
+      Associations_Table.Table (K) := (O_Id, N_Id, Kind, No_Assoc);
+      Maps_Table.Table (M).Assoc_Next := K + 1;
+
+      if Headers_Table.Table (Offh + J) /= No_Assoc then
+
+         --  Place new association at head of chain.
+
+         Associations_Table.Table (K).Next := Headers_Table.Table (Offh + J);
+      end if;
+
+      Headers_Table.Table (Offh + J) := K;
+   end Add_Association;
+
+   ------------------------
+   -- Build_Instance_Map --
+   ------------------------
+
+   function Build_Instance_Map (M : Map) return Map is
+      Info    : constant Map_Info     := Maps_Table.Table (M);
+      Res     : constant Map          := New_Map (Int (Info.Assoc_Num));
+      Offh1   : constant Header_Index := Info.Header_Offset;
+      Offa1   : constant Assoc_Index  := Info.Assoc_Offset;
+      Offh2   : constant Header_Index := Maps_Table.Table (Res).Header_Offset;
+      Offa2   : constant Assoc_Index  := Maps_Table.Table (Res).Assoc_Offset;
+      A       : Assoc;
+      A_Index : Assoc_Index;
+
+   begin
+      for J in 0 .. Info.Header_Num - 1 loop
+         A_Index := Headers_Table.Table (Offh1 + J);
+
+         if A_Index /= No_Assoc then
+            Headers_Table.Table (Offh2 + J) := A_Index + (Offa2 - Offa1);
+         end if;
+      end loop;
+
+      for J in 0 .. Info.Assoc_Num - 1 loop
+         A  := Associations_Table.Table (Offa1 + J);
+
+         --  For local entities that come from source, create the
+         --  corresponding local entities in the instance. Entities that
+         --  do not come from source are etypes, and new ones will be
+         --  generated when analyzing the instance.
+
+         if No (A.New_Id)
+           and then A.Kind = S_Local
+           and then Comes_From_Source (A.Old_Id)
+         then
+            A.New_Id := New_Copy (A.Old_Id);
+            A.New_Id := New_Entity (Nkind (A.Old_Id), Sloc (A.Old_Id));
+            Set_Chars (A.New_Id, Chars (A.Old_Id));
+         end if;
+
+         if A.Next /= No_Assoc then
+            A.Next := A.Next + (Offa2 - Offa1);
+         end if;
+
+         Associations_Table.Table (Offa2 + J) := A;
+      end loop;
+
+      Maps_Table.Table (Res).Assoc_Next := Associations_Table.Last;
+      return Res;
+   end Build_Instance_Map;
+
+   -------------
+   -- Compose --
+   -------------
+
+   function Compose (Orig_Map : Map; New_Map : Map) return Map is
+      Res : constant Map         := Copy (Orig_Map);
+      Off : constant Assoc_Index := Maps_Table.Table (Res).Assoc_Offset;
+      A   : Assoc;
+      K   : Assoc_Index;
+
+   begin
+      --  Iterate over the contents of Orig_Map, looking for entities
+      --  that are further mapped under New_Map.
+
+      for J in 0 .. Maps_Table.Table (Res).Assoc_Num - 1  loop
+         A := Associations_Table.Table (Off + J);
+         K := Find_Assoc (New_Map, A.New_Id);
+
+         if K /= No_Assoc then
+            Associations_Table.Table (Off + J).New_Id
+              := Associations_Table.Table (K).New_Id;
+         end if;
+      end loop;
+
+      return Res;
+   end Compose;
+
+   ----------
+   -- Copy --
+   ----------
+
+   function Copy (M : Map) return Map is
+      Info    : constant Map_Info     := Maps_Table.Table (M);
+      Res     : constant Map          := New_Map (Int (Info.Assoc_Num));
+      Offh1   : constant Header_Index := Info.Header_Offset;
+      Offa1   : constant Assoc_Index  := Info.Assoc_Offset;
+      Offh2   : constant Header_Index := Maps_Table.Table (Res).Header_Offset;
+      Offa2   : constant Assoc_Index  := Maps_Table.Table (Res).Assoc_Offset;
+      A       : Assoc;
+      A_Index : Assoc_Index;
+
+   begin
+      for J in 0 .. Info.Header_Num - 1 loop
+         A_Index := Headers_Table.Table (Offh1 + J) + (Offa2 - Offa1);
+
+         if A_Index /= No_Assoc then
+            Headers_Table.Table (Offh2 + J) := A_Index + (Offa2 - Offa1);
+         end if;
+      end loop;
+
+      for J in 0 .. Info.Assoc_Num - 1 loop
+         A := Associations_Table.Table (Offa1 + J);
+         A.Next := A.Next + (Offa2 - Offa1);
+         Associations_Table.Table (Offa2 + J) := A;
+      end loop;
+
+      Maps_Table.Table (Res).Assoc_Next := Associations_Table.Last;
+      return Res;
+   end Copy;
+
+   ----------------
+   -- Find_Assoc --
+   ----------------
+
+   function Find_Assoc (M : Map; E : Entity_Id) return Assoc_Index is
+      Offh    : constant Header_Index := Maps_Table.Table (M).Header_Offset;
+      Offs    : constant Header_Index := Maps_Table.Table (M).Header_Num;
+      J       : constant Header_Index := Header_Index (E) mod Offs;
+      A       : Assoc;
+      A_Index : Assoc_Index;
+
+   begin
+      A_Index := Headers_Table.Table (Offh + J);
+
+      if A_Index = No_Assoc then
+         return A_Index;
+
+      else
+         A := Associations_Table.Table (A_Index);
+
+         while Present (A.Old_Id) loop
+
+            if A.Old_Id = E then
+               return A_Index;
+
+            elsif A.Next = No_Assoc then
+               return No_Assoc;
+
+            else
+               A_Index := A.Next;
+               A := Associations_Table.Table (A.Next);
+            end if;
+         end loop;
+
+         return No_Assoc;
+      end if;
+   end Find_Assoc;
+
+   ----------------------
+   -- Find_Header_Size --
+   ----------------------
+
+   function Find_Header_Size (N : Int) return Header_Index is
+      Siz : Header_Index;
+
+   begin
+      Siz := 2;
+      while 2 * Siz < Header_Index (N) loop
+         Siz := 2 * Siz;
+      end loop;
+
+      return Siz;
+   end Find_Header_Size;
+
+   ------------
+   -- Lookup --
+   ------------
+
+   function Lookup (M : Map; E : Entity_Id) return Entity_Id is
+      Offh : constant Header_Index := Maps_Table.Table (M).Header_Offset;
+      Offs : constant Header_Index := Maps_Table.Table (M).Header_Num;
+      J    : constant Header_Index := Header_Index (E) mod Offs;
+      A    : Assoc;
+
+   begin
+      if Headers_Table.Table (Offh + J) = No_Assoc then
+         return Empty;
+
+      else
+         A := Associations_Table.Table (Headers_Table.Table (Offh + J));
+
+         while Present (A.Old_Id) loop
+
+            if A.Old_Id = E then
+               return A.New_Id;
+
+            elsif A.Next = No_Assoc then
+               return Empty;
+
+            else
+               A := Associations_Table.Table (A.Next);
+            end if;
+         end loop;
+
+         return Empty;
+      end if;
+   end Lookup;
+
+   -------------
+   -- New_Map --
+   -------------
+
+   function New_Map (Num_Assoc : Int) return Map is
+      Header_Size : Header_Index := Find_Header_Size (Num_Assoc);
+      Res         : Map_Info;
+
+   begin
+      --  Allocate the tables for the new map at the current end of the
+      --  global tables.
+
+      Associations_Table.Increment_Last;
+      Headers_Table.Increment_Last;
+      Maps_Table.Increment_Last;
+
+      Res.Header_Offset := Headers_Table.Last;
+      Res.Header_Num    := Header_Size;
+      Res.Assoc_Offset  := Associations_Table.Last;
+      Res.Assoc_Next    := Associations_Table.Last;
+      Res.Assoc_Num     := Assoc_Index (Num_Assoc);
+
+      Headers_Table.Set_Last (Headers_Table.Last + Header_Size);
+      Associations_Table.Set_Last
+        (Associations_Table.Last + Assoc_Index (Num_Assoc));
+      Maps_Table.Table (Maps_Table.Last) := Res;
+
+      for J in 1 .. Header_Size loop
+         Headers_Table.Table (Headers_Table.Last - J) := No_Assoc;
+      end loop;
+
+      return Maps_Table.Last;
+   end New_Map;
+
+   ------------------------
+   -- Update_Association --
+   ------------------------
+
+   procedure Update_Association
+     (M    : in out Map;
+      O_Id : Entity_Id;
+      N_Id : Entity_Id;
+      Kind : Scope_Kind := S_Local)
+   is
+      J : constant Assoc_Index := Find_Assoc (M, O_Id);
+
+   begin
+      Associations_Table.Table (J).New_Id := N_Id;
+      Associations_Table.Table (J).Kind := Kind;
+   end Update_Association;
+
+   ---------------
+   -- Write_Map --
+   ---------------
+
+   procedure Write_Map (E : Entity_Id) is
+      M    : constant Map          := Map (UI_To_Int (Renaming_Map (E)));
+      Info : constant Map_Info     := Maps_Table.Table (M);
+      Offh : constant Header_Index := Info.Header_Offset;
+      Offa : constant Assoc_Index  := Info.Assoc_Offset;
+      A    : Assoc;
+
+   begin
+      Write_Str ("Size : ");
+      Write_Int (Int (Info.Assoc_Num));
+      Write_Eol;
+
+      Write_Str ("Headers");
+      Write_Eol;
+
+      for J in 0 .. Info.Header_Num - 1 loop
+         Write_Int (Int (Offh + J));
+         Write_Str (" : ");
+         Write_Int (Int (Headers_Table.Table (Offh + J)));
+         Write_Eol;
+      end loop;
+
+      for J in 0 .. Info.Assoc_Num - 1 loop
+         A := Associations_Table.Table (Offa + J);
+         Write_Int (Int (Offa + J));
+         Write_Str (" : ");
+         Write_Name (Chars (A.Old_Id));
+         Write_Str ("  ");
+         Write_Int (Int (A.Old_Id));
+         Write_Str (" ==> ");
+         Write_Int (Int (A.New_Id));
+         Write_Str (" next = ");
+         Write_Int (Int (A.Next));
+         Write_Eol;
+      end loop;
+   end Write_Map;
+
+end Sem_Maps;
diff --git a/gcc/ada/sem_maps.ads b/gcc/ada/sem_maps.ads
new file mode 100644 (file)
index 0000000..3033f89
--- /dev/null
@@ -0,0 +1,170 @@
+------------------------------------------------------------------------------
+--                                                                          --
+--                         GNAT COMPILER COMPONENTS                         --
+--                                                                          --
+--                             S E M _ M A P S                              --
+--                                                                          --
+--                                 S p e c                                  --
+--                                                                          --
+--                              $Revision: 1.4 $
+--                                                                          --
+--          Copyright (C) 1996-1999 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- --
+-- ware  Foundation;  either version 2,  or (at your option) any later ver- --
+-- sion.  GNAT is distributed in the hope that it will be useful, but WITH- --
+-- OUT ANY WARRANTY;  without even the  implied warranty of MERCHANTABILITY --
+-- or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License --
+-- for  more details.  You should have  received  a copy of the GNU General --
+-- Public License  distributed with GNAT;  see file COPYING.  If not, write --
+-- to  the Free Software Foundation,  59 Temple Place - Suite 330,  Boston, --
+-- MA 02111-1307, USA.                                                      --
+--                                                                          --
+-- GNAT was originally developed  by the GNAT team at  New York University. --
+-- It is now maintained by Ada Core Technologies Inc (http://www.gnat.com). --
+--                                                                          --
+------------------------------------------------------------------------------
+
+--  This package contains the operations on the renaming maps used for
+--  generic analysis and instantiation. Renaming maps are created when
+--  a generic unit is analyzed, in order to capture all references to
+--  global variables within the unit. The renaming map of a generic unit
+--  copied prior to each instantiation, and then updated by mapping the
+--  formals into the actuals and the local entities into entities local to
+--  the instance. When the generic tree is copied to produce the instance,
+--  all references are updated by means of the renaming map.
+
+--  Map composition of renaming maps takes place for nested instantiations,
+--  for generic child units, and for formal packages.
+
+--  For additional details, see the documentation in sem_ch12.
+
+with Table;
+with Types; use Types;
+
+package Sem_Maps is
+
+   type Map is new Int;
+
+   type Assoc is private;
+
+   type Scope_Kind is (S_Global, S_Formal, S_Local);
+
+   function New_Map (Num_Assoc : Int) return Map;
+   --  Build empty map with the given number of associations, and a
+   --  headers table of the appropriate size.
+
+   function Compose (Orig_Map : Map; New_Map : Map) return Map;
+   --  Update the associations in Orig_Map, so that if Orig_Map (e1) = e2
+   --  and New_Map (e2) = e3, then the image of e1 under the result is e3.
+
+   function Copy (M : Map) return Map;
+   --  Full copy of contents and headers.
+
+   function Lookup (M : Map; E : Entity_Id) return Entity_Id;
+   --  Retrieve image of E under M, Empty if undefined.
+
+   procedure Add_Association
+     (M    : in out Map;
+      O_Id : Entity_Id;
+      N_Id : Entity_Id;
+      Kind : Scope_Kind := S_Local);
+   --  Update M in place. On entry M (O_Id) must not be defined.
+
+   procedure Update_Association
+     (M    : in out Map;
+      O_Id : Entity_Id;
+      N_Id : Entity_Id;
+      Kind : Scope_Kind := S_Local);
+   --  Update the entry in M for O_Id.
+
+   function Build_Instance_Map (M : Map) return Map;
+   --  Copy renaming map of generic, and create new entities for all the
+   --  local entities within.
+
+private
+
+   --  New maps are created when a generic is analyzed, and for each of
+   --  its instantiations. Maps are also updated for nested generics, for
+   --  child units, and for formal packages. As a result we need to allocate
+   --  maps dynamically.
+
+   --  When analyzing a generic, we do not know how many references are
+   --  in it. We build an initial map after generic analysis, using a static
+   --  structure that relies on the compiler's extensible table mechanism.
+   --  After constructing this initial map, all subsequent uses and updates
+   --  of this map do not modify its domain, so that dynamically allocated
+   --  maps have a fixed size and never need to be reallocated. Furthermore,
+   --  the headers of the hash table of a dynamically allocated map can be
+   --  chosen according to the total number of entries in the map, to
+   --  accomodate efficiently generic units of different sizes (Unchecked_
+   --  Conversion vs. Generic_Elementary_Functions, for example). So in
+   --  fact both components of a map have fixed size, and can be allocated
+   --  using the standard table mechanism. A Maps_Table holds records that
+   --  contain indices into the global Headers table and the Associations
+   --  table, and a Map is an index into the Maps_Table.
+   --
+   --              Maps_Table          Headers_Table     Associations_Table
+   --
+   --                                    |_____|          |___________ |
+   --               |_____|              |     |          |            |
+   --        ------>|Map  |------------------------------>|Associations|
+   --               |Info |------------->|     |=========>| for one    |
+   --               |_____|              |     |====|     |   unit     |
+   --               |     |              |     |    |====>|            |
+   --                                    |_____|          |____________|
+   --                                    |     |          |            |
+   type Header_Index is new Int;
+   type Assoc_Index  is new Int;
+   No_Assoc : constant Assoc_Index := -1;
+
+   type Map_Info is record
+      Header_Offset : Header_Index;
+      Header_Num    : Header_Index;
+      Assoc_Offset  : Assoc_Index;
+      Assoc_Num     : Assoc_Index;
+      Assoc_Next    : Assoc_Index;
+   end record;
+
+   type Assoc is record
+      Old_Id : Entity_Id   := Empty;
+      New_Id : Entity_Id   := Empty;
+      Kind   : Scope_Kind  := S_Local;
+      Next   : Assoc_Index := No_Assoc;
+   end record;
+
+   --  All maps are accessed through the following table. The map attribute
+   --  of a generic unit or an instance is an index into this table.
+
+   package Maps_Table is new Table.Table (
+      Table_Component_Type => Map_Info,
+      Table_Index_Type     => Map,
+      Table_Low_Bound      => 0,
+      Table_Initial        => 100,
+      Table_Increment      => 10,
+      Table_Name           => "Maps_Table");
+
+   --  All headers for hash tables are allocated in one global table. Each
+   --  map stores the offset into this table at which its own headers start.
+
+   package Headers_Table is new Table.Table (
+      Table_Component_Type => Assoc_Index,
+      Table_Index_Type     => Header_Index,
+      Table_Low_Bound      => 0,
+      Table_Initial        => 1000,
+      Table_Increment      => 10,
+      Table_Name           => "Headers_Table");
+
+   --  All associations are allocated in one global table. Each map stores
+   --  the offset into this table at which its own associations start.
+
+   package Associations_Table is new Table.Table (
+      Table_Component_Type => Assoc,
+      Table_Index_Type     => Assoc_Index,
+      Table_Low_Bound      => 1,
+      Table_Initial        => 1000,
+      Table_Increment      => 10,
+      Table_Name           => "Associations_Table");
+
+end Sem_Maps;
diff --git a/gcc/ada/sem_mech.adb b/gcc/ada/sem_mech.adb
new file mode 100644 (file)
index 0000000..800a5e8
--- /dev/null
@@ -0,0 +1,437 @@
+------------------------------------------------------------------------------
+--                                                                          --
+--                         GNAT COMPILER COMPONENTS                         --
+--                                                                          --
+--                             S E M _ M E C H                              --
+--                                                                          --
+--                                 B o d y                                  --
+--                                                                          --
+--                            $Revision: 1.16 $
+--                                                                          --
+--          Copyright (C) 1996-2001 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- --
+-- ware  Foundation;  either version 2,  or (at your option) any later ver- --
+-- sion.  GNAT is distributed in the hope that it will be useful, but WITH- --
+-- OUT ANY WARRANTY;  without even the  implied warranty of MERCHANTABILITY --
+-- or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License --
+-- for  more details.  You should have  received  a copy of the GNU General --
+-- Public License  distributed with GNAT;  see file COPYING.  If not, write --
+-- to  the Free Software Foundation,  59 Temple Place - Suite 330,  Boston, --
+-- MA 02111-1307, USA.                                                      --
+--                                                                          --
+-- GNAT was originally developed  by the GNAT team at  New York University. --
+-- It is now maintained by Ada Core Technologies Inc (http://www.gnat.com). --
+--                                                                          --
+------------------------------------------------------------------------------
+
+with Atree;    use Atree;
+with Einfo;    use Einfo;
+with Errout;   use Errout;
+with Targparm; use Targparm;
+with Nlists;   use Nlists;
+with Sem;      use Sem;
+with Sem_Util; use Sem_Util;
+with Sinfo;    use Sinfo;
+with Snames;   use Snames;
+with Stand;    use Stand;
+
+package body Sem_Mech is
+
+   -------------------------
+   -- Set_Mechanism_Value --
+   -------------------------
+
+   procedure Set_Mechanism_Value (Ent : Entity_Id; Mech_Name : Node_Id) is
+      Class : Node_Id;
+      Param : Node_Id;
+
+      procedure Bad_Class;
+      --  Signal bad descriptor class name
+
+      procedure Bad_Mechanism;
+      --  Signal bad mechanism name
+
+      procedure Bad_Class is
+      begin
+         Error_Msg_N ("unrecognized descriptor class name", Class);
+      end Bad_Class;
+
+      procedure Bad_Mechanism is
+      begin
+         Error_Msg_N ("unrecognized mechanism name", Mech_Name);
+      end Bad_Mechanism;
+
+   --  Start of processing for Set_Mechanism_Value
+
+   begin
+      if Mechanism (Ent) /= Default_Mechanism then
+         Error_Msg_NE
+           ("mechanism for & has already been set", Mech_Name, Ent);
+      end if;
+
+      --  MECHANISM_NAME ::= value | reference | descriptor
+
+      if Nkind (Mech_Name) = N_Identifier then
+         if Chars (Mech_Name) = Name_Value then
+            Set_Mechanism_With_Checks (Ent, By_Copy, Mech_Name);
+            return;
+
+         elsif Chars (Mech_Name) = Name_Reference then
+            Set_Mechanism_With_Checks (Ent, By_Reference, Mech_Name);
+            return;
+
+         elsif Chars (Mech_Name) = Name_Descriptor then
+            Check_VMS (Mech_Name);
+            Set_Mechanism_With_Checks (Ent, By_Descriptor, Mech_Name);
+            return;
+
+         elsif Chars (Mech_Name) = Name_Copy then
+            Error_Msg_N
+              ("bad mechanism name, Value assumed", Mech_Name);
+            Set_Mechanism (Ent, By_Copy);
+
+         else
+            Bad_Mechanism;
+            return;
+         end if;
+
+      --  MECHANISM_NAME ::= descriptor (CLASS_NAME)
+      --  CLASS_NAME     ::= ubs | ubsb | uba | s | sb | a | nca
+
+      --  Note: this form is parsed as an indexed component
+
+      elsif Nkind (Mech_Name) = N_Indexed_Component then
+         Class := First (Expressions (Mech_Name));
+
+         if Nkind (Prefix (Mech_Name)) /= N_Identifier
+           or else Chars (Prefix (Mech_Name)) /= Name_Descriptor
+           or else Present (Next (Class))
+         then
+            Bad_Mechanism;
+            return;
+         end if;
+
+      --  MECHANISM_NAME ::= descriptor (Class => CLASS_NAME)
+      --  CLASS_NAME     ::= ubs | ubsb | uba | s | sb | a | nca
+
+      --  Note: this form is parsed as a function call
+
+      elsif Nkind (Mech_Name) = N_Function_Call then
+
+         Param := First (Parameter_Associations (Mech_Name));
+
+         if Nkind (Name (Mech_Name)) /= N_Identifier
+           or else Chars (Name (Mech_Name)) /= Name_Descriptor
+           or else Present (Next (Param))
+           or else No (Selector_Name (Param))
+           or else Chars (Selector_Name (Param)) /= Name_Class
+         then
+            Bad_Mechanism;
+            return;
+         else
+            Class := Explicit_Actual_Parameter (Param);
+         end if;
+
+      else
+         Bad_Mechanism;
+         return;
+      end if;
+
+      --  Fall through here with Class set to descriptor class name
+
+      Check_VMS (Mech_Name);
+
+      if Nkind (Class) /= N_Identifier then
+         Bad_Class;
+         return;
+
+      elsif Chars (Class) = Name_UBS then
+         Set_Mechanism_With_Checks (Ent, By_Descriptor_UBS,  Mech_Name);
+
+      elsif Chars (Class) = Name_UBSB then
+         Set_Mechanism_With_Checks (Ent, By_Descriptor_UBSB, Mech_Name);
+
+      elsif Chars (Class) = Name_UBA then
+         Set_Mechanism_With_Checks (Ent, By_Descriptor_UBA,  Mech_Name);
+
+      elsif Chars (Class) = Name_S then
+         Set_Mechanism_With_Checks (Ent, By_Descriptor_S,    Mech_Name);
+
+      elsif Chars (Class) = Name_SB then
+         Set_Mechanism_With_Checks (Ent, By_Descriptor_SB,   Mech_Name);
+
+      elsif Chars (Class) = Name_A then
+         Set_Mechanism_With_Checks (Ent, By_Descriptor_A,    Mech_Name);
+
+      elsif Chars (Class) = Name_NCA then
+         Set_Mechanism_With_Checks (Ent, By_Descriptor_NCA,  Mech_Name);
+
+      else
+         Bad_Class;
+         return;
+      end if;
+
+   end Set_Mechanism_Value;
+
+   -------------------------------
+   -- Set_Mechanism_With_Checks --
+   -------------------------------
+
+   procedure Set_Mechanism_With_Checks
+     (Ent  : Entity_Id;
+      Mech : Mechanism_Type;
+      Enod : Node_Id)
+   is
+   begin
+      --  Right now we only do some checks for functions returning arguments
+      --  by desctiptor. Probably mode checks need to be added here ???
+
+      if Mech in Descriptor_Codes and then not Is_Formal (Ent) then
+         if Is_Record_Type (Etype (Ent)) then
+            Error_Msg_N ("?records cannot be returned by Descriptor", Enod);
+            return;
+         end if;
+      end if;
+
+      --  If we fall through, all checks have passed
+
+      Set_Mechanism (Ent, Mech);
+   end Set_Mechanism_With_Checks;
+
+   --------------------
+   -- Set_Mechanisms --
+   --------------------
+
+   procedure Set_Mechanisms (E : Entity_Id) is
+      Formal : Entity_Id;
+      Typ    : Entity_Id;
+
+   begin
+      --  Skip this processing if inside a generic template. Not only is
+      --  it uneccessary (since neither extra formals nor mechanisms are
+      --  relevant for the template itself), but at least at the moment,
+      --  procedures get frozen early inside a template so attempting to
+      --  look at the formal types does not work too well if they are
+      --  private types that have not been frozen yet.
+
+      if Inside_A_Generic then
+         return;
+      end if;
+
+      --  Loop through formals
+
+      Formal := First_Formal (E);
+      while Present (Formal) loop
+
+         if Mechanism (Formal) = Default_Mechanism then
+            Typ := Underlying_Type (Etype (Formal));
+
+            --  If there is no underlying type, then skip this processing and
+            --  leave the convention set to Default_Mechanism. It seems odd
+            --  that there should ever be such cases but there are (see
+            --  comments for filed regression tests 1418-001 and 1912-009) ???
+
+            if No (Typ) then
+               goto Skip_Formal;
+            end if;
+
+            case Convention (E) is
+
+               ---------
+               -- Ada --
+               ---------
+
+               --  Note: all RM defined conventions are treated the same
+               --  from the point of view of parameter passing mechanims
+
+               when Convention_Ada       |
+                    Convention_Intrinsic |
+                    Convention_Entry     |
+                    Convention_Protected |
+                    Convention_Stubbed   =>
+
+                  --  By reference types are passed by reference (RM 6.2(4))
+
+                  if Is_By_Reference_Type (Typ) then
+                     Set_Mechanism (Formal, By_Reference);
+
+                  --  By copy types are passed by copy (RM 6.2(3))
+
+                  elsif Is_By_Copy_Type (Typ) then
+                     Set_Mechanism (Formal, By_Copy);
+
+                  --  All other types we leave the Default_Mechanism set, so
+                  --  that the backend can choose the appropriate method.
+
+                  else
+                     null;
+                  end if;
+
+               -------
+               -- C --
+               -------
+
+               --  Note: Assembler, C++, Java, Stdcall also use C conventions
+
+               when Convention_Assembler |
+                    Convention_C         |
+                    Convention_CPP       |
+                    Convention_Java      |
+                    Convention_Stdcall   =>
+
+                  --  The following values are passed by copy
+
+                  --    IN Scalar parameters (RM B.3(66))
+                  --    IN parameters of access types (RM B.3(67))
+                  --    Access parameters (RM B.3(68))
+                  --    Access to subprogram types (RM B.3(71))
+
+                  --  Note: in the case of access parameters, it is the
+                  --  pointer that is passed by value. In GNAT access
+                  --  parameters are treated as IN parameters of an
+                  --  anonymous access type, so this falls out free.
+
+                  --  The bottom line is that all IN elementary types
+                  --  are passed by copy in GNAT.
+
+                  if Is_Elementary_Type (Typ) then
+                     if Ekind (Formal) = E_In_Parameter then
+                        Set_Mechanism (Formal, By_Copy);
+
+                     --  OUT and IN OUT parameters of elementary types are
+                     --  passed by reference (RM B.3(68)). Note that we are
+                     --  not following the advice to pass the address of a
+                     --  copy to preserve by copy semantics.
+
+                     else
+                        Set_Mechanism (Formal, By_Reference);
+                     end if;
+
+                  --  Records are normally passed by reference (RM B.3(69)).
+                  --  However, this can be overridden by the use of the
+                  --  C_Pass_By_Copy pragma or C_Pass_By_Copy convention.
+
+                  elsif Is_Record_Type (Typ) then
+
+                     --  If the record is not convention C, then we always
+                     --  pass by reference, C_Pass_By_Copy does not apply.
+
+                     if Convention (Typ) /= Convention_C then
+                        Set_Mechanism (Formal, By_Reference);
+
+                     --  If convention C_Pass_By_Copy was specified for
+                     --  the record type, then we pass by copy.
+
+                     elsif C_Pass_By_Copy (Typ) then
+                        Set_Mechanism (Formal, By_Copy);
+
+                     --  Otherwise, for a C convention record, we set the
+                     --  convention in accordance with a possible use of
+                     --  the C_Pass_By_Copy pragma. Note that the value of
+                     --  Default_C_Record_Mechanism in the absence of such
+                     --  a pragma is By_Reference.
+
+                     else
+                        Set_Mechanism (Formal, Default_C_Record_Mechanism);
+                     end if;
+
+                  --  Array types are passed by reference (B.3 (71))
+
+                  elsif Is_Array_Type (Typ) then
+                     Set_Mechanism (Formal, By_Reference);
+
+                  --  For all other types, use Default_Mechanism mechanism
+
+                  else
+                     null;
+                  end if;
+
+               -----------
+               -- COBOL --
+               -----------
+
+               when Convention_COBOL =>
+
+                  --  Access parameters (which in GNAT look like IN parameters
+                  --  of an access type) are passed by copy (RM B.4(96)) as
+                  --  are all other IN parameters of scalar type (RM B.4(97)).
+
+                  --  For now we pass these parameters by reference as well.
+                  --  The RM specifies the intent BY_CONTENT, but gigi does
+                  --  not currently transform By_Copy properly. If we pass by
+                  --  reference, it will be imperative to introduce copies ???
+
+                  if Is_Elementary_Type (Typ)
+                    and then Ekind (Formal) = E_In_Parameter
+                  then
+                     Set_Mechanism (Formal, By_Reference);
+
+                  --  All other parameters (i.e. all non-scalar types, and
+                  --  all OUT or IN OUT parameters) are passed by reference.
+                  --  Note that at the moment we are not bothering to make
+                  --  copies of scalar types as recommended in the RM.
+
+                  else
+                     Set_Mechanism (Formal, By_Reference);
+                  end if;
+
+               -------------
+               -- Fortran --
+               -------------
+
+               when Convention_Fortran =>
+
+                  --  In OpenVMS, pass a character of array of character
+                  --  value using Descriptor(S). Should this also test
+                  --  Debug_Flag_M ???
+
+                  if OpenVMS_On_Target
+                    and then (Root_Type (Typ) = Standard_Character
+                               or else
+                                 (Is_Array_Type (Typ)
+                                   and then
+                                     Root_Type (Component_Type (Typ)) =
+                                                     Standard_Character))
+                  then
+                     Set_Mechanism (Formal, By_Descriptor_S);
+
+                  --  Access types are passed by default (presumably this
+                  --  will mean they are passed by copy)
+
+                  elsif Is_Access_Type (Typ) then
+                     null;
+
+                  --  For now, we pass all other parameters by reference.
+                  --  It is not clear that this is right in the long run,
+                  --  but it seems to correspond to what gnu f77 wants.
+
+
+                  else
+                     Set_Mechanism (Formal, By_Reference);
+                  end if;
+
+            end case;
+         end if;
+
+         <<Skip_Formal>> -- remove this when problem above is fixed ???
+
+         Next_Formal (Formal);
+      end loop;
+
+      --  Now deal with return type, we always leave the default mechanism
+      --  set except for the case of returning a By_Reference type for an
+      --  Ada convention, where we force return by reference
+
+      if Ekind (E) = E_Function
+        and then Mechanism (E) = Default_Mechanism
+        and then not Has_Foreign_Convention (E)
+        and then Is_By_Reference_Type (Etype (E))
+      then
+         Set_Mechanism (E, By_Reference);
+      end if;
+
+   end Set_Mechanisms;
+
+end Sem_Mech;
diff --git a/gcc/ada/sem_mech.ads b/gcc/ada/sem_mech.ads
new file mode 100644 (file)
index 0000000..4b0993d
--- /dev/null
@@ -0,0 +1,173 @@
+------------------------------------------------------------------------------
+--                                                                          --
+--                         GNAT COMPILER COMPONENTS                         --
+--                                                                          --
+--                             S E M _ M E C H                              --
+--                                                                          --
+--                                 S p e c                                  --
+--                                                                          --
+--                            $Revision: 1.6 $                              --
+--                                                                          --
+--          Copyright (C) 1996-1997 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- --
+-- ware  Foundation;  either version 2,  or (at your option) any later ver- --
+-- sion.  GNAT is distributed in the hope that it will be useful, but WITH- --
+-- OUT ANY WARRANTY;  without even the  implied warranty of MERCHANTABILITY --
+-- or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License --
+-- for  more details.  You should have  received  a copy of the GNU General --
+-- Public License  distributed with GNAT;  see file COPYING.  If not, write --
+-- to  the Free Software Foundation,  59 Temple Place - Suite 330,  Boston, --
+-- MA 02111-1307, USA.                                                      --
+--                                                                          --
+-- GNAT was originally developed  by the GNAT team at  New York University. --
+-- It is now maintained by Ada Core Technologies Inc (http://www.gnat.com). --
+--                                                                          --
+------------------------------------------------------------------------------
+
+--  This package contains the routine used to establish calling mechanisms
+--  The reason we separate this off into its own package is that it is
+--  entirely possible that it may need some target specific specialization.
+
+with Types; use Types;
+
+package Sem_Mech is
+
+   -------------------------------------------------
+   -- Definitions for Parameter Mechanism Control --
+   -------------------------------------------------
+
+   --  For parameters passed to subprograms, and for function return values,
+   --  as passing mechanism is defined. The entity attribute Mechanism returns
+   --  an indication of the mechanism, and Set_Mechanism can be used to set
+   --  the mechanism. At the program level, there are three ways to explicitly
+   --  set the mechanism:
+
+   --    An Import_xxx or Export_xxx pragma (where xxx is Function, Procedure,
+   --    or Valued_Procedure) can explicitly set the mechanism for either a
+   --    parameter or a function return value. A mechanism explicitly set by
+   --    such a pragma overrides the effect of C_Pass_By_Copy described below.
+
+   --    If convention C_Pass_By_Copy is set for a record, and the record type
+   --    is used as the formal type of a subprogram with a foreign convention,
+   --    then the mechanism is set to By_Copy.
+
+   --    If a pragma C_Pass_By_Copy applies, and a record type has Convention
+   --    C, and the record type is used as the formal type of a subprogram
+   --    with a foreign convention, then the mechanism is set to use By_Copy
+   --    if the size of the record is sufficiently small (as determined by
+   --    the value of the parameter to pragma C_Pass_By_Copy).
+
+   --  The subtype Mechanism_Type (declared in Types) is used to describe
+   --  the mechanism to be used. The following special values of this type
+   --  specify the mechanism, as follows.
+
+   Default_Mechanism : constant Mechanism_Type := 0;
+   --  The default setting indicates that the backend will choose the proper
+   --  default mechanism. This depends on the convention of the subprogram
+   --  involved, and is generally target dependent. In the compiler, the
+   --  backend chooses the mechanism in this case in accordance with any
+   --  requirements imposed by the ABI. Note that Default is never used for
+   --  record types on foreign convention subprograms, since By_Reference
+   --  is forced for such types unless one of the above described approaches
+   --  is used to explicitly force By_Copy.
+
+   By_Copy : constant Mechanism_Type := -1;
+   --  Passing by copy is forced. The exact meaning of By_Copy (e.g. whether
+   --  at a low level the value is passed in registers, or the value is copied
+   --  and a pointer is passed), is determined by the backend in accordance
+   --  with requirements imposed by the ABI. Note that in the extended import
+   --  and export pragma mechanisms, this is called Value, rather than Copy.
+
+   By_Reference : constant Mechanism_Type := -2;
+   --  Passing by reference is forced. This is always equivalent to passing
+   --  a simple pointer in the case of subprograms with a foreign convention.
+   --  For unconstrained arrays passed to foreign convention subprograms, the
+   --  address of the first element of the array is passed. For convention
+   --  Ada, the result is logically to pass a reference, but the precise
+   --  mechanism (e.g. to pass bounds of unconstrained types and other needed
+   --  special information) is determined by the backend in accordance with
+   --  requirements imposed by the ABI as interpreted for Ada.
+
+   By_Descriptor      : constant Mechanism_Type := -3;
+   By_Descriptor_UBS  : constant Mechanism_Type := -4;
+   By_Descriptor_UBSB : constant Mechanism_Type := -5;
+   By_Descriptor_UBA  : constant Mechanism_Type := -6;
+   By_Descriptor_S    : constant Mechanism_Type := -7;
+   By_Descriptor_SB   : constant Mechanism_Type := -8;
+   By_Descriptor_A    : constant Mechanism_Type := -9;
+   By_Descriptor_NCA  : constant Mechanism_Type := -10;
+   --  These values are used only in OpenVMS ports of GNAT. Pass by descriptor
+   --  is forced, as described in the OpenVMS ABI. The suffix indicates the
+   --  descriptor type:
+   --
+   --     UBS    unaligned bit string
+   --     UBSB   aligned bit string with arbitrary bounds
+   --     UBA    unaligned bit array
+   --     S      string, also a scalar or access type parameter
+   --     SB     string with arbitrary bounds
+   --     A      contiguous array
+   --     NCA    non-contiguous array
+   --
+   --  Note: the form with no suffix is used if the Import/Export pragma
+   --  uses the simple form of the mechanism name where no descriptor
+   --  type is supplied. In this case the back end assigns a descriptor
+   --  type based on the Ada type in accordance with the OpenVMS ABI.
+
+   subtype Descriptor_Codes is Mechanism_Type
+     range By_Descriptor_NCA .. By_Descriptor;
+   --  Subtype including all descriptor mechanisms
+
+   --  All the above special values are non-positive. Positive values for
+   --  Mechanism_Type values have a special meaning. They are used only in
+   --  the case of records, as a result of the use of the C_Pass_By_Copy
+   --  pragma, and the meaning is that if the size of the record is known
+   --  at compile time and does not exceed the mechanism type value, then
+   --  By_Copy passing is forced, otherwise By_Reference is forced.
+
+   ----------------------
+   -- Global Variables --
+   ----------------------
+
+   Default_C_Record_Mechanism : Mechanism_Type := By_Reference;
+   --  This value is the default mechanism used for C convention records
+   --  in foreign-convention subprograms if no mechanism is otherwise
+   --  specified. This value is modified appropriately by the occurrence
+   --  of a C_Pass_By_Copy configuration pragma.
+
+   -----------------
+   -- Subprograms --
+   -----------------
+
+   procedure Set_Mechanisms (E : Entity_Id);
+   --  E is a subprogram or subprogram type that has been frozen, so the
+   --  convention of the subprogram and all its formal types and result
+   --  type in the case of a function are established. The function of
+   --  this call is to set mechanism values for formals and for the
+   --  function return if they have not already been explicitly set by
+   --  a use of an extended Import or Export pragma. The idea is to set
+   --  mechanism values whereever the semantics is dictated by either
+   --  requirements or implementation advice in the RM, and to leave
+   --  the mechanism set to Default if there is no requirement, so that
+   --  the back-end is free to choose the most efficient method.
+
+   procedure Set_Mechanism_Value (Ent : Entity_Id; Mech_Name : Node_Id);
+   --  Mech is a parameter passing mechanism (see Import_Function syntax
+   --  for MECHANISM_NAME). This routine checks that the mechanism argument
+   --  has the right form, and if not issues an error message. If the
+   --  argument has the right form then the Mechanism field of Ent is
+   --  set appropriately. It also performs some error checks. Note that
+   --  the mechanism name has not been analyzed (and cannot indeed be
+   --  analyzed, since it is semantic nonsense), so we get it in the
+   --  exact form created by the parser.
+
+   procedure Set_Mechanism_With_Checks
+     (Ent  : Entity_Id;
+      Mech : Mechanism_Type;
+      Enod : Node_Id);
+   --  Sets the mechanism of Ent to the given Mech value, after first checking
+   --  that the request makes sense. If it does not make sense, a warning is
+   --  posted on node Enod, and the Mechanism of Ent is unchanged.
+
+end Sem_Mech;
diff --git a/gcc/ada/sem_prag.adb b/gcc/ada/sem_prag.adb
new file mode 100644 (file)
index 0000000..4910c78
--- /dev/null
@@ -0,0 +1,8796 @@
+------------------------------------------------------------------------------
+--                                                                          --
+--                         GNAT COMPILER COMPONENTS                         --
+--                                                                          --
+--                             S E M _ P R A G                              --
+--                                                                          --
+--                                 B o d y                                  --
+--                                                                          --
+--                            $Revision: 1.558 $
+--                                                                          --
+--          Copyright (C) 1992-2001, 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- --
+-- ware  Foundation;  either version 2,  or (at your option) any later ver- --
+-- sion.  GNAT is distributed in the hope that it will be useful, but WITH- --
+-- OUT ANY WARRANTY;  without even the  implied warranty of MERCHANTABILITY --
+-- or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License --
+-- for  more details.  You should have  received  a copy of the GNU General --
+-- Public License  distributed with GNAT;  see file COPYING.  If not, write --
+-- to  the Free Software Foundation,  59 Temple Place - Suite 330,  Boston, --
+-- MA 02111-1307, USA.                                                      --
+--                                                                          --
+-- GNAT was originally developed  by the GNAT team at  New York University. --
+-- It is now maintained by Ada Core Technologies Inc (http://www.gnat.com). --
+--                                                                          --
+------------------------------------------------------------------------------
+
+--  This unit contains the semantic processing for all pragmas, both language
+--  and implementation defined. For most pragmas, the parser only does the
+--  most basic job of checking the syntax, so Sem_Prag also contains the code
+--  to complete the syntax checks. Certain pragmas are handled partially or
+--  completely by the parser (see Par.Prag for further details).
+
+with Atree;    use Atree;
+with Casing;   use Casing;
+with Csets;    use Csets;
+with Debug;    use Debug;
+with Einfo;    use Einfo;
+with Elists;   use Elists;
+with Errout;   use Errout;
+with Expander; use Expander;
+with Exp_Dist; use Exp_Dist;
+with Fname;    use Fname;
+with Hostparm; use Hostparm;
+with Lib;      use Lib;
+with Namet;    use Namet;
+with Nlists;   use Nlists;
+with Nmake;    use Nmake;
+with Opt;      use Opt;
+with Output;   use Output;
+with Restrict; use Restrict;
+with Rtsfind;  use Rtsfind;
+with Sem;      use Sem;
+with Sem_Ch8;  use Sem_Ch8;
+with Sem_Ch13; use Sem_Ch13;
+with Sem_Disp; use Sem_Disp;
+with Sem_Elim; use Sem_Elim;
+with Sem_Eval; use Sem_Eval;
+with Sem_Intr; use Sem_Intr;
+with Sem_Mech; use Sem_Mech;
+with Sem_Res;  use Sem_Res;
+with Sem_Type; use Sem_Type;
+with Sem_Util; use Sem_Util;
+with Sem_VFpt; use Sem_VFpt;
+with Stand;    use Stand;
+with Sinfo;    use Sinfo;
+with Sinfo.CN; use Sinfo.CN;
+with Sinput;   use Sinput;
+with Snames;   use Snames;
+with Stringt;  use Stringt;
+with Stylesw;  use Stylesw;
+with Targparm; use Targparm;
+with Tbuild;   use Tbuild;
+with Ttypes;
+with Uintp;    use Uintp;
+with Urealp;   use Urealp;
+with Validsw;  use Validsw;
+
+package body Sem_Prag is
+
+   ----------------------------------------------
+   -- Common Handling of Import-Export Pragmas --
+   ----------------------------------------------
+
+   --  In the following section, a number of Import_xxx and Export_xxx
+   --  pragmas are defined by GNAT. These are compatible with the DEC
+   --  pragmas of the same name, and all have the following common
+   --  form and processing:
+
+   --  pragma Export_xxx
+   --        [Internal                 =>] LOCAL_NAME,
+   --     [, [External                 =>] EXTERNAL_SYMBOL]
+   --     [, other optional parameters   ]);
+
+   --  pragma Import_xxx
+   --        [Internal                 =>] LOCAL_NAME,
+   --     [, [External                 =>] EXTERNAL_SYMBOL]
+   --     [, other optional parameters   ]);
+
+   --   EXTERNAL_SYMBOL ::=
+   --     IDENTIFIER
+   --   | static_string_EXPRESSION
+
+   --  The internal LOCAL_NAME designates the entity that is imported or
+   --  exported, and must refer to an entity in the current declarative
+   --  part (as required by the rules for LOCAL_NAME).
+
+   --  The external linker name is designated by the External parameter
+   --  if given, or the Internal parameter if not (if there is no External
+   --  parameter, the External parameter is a copy of the Internal name).
+
+   --  If the External parameter is given as a string, then this string
+   --  is treated as an external name (exactly as though it had been given
+   --  as an External_Name parameter for a normal Import pragma).
+
+   --  If the External parameter is given as an identifier (or there is no
+   --  External parameter, so that the Internal identifier is used), then
+   --  the external name is the characters of the identifier, translated
+   --  to all upper case letters for OpenVMS versions of GNAT, and to all
+   --  lower case letters for all other versions
+
+   --  Note: the external name specified or implied by any of these special
+   --  Import_xxx or Export_xxx pragmas override an external or link name
+   --  specified in a previous Import or Export pragma.
+
+   --  Note: these and all other DEC-compatible GNAT pragmas allow full
+   --  use of named notation, following the standard rules for subprogram
+   --  calls, i.e. parameters can be given in any order if named notation
+   --  is used, and positional and named notation can be mixed, subject to
+   --  the rule that all positional parameters must appear first.
+
+   --  Note: All these pragmas are implemented exactly following the DEC
+   --  design and implementation and are intended to be fully compatible
+   --  with the use of these pragmas in the DEC Ada compiler.
+
+   -------------------------------------
+   -- Local Subprograms and Variables --
+   -------------------------------------
+
+   function Adjust_External_Name_Case (N : Node_Id) return Node_Id;
+   --  This routine is used for possible casing adjustment of an explicit
+   --  external name supplied as a string literal (the node N), according
+   --  to the casing requirement of Opt.External_Name_Casing. If this is
+   --  set to As_Is, then the string literal is returned unchanged, but if
+   --  it is set to Uppercase or Lowercase, then a new string literal with
+   --  appropriate casing is constructed.
+
+   function Is_Generic_Subprogram (Id : Entity_Id) return Boolean;
+   --  Return True if Id is a generic procedure or a function
+
+   function Get_Base_Subprogram (Def_Id : Entity_Id) return Entity_Id;
+   --  If Def_Id refers to a renamed subprogram, then the base subprogram
+   --  (the original one, following the renaming chain) is returned.
+   --  Otherwise the entity is returned unchanged. Should be in Einfo???
+
+   procedure Set_Unit_Name (N : Node_Id; With_Item : Node_Id);
+   --  Place semantic information on the argument of an Elaborate or
+   --  Elaborate_All pragma. Entity name for unit and its parents is
+   --  taken from item in previous with_clause that mentions the unit.
+
+   Locking_Policy_Sloc          : Source_Ptr := No_Location;
+   Queuing_Policy_Sloc          : Source_Ptr := No_Location;
+   Task_Dispatching_Policy_Sloc : Source_Ptr := No_Location;
+   --  These global variables remember the location of a previous locking,
+   --  queuing or task dispatching policy pragma, so that appropriate error
+   --  messages can be generated for inconsistent pragmas. Note that it is
+   --  fine that these are global locations, because the check for consistency
+   --  is over the entire program.
+
+   -------------------------------
+   -- Adjust_External_Name_Case --
+   -------------------------------
+
+   function Adjust_External_Name_Case (N : Node_Id) return Node_Id is
+      CC : Char_Code;
+
+   begin
+      --  Adjust case of literal if required
+
+      if Opt.External_Name_Exp_Casing = As_Is then
+         return N;
+
+      else
+         --  Copy existing string
+
+         Start_String;
+
+         --  Set proper casing
+
+         for J in 1 .. String_Length (Strval (N)) loop
+            CC := Get_String_Char (Strval (N), J);
+
+            if Opt.External_Name_Exp_Casing = Uppercase
+              and then CC >= Get_Char_Code ('a')
+              and then CC <= Get_Char_Code ('z')
+            then
+               Store_String_Char (CC - 32);
+
+            elsif Opt.External_Name_Exp_Casing = Lowercase
+              and then CC >= Get_Char_Code ('A')
+              and then CC <= Get_Char_Code ('Z')
+            then
+               Store_String_Char (CC + 32);
+
+            else
+               Store_String_Char (CC);
+            end if;
+         end loop;
+
+         return
+           Make_String_Literal (Sloc (N),
+             Strval => End_String);
+      end if;
+   end Adjust_External_Name_Case;
+
+   --------------------
+   -- Analyze_Pragma --
+   --------------------
+
+   procedure Analyze_Pragma (N : Node_Id) is
+      Loc     : constant Source_Ptr := Sloc (N);
+      Prag_Id : Pragma_Id;
+
+      Pragma_Exit : exception;
+      --  This exception is used to exit pragma processing completely. It
+      --  is used when an error is detected, and in other situations where
+      --  it is known that no further processing is required.
+
+      Arg_Count : Nat;
+      --  Number of pragma argument associations
+
+      Arg1 : Node_Id;
+      Arg2 : Node_Id;
+      Arg3 : Node_Id;
+      Arg4 : Node_Id;
+      --  First four pragma arguments (pragma argument association nodes,
+      --  or Empty if the corresponding argument does not exist).
+
+      procedure Check_Ada_83_Warning;
+      --  Issues a warning message for the current pragma if operating in Ada
+      --  83 mode (used for language pragmas that are not a standard part of
+      --  Ada 83). This procedure does not raise Error_Pragma. Also notes use
+      --  of 95 pragma.
+
+      procedure Check_Arg_Count (Required : Nat);
+      --  Check argument count for pragma is equal to given parameter.
+      --  If not, then issue an error message and raise Pragma_Exit.
+
+      --  Note: all routines whose name is Check_Arg_Is_xxx take an
+      --  argument Arg which can either be a pragma argument association,
+      --  in which case the check is applied to the expression of the
+      --  association or an expression directly.
+
+      procedure Check_Arg_Is_Identifier (Arg : Node_Id);
+      --  Check the specified argument Arg to make sure that it is an
+      --  identifier. If not give error and raise Pragma_Exit.
+
+      procedure Check_Arg_Is_Integer_Literal (Arg : Node_Id);
+      --  Check the specified argument Arg to make sure that it is an
+      --  integer literal. If not give error and raise Pragma_Exit.
+
+      procedure Check_Arg_Is_Library_Level_Local_Name (Arg : Node_Id);
+      --  Check the specified argument Arg to make sure that it has the
+      --  proper syntactic form for a local name and meets the semantic
+      --  requirements for a local name. The local name is analyzed as
+      --  part of the processing for this call. In addition, the local
+      --  name is required to represent an entity at the library level.
+
+      procedure Check_Arg_Is_Local_Name (Arg : Node_Id);
+      --  Check the specified argument Arg to make sure that it has the
+      --  proper syntactic form for a local name and meets the semantic
+      --  requirements for a local name. The local name is analyzed as
+      --  part of the processing for this call.
+
+      procedure Check_Arg_Is_Locking_Policy (Arg : Node_Id);
+      --  Check the specified argument Arg to make sure that it is a valid
+      --  locking policy name. If not give error and raise Pragma_Exit.
+
+      procedure Check_Arg_Is_One_Of (Arg : Node_Id; N1, N2 : Name_Id);
+      procedure Check_Arg_Is_One_Of (Arg : Node_Id; N1, N2, N3 : Name_Id);
+      --  Check the specified argument Arg to make sure that it is an
+      --  identifier whose name matches either N1 or N2 (or N3 if present).
+      --  If not then give error and raise Pragma_Exit.
+
+      procedure Check_Arg_Is_Queuing_Policy (Arg : Node_Id);
+      --  Check the specified argument Arg to make sure that it is a valid
+      --  queuing policy name. If not give error and raise Pragma_Exit.
+
+      procedure Check_Arg_Is_Static_Expression
+        (Arg : Node_Id;
+         Typ : Entity_Id);
+      --  Check the specified argument Arg to make sure that it is a static
+      --  expression of the given type (i.e. it will be analyzed and resolved
+      --  using this type, which can be any valid argument to Resolve, e.g.
+      --  Any_Integer is OK). If not, given error and raise Pragma_Exit.
+
+      procedure Check_Arg_Is_String_Literal (Arg : Node_Id);
+      --  Check the specified argument Arg to make sure that it is a
+      --  string literal. If not give error and raise Pragma_Exit
+
+      procedure Check_Arg_Is_Task_Dispatching_Policy (Arg : Node_Id);
+      --  Check the specified argument Arg to make sure that it is a valid
+      --  valid task dispatching policy name. If not give error and raise
+      --  Pragma_Exit.
+
+      procedure Check_At_Least_N_Arguments (N : Nat);
+      --  Check there are at least N arguments present
+
+      procedure Check_At_Most_N_Arguments (N : Nat);
+      --  Check there are no more than N arguments present
+
+      procedure Check_First_Subtype (Arg : Node_Id);
+      --  Checks that Arg, whose expression is an entity name referencing
+      --  a subtype, does not reference a type that is not a first subtype.
+
+      procedure Check_In_Main_Program;
+      --  Common checks for pragmas that appear within a main program
+      --  (Priority, Main_Storage, Time_Slice).
+
+      procedure Check_Interrupt_Or_Attach_Handler;
+      --  Common processing for first argument of pragma Interrupt_Handler
+      --  or pragma Attach_Handler.
+
+      procedure Check_Is_In_Decl_Part_Or_Package_Spec;
+      --  Check that pragma appears in a declarative part, or in a package
+      --  specification, i.e. that it does not occur in a statement sequence
+      --  in a body.
+
+      procedure Check_No_Identifier (Arg : Node_Id);
+      --  Checks that the given argument does not have an identifier. If
+      --  an identifier is present, then an error message is issued, and
+      --  Pragma_Exit is raised.
+
+      procedure Check_No_Identifiers;
+      --  Checks that none of the arguments to the pragma has an identifier.
+      --  If any argument has an identifier, then an error message is issued,
+      --  and Pragma_Exit is raised.
+
+      procedure Check_Non_Overloaded_Function (Arg : Node_Id);
+      --  Check that the given argument is the name of a local function of
+      --  one argument that is not overloaded in the current local scope.
+
+      procedure Check_Optional_Identifier (Arg : Node_Id; Id : Name_Id);
+      --  Checks if the given argument has an identifier, and if so, requires
+      --  it to match the given identifier name. If there is a non-matching
+      --  identifier, then an error message is given and Error_Pragmas raised.
+
+      procedure Check_Optional_Identifier (Arg : Node_Id; Id : String);
+      --  Checks if the given argument has an identifier, and if so, requires
+      --  it to match the given identifier name. If there is a non-matching
+      --  identifier, then an error message is given and Error_Pragmas raised.
+      --  In this version of the procedure, the identifier name is given as
+      --  a string with lower case letters.
+
+      procedure Check_Static_Constraint (Constr : Node_Id);
+      --  Constr is a constraint from an N_Subtype_Indication node from a
+      --  component constraint in an Unchecked_Union type. This routine checks
+      --  that the constraint is static as required by the restrictions for
+      --  Unchecked_Union.
+
+      procedure Check_Valid_Configuration_Pragma;
+      --  Legality checks for placement of a configuration pragma
+
+      procedure Check_Valid_Library_Unit_Pragma;
+      --  Legality checks for library unit pragmas. A special case arises for
+      --  pragmas in generic instances that come from copies of the original
+      --  library unit pragmas in the generic templates. In the case of other
+      --  than library level instantiations these can appear in contexts which
+      --  would normally be invalid (they only apply to the original template
+      --  and to library level instantiations), and they are simply ignored,
+      --  which is implemented by rewriting them as null statements.
+
+      procedure Error_Pragma (Msg : String);
+      pragma No_Return (Error_Pragma);
+      --  Outputs error message for current pragma. The message contains an %
+      --  that will be replaced with the pragma name, and the flag is placed
+      --  on the pragma itself. Pragma_Exit is then raised.
+
+      procedure Error_Pragma_Arg (Msg : String; Arg : Node_Id);
+      pragma No_Return (Error_Pragma_Arg);
+      --  Outputs error message for current pragma. The message may contain
+      --  a % that will be replaced with the pragma name. The parameter Arg
+      --  may either be a pragma argument association, in which case the flag
+      --  is placed on the expression of this association, or an expression,
+      --  in which case the flag is placed directly on the expression. The
+      --  message is placed using Error_Msg_N, so the message may also contain
+      --  an & insertion character which will reference the given Arg value.
+      --  After placing the message, Pragma_Exit is raised.
+
+      procedure Error_Pragma_Arg (Msg1, Msg2 : String; Arg : Node_Id);
+      pragma No_Return (Error_Pragma_Arg);
+      --  Similar to above form of Error_Pragma_Arg except that two messages
+      --  are provided, the second is a continuation comment starting with \.
+
+      procedure Error_Pragma_Arg_Ident (Msg : String; Arg : Node_Id);
+      pragma No_Return (Error_Pragma_Arg_Ident);
+      --  Outputs error message for current pragma. The message may contain
+      --  a % that will be replaced with the pragma name. The parameter Arg
+      --  must be a pragma argument association with a non-empty identifier
+      --  (i.e. its Chars field must be set), and the error message is placed
+      --  on the identifier. The message is placed using Error_Msg_N so
+      --  the message may also contain an & insertion character which will
+      --  reference the identifier. After placing the message, Pragma_Exit
+      --  is raised.
+
+      function Find_Lib_Unit_Name return Entity_Id;
+      --  Used for a library unit pragma to find the entity to which the
+      --  library unit pragma applies, returns the entity found.
+
+      procedure Find_Program_Unit_Name (Id : Node_Id);
+      --  If the pragma is a compilation unit pragma, the id must denote the
+      --  compilation unit in the same compilation, and the pragma must appear
+      --  in the list of preceding or trailing pragmas. If it is a program
+      --  unit pragma that is not a compilation unit pragma, then the
+      --  identifier must be visible.
+
+      type Name_List is array (Natural range <>) of Name_Id;
+      type Args_List is array (Natural range <>) of Node_Id;
+      procedure Gather_Associations
+        (Names : Name_List;
+         Args  : out Args_List);
+      --  This procedure is used to gather the arguments for a pragma that
+      --  permits arbitrary ordering of parameters using the normal rules
+      --  for named and positional parameters. The Names argument is a list
+      --  of Name_Id values that corresponds to the allowed pragma argument
+      --  association identifiers in order. The result returned in Args is
+      --  a list of corresponding expressions that are the pragma arguments.
+      --  Note that this is a list of expressions, not of pragma argument
+      --  associations (Gather_Associations has completely checked all the
+      --  optional identifiers when it returns). An entry in Args is Empty
+      --  on return if the corresponding argument is not present.
+
+      function Get_Pragma_Arg (Arg : Node_Id) return Node_Id;
+      --  All the routines that check pragma arguments take either a pragma
+      --  argument association (in which case the expression of the argument
+      --  association is checked), or the expression directly. The function
+      --  Get_Pragma_Arg is a utility used to deal with these two cases. If
+      --  Arg is a pragma argument association node, then its expression is
+      --  returned, otherwise Arg is returned unchanged.
+
+      procedure GNAT_Pragma;
+      --  Called for all GNAT defined pragmas to note the use of the feature,
+      --  and also check the relevant restriction (No_Implementation_Pragmas).
+
+      function Is_Before_First_Decl
+        (Pragma_Node : Node_Id;
+         Decls       : List_Id)
+         return        Boolean;
+      --  Return True if Pragma_Node is before the first declarative item in
+      --  Decls where Decls is the list of declarative items.
+
+      function Is_Configuration_Pragma return Boolean;
+      --  Deterermines if the placement of the current pragma is appropriate
+      --  for a configuration pragma (precedes the current compilation unit)
+
+      procedure Pragma_Misplaced;
+      --  Issue fatal error message for misplaced pragma
+
+      procedure Process_Atomic_Shared_Volatile;
+      --  Common processing for pragmas Atomic, Shared, Volatile. Note that
+      --  Shared is an obsolete Ada 83 pragma, treated as being identical
+      --  in effect to pragma Atomic.
+
+      procedure Process_Convention (C : out Convention_Id; E : out Entity_Id);
+      --  Common procesing for Convention, Interface, Import and Export.
+      --  Checks first two arguments of pragma, and sets the appropriate
+      --  convention value in the specified entity or entities. On return
+      --  C is the convention, E is the referenced entity.
+
+      procedure Process_Extended_Import_Export_Exception_Pragma
+        (Arg_Internal : Node_Id;
+         Arg_External : Node_Id;
+         Arg_Form     : Node_Id;
+         Arg_Code     : Node_Id);
+      --  Common processing for the pragmas Import/Export_Exception.
+      --  The three arguments correspond to the three named parameters of
+      --  the pragma. An argument is empty if the corresponding parameter
+      --  is not present in the pragma.
+
+      procedure Process_Extended_Import_Export_Object_Pragma
+        (Arg_Internal : Node_Id;
+         Arg_External : Node_Id;
+         Arg_Size     : Node_Id);
+      --  Common processing for the pragmass Import/Export_Object.
+      --  The three arguments correspond to the three named parameters
+      --  of the pragmas. An argument is empty if the corresponding
+      --  parameter is not present in the pragma.
+
+      procedure Process_Extended_Import_Export_Internal_Arg
+        (Arg_Internal : Node_Id := Empty);
+      --  Common processing for all extended Import and Export pragmas. The
+      --  argument is the pragma parameter for the Internal argument. If
+      --  Arg_Internal is empty or inappropriate, an error message is posted.
+      --  Otherwise, on normal return, the Entity_Field of Arg_Internal is
+      --  set to identify the referenced entity.
+
+      procedure Process_Extended_Import_Export_Subprogram_Pragma
+        (Arg_Internal                 : Node_Id;
+         Arg_External                 : Node_Id;
+         Arg_Parameter_Types          : Node_Id;
+         Arg_Result_Type              : Node_Id := Empty;
+         Arg_Mechanism                : Node_Id;
+         Arg_Result_Mechanism         : Node_Id := Empty;
+         Arg_First_Optional_Parameter : Node_Id := Empty);
+      --  Common processing for all extended Import and Export pragmas
+      --  applying to subprograms. The caller omits any arguments that do
+      --  bnot apply to the pragma in question (for example, Arg_Result_Type
+      --  can be non-Empty only in the Import_Function and Export_Function
+      --  cases). The argument names correspond to the allowed pragma
+      --  association identifiers.
+
+      procedure Process_Generic_List;
+      --  Common processing for Share_Generic and Inline_Generic
+
+      procedure Process_Import_Or_Interface;
+      --  Common processing for Import of Interface
+
+      procedure Process_Inline (Active : Boolean);
+      --  Common processing for Inline and Inline_Always. The parameter
+      --  indicates if the inline pragma is active, i.e. if it should
+      --  actually cause inlining to occur.
+
+      procedure Process_Interface_Name
+        (Subprogram_Def : Entity_Id;
+         Ext_Arg        : Node_Id;
+         Link_Arg       : Node_Id);
+      --  Given the last two arguments of pragma Import, pragma Export, or
+      --  pragma Interface_Name, performs validity checks and sets the
+      --  Interface_Name field of the given subprogram entity to the
+      --  appropriate external or link name, depending on the arguments
+      --  given. Ext_Arg is always present, but Link_Arg may be missing.
+      --  Note that Ext_Arg may represent the Link_Name if Link_Arg is
+      --  missing, and appropriate named notation is used for Ext_Arg.
+      --  If neither Ext_Arg nor Link_Arg is present, the interface name
+      --  is set to the default from the subprogram name.
+
+      procedure Process_Interrupt_Or_Attach_Handler;
+      --  Attach the pragmas to the rep item chain.
+
+      procedure Process_Suppress_Unsuppress (Suppress_Case : Boolean);
+      --  Common processing for Suppress and Unsuppress. The boolean parameter
+      --  Suppress_Case is True for the Suppress case, and False for the
+      --  Unsuppress case.
+
+      procedure Set_Exported (E : Entity_Id; Arg : Node_Id);
+      --  This procedure sets the Is_Exported flag for the given entity,
+      --  checking that the entity was not previously imported. Arg is
+      --  the argument that specified the entity.
+
+      procedure Set_Extended_Import_Export_External_Name
+        (Internal_Ent : Entity_Id;
+         Arg_External : Node_Id);
+      --  Common processing for all extended import export pragmas. The first
+      --  argument, Internal_Ent, is the internal entity, which has already
+      --  been checked for validity by the caller. Arg_External is from the
+      --  Import or Export pragma, and may be null if no External parameter
+      --  was present. If Arg_External is present and is a non-null string
+      --  (a null string is treated as the default), then the Interface_Name
+      --  field of Internal_Ent is set appropriately.
+
+      procedure Set_Imported (E : Entity_Id);
+      --  This procedure sets the Is_Imported flag for the given entity,
+      --  checking that it is not previously exported or imported.
+
+      procedure Set_Mechanism_Value (Ent : Entity_Id; Mech_Name : Node_Id);
+      --  Mech is a parameter passing mechanism (see Import_Function syntax
+      --  for MECHANISM_NAME). This routine checks that the mechanism argument
+      --  has the right form, and if not issues an error message. If the
+      --  argument has the right form then the Mechanism field of Ent is
+      --  set appropriately.
+
+      --------------------------
+      -- Check_Ada_83_Warning --
+      --------------------------
+
+      procedure Check_Ada_83_Warning is
+      begin
+         GNAT_Pragma;
+
+         if Ada_83 and then Comes_From_Source (N) then
+            Error_Msg_N ("(Ada 83) pragma& is non-standard?", N);
+         end if;
+      end Check_Ada_83_Warning;
+
+      ---------------------
+      -- Check_Arg_Count --
+      ---------------------
+
+      procedure Check_Arg_Count (Required : Nat) is
+      begin
+         if Arg_Count /= Required then
+            Error_Pragma ("wrong number of arguments for pragma%");
+         end if;
+      end Check_Arg_Count;
+
+      -----------------------------
+      -- Check_Arg_Is_Identifier --
+      -----------------------------
+
+      procedure Check_Arg_Is_Identifier (Arg : Node_Id) is
+         Argx : constant Node_Id := Get_Pragma_Arg (Arg);
+
+      begin
+         if Nkind (Argx) /= N_Identifier then
+            Error_Pragma_Arg
+              ("argument for pragma% must be identifier", Argx);
+         end if;
+      end Check_Arg_Is_Identifier;
+
+      ----------------------------------
+      -- Check_Arg_Is_Integer_Literal --
+      ----------------------------------
+
+      procedure Check_Arg_Is_Integer_Literal (Arg : Node_Id) is
+         Argx : constant Node_Id := Get_Pragma_Arg (Arg);
+
+      begin
+         if Nkind (Argx) /= N_Integer_Literal then
+            Error_Pragma_Arg
+              ("argument for pragma% must be integer literal", Argx);
+         end if;
+      end Check_Arg_Is_Integer_Literal;
+
+      -------------------------------------------
+      -- Check_Arg_Is_Library_Level_Local_Name --
+      -------------------------------------------
+
+      --  LOCAL_NAME ::=
+      --    DIRECT_NAME
+      --  | DIRECT_NAME'ATTRIBUTE_DESIGNATOR
+      --  | library_unit_NAME
+
+      procedure Check_Arg_Is_Library_Level_Local_Name (Arg : Node_Id) is
+      begin
+         Check_Arg_Is_Local_Name (Arg);
+
+         if not Is_Library_Level_Entity (Entity (Expression (Arg)))
+           and then Comes_From_Source (N)
+         then
+            Error_Pragma_Arg
+              ("argument for pragma% must be library level entity", Arg);
+         end if;
+      end Check_Arg_Is_Library_Level_Local_Name;
+
+      -----------------------------
+      -- Check_Arg_Is_Local_Name --
+      -----------------------------
+
+      --  LOCAL_NAME ::=
+      --    DIRECT_NAME
+      --  | DIRECT_NAME'ATTRIBUTE_DESIGNATOR
+      --  | library_unit_NAME
+
+      procedure Check_Arg_Is_Local_Name (Arg : Node_Id) is
+         Argx : constant Node_Id := Get_Pragma_Arg (Arg);
+
+      begin
+         Analyze (Argx);
+
+         if Nkind (Argx) not in N_Direct_Name
+           and then (Nkind (Argx) /= N_Attribute_Reference
+                      or else Present (Expressions (Argx))
+                      or else Nkind (Prefix (Argx)) /= N_Identifier)
+           and then (not Is_Entity_Name (Argx)
+                      or else not Is_Compilation_Unit (Entity (Argx)))
+         then
+            Error_Pragma_Arg ("argument for pragma% must be local name", Argx);
+         end if;
+
+         if Is_Entity_Name (Argx)
+           and then Scope (Entity (Argx)) /= Current_Scope
+         then
+            Error_Pragma_Arg
+              ("pragma% argument must be in same declarative part", Arg);
+         end if;
+      end Check_Arg_Is_Local_Name;
+
+      ---------------------------------
+      -- Check_Arg_Is_Locking_Policy --
+      ---------------------------------
+
+      procedure Check_Arg_Is_Locking_Policy (Arg : Node_Id) is
+         Argx : constant Node_Id := Get_Pragma_Arg (Arg);
+
+      begin
+         Check_Arg_Is_Identifier (Argx);
+
+         if not Is_Locking_Policy_Name (Chars (Argx)) then
+            Error_Pragma_Arg
+              ("& is not a valid locking policy name", Argx);
+         end if;
+      end Check_Arg_Is_Locking_Policy;
+
+      -------------------------
+      -- Check_Arg_Is_One_Of --
+      -------------------------
+
+      procedure Check_Arg_Is_One_Of (Arg : Node_Id; N1, N2 : Name_Id) is
+         Argx : constant Node_Id := Get_Pragma_Arg (Arg);
+
+      begin
+         Check_Arg_Is_Identifier (Argx);
+
+         if Chars (Argx) /= N1 and then Chars (Argx) /= N2 then
+            Error_Msg_Name_2 := N1;
+            Error_Msg_Name_3 := N2;
+            Error_Pragma_Arg ("argument for pragma% must be% or%", Argx);
+         end if;
+      end Check_Arg_Is_One_Of;
+
+      procedure Check_Arg_Is_One_Of
+        (Arg        : Node_Id;
+         N1, N2, N3 : Name_Id)
+      is
+         Argx : constant Node_Id := Get_Pragma_Arg (Arg);
+
+      begin
+         Check_Arg_Is_Identifier (Argx);
+
+         if Chars (Argx) /= N1
+           and then Chars (Argx) /= N2
+           and then Chars (Argx) /= N3
+         then
+            Error_Pragma_Arg ("invalid argument for pragma%", Argx);
+         end if;
+      end Check_Arg_Is_One_Of;
+
+      ---------------------------------
+      -- Check_Arg_Is_Queuing_Policy --
+      ---------------------------------
+
+      procedure Check_Arg_Is_Queuing_Policy (Arg : Node_Id) is
+         Argx : constant Node_Id := Get_Pragma_Arg (Arg);
+
+      begin
+         Check_Arg_Is_Identifier (Argx);
+
+         if not Is_Queuing_Policy_Name (Chars (Argx)) then
+            Error_Pragma_Arg
+              ("& is not a valid queuing policy name", Argx);
+         end if;
+      end Check_Arg_Is_Queuing_Policy;
+
+      ------------------------------------
+      -- Check_Arg_Is_Static_Expression --
+      ------------------------------------
+
+      procedure Check_Arg_Is_Static_Expression
+        (Arg : Node_Id;
+         Typ : Entity_Id)
+      is
+         Argx : constant Node_Id := Get_Pragma_Arg (Arg);
+
+      begin
+         Analyze_And_Resolve (Argx, Typ);
+
+         if Is_OK_Static_Expression (Argx) then
+            return;
+
+         elsif Etype (Argx) = Any_Type then
+            raise Pragma_Exit;
+
+         --  An interesting special case, if we have a string literal and
+         --  we are in Ada 83 mode, then we allow it even though it will
+         --  not be flagged as static. This allows the use of Ada 95
+         --  pragmas like Import in Ada 83 mode. They will of course be
+         --  flagged with warnings as usual, but will not cause errors.
+
+         elsif Ada_83 and then Nkind (Argx) = N_String_Literal then
+            return;
+
+         --  Static expression that raises Constraint_Error. This has
+         --  already been flagged, so just exit from pragma processing.
+
+         elsif Is_Static_Expression (Argx) then
+            raise Pragma_Exit;
+
+         --  Finally, we have a real error
+
+         else
+            Error_Pragma_Arg
+              ("argument for pragma% must be a static expression", Argx);
+         end if;
+
+      end Check_Arg_Is_Static_Expression;
+
+      ---------------------------------
+      -- Check_Arg_Is_String_Literal --
+      ---------------------------------
+
+      procedure Check_Arg_Is_String_Literal (Arg : Node_Id) is
+         Argx : constant Node_Id := Get_Pragma_Arg (Arg);
+
+      begin
+         if Nkind (Argx) /= N_String_Literal then
+            Error_Pragma_Arg
+              ("argument for pragma% must be string literal", Argx);
+         end if;
+
+      end Check_Arg_Is_String_Literal;
+
+      ------------------------------------------
+      -- Check_Arg_Is_Task_Dispatching_Policy --
+      ------------------------------------------
+
+      procedure Check_Arg_Is_Task_Dispatching_Policy (Arg : Node_Id) is
+         Argx : constant Node_Id := Get_Pragma_Arg (Arg);
+
+      begin
+         Check_Arg_Is_Identifier (Argx);
+
+         if not Is_Task_Dispatching_Policy_Name (Chars (Argx)) then
+            Error_Pragma_Arg
+              ("& is not a valid task dispatching policy name", Argx);
+         end if;
+      end Check_Arg_Is_Task_Dispatching_Policy;
+
+      --------------------------------
+      -- Check_At_Least_N_Arguments --
+      --------------------------------
+
+      procedure Check_At_Least_N_Arguments (N : Nat) is
+      begin
+         if Arg_Count < N then
+            Error_Pragma ("too few arguments for pragma%");
+         end if;
+      end Check_At_Least_N_Arguments;
+
+      -------------------------------
+      -- Check_At_Most_N_Arguments --
+      -------------------------------
+
+      procedure Check_At_Most_N_Arguments (N : Nat) is
+         Arg : Node_Id;
+
+      begin
+         if Arg_Count > N then
+            Arg := Arg1;
+
+            for J in 1 .. N loop
+               Next (Arg);
+               Error_Pragma_Arg ("too many arguments for pragma%", Arg);
+            end loop;
+         end if;
+      end Check_At_Most_N_Arguments;
+
+      -------------------------
+      -- Check_First_Subtype --
+      -------------------------
+
+      procedure Check_First_Subtype (Arg : Node_Id) is
+         Argx : constant Node_Id := Get_Pragma_Arg (Arg);
+
+      begin
+         if not Is_First_Subtype (Entity (Argx)) then
+            Error_Pragma_Arg
+              ("pragma% cannot apply to subtype", Argx);
+         end if;
+      end Check_First_Subtype;
+
+      ---------------------------
+      -- Check_In_Main_Program --
+      ---------------------------
+
+      procedure Check_In_Main_Program is
+         P : constant Node_Id := Parent (N);
+
+      begin
+         --  Must be at in subprogram body
+
+         if Nkind (P) /= N_Subprogram_Body then
+            Error_Pragma ("% pragma allowed only in subprogram");
+
+         --  Otherwise warn if obviously not main program
+
+         elsif Present (Parameter_Specifications (Specification (P)))
+           or else not Is_Library_Level_Entity (Defining_Entity (P))
+         then
+            Error_Msg_Name_1 := Chars (N);
+            Error_Msg_N
+              ("?pragma% is only effective in main program", N);
+         end if;
+      end Check_In_Main_Program;
+
+      ---------------------------------------
+      -- Check_Interrupt_Or_Attach_Handler --
+      ---------------------------------------
+
+      procedure Check_Interrupt_Or_Attach_Handler is
+         Arg1_X : constant Node_Id := Expression (Arg1);
+
+      begin
+         Analyze (Arg1_X);
+
+         if not Is_Entity_Name (Arg1_X) then
+            Error_Pragma_Arg
+              ("argument of pragma% must be entity name", Arg1);
+
+         elsif Prag_Id = Pragma_Interrupt_Handler then
+            Check_Restriction (No_Dynamic_Interrupts, N);
+         end if;
+
+         declare
+            Prot_Proc : Entity_Id := Empty;
+            Prot_Type : Entity_Id;
+            Found     : Boolean := False;
+
+         begin
+            if not Is_Overloaded (Arg1_X) then
+               Prot_Proc := Entity (Arg1_X);
+
+            else
+               declare
+                  It    : Interp;
+                  Index : Interp_Index;
+
+               begin
+                  Get_First_Interp (Arg1_X, Index, It);
+                  while Present (It.Nam) loop
+                     Prot_Proc := It.Nam;
+
+                     if Ekind (Prot_Proc) = E_Procedure
+                       and then No (First_Formal (Prot_Proc))
+                     then
+                        if not Found then
+                           Found := True;
+                           Set_Entity (Arg1_X, Prot_Proc);
+                           Set_Is_Overloaded (Arg1_X, False);
+                        else
+                           Error_Pragma_Arg
+                             ("ambiguous handler name for pragma% ", Arg1);
+                        end if;
+                     end if;
+
+                     Get_Next_Interp (Index, It);
+                  end loop;
+
+                  if not Found then
+                     Error_Pragma_Arg
+                       ("argument of pragma% must be parameterless procedure",
+                        Arg1);
+                  else
+                     Prot_Proc := Entity (Arg1_X);
+                  end if;
+               end;
+            end if;
+
+            Prot_Type := Scope (Prot_Proc);
+
+            if Ekind (Prot_Proc) /= E_Procedure
+              or else Ekind (Prot_Type) /= E_Protected_Type
+            then
+               Error_Pragma_Arg
+                 ("argument of pragma% must be protected procedure",
+                  Arg1);
+            end if;
+
+            if not Is_Library_Level_Entity (Prot_Type) then
+               Error_Pragma_Arg
+                 ("pragma% requires library level entity", Arg1);
+            end if;
+
+            if Present (First_Formal (Prot_Proc)) then
+               Error_Pragma_Arg
+                 ("argument of pragma% must be parameterless procedure",
+                  Arg1);
+            end if;
+
+            if Parent (N) /=
+                 Protected_Definition (Parent (Prot_Type))
+            then
+               Error_Pragma ("pragma% must be in protected definition");
+            end if;
+
+         end;
+      end Check_Interrupt_Or_Attach_Handler;
+
+      -------------------------------------------
+      -- Check_Is_In_Decl_Part_Or_Package_Spec --
+      -------------------------------------------
+
+      procedure Check_Is_In_Decl_Part_Or_Package_Spec is
+         P : Node_Id;
+
+      begin
+         P := Parent (N);
+         loop
+            if No (P) then
+               exit;
+
+            elsif Nkind (P) = N_Handled_Sequence_Of_Statements then
+               exit;
+
+            elsif Nkind (P) = N_Package_Specification then
+               return;
+
+            elsif Nkind (P) = N_Block_Statement then
+               return;
+
+            --  Note: the following tests seem a little peculiar, because
+            --  they test for bodies, but if we were in the statement part
+            --  of the body, we would already have hit the handled statement
+            --  sequence, so the only way we get here is by being in the
+            --  declarative part of the body.
+
+            elsif Nkind (P) = N_Subprogram_Body
+              or else Nkind (P) = N_Package_Body
+              or else Nkind (P) = N_Task_Body
+              or else Nkind (P) = N_Entry_Body
+            then
+               return;
+            end if;
+
+            P := Parent (P);
+         end loop;
+
+         Error_Pragma ("pragma% is not in declarative part or package spec");
+
+      end Check_Is_In_Decl_Part_Or_Package_Spec;
+
+      -------------------------
+      -- Check_No_Identifier --
+      -------------------------
+
+      procedure Check_No_Identifier (Arg : Node_Id) is
+      begin
+         if Chars (Arg) /= No_Name then
+            Error_Pragma_Arg_Ident
+              ("pragma% does not permit identifier& here", Arg);
+         end if;
+      end Check_No_Identifier;
+
+      --------------------------
+      -- Check_No_Identifiers --
+      --------------------------
+
+      procedure Check_No_Identifiers is
+         Arg_Node : Node_Id;
+
+      begin
+         if Arg_Count > 0 then
+            Arg_Node := Arg1;
+
+            while Present (Arg_Node) loop
+               Check_No_Identifier (Arg_Node);
+               Next (Arg_Node);
+            end loop;
+         end if;
+      end Check_No_Identifiers;
+
+      -----------------------------------
+      -- Check_Non_Overloaded_Function --
+      -----------------------------------
+
+      procedure Check_Non_Overloaded_Function (Arg : Node_Id) is
+         Ent : Entity_Id;
+
+      begin
+         Check_Arg_Is_Local_Name (Arg);
+         Ent := Entity (Expression (Arg));
+
+         if Present (Homonym (Ent))
+           and then Scope (Homonym (Ent)) = Current_Scope
+         then
+            Error_Pragma_Arg
+              ("argument for pragma% may not be overloaded", Arg);
+         end if;
+
+         if Ekind (Ent) /= E_Function
+           or else No (First_Formal (Ent))
+           or else Present (Next_Formal (First_Formal (Ent)))
+         then
+            Error_Pragma_Arg
+              ("argument for pragma% must be function of one argument", Arg);
+         end if;
+      end Check_Non_Overloaded_Function;
+
+      -------------------------------
+      -- Check_Optional_Identifier --
+      -------------------------------
+
+      procedure Check_Optional_Identifier (Arg : Node_Id; Id : Name_Id) is
+      begin
+         if Present (Arg) and then Chars (Arg) /= No_Name then
+            if Chars (Arg) /= Id then
+               Error_Msg_Name_1 := Chars (N);
+               Error_Msg_Name_2 := Id;
+               Error_Msg_N ("pragma% argument expects identifier%", Arg);
+               raise Pragma_Exit;
+            end if;
+         end if;
+      end Check_Optional_Identifier;
+
+      procedure Check_Optional_Identifier (Arg : Node_Id; Id : String) is
+      begin
+         Name_Buffer (1 .. Id'Length) := Id;
+         Name_Len := Id'Length;
+         Check_Optional_Identifier (Arg, Name_Find);
+      end Check_Optional_Identifier;
+
+      -----------------------------
+      -- Check_Static_Constraint --
+      -----------------------------
+
+      --  Note: for convenience in writing this procedure, in addition to
+      --  the officially (i.e. by spec) allowed argument which is always
+      --  a constraint, it also allows ranges and discriminant associations.
+
+      procedure Check_Static_Constraint (Constr : Node_Id) is
+
+         --------------------
+         -- Require_Static --
+         --------------------
+
+         procedure Require_Static (E : Node_Id);
+         --  Require given expression to be static expression
+
+         procedure Require_Static (E : Node_Id) is
+         begin
+            if not Is_OK_Static_Expression (E) then
+               Error_Msg_N
+                 ("non-static constraint not allowed in Unchecked_Union", E);
+               raise Pragma_Exit;
+            end if;
+         end Require_Static;
+
+      --  Start of processing for Check_Static_Constraint
+
+      begin
+         case Nkind (Constr) is
+            when N_Discriminant_Association =>
+               Require_Static (Expression (Constr));
+
+            when N_Range =>
+               Require_Static (Low_Bound (Constr));
+               Require_Static (High_Bound (Constr));
+
+            when N_Attribute_Reference =>
+               Require_Static (Type_Low_Bound  (Etype (Prefix (Constr))));
+               Require_Static (Type_High_Bound (Etype (Prefix (Constr))));
+
+            when N_Range_Constraint =>
+               Check_Static_Constraint (Range_Expression (Constr));
+
+            when N_Index_Or_Discriminant_Constraint =>
+               declare
+                  IDC : Entity_Id := First (Constraints (Constr));
+
+               begin
+                  while Present (IDC) loop
+                     Check_Static_Constraint (IDC);
+                     Next (IDC);
+                  end loop;
+               end;
+
+            when others =>
+               null;
+         end case;
+      end Check_Static_Constraint;
+
+      --------------------------------------
+      -- Check_Valid_Configuration_Pragma --
+      --------------------------------------
+
+      --  A configuration pragma must appear in the context clause of
+      --  a compilation unit, at the start of the list (i.e. only other
+      --  pragmas may precede it).
+
+      procedure Check_Valid_Configuration_Pragma is
+      begin
+         if not Is_Configuration_Pragma then
+            Error_Pragma ("incorrect placement for configuration pragma%");
+         end if;
+      end Check_Valid_Configuration_Pragma;
+
+      -------------------------------------
+      -- Check_Valid_Library_Unit_Pragma --
+      -------------------------------------
+
+      procedure Check_Valid_Library_Unit_Pragma is
+         Plist       : List_Id;
+         Parent_Node : Node_Id;
+         Unit_Name   : Entity_Id;
+         Valid       : Boolean := True;
+         Unit_Kind   : Node_Kind;
+         Unit_Node   : Node_Id;
+         Sindex      : Source_File_Index;
+
+      begin
+         if not Is_List_Member (N) then
+            Pragma_Misplaced;
+            Valid := False;
+
+         else
+            Plist := List_Containing (N);
+            Parent_Node := Parent (Plist);
+
+            if Parent_Node = Empty then
+               Pragma_Misplaced;
+
+            --  Case of pragma appearing after a compilation unit. In this
+            --  case it must have an argument with the corresponding name
+            --  and must be part of the following pragmas of its parent.
+
+            elsif Nkind (Parent_Node) = N_Compilation_Unit_Aux then
+               if Plist /= Pragmas_After (Parent_Node) then
+                  Pragma_Misplaced;
+
+               elsif Arg_Count = 0 then
+                  Error_Pragma
+                    ("argument required if outside compilation unit");
+
+               else
+                  Check_No_Identifiers;
+                  Check_Arg_Count (1);
+                  Unit_Node := Unit (Parent (Parent_Node));
+                  Unit_Kind := Nkind (Unit_Node);
+
+                  Analyze (Expression (Arg1));
+
+                  if        Unit_Kind = N_Generic_Subprogram_Declaration
+                    or else Unit_Kind = N_Subprogram_Declaration
+                  then
+                     Unit_Name := Defining_Entity (Unit_Node);
+
+                  elsif     Unit_Kind = N_Function_Instantiation
+                    or else Unit_Kind = N_Package_Instantiation
+                    or else Unit_Kind = N_Procedure_Instantiation
+                  then
+                     Unit_Name := Defining_Entity (Unit_Node);
+
+                  else
+                     Unit_Name := Cunit_Entity (Current_Sem_Unit);
+                  end if;
+
+                  if Chars (Unit_Name) /=
+                     Chars (Entity (Expression (Arg1)))
+                  then
+                     Error_Pragma_Arg
+                       ("pragma% argument is not current unit name", Arg1);
+                  end if;
+
+                  if Ekind (Unit_Name) = E_Package
+                    and then Present (Renamed_Entity (Unit_Name))
+                  then
+                     Error_Pragma ("pragma% not allowed for renamed package");
+                  end if;
+               end if;
+
+            --  Pragma appears other than after a compilation unit
+
+            else
+               --  Here we check for the generic instantiation case and also
+               --  for the case of processing a generic formal package. We
+               --  detect these cases by noting that the Sloc on the node
+               --  does not belong to the current compilation unit.
+
+               Sindex := Source_Index (Current_Sem_Unit);
+
+               if Loc not in Source_First (Sindex) .. Source_Last (Sindex) then
+                  Rewrite (N, Make_Null_Statement (Loc));
+                  return;
+
+               --  If before first declaration, the pragma applies to the
+               --  enclosing unit, and the name if present must be this name.
+
+               elsif Is_Before_First_Decl (N, Plist) then
+                  Unit_Node := Unit_Declaration_Node (Current_Scope);
+                  Unit_Kind := Nkind (Unit_Node);
+
+                  if Nkind (Parent (Unit_Node)) /= N_Compilation_Unit then
+                     Pragma_Misplaced;
+
+                  elsif Unit_Kind = N_Subprogram_Body
+                    and then not Acts_As_Spec (Unit_Node)
+                  then
+                     Pragma_Misplaced;
+
+                  elsif Nkind (Parent_Node) = N_Package_Body then
+                     Pragma_Misplaced;
+
+                  elsif Nkind (Parent_Node) = N_Package_Specification
+                    and then Plist = Private_Declarations (Parent_Node)
+                  then
+                     Pragma_Misplaced;
+
+                  elsif (Nkind (Parent_Node) = N_Generic_Package_Declaration
+                          or else Nkind (Parent_Node)
+                            = N_Generic_Subprogram_Declaration)
+                    and then Plist = Generic_Formal_Declarations (Parent_Node)
+                  then
+                     Pragma_Misplaced;
+
+                  elsif Arg_Count > 0 then
+                     Analyze (Expression (Arg1));
+
+                     if Entity (Expression (Arg1)) /= Current_Scope then
+                        Error_Pragma_Arg
+                          ("name in pragma% must be enclosing unit", Arg1);
+                     end if;
+
+                  --  It is legal to have no argument in this context
+
+                  else
+                     return;
+                  end if;
+
+               --  Error if not before first declaration. This is because a
+               --  library unit pragma argument must be the name of a library
+               --  unit (RM 10.1.5(7)), but the only names permitted in this
+               --  context are (RM 10.1.5(6)) names of subprogram declarations,
+               --  generic subprogram declarations or generic instantiations.
+
+               else
+                  Error_Pragma
+                    ("pragma% misplaced, must be before first declaration");
+               end if;
+            end if;
+         end if;
+
+      end Check_Valid_Library_Unit_Pragma;
+
+      ------------------
+      -- Error_Pragma --
+      ------------------
+
+      procedure Error_Pragma (Msg : String) is
+      begin
+         Error_Msg_Name_1 := Chars (N);
+         Error_Msg_N (Msg, N);
+         raise Pragma_Exit;
+      end Error_Pragma;
+
+      ----------------------
+      -- Error_Pragma_Arg --
+      ----------------------
+
+      procedure Error_Pragma_Arg (Msg : String; Arg : Node_Id) is
+      begin
+         Error_Msg_Name_1 := Chars (N);
+         Error_Msg_N (Msg, Get_Pragma_Arg (Arg));
+         raise Pragma_Exit;
+      end Error_Pragma_Arg;
+
+      procedure Error_Pragma_Arg (Msg1, Msg2 : String; Arg : Node_Id) is
+      begin
+         Error_Msg_Name_1 := Chars (N);
+         Error_Msg_N (Msg1, Get_Pragma_Arg (Arg));
+         Error_Pragma_Arg (Msg2, Arg);
+      end Error_Pragma_Arg;
+
+      ----------------------------
+      -- Error_Pragma_Arg_Ident --
+      ----------------------------
+
+      procedure Error_Pragma_Arg_Ident (Msg : String; Arg : Node_Id) is
+      begin
+         Error_Msg_Name_1 := Chars (N);
+         Error_Msg_N (Msg, Arg);
+         raise Pragma_Exit;
+      end Error_Pragma_Arg_Ident;
+
+      ------------------------
+      -- Find_Lib_Unit_Name --
+      ------------------------
+
+      function Find_Lib_Unit_Name return Entity_Id is
+      begin
+         --  Return inner compilation unit entity, for case of nested
+         --  categorization pragmas. This happens in generic unit.
+
+         if Nkind (Parent (N)) = N_Package_Specification
+           and then Defining_Entity (Parent (N)) /= Current_Scope
+         then
+            return Defining_Entity (Parent (N));
+
+         else
+            return Current_Scope;
+         end if;
+      end Find_Lib_Unit_Name;
+
+      ----------------------------
+      -- Find_Program_Unit_Name --
+      ----------------------------
+
+      procedure Find_Program_Unit_Name (Id : Node_Id) is
+         Unit_Name : Entity_Id;
+         Unit_Kind : Node_Kind;
+         P         : constant Node_Id := Parent (N);
+
+      begin
+         if Nkind (P) = N_Compilation_Unit then
+            Unit_Kind := Nkind (Unit (P));
+
+            if Unit_Kind = N_Subprogram_Declaration
+              or else Unit_Kind = N_Package_Declaration
+              or else Unit_Kind in N_Generic_Declaration
+            then
+               Unit_Name := Defining_Entity (Unit (P));
+
+               if Chars (Id) = Chars (Unit_Name) then
+                  Set_Entity (Id, Unit_Name);
+                  Set_Etype (Id, Etype (Unit_Name));
+               else
+                  Set_Etype (Id, Any_Type);
+                  Error_Pragma
+                    ("cannot find program unit referenced by pragma%");
+               end if;
+
+            else
+               Set_Etype (Id, Any_Type);
+               Error_Pragma ("pragma% inapplicable to this unit");
+            end if;
+
+         else
+            Analyze (Id);
+         end if;
+
+      end Find_Program_Unit_Name;
+
+      -------------------------
+      -- Gather_Associations --
+      -------------------------
+
+      procedure Gather_Associations
+        (Names : Name_List;
+         Args  : out Args_List)
+      is
+         Arg : Node_Id;
+
+      begin
+         --  Initialize all parameters to Empty
+
+         for J in Args'Range loop
+            Args (J) := Empty;
+         end loop;
+
+         --  That's all we have to do if there are no argument associations
+
+         if No (Pragma_Argument_Associations (N)) then
+            return;
+         end if;
+
+         --  Otherwise first deal with any positional parameters present
+
+         Arg := First (Pragma_Argument_Associations (N));
+
+         for Index in Args'Range loop
+            exit when No (Arg) or else Chars (Arg) /= No_Name;
+            Args (Index) := Expression (Arg);
+            Next (Arg);
+         end loop;
+
+         --  Positional parameters all processed, if any left, then we
+         --  have too many positional parameters.
+
+         if Present (Arg) and then Chars (Arg) = No_Name then
+            Error_Pragma_Arg
+              ("too many positional associations for pragma%", Arg);
+         end if;
+
+         --  Process named parameters if any are present
+
+         while Present (Arg) loop
+            if Chars (Arg) = No_Name then
+               Error_Pragma_Arg
+                 ("positional association cannot follow named association",
+                  Arg);
+
+            else
+               for Index in Names'Range loop
+                  if Names (Index) = Chars (Arg) then
+                     if Present (Args (Index)) then
+                        Error_Pragma_Arg
+                          ("duplicate argument association for pragma%", Arg);
+                     else
+                        Args (Index) := Expression (Arg);
+                        exit;
+                     end if;
+                  end if;
+
+                  if Index = Names'Last then
+                     Error_Pragma_Arg_Ident
+                       ("pragma% does not allow & argument", Arg);
+                  end if;
+               end loop;
+            end if;
+
+            Next (Arg);
+         end loop;
+      end Gather_Associations;
+
+      --------------------
+      -- Get_Pragma_Arg --
+      --------------------
+
+      function Get_Pragma_Arg (Arg : Node_Id) return Node_Id is
+      begin
+         if Nkind (Arg) = N_Pragma_Argument_Association then
+            return Expression (Arg);
+         else
+            return Arg;
+         end if;
+      end Get_Pragma_Arg;
+
+      -----------------
+      -- GNAT_Pragma --
+      -----------------
+
+      procedure GNAT_Pragma is
+      begin
+         Check_Restriction (No_Implementation_Pragmas, N);
+      end GNAT_Pragma;
+
+      --------------------------
+      -- Is_Before_First_Decl --
+      --------------------------
+
+      function Is_Before_First_Decl
+        (Pragma_Node : Node_Id;
+         Decls       : List_Id)
+         return        Boolean
+      is
+         Item : Node_Id := First (Decls);
+
+      begin
+         --  Only other pragmas can come before this pragma
+
+         loop
+            if No (Item) or else Nkind (Item) /= N_Pragma then
+               return False;
+
+            elsif Item = Pragma_Node then
+               return True;
+            end if;
+
+            Next (Item);
+         end loop;
+
+      end Is_Before_First_Decl;
+
+      -----------------------------
+      -- Is_Configuration_Pragma --
+      -----------------------------
+
+      --  A configuration pragma must appear in the context clause of
+      --  a compilation unit, at the start of the list (i.e. only other
+      --  pragmas may precede it).
+
+      function Is_Configuration_Pragma return Boolean is
+         Lis : constant List_Id := List_Containing (N);
+         Par : constant Node_Id := Parent (N);
+         Prg : Node_Id;
+
+      begin
+         --  If no parent, then we are in the configuration pragma file,
+         --  so the placement is definitely appropriate.
+
+         if No (Par) then
+            return True;
+
+         --  Otherwise we must be in the context clause of a compilation unit
+         --  and the only thing allowed before us in the context list is more
+         --  configuration pragmas.
+
+         elsif Nkind (Par) = N_Compilation_Unit
+           and then Context_Items (Par) = Lis
+         then
+            Prg := First (Lis);
+
+            loop
+               if Prg = N then
+                  return True;
+               elsif Nkind (Prg) /= N_Pragma then
+                  return False;
+               end if;
+
+               Next (Prg);
+            end loop;
+
+         else
+            return False;
+         end if;
+
+      end Is_Configuration_Pragma;
+
+      ----------------------
+      -- Pragma_Misplaced --
+      ----------------------
+
+      procedure Pragma_Misplaced is
+      begin
+         Error_Pragma ("incorrect placement of pragma%");
+      end Pragma_Misplaced;
+
+      ------------------------------------
+      -- Process Atomic_Shared_Volatile --
+      ------------------------------------
+
+      procedure Process_Atomic_Shared_Volatile is
+         E_Id : Node_Id;
+         E    : Entity_Id;
+         D    : Node_Id;
+         K    : Node_Kind;
+
+      begin
+         GNAT_Pragma;
+         Check_Ada_83_Warning;
+         Check_No_Identifiers;
+         Check_Arg_Count (1);
+         Check_Arg_Is_Local_Name (Arg1);
+         E_Id := Expression (Arg1);
+
+         if Etype (E_Id) = Any_Type then
+            return;
+         end if;
+
+         E := Entity (E_Id);
+         D := Declaration_Node (E);
+         K := Nkind (D);
+
+         if Is_Type (E) then
+            if Rep_Item_Too_Early (E, N)
+                 or else
+               Rep_Item_Too_Late (E, N)
+            then
+               return;
+            else
+               Check_First_Subtype (Arg1);
+            end if;
+
+            if Prag_Id /= Pragma_Volatile then
+               Set_Is_Atomic (E);
+               Set_Is_Atomic (Underlying_Type (E));
+            end if;
+
+            Set_Is_Volatile (E);
+            Set_Is_Volatile (Underlying_Type (E));
+
+         elsif K = N_Object_Declaration
+           or else (K = N_Component_Declaration
+                     and then Original_Record_Component (E) = E)
+         then
+            if Rep_Item_Too_Late (E, N) then
+               return;
+            end if;
+
+            if Prag_Id /= Pragma_Volatile then
+               Set_Is_Atomic (E);
+            end if;
+
+            Set_Is_Volatile (E);
+
+         else
+            Error_Pragma_Arg
+              ("inappropriate entity for pragma%", Arg1);
+         end if;
+      end Process_Atomic_Shared_Volatile;
+
+      ------------------------
+      -- Process_Convention --
+      ------------------------
+
+      procedure Process_Convention
+        (C : out Convention_Id;
+         E : out Entity_Id)
+      is
+         Id        : Node_Id;
+         E1        : Entity_Id;
+         Comp_Unit : Unit_Number_Type;
+         Cname     : Name_Id;
+
+         procedure Set_Convention_From_Pragma (E : Entity_Id);
+         --  Set convention in entity E, and also flag that the entity has a
+         --  convention pragma. If entity is for a private or incomplete type,
+         --  also set convention and flag on underlying type. This procedure
+         --  also deals with the special case of C_Pass_By_Copy convention.
+
+         --------------------------------
+         -- Set_Convention_From_Pragma --
+         --------------------------------
+
+         procedure Set_Convention_From_Pragma (E : Entity_Id) is
+         begin
+            Set_Convention (E, C);
+            Set_Has_Convention_Pragma (E);
+
+            if Is_Incomplete_Or_Private_Type (E) then
+               Set_Convention            (Underlying_Type (E), C);
+               Set_Has_Convention_Pragma (Underlying_Type (E), True);
+            end if;
+
+            --  A class-wide type should inherit the convention of
+            --  the specific root type (although this isn't specified
+            --  clearly by the RM).
+
+            if Is_Type (E) and then Present (Class_Wide_Type (E)) then
+               Set_Convention (Class_Wide_Type (E), C);
+            end if;
+
+            --  If the entity is a record type, then check for special case
+            --  of C_Pass_By_Copy, which is treated the same as C except that
+            --  the special record flag is set. This convention is also only
+            --  permitted on record types (see AI95-00131).
+
+            if Cname = Name_C_Pass_By_Copy then
+               if Is_Record_Type (E) then
+                  Set_C_Pass_By_Copy (Base_Type (E));
+               elsif Is_Incomplete_Or_Private_Type (E)
+                 and then Is_Record_Type (Underlying_Type (E))
+               then
+                  Set_C_Pass_By_Copy (Base_Type (Underlying_Type (E)));
+               else
+                  Error_Pragma_Arg
+                    ("C_Pass_By_Copy convention allowed only for record type",
+                     Arg2);
+               end if;
+            end if;
+
+            --  If the entity is a derived boolean type, check for the
+            --  special case of convention C, C++, or Fortran, where we
+            --  consider any nonzero value to represent true.
+
+            if Is_Discrete_Type (E)
+              and then Root_Type (Etype (E)) = Standard_Boolean
+              and then
+                (C = Convention_C
+                   or else
+                 C = Convention_CPP
+                   or else
+                 C = Convention_Fortran)
+            then
+               Set_Nonzero_Is_True (Base_Type (E));
+            end if;
+         end Set_Convention_From_Pragma;
+
+      --  Start of processing for Process_Convention
+
+      begin
+         Check_At_Least_N_Arguments (2);
+         Check_Arg_Is_Identifier (Arg1);
+         Check_Optional_Identifier (Arg1, Name_Convention);
+         Cname := Chars (Expression (Arg1));
+
+         --  C_Pass_By_Copy is treated as a synonym for convention C
+         --  (this is tested again below to set the critical flag)
+
+         if Cname = Name_C_Pass_By_Copy then
+            C := Convention_C;
+
+         --  Otherwise we must have something in the standard convention list
+
+         elsif Is_Convention_Name (Cname) then
+            C := Get_Convention_Id (Chars (Expression (Arg1)));
+
+         --  In DEC VMS, it seems that there is an undocumented feature
+         --  that any unrecognized convention is treated as the default,
+         --  which for us is convention C. It does not seem so terrible
+         --  to do this unconditionally, silently in the VMS case, and
+         --  with a warning in the non-VMS case.
+
+         else
+            if not OpenVMS_On_Target then
+               Error_Msg_N
+                 ("?unrecognized convention name, C assumed",
+                  Expression (Arg1));
+            end if;
+
+            C := Convention_C;
+         end if;
+
+         Check_Arg_Is_Local_Name (Arg2);
+         Check_Optional_Identifier (Arg2, Name_Entity);
+
+         Id := Expression (Arg2);
+         Analyze (Id);
+
+         if not Is_Entity_Name (Id) then
+            Error_Pragma_Arg ("entity name required", Arg2);
+         end if;
+
+         E := Entity (Id);
+
+         --  Go to renamed subprogram if present, since convention applies
+         --  to the actual renamed entity, not to the renaming entity.
+
+         if Is_Subprogram (E)
+           and then Present (Alias (E))
+           and then Nkind (Parent (Declaration_Node (E))) =
+                      N_Subprogram_Renaming_Declaration
+         then
+            E := Alias (E);
+         end if;
+
+         --  Check that we not applying this to a specless body
+
+         if Is_Subprogram (E)
+           and then Nkind (Parent (Declaration_Node (E))) = N_Subprogram_Body
+         then
+            Error_Pragma
+              ("pragma% requires separate spec and must come before body");
+         end if;
+
+         --  Check that we are not applying this to a named constant
+
+         if Ekind (E) = E_Named_Integer
+              or else
+            Ekind (E) = E_Named_Real
+         then
+            Error_Msg_Name_1 := Chars (N);
+            Error_Msg_N
+              ("cannot apply pragma% to named constant!",
+               Get_Pragma_Arg (Arg2));
+            Error_Pragma_Arg
+              ("\supply appropriate type for&!", Arg2);
+         end if;
+
+         if Etype (E) = Any_Type
+           or else Rep_Item_Too_Early (E, N)
+         then
+            raise Pragma_Exit;
+         else
+            E := Underlying_Type (E);
+         end if;
+
+         if Rep_Item_Too_Late (E, N) then
+            raise Pragma_Exit;
+         end if;
+
+         if Has_Convention_Pragma (E) then
+            Error_Pragma_Arg
+              ("at most one Convention/Export/Import pragma is allowed", Arg2);
+
+         elsif Convention (E) = Convention_Protected
+           or else Ekind (Scope (E)) = E_Protected_Type
+         then
+            Error_Pragma_Arg
+              ("a protected operation cannot be given a different convention",
+                Arg2);
+         end if;
+
+         --  For Intrinsic, a subprogram is required
+
+         if C = Convention_Intrinsic
+           and then not Is_Subprogram (E)
+           and then not Is_Generic_Subprogram (E)
+         then
+            Error_Pragma_Arg
+              ("second argument of pragma% must be a subprogram", Arg2);
+         end if;
+
+         --  For Stdcall, a subprogram, variable or subprogram type is required
+
+         if C = Convention_Stdcall
+           and then not Is_Subprogram (E)
+           and then not Is_Generic_Subprogram (E)
+           and then Ekind (E) /= E_Variable
+           and then not
+             (Is_Access_Type (E)
+              and then Ekind (Designated_Type (E)) = E_Subprogram_Type)
+         then
+            Error_Pragma_Arg
+              ("second argument of pragma% must be subprogram (type)",
+               Arg2);
+         end if;
+
+         if not Is_Subprogram (E)
+           and then not Is_Generic_Subprogram (E)
+         then
+            Set_Convention_From_Pragma (E);
+
+            if Is_Type (E) then
+
+               Check_First_Subtype (Arg2);
+               Set_Convention_From_Pragma (Base_Type (E));
+
+               --  For subprograms, we must set the convention on the
+               --  internally generated directly designated type as well.
+
+               if Ekind (E) = E_Access_Subprogram_Type then
+                  Set_Convention_From_Pragma (Directly_Designated_Type (E));
+               end if;
+            end if;
+
+         --  For the subprogram case, set proper convention for all homonyms
+         --  in same compilation unit.
+         --  Is the test of compilation unit really necessary ???
+         --  What about subprogram renamings here???
+
+         else
+            Comp_Unit := Get_Source_Unit (E);
+            Set_Convention_From_Pragma (E);
+
+            E1 := E;
+            loop
+               E1 := Homonym (E1);
+               exit when No (E1) or else Scope (E1) /= Current_Scope;
+
+               --  Note: below we are missing a check for Rep_Item_Too_Late.
+               --  That is deliberate, we cannot chain the rep item on more
+               --  than one Rep_Item chain, to be fixed later ???
+
+               if Comp_Unit = Get_Source_Unit (E1) then
+                  Set_Convention_From_Pragma (E1);
+               end if;
+            end loop;
+         end if;
+
+      end Process_Convention;
+
+      -----------------------------------------------------
+      -- Process_Extended_Import_Export_Exception_Pragma --
+      -----------------------------------------------------
+
+      procedure Process_Extended_Import_Export_Exception_Pragma
+        (Arg_Internal : Node_Id;
+         Arg_External : Node_Id;
+         Arg_Form     : Node_Id;
+         Arg_Code     : Node_Id)
+      is
+         Def_Id   : Entity_Id;
+         Code_Val : Uint;
+
+      begin
+         Process_Extended_Import_Export_Internal_Arg (Arg_Internal);
+         Def_Id := Entity (Arg_Internal);
+
+         if Ekind (Def_Id) /= E_Exception then
+            Error_Pragma_Arg
+              ("pragma% must refer to declared exception", Arg_Internal);
+         end if;
+
+         Set_Extended_Import_Export_External_Name (Def_Id, Arg_External);
+
+         if Present (Arg_Form) then
+            Check_Arg_Is_One_Of (Arg_Form, Name_Ada, Name_VMS);
+         end if;
+
+         if Present (Arg_Form)
+           and then Chars (Arg_Form) = Name_Ada
+         then
+            null;
+         else
+            Set_Is_VMS_Exception (Def_Id);
+            Set_Exception_Code (Def_Id, No_Uint);
+         end if;
+
+         if Present (Arg_Code) then
+            if not Is_VMS_Exception (Def_Id) then
+               Error_Pragma_Arg
+                 ("Code option for pragma% not allowed for Ada case",
+                  Arg_Code);
+            end if;
+
+            Check_Arg_Is_Static_Expression (Arg_Code, Any_Integer);
+            Code_Val := Expr_Value (Arg_Code);
+
+            if not UI_Is_In_Int_Range (Code_Val) then
+               Error_Pragma_Arg
+                 ("Code option for pragma% must be in 32-bit range",
+                  Arg_Code);
+
+            else
+               Set_Exception_Code (Def_Id, Code_Val);
+            end if;
+         end if;
+
+      end Process_Extended_Import_Export_Exception_Pragma;
+
+      -------------------------------------------------
+      -- Process_Extended_Import_Export_Internal_Arg --
+      -------------------------------------------------
+
+      procedure Process_Extended_Import_Export_Internal_Arg
+        (Arg_Internal : Node_Id := Empty)
+      is
+      begin
+         GNAT_Pragma;
+
+         if No (Arg_Internal) then
+            Error_Pragma ("Internal parameter required for pragma%");
+         end if;
+
+         if Nkind (Arg_Internal) = N_Identifier then
+            null;
+
+         elsif Nkind (Arg_Internal) = N_Operator_Symbol
+           and then (Prag_Id = Pragma_Import_Function
+                       or else
+                     Prag_Id = Pragma_Export_Function)
+         then
+            null;
+
+         else
+            Error_Pragma_Arg
+              ("wrong form for Internal parameter for pragma%", Arg_Internal);
+         end if;
+
+         Check_Arg_Is_Local_Name (Arg_Internal);
+
+      end Process_Extended_Import_Export_Internal_Arg;
+
+      --------------------------------------------------
+      -- Process_Extended_Import_Export_Object_Pragma --
+      --------------------------------------------------
+
+      procedure Process_Extended_Import_Export_Object_Pragma
+        (Arg_Internal : Node_Id;
+         Arg_External : Node_Id;
+         Arg_Size     : Node_Id)
+      is
+         Def_Id   : Entity_Id;
+
+      begin
+         Process_Extended_Import_Export_Internal_Arg (Arg_Internal);
+         Def_Id := Entity (Arg_Internal);
+
+         if Ekind (Def_Id) /= E_Constant
+           and then Ekind (Def_Id) /= E_Variable
+         then
+            Error_Pragma_Arg
+              ("pragma% must designate an object", Arg_Internal);
+         end if;
+
+         if Is_Psected (Def_Id) then
+            Error_Pragma_Arg
+              ("previous Psect_Object applies, pragma % not permitted",
+               Arg_Internal);
+         end if;
+
+         if Rep_Item_Too_Late (Def_Id, N) then
+            raise Pragma_Exit;
+         end if;
+
+         Set_Extended_Import_Export_External_Name (Def_Id, Arg_External);
+
+         if Present (Arg_Size)
+           and then Nkind (Arg_Size) /= N_Identifier
+           and then Nkind (Arg_Size) /= N_String_Literal
+         then
+            Error_Pragma_Arg
+              ("pragma% Size argument must be identifier or string literal",
+               Arg_Size);
+         end if;
+
+         --  Export_Object case
+
+         if Prag_Id = Pragma_Export_Object then
+
+            if not Is_Library_Level_Entity (Def_Id) then
+               Error_Pragma_Arg
+                 ("argument for pragma% must be library level entity",
+                  Arg_Internal);
+            end if;
+
+            if Ekind (Current_Scope) = E_Generic_Package then
+               Error_Pragma ("pragma& cannot appear in a generic unit");
+            end if;
+
+            if not Size_Known_At_Compile_Time (Etype (Def_Id)) then
+               Error_Pragma_Arg
+                 ("exported object must have compile time known size",
+                  Arg_Internal);
+            end if;
+
+            if Is_Exported (Def_Id) then
+               Error_Msg_N
+                 ("?duplicate Export_Object pragma", N);
+            else
+               Set_Exported (Def_Id, Arg_Internal);
+            end if;
+
+         --  Import_Object case
+
+         else
+            if Is_Concurrent_Type (Etype (Def_Id)) then
+               Error_Pragma_Arg
+                 ("cannot use pragma% for task/protected object",
+                  Arg_Internal);
+            end if;
+
+            if Ekind (Def_Id) = E_Constant then
+               Error_Pragma_Arg
+                 ("cannot import a constant", Arg_Internal);
+            end if;
+
+            if Has_Discriminants (Etype (Def_Id)) then
+               Error_Msg_N
+                 ("imported value must be initialized?", Arg_Internal);
+            end if;
+
+            if Is_Access_Type (Etype (Def_Id)) then
+               Error_Pragma_Arg
+                 ("cannot import object of an access type?", Arg_Internal);
+            end if;
+
+            if Is_Imported (Def_Id) then
+               Error_Msg_N
+                 ("?duplicate Import_Object pragma", N);
+            else
+               Set_Imported (Def_Id);
+            end if;
+         end if;
+
+      end Process_Extended_Import_Export_Object_Pragma;
+
+      ------------------------------------------------------
+      -- Process_Extended_Import_Export_Subprogram_Pragma --
+      ------------------------------------------------------
+
+      procedure Process_Extended_Import_Export_Subprogram_Pragma
+        (Arg_Internal                 : Node_Id;
+         Arg_External                 : Node_Id;
+         Arg_Parameter_Types          : Node_Id;
+         Arg_Result_Type              : Node_Id := Empty;
+         Arg_Mechanism                : Node_Id;
+         Arg_Result_Mechanism         : Node_Id := Empty;
+         Arg_First_Optional_Parameter : Node_Id := Empty)
+      is
+         Ent       : Entity_Id;
+         Def_Id    : Entity_Id;
+         Hom_Id    : Entity_Id;
+         Formal    : Entity_Id;
+         Ambiguous : Boolean;
+         Match     : Boolean;
+         Dval      : Node_Id;
+
+         function Same_Base_Type (Ptype, Formal : Entity_Id) return Boolean;
+         --  Determines if Ptype references the type of Formal. Note that
+         --  only the base types need to match according to the spec.
+
+         function Same_Base_Type (Ptype, Formal : Entity_Id) return Boolean is
+         begin
+            Find_Type (Ptype);
+
+            if not Is_Entity_Name (Ptype)
+              or else Entity (Ptype) = Any_Type
+            then
+               raise Pragma_Exit;
+            end if;
+
+            return Base_Type (Entity (Ptype)) = Base_Type (Etype (Formal));
+         end Same_Base_Type;
+
+      --  Start of processing for
+      --  Process_Extended_Import_Export_Subprogram_Pragma
+
+      begin
+         Process_Extended_Import_Export_Internal_Arg (Arg_Internal);
+         Hom_Id := Entity (Arg_Internal);
+         Ent := Empty;
+         Ambiguous := False;
+
+         --  Loop through homonyms (overloadings) of Hom_Id
+
+         while Present (Hom_Id) loop
+            Def_Id := Get_Base_Subprogram (Hom_Id);
+
+            --  We need a subprogram in the current scope
+
+            if not Is_Subprogram (Def_Id)
+              or else Scope (Def_Id) /= Current_Scope
+            then
+               null;
+
+            else
+               Match := True;
+
+               --  Pragma cannot apply to subprogram body
+
+               if Is_Subprogram (Def_Id)
+                 and then
+                   Nkind (Parent
+                     (Declaration_Node (Def_Id))) = N_Subprogram_Body
+               then
+                  Error_Pragma
+                    ("pragma% requires separate spec"
+                      & " and must come before body");
+               end if;
+
+               --  Test result type if given, note that the result type
+               --  parameter can only be present for the function cases.
+
+               if Present (Arg_Result_Type)
+                 and then not Same_Base_Type (Arg_Result_Type, Def_Id)
+               then
+                  Match := False;
+
+               --  Test parameter types if given. Note that this parameter
+               --  has not been analyzed (and must not be, since it is
+               --  semantic nonsense), so we get it as the parser left it.
+
+               elsif Present (Arg_Parameter_Types) then
+                  Check_Matching_Types : declare
+                     Formal : Entity_Id;
+                     Ptype  : Node_Id;
+
+                  begin
+                     Formal := First_Formal (Def_Id);
+
+                     if Nkind (Arg_Parameter_Types) = N_Null then
+                        if Present (Formal) then
+                           Match := False;
+                        end if;
+
+                     --  A list of one type, e.g. (List) is parsed as
+                     --  a parenthesized expression.
+
+                     elsif Nkind (Arg_Parameter_Types) /= N_Aggregate
+                       and then Paren_Count (Arg_Parameter_Types) = 1
+                     then
+                        if No (Formal)
+                          or else Present (Next_Formal (Formal))
+                        then
+                           Match := False;
+                        else
+                           Match :=
+                             Same_Base_Type (Arg_Parameter_Types, Formal);
+                        end if;
+
+                     --  A list of more than one type is parsed as a aggregate
+
+                     elsif Nkind (Arg_Parameter_Types) = N_Aggregate
+                       and then Paren_Count (Arg_Parameter_Types) = 0
+                     then
+                        Ptype := First (Expressions (Arg_Parameter_Types));
+
+                        while Present (Ptype) or else Present (Formal) loop
+                           if No (Ptype)
+                             or else No (Formal)
+                             or else not Same_Base_Type (Ptype, Formal)
+                           then
+                              Match := False;
+                              exit;
+                           else
+                              Next_Formal (Formal);
+                              Next (Ptype);
+                           end if;
+                        end loop;
+
+                     --  Anything else is of the wrong form
+
+                     else
+                        Error_Pragma_Arg
+                          ("wrong form for Parameter_Types parameter",
+                           Arg_Parameter_Types);
+                     end if;
+                  end Check_Matching_Types;
+               end if;
+
+               --  Match is now False if the entry we found did not match
+               --  either a supplied Parameter_Types or Result_Types argument
+
+               if Match then
+                  if No (Ent) then
+                     Ent := Def_Id;
+
+                  --  Ambiguous case, the flag Ambiguous shows if we already
+                  --  detected this and output the initial messages.
+
+                  else
+                     if not Ambiguous then
+                        Ambiguous := True;
+                        Error_Msg_Name_1 := Chars (N);
+                        Error_Msg_N
+                          ("pragma% does not uniquely identify subprogram!",
+                           N);
+                        Error_Msg_Sloc := Sloc (Ent);
+                        Error_Msg_N ("matching subprogram #!", N);
+                        Ent := Empty;
+                     end if;
+
+                     Error_Msg_Sloc := Sloc (Def_Id);
+                     Error_Msg_N ("matching subprogram #!", N);
+                  end if;
+               end if;
+            end if;
+
+            Hom_Id := Homonym (Hom_Id);
+         end loop;
+
+         --  See if we found an entry
+
+         if No (Ent) then
+            if not Ambiguous then
+               if Is_Generic_Subprogram (Entity (Arg_Internal)) then
+                  Error_Pragma
+                    ("pragma% cannot be given for generic subprogram");
+
+               else
+                  Error_Pragma
+                    ("pragma% does not identify local subprogram");
+               end if;
+            end if;
+
+            return;
+         end if;
+
+         --  Import pragmas must be be for imported entities
+
+         if (Prag_Id = Pragma_Import_Function
+               or else
+             Prag_Id = Pragma_Import_Procedure
+               or else
+             Prag_Id = Pragma_Import_Valued_Procedure)
+         then
+            if not Is_Imported (Ent) then
+               Error_Pragma
+                 ("pragma Import or Interface must precede pragma%");
+            end if;
+
+         --  For the Export cases, the pragma Export is sufficient to set
+         --  the entity as exported, if it is not exported already. We
+         --  leave the default Ada convention in this case.
+
+         else
+            Set_Exported (Ent, Arg_Internal);
+         end if;
+
+         --  Special processing for Valued_Procedure cases
+
+         if Prag_Id = Pragma_Import_Valued_Procedure
+           or else
+            Prag_Id = Pragma_Export_Valued_Procedure
+         then
+            Formal := First_Formal (Ent);
+
+            if No (Formal) then
+               Error_Pragma
+                 ("at least one parameter required for pragma%");
+
+            elsif Ekind (Formal) /= E_Out_Parameter then
+               Error_Pragma
+                 ("first parameter must have mode out for pragma%");
+
+            else
+               Set_Is_Valued_Procedure (Ent);
+            end if;
+         end if;
+
+         Set_Extended_Import_Export_External_Name (Ent, Arg_External);
+
+         --  Process Result_Mechanism argument if present. We have already
+         --  checked that this is only allowed for the function case.
+
+         if Present (Arg_Result_Mechanism) then
+            Set_Mechanism_Value (Ent, Arg_Result_Mechanism);
+         end if;
+
+         --  Process Mechanism parameter if present. Note that this parameter
+         --  is not analyzed, and must not be analyzed since it is semantic
+         --  nonsense, so we get it in exactly as the parser left it.
+
+         if Present (Arg_Mechanism) then
+
+            declare
+               Formal : Entity_Id;
+               Massoc : Node_Id;
+               Mname  : Node_Id;
+               Choice : Node_Id;
+
+            begin
+               --  A single mechanism association without a formal parameter
+               --  name is parsed as a parenthesized expression. All other
+               --  cases are parsed as aggregates, so we rewrite the single
+               --  parameter case as an aggregate for consistency.
+
+               if Nkind (Arg_Mechanism) /= N_Aggregate
+                 and then Paren_Count (Arg_Mechanism) = 1
+               then
+                  Rewrite (Arg_Mechanism,
+                    Make_Aggregate (Sloc (Arg_Mechanism),
+                      Expressions => New_List (
+                        Relocate_Node (Arg_Mechanism))));
+               end if;
+
+               --  Case of only mechanism name given, applies to all formals
+
+               if Nkind (Arg_Mechanism) /= N_Aggregate then
+                  Formal := First_Formal (Ent);
+                  while Present (Formal) loop
+                     Set_Mechanism_Value (Formal, Arg_Mechanism);
+                     Next_Formal (Formal);
+                  end loop;
+
+               --  Case of list of mechanism associations given
+
+               else
+                  if Null_Record_Present (Arg_Mechanism) then
+                     Error_Pragma_Arg
+                       ("inappropriate form for Mechanism parameter",
+                        Arg_Mechanism);
+                  end if;
+
+                  --  Deal with positional ones first
+
+                  Formal := First_Formal (Ent);
+                  if Present (Expressions (Arg_Mechanism)) then
+                     Mname := First (Expressions (Arg_Mechanism));
+
+                     while Present (Mname) loop
+                        if No (Formal) then
+                           Error_Pragma_Arg
+                             ("too many mechanism associations", Mname);
+                        end if;
+
+                        Set_Mechanism_Value (Formal, Mname);
+                        Next_Formal (Formal);
+                        Next (Mname);
+                     end loop;
+                  end if;
+
+                  --  Deal with named entries
+
+                  if Present (Component_Associations (Arg_Mechanism)) then
+                     Massoc := First (Component_Associations (Arg_Mechanism));
+
+                     while Present (Massoc) loop
+                        Choice := First (Choices (Massoc));
+
+                        if Nkind (Choice) /= N_Identifier
+                          or else Present (Next (Choice))
+                        then
+                           Error_Pragma_Arg
+                             ("incorrect form for mechanism association",
+                              Massoc);
+                        end if;
+
+                        Formal := First_Formal (Ent);
+                        loop
+                           if No (Formal) then
+                              Error_Pragma_Arg
+                                ("parameter name & not present", Choice);
+                           end if;
+
+                           if Chars (Choice) = Chars (Formal) then
+                              Set_Mechanism_Value
+                                (Formal, Expression (Massoc));
+                              exit;
+                           end if;
+
+                           Next_Formal (Formal);
+                        end loop;
+
+                        Next (Massoc);
+                     end loop;
+                  end if;
+               end if;
+            end;
+         end if;
+
+         --  Process First_Optional_Parameter argument if present. We have
+         --  already checked that this is only allowed for the Import case.
+
+         if Present (Arg_First_Optional_Parameter) then
+            if Nkind (Arg_First_Optional_Parameter) /= N_Identifier then
+               Error_Pragma_Arg
+                 ("first optional parameter must be formal parameter name",
+                  Arg_First_Optional_Parameter);
+            end if;
+
+            Formal := First_Formal (Ent);
+            loop
+               if No (Formal) then
+                  Error_Pragma_Arg
+                    ("specified formal parameter& not found",
+                     Arg_First_Optional_Parameter);
+               end if;
+
+               exit when Chars (Formal) =
+                         Chars (Arg_First_Optional_Parameter);
+
+               Next_Formal (Formal);
+            end loop;
+
+            Set_First_Optional_Parameter (Ent, Formal);
+
+            --  Check specified and all remaining formals have right form
+
+            while Present (Formal) loop
+               if Ekind (Formal) /= E_In_Parameter then
+                  Error_Msg_NE
+                    ("optional formal& is not of mode in!",
+                     Arg_First_Optional_Parameter, Formal);
+
+               else
+                  Dval := Default_Value (Formal);
+
+                  if not Present (Dval) then
+                     Error_Msg_NE
+                       ("optional formal& does not have default value!",
+                        Arg_First_Optional_Parameter, Formal);
+
+                  elsif Compile_Time_Known_Value_Or_Aggr (Dval) then
+                     null;
+
+                  else
+                     Error_Msg_NE
+                       ("default value for optional formal& is non-static!",
+                        Arg_First_Optional_Parameter, Formal);
+                  end if;
+               end if;
+
+               Set_Is_Optional_Parameter (Formal);
+               Next_Formal (Formal);
+            end loop;
+         end if;
+
+      end Process_Extended_Import_Export_Subprogram_Pragma;
+
+      --------------------------
+      -- Process_Generic_List --
+      --------------------------
+
+      procedure Process_Generic_List is
+         Arg : Node_Id;
+         Exp : Node_Id;
+
+      begin
+         GNAT_Pragma;
+         Check_No_Identifiers;
+         Check_At_Least_N_Arguments (1);
+
+         Arg := Arg1;
+         while Present (Arg) loop
+            Exp := Expression (Arg);
+            Analyze (Exp);
+
+            if not Is_Entity_Name (Exp)
+              or else
+                (not Is_Generic_Instance (Entity (Exp))
+                  and then
+                 not Is_Generic_Unit (Entity (Exp)))
+            then
+               Error_Pragma_Arg
+                 ("pragma% argument must be name of generic unit/instance",
+                  Arg);
+            end if;
+
+            Next (Arg);
+         end loop;
+      end Process_Generic_List;
+
+      ---------------------------------
+      -- Process_Import_Or_Interface --
+      ---------------------------------
+
+      procedure Process_Import_Or_Interface is
+         C      : Convention_Id;
+         Def_Id : Entity_Id;
+         Hom_Id : Entity_Id;
+
+      begin
+         Process_Convention (C, Def_Id);
+         Kill_Size_Check_Code (Def_Id);
+         Note_Possible_Modification (Expression (Arg2));
+
+         if Ekind (Def_Id) = E_Variable
+              or else
+            Ekind (Def_Id) = E_Constant
+         then
+            --  User initialization is not allowed for imported object, but
+            --  the object declaration may contain a default initialization,
+            --  that will be discarded.
+
+            if Present (Expression (Parent (Def_Id)))
+               and then Comes_From_Source (Expression (Parent (Def_Id)))
+            then
+               Error_Msg_Sloc := Sloc (Def_Id);
+               Error_Pragma_Arg
+                 ("no initialization allowed for declaration of& #",
+                  "\imported entities cannot be initialized ('R'M' 'B.1(24))",
+                  Arg2);
+
+            else
+               Set_Imported (Def_Id);
+               Set_Is_Public (Def_Id);
+               Process_Interface_Name (Def_Id, Arg3, Arg4);
+            end if;
+
+         elsif Is_Subprogram (Def_Id)
+           or else Is_Generic_Subprogram (Def_Id)
+         then
+            --  If the name is overloaded, pragma applies to all of the
+            --  denoted entities in the same declarative part.
+
+            Hom_Id := Def_Id;
+
+            while Present (Hom_Id) loop
+               Def_Id := Get_Base_Subprogram (Hom_Id);
+
+               --  Ignore inherited subprograms because the pragma will
+               --  apply to the parent operation, which is the one called.
+
+               if Is_Overloadable (Def_Id)
+                 and then Present (Alias (Def_Id))
+               then
+                  null;
+
+               --  Verify that the homonym is in the same declarative
+               --  part (not just the same scope).
+
+               elsif Parent (Unit_Declaration_Node (Def_Id)) /= Parent (N)
+                 and then Nkind (Parent (N)) /= N_Compilation_Unit_Aux
+               then
+                  exit;
+
+               else
+                  Set_Imported (Def_Id);
+
+                  --  If Import intrinsic, set intrinsic flag
+                  --  and verify that it is known as such.
+
+                  if C = Convention_Intrinsic then
+                     Set_Is_Intrinsic_Subprogram (Def_Id);
+                     Check_Intrinsic_Subprogram
+                       (Def_Id, Expression (Arg2));
+                  end if;
+
+                  --  All interfaced procedures need an external
+                  --  symbol created for them since they are
+                  --  always referenced from another object file.
+
+                  Set_Is_Public (Def_Id);
+                  Set_Has_Completion (Def_Id);
+                  Process_Interface_Name (Def_Id, Arg3, Arg4);
+               end if;
+
+               if Is_Compilation_Unit (Hom_Id) then
+
+                  --  Its possible homonyms are not affected by the pragma.
+                  --  Such homonyms might be present in the context of other
+                  --  units being compiled.
+
+                  exit;
+
+               else
+                  Hom_Id := Homonym (Hom_Id);
+               end if;
+            end loop;
+
+         --  When the convention is Java, we also allow Import to be given
+         --  for packages, exceptions, and record components.
+
+         elsif C = Convention_Java
+           and then (Ekind (Def_Id) = E_Package
+                     or else Ekind (Def_Id) = E_Exception
+                     or else Nkind (Parent (Def_Id)) = N_Component_Declaration)
+         then
+            Set_Imported (Def_Id);
+            Set_Is_Public (Def_Id);
+            Process_Interface_Name (Def_Id, Arg3, Arg4);
+
+         else
+            Error_Pragma_Arg
+              ("second argument of pragma% must be object or subprogram",
+               Arg2);
+         end if;
+
+         --  If this pragma applies to a compilation unit, then the unit,
+         --  which is a subprogram, does not require (or allow) a body.
+         --  We also do not need to elaborate imported procedures.
+
+         if Nkind (Parent (N)) = N_Compilation_Unit_Aux then
+            declare
+               Cunit : constant Node_Id := Parent (Parent (N));
+
+            begin
+               Set_Body_Required    (Cunit, False);
+            end;
+         end if;
+
+      end Process_Import_Or_Interface;
+
+      --------------------
+      -- Process_Inline --
+      --------------------
+
+      procedure Process_Inline (Active : Boolean) is
+         Assoc   : Node_Id;
+         Decl    : Node_Id;
+         Subp_Id : Node_Id;
+         Subp    : Entity_Id;
+         Applies : Boolean;
+
+         procedure Make_Inline (Subp : Entity_Id);
+         --  Subp is the defining unit name of the subprogram
+         --  declaration. Set the flag, as well as the flag in the
+         --  corresponding body, if there is one present.
+
+         procedure Set_Inline_Flags (Subp : Entity_Id);
+         --  Sets Is_Inlined and Has_Pragma_Inline flags for Subp
+
+         -----------------
+         -- Make_Inline --
+         -----------------
+
+         procedure Make_Inline (Subp : Entity_Id) is
+            Kind       : Entity_Kind := Ekind (Subp);
+            Inner_Subp : Entity_Id   := Subp;
+
+         begin
+            if Etype (Subp) = Any_Type then
+               return;
+
+            --  Here we have a candidate for inlining, but we must exclude
+            --  derived operations. Otherwise we will end up trying to
+            --  inline a phantom declaration, and the result would be to
+            --  drag in a body which has no direct inlining associated with
+            --  it. That would not only be inefficient but would also result
+            --  in the backend doing cross-unit inlining in cases where it
+            --  was definitely inappropriate to do so.
+
+            --  However, a simple Comes_From_Source test is insufficient,
+            --  since we do want to allow inlining of generic instances,
+            --  which also do not come from source. Predefined operators do
+            --  not come from source but are not inlineable either.
+
+            elsif not Comes_From_Source (Subp)
+              and then not Is_Generic_Instance (Subp)
+              and then Scope (Subp) /= Standard_Standard
+            then
+               Applies := True;
+               return;
+
+            --  The referenced entity must either be the enclosing entity,
+            --  or an entity declared within the current open scope.
+
+            elsif Present (Scope (Subp))
+              and then Scope (Subp) /= Current_Scope
+              and then Subp /= Current_Scope
+            then
+               Error_Pragma_Arg
+                 ("argument of% must be entity in current scope", Assoc);
+               return;
+            end if;
+
+            --  Processing for procedure, operator or function.
+            --  If subprogram is aliased (as for an instance) indicate
+            --  that the renamed entity is inlined.
+
+            if Kind = E_Procedure
+              or else Kind = E_Function
+              or else Kind = E_Operator
+            then
+               while Present (Alias (Inner_Subp)) loop
+                  Inner_Subp := Alias (Inner_Subp);
+               end loop;
+
+               Set_Inline_Flags (Inner_Subp);
+
+               Decl := Parent (Parent (Inner_Subp));
+
+               if Nkind (Decl) = N_Subprogram_Declaration
+                 and then Present (Corresponding_Body (Decl))
+               then
+                  Set_Inline_Flags (Corresponding_Body (Decl));
+               end if;
+
+               Applies := True;
+
+            --  For a generic subprogram set flag as well, for use at
+            --  the point of instantiation, to determine whether the
+            --  body should be generated.
+
+            elsif Kind = E_Generic_Procedure
+              or else Kind = E_Generic_Function
+            then
+               Set_Inline_Flags (Subp);
+               Applies := True;
+
+            --  Literals are by definition inlined.
+
+            elsif Kind = E_Enumeration_Literal then
+               null;
+
+            --  Anything else is an error
+
+            else
+               Error_Pragma_Arg
+                 ("expect subprogram name for pragma%", Assoc);
+            end if;
+         end Make_Inline;
+
+         ----------------------
+         -- Set_Inline_Flags --
+         ----------------------
+
+         procedure Set_Inline_Flags (Subp : Entity_Id) is
+         begin
+            if Active then
+               Set_Is_Inlined (Subp, True);
+            end if;
+
+            if not Has_Pragma_Inline (Subp) then
+               Set_Has_Pragma_Inline (Subp);
+               Set_Next_Rep_Item (N, First_Rep_Item (Subp));
+               Set_First_Rep_Item (Subp, N);
+            end if;
+         end Set_Inline_Flags;
+
+      --  Start of processing for Process_Inline
+
+      begin
+         Check_No_Identifiers;
+         Check_At_Least_N_Arguments (1);
+
+         if Active then
+            Inline_Processing_Required := True;
+         end if;
+
+         Assoc := Arg1;
+         while Present (Assoc) loop
+            Subp_Id := Expression (Assoc);
+            Analyze (Subp_Id);
+            Applies := False;
+
+            if Is_Entity_Name (Subp_Id) then
+               Subp := Entity (Subp_Id);
+
+               if Subp = Any_Id then
+                  Applies := True;
+
+               else
+                  Make_Inline (Subp);
+
+                  while Present (Homonym (Subp))
+                    and then Scope (Homonym (Subp)) = Current_Scope
+                  loop
+                     Make_Inline (Homonym (Subp));
+                     Subp := Homonym (Subp);
+                  end loop;
+               end if;
+            end if;
+
+            if not Applies then
+               Error_Pragma_Arg
+                 ("inappropriate argument for pragma%", Assoc);
+            end if;
+
+            Next (Assoc);
+         end loop;
+
+      end Process_Inline;
+
+      ----------------------------
+      -- Process_Interface_Name --
+      ----------------------------
+
+      procedure Process_Interface_Name
+        (Subprogram_Def : Entity_Id;
+         Ext_Arg        : Node_Id;
+         Link_Arg       : Node_Id)
+      is
+         Ext_Nam    : Node_Id;
+         Link_Nam   : Node_Id;
+         String_Val : String_Id;
+
+         procedure Check_Form_Of_Interface_Name (SN : Node_Id);
+         --  SN is a string literal node for an interface name. This routine
+         --  performs some minimal checks that the name is reasonable. In
+         --  particular that no spaces or other obviously incorrect characters
+         --  appear. This is only a warning, since any characters are allowed.
+
+         procedure Check_Form_Of_Interface_Name (SN : Node_Id) is
+            S  : constant String_Id := Strval (Expr_Value_S (SN));
+            SL : constant Nat       := String_Length (S);
+            C  : Char_Code;
+
+         begin
+            if SL = 0 then
+               Error_Msg_N ("interface name cannot be null string", SN);
+            end if;
+
+            for J in 1 .. SL loop
+               C := Get_String_Char (S, J);
+
+               if not In_Character_Range (C)
+                 or else Get_Character (C) = ' '
+                 or else Get_Character (C) = ','
+               then
+                  Error_Msg_N
+                    ("?interface name contains illegal character", SN);
+               end if;
+            end loop;
+         end Check_Form_Of_Interface_Name;
+
+      --  Start of processing for Process_Interface_Name
+
+      begin
+         if No (Link_Arg) then
+            if No (Ext_Arg) then
+               return;
+
+            elsif Chars (Ext_Arg) = Name_Link_Name then
+               Ext_Nam  := Empty;
+               Link_Nam := Expression (Ext_Arg);
+
+            else
+               Check_Optional_Identifier (Ext_Arg, Name_External_Name);
+               Ext_Nam  := Expression (Ext_Arg);
+               Link_Nam := Empty;
+            end if;
+
+         else
+            Check_Optional_Identifier (Ext_Arg,  Name_External_Name);
+            Check_Optional_Identifier (Link_Arg, Name_Link_Name);
+            Ext_Nam  := Expression (Ext_Arg);
+            Link_Nam := Expression (Link_Arg);
+         end if;
+
+         --  Check expressions for external name and link name are static
+
+         if Present (Ext_Nam) then
+            Check_Arg_Is_Static_Expression (Ext_Nam, Standard_String);
+            Check_Form_Of_Interface_Name (Ext_Nam);
+
+            --  Verify that the external name is not the name of a local
+            --  entity, which would hide the imported one and lead to
+            --  run-time surprises. The problem can only arise for entities
+            --  declared in a package body (otherwise the external name is
+            --  fully qualified and won't conflict).
+
+            declare
+               Nam : Name_Id;
+               E   : Entity_Id;
+               Par : Node_Id;
+
+            begin
+               if Prag_Id = Pragma_Import then
+                  String_To_Name_Buffer (Strval (Expr_Value_S (Ext_Nam)));
+                  Nam := Name_Find;
+                  E   := Entity_Id (Get_Name_Table_Info (Nam));
+
+                  if Nam /= Chars (Subprogram_Def)
+                    and then Present (E)
+                    and then not Is_Overloadable (E)
+                    and then Is_Immediately_Visible (E)
+                    and then not Is_Imported (E)
+                    and then Ekind (Scope (E)) = E_Package
+                  then
+                     Par := Parent (E);
+
+                     while Present (Par) loop
+                        if Nkind (Par) = N_Package_Body then
+                           Error_Msg_Sloc  := Sloc (E);
+                           Error_Msg_NE
+                             ("imported entity is hidden by & declared#",
+                                 Ext_Arg, E);
+                           exit;
+                        end if;
+
+                        Par := Parent (Par);
+                     end loop;
+                  end if;
+               end if;
+            end;
+         end if;
+
+         if Present (Link_Nam) then
+            Check_Arg_Is_Static_Expression (Link_Nam, Standard_String);
+            Check_Form_Of_Interface_Name (Link_Nam);
+         end if;
+
+         --  If there is no link name, just set the external name
+
+         if No (Link_Nam) then
+            Set_Encoded_Interface_Name
+              (Get_Base_Subprogram (Subprogram_Def),
+               Adjust_External_Name_Case (Expr_Value_S (Ext_Nam)));
+
+         --  For the Link_Name case, the given literal is preceded by an
+         --  asterisk, which indicates to GCC that the given name should
+         --  be taken literally, and in particular that no prepending of
+         --  underlines should occur, even in systems where this is the
+         --  normal default.
+
+         else
+            Start_String;
+            Store_String_Char (Get_Char_Code ('*'));
+            String_Val := Strval (Expr_Value_S (Link_Nam));
+
+            for J in 1 .. String_Length (String_Val) loop
+               Store_String_Char (Get_String_Char (String_Val, J));
+            end loop;
+
+            Link_Nam :=
+              Make_String_Literal (Sloc (Link_Nam), End_String);
+
+            Set_Encoded_Interface_Name
+              (Get_Base_Subprogram (Subprogram_Def), Link_Nam);
+         end if;
+      end Process_Interface_Name;
+
+      -----------------------------------------
+      -- Process_Interrupt_Or_Attach_Handler --
+      -----------------------------------------
+
+      procedure Process_Interrupt_Or_Attach_Handler is
+         Arg1_X    : constant Node_Id   := Expression (Arg1);
+         Prot_Proc : constant Entity_Id := Entity (Arg1_X);
+         Prot_Type : constant Entity_Id := Scope (Prot_Proc);
+
+      begin
+         Set_Is_Interrupt_Handler (Prot_Proc);
+
+         if Prag_Id = Pragma_Interrupt_Handler
+           or Prag_Id = Pragma_Attach_Handler
+         then
+            Record_Rep_Item (Prot_Type, N);
+         end if;
+
+      end Process_Interrupt_Or_Attach_Handler;
+
+      ---------------------------------
+      -- Process_Suppress_Unsuppress --
+      ---------------------------------
+
+      procedure Process_Suppress_Unsuppress (Suppress_Case : Boolean) is
+         C         : Check_Id;
+         E_Id      : Node_Id;
+         E         : Entity_Id;
+         Effective : Boolean;
+
+         procedure Suppress_Unsuppress_Echeck (E : Entity_Id; C : Check_Id);
+         --  Used to suppress a single check on the given entity
+
+         procedure Suppress_Unsuppress_Echeck (E : Entity_Id; C : Check_Id) is
+         begin
+            --  First set appropriate suppress flags in the entity
+
+            case C is
+               when Access_Check =>
+                  Effective := Suppress_Access_Checks (E);
+                  Set_Suppress_Access_Checks (E, Suppress_Case);
+
+               when Accessibility_Check =>
+                  Effective := Suppress_Accessibility_Checks (E);
+                  Set_Suppress_Accessibility_Checks (E, Suppress_Case);
+
+               when Discriminant_Check =>
+                  Effective := Suppress_Discriminant_Checks  (E);
+                  Set_Suppress_Discriminant_Checks (E, Suppress_Case);
+
+               when Division_Check =>
+                  Effective := Suppress_Division_Checks (E);
+                  Set_Suppress_Division_Checks (E, Suppress_Case);
+
+               when Elaboration_Check =>
+                  Effective := Suppress_Elaboration_Checks (E);
+                  Set_Suppress_Elaboration_Checks (E, Suppress_Case);
+
+               when Index_Check =>
+                  Effective := Suppress_Index_Checks (E);
+                  Set_Suppress_Index_Checks (E, Suppress_Case);
+
+               when Length_Check =>
+                  Effective := Suppress_Length_Checks (E);
+                  Set_Suppress_Length_Checks (E, Suppress_Case);
+
+               when Overflow_Check =>
+                  Effective := Suppress_Overflow_Checks (E);
+                  Set_Suppress_Overflow_Checks (E, Suppress_Case);
+
+               when Range_Check =>
+                  Effective := Suppress_Range_Checks (E);
+                  Set_Suppress_Range_Checks (E, Suppress_Case);
+
+               when Storage_Check =>
+                  Effective := Suppress_Storage_Checks (E);
+                  Set_Suppress_Storage_Checks (E, Suppress_Case);
+
+               when Tag_Check =>
+                  Effective := Suppress_Tag_Checks (E);
+                  Set_Suppress_Tag_Checks (E, Suppress_Case);
+
+               when All_Checks =>
+                  Suppress_Unsuppress_Echeck (E, Access_Check);
+                  Suppress_Unsuppress_Echeck (E, Accessibility_Check);
+                  Suppress_Unsuppress_Echeck (E, Discriminant_Check);
+                  Suppress_Unsuppress_Echeck (E, Division_Check);
+                  Suppress_Unsuppress_Echeck (E, Elaboration_Check);
+                  Suppress_Unsuppress_Echeck (E, Index_Check);
+                  Suppress_Unsuppress_Echeck (E, Length_Check);
+                  Suppress_Unsuppress_Echeck (E, Overflow_Check);
+                  Suppress_Unsuppress_Echeck (E, Range_Check);
+                  Suppress_Unsuppress_Echeck (E, Storage_Check);
+                  Suppress_Unsuppress_Echeck (E, Tag_Check);
+            end case;
+
+            --  If the entity is not declared in the current scope, then we
+            --  make an entry in the Entity_Suppress table so that the flag
+            --  will be removed on exit. This entry is only made if the
+            --  suppress did something (i.e. the flag was not already set).
+
+            if Effective and then Scope (E) /= Current_Scope then
+               Entity_Suppress.Increment_Last;
+               Entity_Suppress.Table
+                 (Entity_Suppress.Last).Entity := E;
+               Entity_Suppress.Table
+                 (Entity_Suppress.Last).Check  := C;
+            end if;
+
+            --  If this is a first subtype, and the base type is distinct,
+            --  then also set the suppress flags on the base type.
+
+            if Is_First_Subtype (E)
+              and then Etype (E) /= E
+            then
+               Suppress_Unsuppress_Echeck (Etype (E), C);
+            end if;
+         end Suppress_Unsuppress_Echeck;
+
+      --  Start of processing for Process_Suppress_Unsuppress
+
+      begin
+         --  Suppress/Unsuppress can appear as a configuration pragma,
+         --  or in a declarative part or a package spec (RM 11.5(5))
+
+         if not Is_Configuration_Pragma then
+            Check_Is_In_Decl_Part_Or_Package_Spec;
+         end if;
+
+         Check_At_Least_N_Arguments (1);
+         Check_At_Most_N_Arguments (2);
+         Check_No_Identifier (Arg1);
+         Check_Arg_Is_Identifier (Arg1);
+
+         if not Is_Check_Name (Chars (Expression (Arg1))) then
+            Error_Pragma_Arg
+              ("argument of pragma% is not valid check name", Arg1);
+
+         else
+            C := Get_Check_Id (Chars (Expression (Arg1)));
+         end if;
+
+         if Arg_Count = 1 then
+            case C is
+               when Access_Check =>
+                  Scope_Suppress.Access_Checks := Suppress_Case;
+
+               when Accessibility_Check =>
+                  Scope_Suppress.Accessibility_Checks := Suppress_Case;
+
+               when Discriminant_Check =>
+                  Scope_Suppress.Discriminant_Checks := Suppress_Case;
+
+               when Division_Check =>
+                  Scope_Suppress.Division_Checks := Suppress_Case;
+
+               when Elaboration_Check =>
+                  Scope_Suppress.Elaboration_Checks := Suppress_Case;
+
+               when Index_Check =>
+                  Scope_Suppress.Index_Checks := Suppress_Case;
+
+               when Length_Check =>
+                  Scope_Suppress.Length_Checks := Suppress_Case;
+
+               when Overflow_Check =>
+                  Scope_Suppress.Overflow_Checks := Suppress_Case;
+
+               when Range_Check =>
+                  Scope_Suppress.Range_Checks := Suppress_Case;
+
+               when Storage_Check =>
+                  Scope_Suppress.Storage_Checks := Suppress_Case;
+
+               when Tag_Check =>
+                  Scope_Suppress.Tag_Checks := Suppress_Case;
+
+               when All_Checks =>
+                  Scope_Suppress := (others => Suppress_Case);
+
+            end case;
+
+         --  Case of two arguments present, where the check is
+         --  suppressed for a specified entity (given as the second
+         --  argument of the pragma)
+
+         else
+            Check_Optional_Identifier (Arg2, Name_On);
+            E_Id := Expression (Arg2);
+            Analyze (E_Id);
+
+            if not Is_Entity_Name (E_Id) then
+               Error_Pragma_Arg
+                 ("second argument of pragma% must be entity name", Arg2);
+            end if;
+
+            E := Entity (E_Id);
+
+            if E = Any_Id then
+               return;
+            else
+               loop
+                  Suppress_Unsuppress_Echeck (E, C);
+
+                  if Is_Generic_Instance (E)
+                    and then Is_Subprogram (E)
+                    and then Present (Alias (E))
+                  then
+                     Suppress_Unsuppress_Echeck (Alias (E), C);
+                  end if;
+
+                  if C = Elaboration_Check and then Suppress_Case then
+                     Set_Suppress_Elaboration_Warnings (E);
+                  end if;
+
+                  --  If we are within a package specification, the
+                  --  pragma only applies to homonyms in the same scope.
+
+                  exit when No (Homonym (E))
+                    or else (Scope (Homonym (E)) /= Current_Scope
+                              and then Ekind (Current_Scope) = E_Package
+                              and then not In_Package_Body (Current_Scope));
+
+                  E := Homonym (E);
+               end loop;
+            end if;
+         end if;
+
+      end Process_Suppress_Unsuppress;
+
+      ------------------
+      -- Set_Exported --
+      ------------------
+
+      procedure Set_Exported (E : Entity_Id; Arg : Node_Id) is
+      begin
+         if Is_Imported (E) then
+            Error_Pragma_Arg
+              ("cannot export entity& that was previously imported", Arg);
+
+         elsif Present (Address_Clause (E)) then
+            Error_Pragma_Arg
+              ("cannot export entity& that has an address clause", Arg);
+         end if;
+
+         Set_Is_Exported (E);
+
+         --  Deal with exporting non-library level entity
+
+         if not Is_Library_Level_Entity (E) then
+
+            --  Not allowed at all for subprograms
+
+            if Is_Subprogram (E) then
+               Error_Pragma_Arg ("local subprogram& cannot be exported", Arg);
+
+            --  Otherwise set public and statically allocated
+
+            else
+               Set_Is_Public (E);
+               Set_Is_Statically_Allocated (E);
+            end if;
+         end if;
+
+         if Inside_A_Generic then
+            Error_Msg_NE
+              ("all instances of& will have the same external name?", Arg, E);
+         end if;
+
+      end Set_Exported;
+
+      ----------------------------------------------
+      -- Set_Extended_Import_Export_External_Name --
+      ----------------------------------------------
+
+      procedure Set_Extended_Import_Export_External_Name
+        (Internal_Ent : Entity_Id;
+         Arg_External : Node_Id)
+      is
+         Old_Name : constant Node_Id := Interface_Name (Internal_Ent);
+         New_Name : Node_Id;
+
+      begin
+         if No (Arg_External) then
+            return;
+
+         elsif Nkind (Arg_External) = N_String_Literal then
+            if String_Length (Strval (Arg_External)) = 0 then
+               return;
+            else
+               New_Name := Adjust_External_Name_Case (Arg_External);
+            end if;
+
+         elsif Nkind (Arg_External) = N_Identifier then
+            New_Name := Get_Default_External_Name (Arg_External);
+
+         else
+            Error_Pragma_Arg
+              ("incorrect form for External parameter for pragma%",
+               Arg_External);
+         end if;
+
+         --  If we already have an external name set (by a prior normal
+         --  Import or Export pragma), then the external names must match
+
+         if Present (Interface_Name (Internal_Ent)) then
+            declare
+               S1 : constant String_Id := Strval (Old_Name);
+               S2 : constant String_Id := Strval (New_Name);
+
+               procedure Mismatch;
+               --  Called if names do not match
+
+               procedure Mismatch is
+               begin
+                  Error_Msg_Sloc := Sloc (Old_Name);
+                  Error_Pragma_Arg
+                    ("external name does not match that given #",
+                     Arg_External);
+               end Mismatch;
+
+            begin
+               if String_Length (S1) /= String_Length (S2) then
+                  Mismatch;
+
+               else
+                  for J in 1 .. String_Length (S1) loop
+                     if Get_String_Char (S1, J) /= Get_String_Char (S2, J) then
+                        Mismatch;
+                     end if;
+                  end loop;
+               end if;
+            end;
+
+         --  Otherwise set the given name
+
+         else
+            Set_Encoded_Interface_Name (Internal_Ent, New_Name);
+         end if;
+
+      end Set_Extended_Import_Export_External_Name;
+
+      ------------------
+      -- Set_Imported --
+      ------------------
+
+      procedure Set_Imported (E : Entity_Id) is
+      begin
+         Error_Msg_Sloc  := Sloc (E);
+
+         if Is_Exported (E) or else Is_Imported (E) then
+            Error_Msg_NE ("import of& declared# not allowed", N, E);
+
+            if Is_Exported (E) then
+               Error_Msg_N ("\entity was previously exported", N);
+            else
+               Error_Msg_N ("\entity was previously imported", N);
+            end if;
+
+            Error_Pragma ("\(pragma% applies to all previous entities)");
+
+         else
+            Set_Is_Imported (E);
+
+            --  If the entity is an object that is not at the library
+            --  level, then it is statically allocated. We do not worry
+            --  about objects with address clauses in this context since
+            --  they are not really imported in the linker sense.
+
+            if Is_Object (E)
+              and then not Is_Library_Level_Entity (E)
+              and then No (Address_Clause (E))
+            then
+               Set_Is_Statically_Allocated (E);
+            end if;
+         end if;
+      end Set_Imported;
+
+      -------------------------
+      -- Set_Mechanism_Value --
+      -------------------------
+
+      --  Note: the mechanism name has not been analyzed (and cannot indeed
+      --  be analyzed, since it is semantic nonsense), so we get it in the
+      --  exact form created by the parser.
+
+      procedure Set_Mechanism_Value (Ent : Entity_Id; Mech_Name : Node_Id) is
+         Class : Node_Id;
+         Param : Node_Id;
+
+         procedure Bad_Class;
+         --  Signal bad descriptor class name
+
+         procedure Bad_Mechanism;
+         --  Signal bad mechanism name
+
+         procedure Bad_Class is
+         begin
+            Error_Pragma_Arg ("unrecognized descriptor class name", Class);
+         end Bad_Class;
+
+         procedure Bad_Mechanism is
+         begin
+            Error_Pragma_Arg ("unrecognized mechanism name", Mech_Name);
+         end Bad_Mechanism;
+
+      --  Start of processing for Set_Mechanism_Value
+
+      begin
+         if Mechanism (Ent) /= Default_Mechanism then
+            Error_Msg_NE
+              ("mechanism for & has already been set", Mech_Name, Ent);
+         end if;
+
+         --  MECHANISM_NAME ::= value | reference | descriptor
+
+         if Nkind (Mech_Name) = N_Identifier then
+            if Chars (Mech_Name) = Name_Value then
+               Set_Mechanism (Ent, By_Copy);
+               return;
+
+            elsif Chars (Mech_Name) = Name_Reference then
+               Set_Mechanism (Ent, By_Reference);
+               return;
+
+            elsif Chars (Mech_Name) = Name_Descriptor then
+               Check_VMS (Mech_Name);
+               Set_Mechanism (Ent, By_Descriptor);
+               return;
+
+            elsif Chars (Mech_Name) = Name_Copy then
+               Error_Pragma_Arg
+                 ("bad mechanism name, Value assumed", Mech_Name);
+
+            else
+               Bad_Mechanism;
+            end if;
+
+         --  MECHANISM_NAME ::= descriptor (CLASS_NAME)
+         --  CLASS_NAME     ::= ubs | ubsb | uba | s | sb | a | nca
+
+         --  Note: this form is parsed as an indexed component
+
+         elsif Nkind (Mech_Name) = N_Indexed_Component then
+            Class := First (Expressions (Mech_Name));
+
+            if Nkind (Prefix (Mech_Name)) /= N_Identifier
+              or else Chars (Prefix (Mech_Name)) /= Name_Descriptor
+              or else Present (Next (Class))
+            then
+               Bad_Mechanism;
+            end if;
+
+         --  MECHANISM_NAME ::= descriptor (Class => CLASS_NAME)
+         --  CLASS_NAME     ::= ubs | ubsb | uba | s | sb | a | nca
+
+         --  Note: this form is parsed as a function call
+
+         elsif Nkind (Mech_Name) = N_Function_Call then
+
+            Param := First (Parameter_Associations (Mech_Name));
+
+            if Nkind (Name (Mech_Name)) /= N_Identifier
+              or else Chars (Name (Mech_Name)) /= Name_Descriptor
+              or else Present (Next (Param))
+              or else No (Selector_Name (Param))
+              or else Chars (Selector_Name (Param)) /= Name_Class
+            then
+               Bad_Mechanism;
+            else
+               Class := Explicit_Actual_Parameter (Param);
+            end if;
+
+         else
+            Bad_Mechanism;
+         end if;
+
+         --  Fall through here with Class set to descriptor class name
+
+         Check_VMS (Mech_Name);
+
+         if Nkind (Class) /= N_Identifier then
+            Bad_Class;
+
+         elsif Chars (Class) = Name_UBS then
+            Set_Mechanism (Ent, By_Descriptor_UBS);
+
+         elsif Chars (Class) = Name_UBSB then
+            Set_Mechanism (Ent, By_Descriptor_UBSB);
+
+         elsif Chars (Class) = Name_UBA then
+            Set_Mechanism (Ent, By_Descriptor_UBA);
+
+         elsif Chars (Class) = Name_S then
+            Set_Mechanism (Ent, By_Descriptor_S);
+
+         elsif Chars (Class) = Name_SB then
+            Set_Mechanism (Ent, By_Descriptor_SB);
+
+         elsif Chars (Class) = Name_A then
+            Set_Mechanism (Ent, By_Descriptor_A);
+
+         elsif Chars (Class) = Name_NCA then
+            Set_Mechanism (Ent, By_Descriptor_NCA);
+
+         else
+            Bad_Class;
+         end if;
+
+      end Set_Mechanism_Value;
+
+   --  Start of processing for Analyze_Pragma
+
+   begin
+      if not Is_Pragma_Name (Chars (N)) then
+         Error_Pragma ("unrecognized pragma%!?");
+      else
+         Prag_Id := Get_Pragma_Id (Chars (N));
+      end if;
+
+      --  Preset arguments
+
+      Arg1 := Empty;
+      Arg2 := Empty;
+      Arg3 := Empty;
+      Arg4 := Empty;
+
+      if Present (Pragma_Argument_Associations (N)) then
+         Arg1 := First (Pragma_Argument_Associations (N));
+
+         if Present (Arg1) then
+            Arg2 := Next (Arg1);
+
+            if Present (Arg2) then
+               Arg3 := Next (Arg2);
+
+               if Present (Arg3) then
+                  Arg4 := Next (Arg3);
+               end if;
+            end if;
+         end if;
+      end if;
+
+      --  Count number of arguments
+
+      declare
+         Arg_Node : Node_Id;
+
+      begin
+         Arg_Count := 0;
+         Arg_Node := Arg1;
+
+         while Present (Arg_Node) loop
+            Arg_Count := Arg_Count + 1;
+            Next (Arg_Node);
+         end loop;
+      end;
+
+      --  An enumeration type defines the pragmas that are supported by the
+      --  implementation. Get_Pragma_Id (in package Prag) transorms a name
+      --  into the corresponding enumeration value for the following case.
+
+      case Prag_Id is
+
+         -----------------
+         -- Abort_Defer --
+         -----------------
+
+         --  pragma Abort_Defer;
+
+         when Pragma_Abort_Defer =>
+            GNAT_Pragma;
+            Check_Arg_Count (0);
+
+            --  The only required semantic processing is to check the
+            --  placement. This pragma must appear at the start of the
+            --  statement sequence of a handled sequence of statements.
+
+            if Nkind (Parent (N)) /= N_Handled_Sequence_Of_Statements
+              or else N /= First (Statements (Parent (N)))
+            then
+               Pragma_Misplaced;
+            end if;
+
+         ------------
+         -- Ada_83 --
+         ------------
+
+         --  pragma Ada_83;
+
+         --  Note: this pragma also has some specific processing in Par.Prag
+         --  because we want to set the Ada 83 mode switch during parsing.
+
+         when Pragma_Ada_83 =>
+            GNAT_Pragma;
+            Ada_83 := True;
+            Ada_95 := False;
+            Check_Arg_Count (0);
+
+         ------------
+         -- Ada_95 --
+         ------------
+
+         --  pragma Ada_95;
+
+         --  Note: this pragma also has some specific processing in Par.Prag
+         --  because we want to set the Ada 83 mode switch during parsing.
+
+         when Pragma_Ada_95 =>
+            GNAT_Pragma;
+            Ada_83 := False;
+            Ada_95 := True;
+            Check_Arg_Count (0);
+
+         ----------------------
+         -- All_Calls_Remote --
+         ----------------------
+
+         --  pragma All_Calls_Remote [(library_package_NAME)];
+
+         when Pragma_All_Calls_Remote => All_Calls_Remote : declare
+            Lib_Entity : Entity_Id;
+
+         begin
+            Check_Ada_83_Warning;
+            Check_Valid_Library_Unit_Pragma;
+
+            if Nkind (N) = N_Null_Statement then
+               return;
+            end if;
+
+            Lib_Entity := Find_Lib_Unit_Name;
+
+            --  This pragma should only apply to a RCI unit (RM E.2.3(23)).
+
+            if Present (Lib_Entity)
+              and then not Debug_Flag_U
+            then
+               if not Is_Remote_Call_Interface (Lib_Entity) then
+                  Error_Pragma ("pragma% only apply to rci unit");
+
+               --  Set flag for entity of the library unit
+
+               else
+                  Set_Has_All_Calls_Remote (Lib_Entity);
+               end if;
+
+            end if;
+         end All_Calls_Remote;
+
+         --------------
+         -- Annotate --
+         --------------
+
+         --  pragma Annotate (IDENTIFIER {, ARG});
+         --  ARG ::= NAME | EXPRESSION
+
+         when Pragma_Annotate => Annotate : begin
+            GNAT_Pragma;
+            Check_At_Least_N_Arguments (1);
+            Check_Arg_Is_Identifier (Arg1);
+
+            declare
+               Arg : Node_Id := Arg2;
+               Exp : Node_Id;
+
+            begin
+               while Present (Arg) loop
+                  Exp := Expression (Arg);
+                  Analyze (Exp);
+
+                  if Is_Entity_Name (Exp) then
+                     null;
+
+                  elsif Nkind (Exp) = N_String_Literal then
+                     Resolve (Exp, Standard_String);
+
+                  elsif Is_Overloaded (Exp) then
+                     Error_Pragma_Arg ("ambiguous argument for pragma%", Exp);
+
+                  else
+                     Resolve (Exp, Etype (Exp));
+                  end if;
+
+                  Next (Arg);
+               end loop;
+            end;
+         end Annotate;
+
+         ------------
+         -- Assert --
+         ------------
+
+         --  pragma Assert (Boolean_EXPRESSION [, static_string_EXPRESSION]);
+
+         when Pragma_Assert =>
+            GNAT_Pragma;
+            Check_No_Identifiers;
+
+            if Arg_Count > 1 then
+               Check_Arg_Count (2);
+               Check_Arg_Is_Static_Expression (Arg2, Standard_String);
+            end if;
+
+            --  If expansion is active and assertions are inactive, then
+            --  we rewrite the Assertion as:
+
+            --    if False and then condition then
+            --       null;
+            --    end if;
+
+            --  The reason we do this rewriting during semantic analysis
+            --  rather than as part of normal expansion is that we cannot
+            --  analyze and expand the code for the boolean expression
+            --  directly, or it may cause insertion of actions that would
+            --  escape the attempt to suppress the assertion code.
+
+            if Expander_Active and not Assertions_Enabled then
+               Rewrite (N,
+                 Make_If_Statement (Loc,
+                   Condition =>
+                     Make_And_Then (Loc,
+                       Left_Opnd  => New_Occurrence_Of (Standard_False, Loc),
+                       Right_Opnd => Get_Pragma_Arg (Arg1)),
+                   Then_Statements => New_List (
+                     Make_Null_Statement (Loc))));
+
+               Analyze (N);
+
+            --  Otherwise (if assertions are enabled, or if we are not
+            --  operating with expansion active), then we just analyze
+            --  and resolve the expression.
+
+            else
+               Analyze_And_Resolve (Expression (Arg1), Any_Boolean);
+            end if;
+
+         ---------------
+         -- AST_Entry --
+         ---------------
+
+         --  pragma AST_Entry (entry_IDENTIFIER);
+
+         when Pragma_AST_Entry => AST_Entry : declare
+            Ent : Node_Id;
+
+         begin
+            GNAT_Pragma;
+            Check_VMS (N);
+            Check_Arg_Count (1);
+            Check_No_Identifiers;
+            Check_Arg_Is_Local_Name (Arg1);
+            Ent := Entity (Expression (Arg1));
+
+            --  Note: the implementation of the AST_Entry pragma could handle
+            --  the entry family case fine, but for now we are consistent with
+            --  the DEC rules, and do not allow the pragma, which of course
+            --  has the effect of also forbidding the attribute.
+
+            if Ekind (Ent) /= E_Entry then
+               Error_Pragma_Arg
+                 ("pragma% argument must be simple entry name", Arg1);
+
+            elsif Is_AST_Entry (Ent) then
+               Error_Pragma_Arg
+                 ("duplicate % pragma for entry", Arg1);
+
+            elsif Has_Homonym (Ent) then
+               Error_Pragma_Arg
+                 ("pragma% argument cannot specify overloaded entry", Arg1);
+
+            else
+               declare
+                  FF : constant Entity_Id := First_Formal (Ent);
+
+               begin
+                  if Present (FF) then
+                     if Present (Next_Formal (FF)) then
+                        Error_Pragma_Arg
+                          ("entry for pragma% can have only one argument",
+                           Arg1);
+
+                     elsif Parameter_Mode (FF) /= E_In_Parameter then
+                        Error_Pragma_Arg
+                          ("entry parameter for pragma% must have mode IN",
+                           Arg1);
+                     end if;
+                  end if;
+               end;
+
+               Set_Is_AST_Entry (Ent);
+            end if;
+         end AST_Entry;
+
+         ------------------
+         -- Asynchronous --
+         ------------------
+
+         --  pragma Asynchronous (LOCAL_NAME);
+
+         when Pragma_Asynchronous => Asynchronous : declare
+            Nm     : Entity_Id;
+            C_Ent  : Entity_Id;
+            L      : List_Id;
+            S      : Node_Id;
+            N      : Node_Id;
+            Formal : Entity_Id;
+
+            procedure Process_Async_Pragma;
+            --  Common processing for procedure and access-to-procedure case
+
+            --------------------------
+            -- Process_Async_Pragma --
+            --------------------------
+
+            procedure Process_Async_Pragma is
+            begin
+               if not Present (L) then
+                  Set_Is_Asynchronous (Nm);
+                  return;
+               end if;
+
+               --  The formals should be of mode IN (RM E.4.1(6))
+
+               S := First (L);
+               while Present (S) loop
+                  Formal := Defining_Identifier (S);
+
+                  if Nkind (Formal) = N_Defining_Identifier
+                    and then Ekind (Formal) /= E_In_Parameter
+                  then
+                     Error_Pragma_Arg
+                       ("pragma% procedure can only have IN parameter",
+                        Arg1);
+                  end if;
+
+                  Next (S);
+               end loop;
+
+               Set_Is_Asynchronous (Nm);
+            end Process_Async_Pragma;
+
+         --  Start of processing for pragma Asynchronous
+
+         begin
+            Check_Ada_83_Warning;
+            Check_No_Identifiers;
+            Check_Arg_Count (1);
+            Check_Arg_Is_Local_Name (Arg1);
+
+            if Debug_Flag_U then
+               return;
+            end if;
+
+            C_Ent := Cunit_Entity (Current_Sem_Unit);
+            Analyze (Expression (Arg1));
+            Nm := Entity (Expression (Arg1));
+
+            if not Is_Remote_Call_Interface (C_Ent)
+              and then not Is_Remote_Types (C_Ent)
+            then
+               --  This pragma should only appear in an RCI or Remote Types
+               --  unit (RM E.4.1(4))
+
+               Error_Pragma
+                 ("pragma% not in Remote_Call_Interface or " &
+                  "Remote_Types unit");
+            end if;
+
+            if Ekind (Nm) = E_Procedure
+              and then Nkind (Parent (Nm)) = N_Procedure_Specification
+            then
+               if not Is_Remote_Call_Interface (Nm) then
+                  Error_Pragma_Arg
+                    ("pragma% cannot be applied on non-remote procedure",
+                     Arg1);
+               end if;
+
+               L := Parameter_Specifications (Parent (Nm));
+               Process_Async_Pragma;
+               return;
+
+            elsif Ekind (Nm) = E_Function then
+               Error_Pragma_Arg
+                 ("pragma% cannot be applied to function", Arg1);
+
+            elsif Ekind (Nm) = E_Record_Type
+              and then Present (Corresponding_Remote_Type (Nm))
+            then
+               N := Declaration_Node (Corresponding_Remote_Type (Nm));
+
+               if Nkind (N) = N_Full_Type_Declaration
+                 and then Nkind (Type_Definition (N)) =
+                                     N_Access_Procedure_Definition
+               then
+                  L := Parameter_Specifications (Type_Definition (N));
+                  Process_Async_Pragma;
+
+               else
+                  Error_Pragma_Arg
+                    ("pragma% cannot reference access-to-function type",
+                    Arg1);
+               end if;
+
+            --  Only other possibility is Access-to-class-wide type
+
+            elsif Is_Access_Type (Nm)
+              and then Is_Class_Wide_Type (Designated_Type (Nm))
+            then
+               Check_First_Subtype (Arg1);
+               Set_Is_Asynchronous (Nm);
+               if Expander_Active then
+                  RACW_Type_Is_Asynchronous (Nm);
+               end if;
+
+            else
+               Error_Pragma_Arg ("inappropriate argument for pragma%", Arg1);
+            end if;
+
+         end Asynchronous;
+
+         ------------
+         -- Atomic --
+         ------------
+
+         --  pragma Atomic (LOCAL_NAME);
+
+         when Pragma_Atomic =>
+            Process_Atomic_Shared_Volatile;
+
+         -----------------------
+         -- Atomic_Components --
+         -----------------------
+
+         --  pragma Atomic_Components (array_LOCAL_NAME);
+
+         --  This processing is shared by Volatile_Components
+
+         when Pragma_Atomic_Components   |
+              Pragma_Volatile_Components =>
+
+         Atomic_Components : declare
+            E_Id : Node_Id;
+            E    : Entity_Id;
+            D    : Node_Id;
+            K    : Node_Kind;
+
+         begin
+            GNAT_Pragma;
+            Check_Ada_83_Warning;
+            Check_No_Identifiers;
+            Check_Arg_Count (1);
+            Check_Arg_Is_Local_Name (Arg1);
+            E_Id := Expression (Arg1);
+
+            if Etype (E_Id) = Any_Type then
+               return;
+            end if;
+
+            E := Entity (E_Id);
+
+            if Rep_Item_Too_Early (E, N)
+                 or else
+               Rep_Item_Too_Late (E, N)
+            then
+               return;
+            end if;
+
+            D := Declaration_Node (E);
+            K := Nkind (D);
+
+            if (K = N_Full_Type_Declaration and then Is_Array_Type (E))
+              or else
+                ((Ekind (E) = E_Constant or else Ekind (E) = E_Variable)
+                   and then Nkind (D) = N_Object_Declaration
+                   and then Nkind (Object_Definition (D)) =
+                                       N_Constrained_Array_Definition)
+            then
+               --  The flag is set on the object, or on the base type
+
+               if Nkind (D) /= N_Object_Declaration then
+                  E := Base_Type (E);
+               end if;
+
+               Set_Has_Volatile_Components (E);
+
+               if Prag_Id = Pragma_Atomic_Components then
+                  Set_Has_Atomic_Components (E);
+
+                  if Is_Packed (E) then
+                     Set_Is_Packed (E, False);
+
+                     Error_Pragma_Arg
+                       ("?Pack canceled, cannot pack atomic components",
+                        Arg1);
+                  end if;
+               end if;
+
+            else
+               Error_Pragma_Arg ("inappropriate entity for pragma%", Arg1);
+            end if;
+         end Atomic_Components;
+
+         --------------------
+         -- Attach_Handler --
+         --------------------
+
+         --  pragma Attach_Handler (handler_NAME, EXPRESSION);
+
+         when Pragma_Attach_Handler =>
+            Check_Ada_83_Warning;
+            Check_No_Identifiers;
+            Check_Arg_Count (2);
+            Check_Interrupt_Or_Attach_Handler;
+            Analyze_And_Resolve (Expression (Arg2), RTE (RE_Interrupt_Id));
+            Process_Interrupt_Or_Attach_Handler;
+
+         --------------------
+         -- C_Pass_By_Copy --
+         --------------------
+
+         --  pragma C_Pass_By_Copy ([Max_Size =>] static_integer_EXPRESSION);
+
+         when Pragma_C_Pass_By_Copy => C_Pass_By_Copy : declare
+            Arg : Node_Id;
+            Val : Uint;
+
+         begin
+            GNAT_Pragma;
+            Check_Valid_Configuration_Pragma;
+            Check_Arg_Count (1);
+            Check_Optional_Identifier (Arg1, "max_size");
+
+            Arg := Expression (Arg1);
+            Check_Arg_Is_Static_Expression (Arg, Any_Integer);
+
+            Val := Expr_Value (Arg);
+
+            if Val <= 0 then
+               Error_Pragma_Arg
+                 ("maximum size for pragma% must be positive", Arg1);
+
+            elsif UI_Is_In_Int_Range (Val) then
+               Default_C_Record_Mechanism := UI_To_Int (Val);
+
+            --  If a giant value is given, Int'Last will do well enough.
+            --  If sometime someone complains that a record larger than
+            --  two gigabytes is not copied, we will worry about it then!
+
+            else
+               Default_C_Record_Mechanism := Mechanism_Type'Last;
+            end if;
+         end C_Pass_By_Copy;
+
+         -------------
+         -- Comment --
+         -------------
+
+         --  pragma Comment (static_string_EXPRESSION)
+
+         --  Processing for pragma Comment shares the circuitry for
+         --  pragma Ident. The only differences are that Ident enforces
+         --  a limit of 31 characters on its argument, and also enforces
+         --  limitations on placement for DEC compatibility. Pragma
+         --  Comment shares neither of these restrictions.
+
+         -------------------
+         -- Common_Object --
+         -------------------
+
+         --  pragma Common_Object (
+         --        [Internal =>] LOCAL_NAME,
+         --     [, [External =>] EXTERNAL_SYMBOL]
+         --     [, [Size     =>] EXTERNAL_SYMBOL]);
+
+         --  Processing for this pragma is shared with Psect_Object
+
+         ----------------------------
+         -- Complex_Representation --
+         ----------------------------
+
+         --  pragma Complex_Representation ([Entity =>] LOCAL_NAME);
+
+         when Pragma_Complex_Representation => Complex_Representation : declare
+            E_Id : Entity_Id;
+            E    : Entity_Id;
+            Ent  : Entity_Id;
+
+         begin
+            GNAT_Pragma;
+            Check_Arg_Count (1);
+            Check_Optional_Identifier (Arg1, Name_Entity);
+            Check_Arg_Is_Local_Name (Arg1);
+            E_Id := Expression (Arg1);
+
+            if Etype (E_Id) = Any_Type then
+               return;
+            end if;
+
+            E := Entity (E_Id);
+
+            if not Is_Record_Type (E) then
+               Error_Pragma_Arg
+                 ("argument for pragma% must be record type", Arg1);
+            end if;
+
+            Ent := First_Entity (E);
+
+            if No (Ent)
+              or else No (Next_Entity (Ent))
+              or else Present (Next_Entity (Next_Entity (Ent)))
+              or else not Is_Floating_Point_Type (Etype (Ent))
+              or else Etype (Ent) /= Etype (Next_Entity (Ent))
+            then
+               Error_Pragma_Arg
+                 ("record for pragma% must have two fields of same fpt type",
+                  Arg1);
+
+            else
+               Set_Has_Complex_Representation (Base_Type (E));
+            end if;
+         end Complex_Representation;
+
+         -------------------------
+         -- Component_Alignment --
+         -------------------------
+
+         --  pragma Component_Alignment (
+         --        [Form =>] ALIGNMENT_CHOICE
+         --     [, [Name =>] type_LOCAL_NAME]);
+         --
+         --   ALIGNMENT_CHOICE ::=
+         --     Component_Size
+         --   | Component_Size_4
+         --   | Storage_Unit
+         --   | Default
+
+         when Pragma_Component_Alignment => Component_AlignmentP : declare
+            Args  : Args_List (1 .. 2);
+            Names : Name_List (1 .. 2) := (
+                      Name_Form,
+                      Name_Name);
+
+            Form  : Node_Id renames Args (1);
+            Name  : Node_Id renames Args (2);
+
+            Atype : Component_Alignment_Kind;
+            Typ   : Entity_Id;
+
+         begin
+            GNAT_Pragma;
+            Gather_Associations (Names, Args);
+
+            if No (Form) then
+               Error_Pragma ("missing Form argument for pragma%");
+            end if;
+
+            Check_Arg_Is_Identifier (Form);
+
+            --  Get proper alignment, note that Default = Component_Size
+            --  on all machines we have so far, and we want to set this
+            --  value rather than the default value to indicate that it
+            --  has been explicitly set (and thus will not get overridden
+            --  by the default component alignment for the current scope)
+
+            if Chars (Form) = Name_Component_Size then
+               Atype := Calign_Component_Size;
+
+            elsif Chars (Form) = Name_Component_Size_4 then
+               Atype := Calign_Component_Size_4;
+
+            elsif Chars (Form) = Name_Default then
+               Atype := Calign_Component_Size;
+
+            elsif Chars (Form) = Name_Storage_Unit then
+               Atype := Calign_Storage_Unit;
+
+            else
+               Error_Pragma_Arg
+                 ("invalid Form parameter for pragma%", Form);
+            end if;
+
+            --  Case with no name, supplied, affects scope table entry
+
+            if No (Name) then
+               Scope_Stack.Table
+                 (Scope_Stack.Last).Component_Alignment_Default := Atype;
+
+            --  Case of name supplied
+
+            else
+               Check_Arg_Is_Local_Name (Name);
+               Find_Type (Name);
+               Typ := Entity (Name);
+
+               if Typ = Any_Type
+                 or else Rep_Item_Too_Early (Typ, N)
+               then
+                  return;
+               else
+                  Typ := Underlying_Type (Typ);
+               end if;
+
+               if not Is_Record_Type (Typ)
+                 and then not Is_Array_Type (Typ)
+               then
+                  Error_Pragma_Arg
+                    ("Name parameter of pragma% must identify record or " &
+                     "array type", Name);
+               end if;
+
+               --  An explicit Component_Alignment pragma overrides an
+               --  implicit pragma Pack, but not an explicit one.
+
+               if not Has_Pragma_Pack (Base_Type (Typ)) then
+                  Set_Is_Packed (Base_Type (Typ), False);
+                  Set_Component_Alignment (Base_Type (Typ), Atype);
+               end if;
+            end if;
+
+         end Component_AlignmentP;
+
+         ----------------
+         -- Controlled --
+         ----------------
+
+         --  pragma Controlled (first_subtype_LOCAL_NAME);
+
+         when Pragma_Controlled => Controlled : declare
+            Arg : Node_Id;
+
+         begin
+            Check_No_Identifiers;
+            Check_Arg_Count (1);
+            Check_Arg_Is_Local_Name (Arg1);
+            Arg := Expression (Arg1);
+
+            if not Is_Entity_Name (Arg)
+              or else not Is_Access_Type (Entity (Arg))
+            then
+               Error_Pragma_Arg ("pragma% requires access type", Arg1);
+            else
+               Set_Has_Pragma_Controlled (Base_Type (Entity (Arg)));
+            end if;
+         end Controlled;
+
+         ----------------
+         -- Convention --
+         ----------------
+
+         --  pragma Convention ([Convention =>] convention_IDENTIFIER,
+         --    [Entity =>] LOCAL_NAME);
+
+         when Pragma_Convention => Convention : declare
+            C : Convention_Id;
+            E : Entity_Id;
+
+         begin
+            Check_Ada_83_Warning;
+            Check_Arg_Count (2);
+            Process_Convention (C, E);
+         end Convention;
+
+         ---------------
+         -- CPP_Class --
+         ---------------
+
+         --  pragma CPP_Class ([Entity =>] local_NAME)
+
+         when Pragma_CPP_Class => CPP_Class : declare
+            Arg         : Node_Id;
+            Typ         : Entity_Id;
+            Default_DTC : Entity_Id := Empty;
+            VTP_Type    : constant Entity_Id  := RTE (RE_Vtable_Ptr);
+            C           : Entity_Id;
+            Tag_C       : Entity_Id;
+
+         begin
+            GNAT_Pragma;
+            Check_Arg_Count (1);
+            Check_Optional_Identifier (Arg1, Name_Entity);
+            Check_Arg_Is_Local_Name (Arg1);
+
+            Arg := Expression (Arg1);
+            Analyze (Arg);
+
+            if Etype (Arg) = Any_Type then
+               return;
+            end if;
+
+            if not Is_Entity_Name (Arg)
+              or else not Is_Type (Entity (Arg))
+            then
+               Error_Pragma_Arg ("pragma% requires a type mark", Arg1);
+            end if;
+
+            Typ := Entity (Arg);
+
+            if not Is_Record_Type (Typ) then
+               Error_Pragma_Arg ("pragma% applicable to a record, "
+                 & "tagged record or record extension", Arg1);
+            end if;
+
+            Default_DTC := First_Component (Typ);
+            while Present (Default_DTC)
+              and then Etype (Default_DTC) /= VTP_Type
+            loop
+               Next_Component (Default_DTC);
+            end loop;
+
+            --  Case of non tagged type
+
+            if not Is_Tagged_Type (Typ) then
+               Set_Is_CPP_Class (Typ);
+
+               if Present (Default_DTC) then
+                  Error_Pragma_Arg
+                    ("only tagged records can contain vtable pointers", Arg1);
+               end if;
+
+            --  Case of tagged type with no vtable ptr
+
+            --  What is test for Typ = Root_Typ (Typ) about here ???
+
+            elsif Is_Tagged_Type (Typ)
+              and then Typ = Root_Type (Typ)
+              and then No (Default_DTC)
+            then
+               Error_Pragma_Arg
+                 ("a cpp_class must contain a vtable pointer", Arg1);
+
+            --  Tagged type that has a vtable ptr
+
+            elsif Present (Default_DTC) then
+               Set_Is_CPP_Class (Typ);
+               Set_Is_Limited_Record (Typ);
+               Set_Is_Tag (Default_DTC);
+               Set_DT_Entry_Count (Default_DTC, No_Uint);
+
+               --  Since a CPP type has no direct link to its associated tag
+               --  most tags checks cannot be performed
+
+               Set_Suppress_Tag_Checks (Typ);
+               Set_Suppress_Tag_Checks (Class_Wide_Type (Typ));
+
+               --  Get rid of the _tag component when there was one.
+               --  It is only useful for regular tagged types
+
+               if Expander_Active and then Typ = Root_Type (Typ) then
+
+                  Tag_C := Tag_Component (Typ);
+                  C := First_Entity (Typ);
+
+                  if C = Tag_C then
+                     Set_First_Entity (Typ, Next_Entity (Tag_C));
+
+                  else
+                     while Next_Entity (C) /= Tag_C loop
+                        Next_Entity (C);
+                     end loop;
+
+                     Set_Next_Entity (C, Next_Entity (Tag_C));
+                  end if;
+               end if;
+            end if;
+         end CPP_Class;
+
+         ---------------------
+         -- CPP_Constructor --
+         ---------------------
+
+         --  pragma CPP_Constructor ([Entity =>] LOCAL_NAME);
+
+         when Pragma_CPP_Constructor => CPP_Constructor : declare
+            Id     : Entity_Id;
+            Def_Id : Entity_Id;
+
+         begin
+            GNAT_Pragma;
+            Check_Arg_Count (1);
+            Check_Optional_Identifier (Arg1, Name_Entity);
+            Check_Arg_Is_Local_Name (Arg1);
+
+            Id := Expression (Arg1);
+            Find_Program_Unit_Name (Id);
+
+            --  If we did not find the name, we are done
+
+            if Etype (Id) = Any_Type then
+               return;
+            end if;
+
+            Def_Id := Entity (Id);
+
+            if Ekind (Def_Id) = E_Function
+              and then Is_Class_Wide_Type (Etype (Def_Id))
+              and then Is_CPP_Class (Etype (Etype (Def_Id)))
+            then
+               --  What the heck is this??? this pragma allows only 1 arg
+
+               if Arg_Count >= 2 then
+                  Check_At_Most_N_Arguments (3);
+                  Process_Interface_Name (Def_Id, Arg2, Arg3);
+               end if;
+
+               if No (Parameter_Specifications (Parent (Def_Id))) then
+                  Set_Has_Completion (Def_Id);
+                  Set_Is_Constructor (Def_Id);
+               else
+                  Error_Pragma_Arg
+                    ("non-default constructors not implemented", Arg1);
+               end if;
+
+            else
+               Error_Pragma_Arg
+                 ("pragma% requires function returning a 'C'P'P_Class type",
+                   Arg1);
+            end if;
+         end CPP_Constructor;
+
+         -----------------
+         -- CPP_Virtual --
+         -----------------
+
+         --  pragma CPP_Virtual
+         --      [Entity =>]       LOCAL_NAME
+         --    [ [Vtable_Ptr =>]   LOCAL_NAME,
+         --      [Position =>]     static_integer_EXPRESSION]);
+
+         when Pragma_CPP_Virtual => CPP_Virtual : declare
+            Arg      : Node_Id;
+            Typ      : Entity_Id;
+            Subp     : Entity_Id;
+            VTP_Type : constant Entity_Id  := RTE (RE_Vtable_Ptr);
+            DTC      : Entity_Id;
+            V        : Uint;
+
+         begin
+            GNAT_Pragma;
+
+            if Arg_Count = 3 then
+               Check_Optional_Identifier (Arg2, "vtable_ptr");
+
+               --  We allow Entry_Count as well as Position for the third
+               --  parameter for back compatibility with versions of GNAT
+               --  before version 3.12. The documentation has always said
+               --  Position, but the code up to 3.12 said Entry_Count.
+
+               if Chars (Arg3) /= Name_Position then
+                  Check_Optional_Identifier (Arg3, "entry_count");
+               end if;
+
+            else
+               Check_Arg_Count (1);
+            end if;
+
+            Check_Optional_Identifier (Arg1, Name_Entity);
+            Check_Arg_Is_Local_Name (Arg1);
+
+            --  First argument must be a subprogram name
+
+            Arg := Expression (Arg1);
+            Find_Program_Unit_Name (Arg);
+
+            if Etype (Arg) = Any_Type then
+               return;
+            else
+               Subp := Entity (Arg);
+            end if;
+
+            if not (Is_Subprogram (Subp)
+                     and then Is_Dispatching_Operation (Subp))
+            then
+               Error_Pragma_Arg
+                 ("pragma% must reference a primitive operation", Arg1);
+            end if;
+
+            Typ := Find_Dispatching_Type (Subp);
+
+            --  If only one Argument defaults are :
+            --    . DTC_Entity is the default Vtable pointer
+            --    . DT_Position will be set at the freezing point
+
+            if Arg_Count = 1 then
+               Set_DTC_Entity (Subp, Tag_Component (Typ));
+               return;
+            end if;
+
+            --  Second argument is a component name of type Vtable_Ptr
+
+            Arg := Expression (Arg2);
+
+            if Nkind (Arg) /= N_Identifier then
+               Error_Msg_NE ("must be a& component name", Arg, Typ);
+               raise Pragma_Exit;
+            end if;
+
+            DTC := First_Component (Typ);
+            while Present (DTC) and then Chars (DTC) /= Chars (Arg) loop
+               Next_Component (DTC);
+            end loop;
+
+            if No (DTC) then
+               Error_Msg_NE ("must be a& component name", Arg, Typ);
+               raise Pragma_Exit;
+
+            elsif Etype (DTC) /= VTP_Type then
+               Wrong_Type (Arg, VTP_Type);
+               return;
+            end if;
+
+            --  Third argument is an integer (DT_Position)
+
+            Arg := Expression (Arg3);
+            Analyze_And_Resolve (Arg, Any_Integer);
+
+            if not Is_Static_Expression (Arg) then
+               Error_Pragma_Arg
+                 ("third argument of pragma% must be a static expression",
+                  Arg3);
+
+            else
+               V := Expr_Value (Expression (Arg3));
+
+               if V <= 0 then
+                  Error_Pragma_Arg
+                    ("third argument of pragma% must be positive",
+                     Arg3);
+
+               else
+                  Set_DTC_Entity (Subp, DTC);
+                  Set_DT_Position (Subp, V);
+               end if;
+            end if;
+         end CPP_Virtual;
+
+         ----------------
+         -- CPP_Vtable --
+         ----------------
+
+         --  pragma CPP_Vtable (
+         --    [Entity =>]       LOCAL_NAME
+         --    [Vtable_Ptr =>]   LOCAL_NAME,
+         --    [Entry_Count =>]  static_integer_EXPRESSION);
+
+         when Pragma_CPP_Vtable => CPP_Vtable : declare
+            Arg      : Node_Id;
+            Typ      : Entity_Id;
+            VTP_Type : constant Entity_Id  := RTE (RE_Vtable_Ptr);
+            DTC      : Entity_Id;
+            V        : Uint;
+            Elmt     : Elmt_Id;
+
+         begin
+            GNAT_Pragma;
+            Check_Arg_Count (3);
+            Check_Optional_Identifier (Arg1, Name_Entity);
+            Check_Optional_Identifier (Arg2, "vtable_ptr");
+            Check_Optional_Identifier (Arg3, "entry_count");
+            Check_Arg_Is_Local_Name (Arg1);
+
+            --  First argument is a record type name
+
+            Arg := Expression (Arg1);
+            Analyze (Arg);
+
+            if Etype (Arg) = Any_Type then
+               return;
+            else
+               Typ := Entity (Arg);
+            end if;
+
+            if not (Is_Tagged_Type (Typ) and then Is_CPP_Class (Typ)) then
+               Error_Pragma_Arg ("'C'P'P_Class tagged type expected", Arg1);
+            end if;
+
+            --  Second argument is a component name of type Vtable_Ptr
+
+            Arg := Expression (Arg2);
+
+            if Nkind (Arg) /= N_Identifier then
+               Error_Msg_NE ("must be a& component name", Arg, Typ);
+               raise Pragma_Exit;
+            end if;
+
+            DTC := First_Component (Typ);
+            while Present (DTC) and then Chars (DTC) /= Chars (Arg) loop
+               Next_Component (DTC);
+            end loop;
+
+            if No (DTC) then
+               Error_Msg_NE ("must be a& component name", Arg, Typ);
+               raise Pragma_Exit;
+
+            elsif Etype (DTC) /= VTP_Type then
+               Wrong_Type (DTC, VTP_Type);
+               return;
+
+            --  If it is the first pragma Vtable, This becomes the default tag
+
+            elsif (not Is_Tag (DTC))
+              and then DT_Entry_Count (Tag_Component (Typ)) = No_Uint
+            then
+               Set_Is_Tag (Tag_Component (Typ), False);
+               Set_Is_Tag (DTC, True);
+               Set_DT_Entry_Count (DTC, No_Uint);
+            end if;
+
+            --  Those pragmas must appear before any primitive operation
+            --  definition (except inherited ones) otherwise the default
+            --  may be wrong
+
+            Elmt := First_Elmt (Primitive_Operations (Typ));
+            while Present (Elmt) loop
+               if No (Alias (Node (Elmt))) then
+                  Error_Msg_Sloc := Sloc (Node (Elmt));
+                  Error_Pragma
+                    ("pragma% must appear before this primitive operation");
+               end if;
+
+               Next_Elmt (Elmt);
+            end loop;
+
+            --  Third argument is an integer (DT_Entry_Count)
+
+            Arg := Expression (Arg3);
+            Analyze_And_Resolve (Arg, Any_Integer);
+
+            if not Is_Static_Expression (Arg) then
+               Error_Pragma_Arg
+                 ("entry count for pragma% must be a static expression", Arg3);
+
+            else
+               V := Expr_Value (Expression (Arg3));
+
+               if V <= 0 then
+                  Error_Pragma_Arg
+                    ("entry count for pragma% must be positive", Arg3);
+               else
+                  Set_DT_Entry_Count (DTC, V);
+               end if;
+            end if;
+
+         end CPP_Vtable;
+
+         -----------
+         -- Debug --
+         -----------
+
+         --  pragma Debug (PROCEDURE_CALL_STATEMENT);
+
+         when Pragma_Debug => Debug : begin
+            GNAT_Pragma;
+
+            --  If assertions are enabled, and we are expanding code, then
+            --  we rewrite the pragma with its corresponding procedure call
+            --  and then analyze the call.
+
+            if Assertions_Enabled and Expander_Active then
+               Rewrite (N, Relocate_Node (Debug_Statement (N)));
+               Analyze (N);
+
+            --  Otherwise we work a bit to get a tree that makes sense
+            --  for ASIS purposes, namely a pragma with an analyzed
+            --  argument that looks like a procedure call.
+
+            else
+               Expander_Mode_Save_And_Set (False);
+               Rewrite (N, Relocate_Node (Debug_Statement (N)));
+               Analyze (N);
+               Rewrite (N,
+                 Make_Pragma (Loc,
+                   Chars => Name_Debug,
+                   Pragma_Argument_Associations =>
+                     New_List (Relocate_Node (N))));
+               Expander_Mode_Restore;
+            end if;
+         end Debug;
+
+         -------------------
+         -- Discard_Names --
+         -------------------
+
+         --  pragma Discard_Names [([On =>] LOCAL_NAME)];
+
+         when Pragma_Discard_Names => Discard_Names : declare
+            E_Id : Entity_Id;
+            E    : Entity_Id;
+
+         begin
+            GNAT_Pragma;
+            Check_Ada_83_Warning;
+
+            --  Deal with configuration pragma case
+
+            if Arg_Count = 0 and then Is_Configuration_Pragma then
+               Global_Discard_Names := True;
+               return;
+
+            --  Otherwise, check correct appropriate context
+
+            else
+               Check_Is_In_Decl_Part_Or_Package_Spec;
+
+               if Arg_Count = 0 then
+
+                  --  If there is no parameter, then from now on this pragma
+                  --  applies to any enumeration, exception or tagged type
+                  --  defined in the current declarative part.
+
+                  Set_Discard_Names (Current_Scope);
+                  return;
+
+               else
+                  Check_Arg_Count (1);
+                  Check_Optional_Identifier (Arg1, Name_On);
+                  Check_Arg_Is_Local_Name (Arg1);
+                  E_Id := Expression (Arg1);
+
+                  if Etype (E_Id) = Any_Type then
+                     return;
+                  else
+                     E := Entity (E_Id);
+                  end if;
+
+                  if (Is_First_Subtype (E)
+                       and then (Is_Enumeration_Type (E)
+                                  or else Is_Tagged_Type (E)))
+                    or else Ekind (E) = E_Exception
+                  then
+                     Set_Discard_Names (E);
+                  else
+                     Error_Pragma_Arg
+                       ("inappropriate entity for pragma%", Arg1);
+                  end if;
+               end if;
+            end if;
+         end Discard_Names;
+
+         ---------------
+         -- Elaborate --
+         ---------------
+
+         --  pragma Elaborate (library_unit_NAME {, library_unit_NAME});
+
+         when Pragma_Elaborate => Elaborate : declare
+            Plist       : List_Id;
+            Parent_Node : Node_Id;
+            Arg         : Node_Id;
+            Citem       : Node_Id;
+
+         begin
+            --  Pragma must be in context items list of a compilation unit
+
+            if not Is_List_Member (N) then
+               Pragma_Misplaced;
+               return;
+
+            else
+               Plist := List_Containing (N);
+               Parent_Node := Parent (Plist);
+
+               if Parent_Node = Empty
+                 or else Nkind (Parent_Node) /= N_Compilation_Unit
+                 or else Context_Items (Parent_Node) /= Plist
+               then
+                  Pragma_Misplaced;
+                  return;
+               end if;
+            end if;
+
+            --  Must be at least one argument
+
+            if Arg_Count = 0 then
+               Error_Pragma ("pragma% requires at least one argument");
+            end if;
+
+            --  In Ada 83 mode, there can be no items following it in the
+            --  context list except other pragmas and implicit with clauses
+            --  (e.g. those added by use of Rtsfind). In Ada 95 mode, this
+            --  placement rule does not apply.
+
+            if Ada_83 and then Comes_From_Source (N) then
+               Citem := Next (N);
+
+               while Present (Citem) loop
+                  if Nkind (Citem) = N_Pragma
+                    or else (Nkind (Citem) = N_With_Clause
+                              and then Implicit_With (Citem))
+                  then
+                     null;
+                  else
+                     Error_Pragma
+                       ("(Ada 83) pragma% must be at end of context clause");
+                  end if;
+
+                  Next (Citem);
+               end loop;
+            end if;
+
+            --  Finally, the arguments must all be units mentioned in a with
+            --  clause in the same context clause. Note we already checked
+            --  (in Par.Prag) that the arguments are either identifiers or
+
+            Arg := Arg1;
+            Outer : while Present (Arg) loop
+               Citem := First (Plist);
+
+               Inner : while Citem /= N loop
+                  if Nkind (Citem) = N_With_Clause
+                    and then Same_Name (Name (Citem), Expression (Arg))
+                  then
+                     Set_Elaborate_Present (Citem, True);
+                     Set_Unit_Name (Expression (Arg), Name (Citem));
+                     Set_Suppress_Elaboration_Warnings (Entity (Name (Citem)));
+                     exit Inner;
+                  end if;
+
+                  Next (Citem);
+               end loop Inner;
+
+               if Citem = N then
+                  Error_Pragma_Arg
+                    ("argument of pragma% is not with'ed unit", Arg);
+               end if;
+
+               Next (Arg);
+            end loop Outer;
+         end Elaborate;
+
+         -------------------
+         -- Elaborate_All --
+         -------------------
+
+         --  pragma Elaborate_All (library_unit_NAME {, library_unit_NAME});
+
+         when Pragma_Elaborate_All => Elaborate_All : declare
+            Plist       : List_Id;
+            Parent_Node : Node_Id;
+            Arg         : Node_Id;
+            Citem       : Node_Id;
+
+         begin
+            Check_Ada_83_Warning;
+
+            --  Pragma must be in context items list of a compilation unit
+
+            if not Is_List_Member (N) then
+               Pragma_Misplaced;
+               return;
+
+            else
+               Plist := List_Containing (N);
+               Parent_Node := Parent (Plist);
+
+               if Parent_Node = Empty
+                 or else Nkind (Parent_Node) /= N_Compilation_Unit
+                 or else Context_Items (Parent_Node) /= Plist
+               then
+                  Pragma_Misplaced;
+                  return;
+               end if;
+            end if;
+
+            --  Must be at least one argument
+
+            if Arg_Count = 0 then
+               Error_Pragma ("pragma% requires at least one argument");
+            end if;
+
+            --  Note: unlike pragma Elaborate, pragma Elaborate_All does not
+            --  have to appear at the end of the context clause, but may
+            --  appear mixed in with other items, even in Ada 83 mode.
+
+            --  Final check: the arguments must all be units mentioned in
+            --  a with clause in the same context clause. Note that we
+            --  already checked (in Par.Prag) that all the arguments are
+            --  either identifiers or selected components.
+
+            Arg := Arg1;
+            Outr : while Present (Arg) loop
+               Citem := First (Plist);
+
+               Innr : while Citem /= N loop
+                  if Nkind (Citem) = N_With_Clause
+                    and then Same_Name (Name (Citem), Expression (Arg))
+                  then
+                     Set_Elaborate_All_Present (Citem, True);
+                     Set_Unit_Name (Expression (Arg), Name (Citem));
+                     Set_Suppress_Elaboration_Warnings (Entity (Name (Citem)));
+                     exit Innr;
+                  end if;
+
+                  Next (Citem);
+               end loop Innr;
+
+               if Citem = N then
+                  Error_Pragma_Arg
+                    ("argument of pragma% is not with'ed unit", Arg);
+               end if;
+
+               Next (Arg);
+            end loop Outr;
+         end Elaborate_All;
+
+         --------------------
+         -- Elaborate_Body --
+         --------------------
+
+         --  pragma Elaborate_Body [( library_unit_NAME )];
+
+         when Pragma_Elaborate_Body => Elaborate_Body : declare
+            Cunit_Node : Node_Id;
+            Cunit_Ent  : Entity_Id;
+
+         begin
+            Check_Ada_83_Warning;
+            Check_Valid_Library_Unit_Pragma;
+
+            if Nkind (N) = N_Null_Statement then
+               return;
+            end if;
+
+            Cunit_Node := Cunit (Current_Sem_Unit);
+            Cunit_Ent  := Cunit_Entity (Current_Sem_Unit);
+
+            if Nkind (Unit (Cunit_Node)) = N_Package_Body
+                 or else
+               Nkind (Unit (Cunit_Node)) = N_Subprogram_Body
+            then
+               Error_Pragma ("pragma% must refer to a spec, not a body");
+            else
+               Set_Body_Required (Cunit_Node, True);
+               Set_Has_Pragma_Elaborate_Body     (Cunit_Ent);
+
+               --  If we are in dynamic elaboration mode, then we suppress
+               --  elaboration warnings for the unit, since it is definitely
+               --  fine NOT to do dynamic checks at the first level (and such
+               --  checks will be suppressed because no elaboration boolean
+               --  is created for Elaborate_Body packages).
+
+               --  But in the static model of elaboration, Elaborate_Body is
+               --  definitely NOT good enough to ensure elaboration safety on
+               --  its own, since the body may WITH other units that are not
+               --  safe from an elaboration point of view, so a client must
+               --  still do an Elaborate_All on such units.
+
+               --  Debug flag -gnatdD restores the old behavior of 3.13,
+               --  where Elaborate_Body always suppressed elab warnings.
+
+               if Dynamic_Elaboration_Checks or Debug_Flag_DD then
+                  Set_Suppress_Elaboration_Warnings (Cunit_Ent);
+               end if;
+            end if;
+         end Elaborate_Body;
+
+         ------------------------
+         -- Elaboration_Checks --
+         ------------------------
+
+         --  pragma Elaboration_Checks (Static | Dynamic);
+
+         when Pragma_Elaboration_Checks =>
+            GNAT_Pragma;
+            Check_Arg_Count (1);
+            Check_Arg_Is_One_Of (Arg1, Name_Static, Name_Dynamic);
+            Dynamic_Elaboration_Checks :=
+              (Chars (Get_Pragma_Arg (Arg1)) = Name_Dynamic);
+
+         ---------------
+         -- Eliminate --
+         ---------------
+
+         --  pragma Eliminate (
+         --      [Unit_Name       =>]  IDENTIFIER |
+         --                            SELECTED_COMPONENT
+         --    [,[Entity          =>]  IDENTIFIER |
+         --                            SELECTED_COMPONENT |
+         --                            STRING_LITERAL]
+         --    [,[Parameter_Types =>]  PARAMETER_TYPES]
+         --    [,[Result_Type     =>]  result_SUBTYPE_MARK]);
+
+         --  PARAMETER_TYPES ::=
+         --    null
+         --    (SUBTYPE_MARK, SUBTYPE_MARK, ...)
+
+         when Pragma_Eliminate => Eliminate : begin
+            GNAT_Pragma;
+            Check_Ada_83_Warning;
+            Check_Valid_Configuration_Pragma;
+            Check_At_Least_N_Arguments (1);
+            Check_At_Most_N_Arguments (4);
+
+            if Arg_Count = 3
+              and then Chars (Arg3) = Name_Result_Type
+            then
+               Arg4 := Arg3;
+               Arg3 := Empty;
+
+            else
+               Check_Optional_Identifier (Arg1, "unit_name");
+               Check_Optional_Identifier (Arg2, Name_Entity);
+               Check_Optional_Identifier (Arg3, Name_Parameter_Types);
+               Check_Optional_Identifier (Arg4, Name_Result_Type);
+            end if;
+
+            Process_Eliminate_Pragma (Arg1, Arg2, Arg3, Arg4);
+         end Eliminate;
+
+         ------------
+         -- Export --
+         ------------
+
+         --  pragma Export (
+         --    [   Convention    =>] convention_IDENTIFIER,
+         --    [   Entity        =>] local_NAME
+         --    [, [External_Name =>] static_string_EXPRESSION ]
+         --    [, [Link_Name     =>] static_string_EXPRESSION ]);
+
+         when Pragma_Export => Export : declare
+            C      : Convention_Id;
+            Def_Id : Entity_Id;
+
+         begin
+            Check_Ada_83_Warning;
+            Check_At_Least_N_Arguments (2);
+            Check_At_Most_N_Arguments  (4);
+            Process_Convention (C, Def_Id);
+            Note_Possible_Modification (Expression (Arg2));
+            Process_Interface_Name (Def_Id, Arg3, Arg4);
+            Set_Exported (Def_Id, Arg2);
+         end Export;
+
+         ----------------------
+         -- Export_Exception --
+         ----------------------
+
+         --  pragma Export_Exception (
+         --        [Internal         =>] LOCAL_NAME,
+         --     [, [External         =>] EXTERNAL_SYMBOL,]
+         --     [, [Form     =>] Ada | VMS]
+         --     [, [Code     =>] static_integer_EXPRESSION]);
+
+         when Pragma_Export_Exception => Export_Exception : declare
+            Args  : Args_List (1 .. 4);
+            Names : Name_List (1 .. 4) := (
+                      Name_Internal,
+                      Name_External,
+                      Name_Form,
+                      Name_Code);
+
+            Internal : Node_Id renames Args (1);
+            External : Node_Id renames Args (2);
+            Form     : Node_Id renames Args (3);
+            Code     : Node_Id renames Args (4);
+
+         begin
+            GNAT_Pragma;
+
+            if Inside_A_Generic then
+               Error_Pragma ("pragma% cannot be used for generic entities");
+            end if;
+
+            Gather_Associations (Names, Args);
+            Process_Extended_Import_Export_Exception_Pragma (
+              Arg_Internal => Internal,
+              Arg_External => External,
+              Arg_Form     => Form,
+              Arg_Code     => Code);
+
+            if not Is_VMS_Exception (Entity (Internal)) then
+               Set_Exported (Entity (Internal), Internal);
+            end if;
+
+         end Export_Exception;
+
+         ---------------------
+         -- Export_Function --
+         ---------------------
+
+         --  pragma Export_Function (
+         --        [Internal         =>] LOCAL_NAME,
+         --     [, [External         =>] EXTERNAL_SYMBOL,]
+         --     [, [Parameter_Types  =>] (PARAMETER_TYPES)]
+         --     [, [Result_Type      =>] SUBTYPE_MARK]
+         --     [, [Mechanism        =>] MECHANISM]
+         --     [, [Result_Mechanism =>] MECHANISM_NAME]);
+
+         when Pragma_Export_Function => Export_Function : declare
+            Args  : Args_List (1 .. 6);
+            Names : Name_List (1 .. 6) := (
+                      Name_Internal,
+                      Name_External,
+                      Name_Parameter_Types,
+                      Name_Result_Type,
+                      Name_Mechanism,
+                      Name_Result_Mechanism);
+
+            Internal         : Node_Id renames Args (1);
+            External         : Node_Id renames Args (2);
+            Parameter_Types  : Node_Id renames Args (3);
+            Result_Type      : Node_Id renames Args (4);
+            Mechanism        : Node_Id renames Args (5);
+            Result_Mechanism : Node_Id renames Args (6);
+
+         begin
+            GNAT_Pragma;
+            Gather_Associations (Names, Args);
+            Process_Extended_Import_Export_Subprogram_Pragma (
+              Arg_Internal         => Internal,
+              Arg_External         => External,
+              Arg_Parameter_Types  => Parameter_Types,
+              Arg_Result_Type      => Result_Type,
+              Arg_Mechanism        => Mechanism,
+              Arg_Result_Mechanism => Result_Mechanism);
+         end Export_Function;
+
+         -------------------
+         -- Export_Object --
+         -------------------
+
+         --  pragma Export_Object (
+         --        [Internal =>] LOCAL_NAME,
+         --     [, [External =>] EXTERNAL_SYMBOL]
+         --     [, [Size     =>] EXTERNAL_SYMBOL]);
+
+         when Pragma_Export_Object => Export_Object : declare
+            Args  : Args_List (1 .. 3);
+            Names : Name_List (1 .. 3) := (
+                      Name_Internal,
+                      Name_External,
+                      Name_Size);
+
+            Internal : Node_Id renames Args (1);
+            External : Node_Id renames Args (2);
+            Size     : Node_Id renames Args (3);
+
+         begin
+            GNAT_Pragma;
+            Gather_Associations (Names, Args);
+            Process_Extended_Import_Export_Object_Pragma (
+              Arg_Internal => Internal,
+              Arg_External => External,
+              Arg_Size     => Size);
+         end Export_Object;
+
+         ----------------------
+         -- Export_Procedure --
+         ----------------------
+
+         --  pragma Export_Procedure (
+         --        [Internal         =>] LOCAL_NAME,
+         --     [, [External         =>] EXTERNAL_SYMBOL,]
+         --     [, [Parameter_Types  =>] (PARAMETER_TYPES)]
+         --     [, [Mechanism        =>] MECHANISM]);
+
+         when Pragma_Export_Procedure => Export_Procedure : declare
+            Args  : Args_List (1 .. 4);
+            Names : Name_List (1 .. 4) := (
+                      Name_Internal,
+                      Name_External,
+                      Name_Parameter_Types,
+                      Name_Mechanism);
+
+            Internal        : Node_Id renames Args (1);
+            External        : Node_Id renames Args (2);
+            Parameter_Types : Node_Id renames Args (3);
+            Mechanism       : Node_Id renames Args (4);
+
+         begin
+            GNAT_Pragma;
+            Gather_Associations (Names, Args);
+            Process_Extended_Import_Export_Subprogram_Pragma (
+              Arg_Internal        => Internal,
+              Arg_External        => External,
+              Arg_Parameter_Types => Parameter_Types,
+              Arg_Mechanism       => Mechanism);
+         end Export_Procedure;
+
+         -----------------------------
+         -- Export_Valued_Procedure --
+         -----------------------------
+
+         --  pragma Export_Valued_Procedure (
+         --        [Internal         =>] LOCAL_NAME,
+         --     [, [External         =>] EXTERNAL_SYMBOL,]
+         --     [, [Parameter_Types  =>] (PARAMETER_TYPES)]
+         --     [, [Mechanism        =>] MECHANISM]);
+
+         when Pragma_Export_Valued_Procedure =>
+         Export_Valued_Procedure : declare
+            Args  : Args_List (1 .. 4);
+            Names : Name_List (1 .. 4) := (
+                      Name_Internal,
+                      Name_External,
+                      Name_Parameter_Types,
+                      Name_Mechanism);
+
+            Internal        : Node_Id renames Args (1);
+            External        : Node_Id renames Args (2);
+            Parameter_Types : Node_Id renames Args (3);
+            Mechanism       : Node_Id renames Args (4);
+
+         begin
+            GNAT_Pragma;
+            Gather_Associations (Names, Args);
+            Process_Extended_Import_Export_Subprogram_Pragma (
+              Arg_Internal        => Internal,
+              Arg_External        => External,
+              Arg_Parameter_Types => Parameter_Types,
+              Arg_Mechanism       => Mechanism);
+         end Export_Valued_Procedure;
+
+         -------------------
+         -- Extend_System --
+         -------------------
+
+         --  pragma Extend_System ([Name =>] Identifier);
+
+         when Pragma_Extend_System => Extend_System : declare
+         begin
+            GNAT_Pragma;
+            Check_Valid_Configuration_Pragma;
+            Check_Arg_Count (1);
+            Check_Optional_Identifier (Arg1, Name_Name);
+            Check_Arg_Is_Identifier (Arg1);
+
+            Get_Name_String (Chars (Expression (Arg1)));
+
+            if Name_Len > 4
+              and then Name_Buffer (1 .. 4) = "aux_"
+            then
+               if Present (System_Extend_Pragma_Arg) then
+                  if Chars (Expression (Arg1)) =
+                     Chars (Expression (System_Extend_Pragma_Arg))
+                  then
+                     null;
+                  else
+                     Error_Msg_Sloc := Sloc (System_Extend_Pragma_Arg);
+                     Error_Pragma ("pragma% conflicts with that at#");
+                  end if;
+
+               else
+                  System_Extend_Pragma_Arg := Arg1;
+               end if;
+            else
+               Error_Pragma ("incorrect name for pragma%, must be Aux_xxx");
+            end if;
+         end Extend_System;
+
+         ------------------------
+         -- Extensions_Allowed --
+         ------------------------
+
+         --  pragma Extensions_Allowed (ON | OFF);
+
+         when Pragma_Extensions_Allowed =>
+            GNAT_Pragma;
+            Check_Arg_Count (1);
+            Check_No_Identifiers;
+            Check_Arg_Is_One_Of (Arg1, Name_On, Name_Off);
+            Extensions_Allowed := (Chars (Expression (Arg1)) = Name_On);
+
+         --------------------------
+         -- External_Name_Casing --
+         --------------------------
+
+         --  pragma External_Name_Casing (
+         --    UPPERCASE | LOWERCASE
+         --    [, AS_IS | UPPERCASE | LOWERCASE]);
+
+         when Pragma_External_Name_Casing =>
+
+         External_Name_Casing : declare
+         begin
+            GNAT_Pragma;
+            Check_No_Identifiers;
+
+            if Arg_Count = 2 then
+               Check_Arg_Is_One_Of
+                 (Arg2, Name_As_Is, Name_Uppercase, Name_Lowercase);
+
+               case Chars (Get_Pragma_Arg (Arg2)) is
+                  when Name_As_Is     =>
+                     Opt.External_Name_Exp_Casing := As_Is;
+
+                  when Name_Uppercase =>
+                     Opt.External_Name_Exp_Casing := Uppercase;
+
+                  when Name_Lowercase =>
+                     Opt.External_Name_Exp_Casing := Lowercase;
+
+                  when others =>
+                     null;
+               end case;
+
+            else
+               Check_Arg_Count (1);
+            end if;
+
+            Check_Arg_Is_One_Of (Arg1, Name_Uppercase, Name_Lowercase);
+
+            case Chars (Get_Pragma_Arg (Arg1)) is
+               when Name_Uppercase =>
+                  Opt.External_Name_Imp_Casing := Uppercase;
+
+               when Name_Lowercase =>
+                  Opt.External_Name_Imp_Casing := Lowercase;
+
+               when others =>
+                  null;
+            end case;
+
+         end External_Name_Casing;
+
+         ---------------------------
+         -- Finalize_Storage_Only --
+         ---------------------------
+
+         --  pragma Finalize_Storage_Only (first_subtype_LOCAL_NAME);
+
+         when Pragma_Finalize_Storage_Only => Finalize_Storage : declare
+            Assoc   : Node_Id := Arg1;
+            Type_Id : Node_Id := Expression (Assoc);
+            Typ     : Entity_Id;
+
+         begin
+            Check_No_Identifiers;
+            Check_Arg_Count (1);
+            Check_Arg_Is_Local_Name (Arg1);
+
+            Find_Type (Type_Id);
+            Typ := Entity (Type_Id);
+
+            if Typ = Any_Type
+              or else Rep_Item_Too_Early (Typ, N)
+            then
+               return;
+            else
+               Typ := Underlying_Type (Typ);
+            end if;
+
+            if not Is_Controlled (Typ) then
+               Error_Pragma ("pragma% must specify controlled type");
+            end if;
+
+            Check_First_Subtype (Arg1);
+
+            if Finalize_Storage_Only (Typ) then
+               Error_Pragma ("duplicate pragma%, only one allowed");
+
+            elsif not Rep_Item_Too_Late (Typ, N) then
+               Set_Finalize_Storage_Only (Typ, True);
+            end if;
+         end Finalize_Storage;
+
+         --------------------------
+         -- Float_Representation --
+         --------------------------
+
+         --  pragma Float_Representation (VAX_Float | IEEE_Float);
+
+         when Pragma_Float_Representation => Float_Representation : declare
+            Argx : Node_Id;
+            Digs : Nat;
+            Ent  : Entity_Id;
+
+         begin
+            GNAT_Pragma;
+
+            if Arg_Count = 1 then
+               Check_Valid_Configuration_Pragma;
+            else
+               Check_Arg_Count (2);
+               Check_Optional_Identifier (Arg2, Name_Entity);
+               Check_Arg_Is_Local_Name (Arg2);
+            end if;
+
+            Check_No_Identifier (Arg1);
+            Check_Arg_Is_One_Of (Arg1, Name_VAX_Float, Name_IEEE_Float);
+
+            if not OpenVMS_On_Target then
+               if Chars (Expression (Arg1)) = Name_VAX_Float then
+                  Error_Pragma
+                    ("?pragma% ignored (applies only to Open'V'M'S)");
+               end if;
+
+               return;
+            end if;
+
+            --  One argument case
+
+            if Arg_Count = 1 then
+
+               if Chars (Expression (Arg1)) = Name_VAX_Float then
+
+                  if Opt.Float_Format = 'I' then
+                     Error_Pragma ("'I'E'E'E format previously specified");
+                  end if;
+
+                  Opt.Float_Format := 'V';
+
+               else
+                  if Opt.Float_Format = 'V' then
+                     Error_Pragma ("'V'A'X format previously specified");
+                  end if;
+
+                  Opt.Float_Format := 'I';
+               end if;
+
+               Set_Standard_Fpt_Formats;
+
+            --  Two argument case
+
+            else
+               Argx := Get_Pragma_Arg (Arg2);
+
+               if not Is_Entity_Name (Argx)
+                 or else not Is_Floating_Point_Type (Entity (Argx))
+               then
+                  Error_Pragma_Arg
+                    ("second argument of% pragma must be floating-point type",
+                     Arg2);
+               end if;
+
+               Ent  := Entity (Argx);
+               Digs := UI_To_Int (Digits_Value (Ent));
+
+               --  Two arguments, VAX_Float case
+
+               if Chars (Expression (Arg1)) = Name_VAX_Float then
+
+                  case Digs is
+                     when  6 => Set_F_Float (Ent);
+                     when  9 => Set_D_Float (Ent);
+                     when 15 => Set_G_Float (Ent);
+
+                     when others =>
+                        Error_Pragma_Arg
+                          ("wrong digits value, must be 6,9 or 15", Arg2);
+                  end case;
+
+               --  Two arguments, IEEE_Float case
+
+               else
+                  case Digs is
+                     when  6 => Set_IEEE_Short (Ent);
+                     when 15 => Set_IEEE_Long  (Ent);
+
+                     when others =>
+                        Error_Pragma_Arg
+                          ("wrong digits value, must be 6 or 15", Arg2);
+                  end case;
+               end if;
+            end if;
+
+         end Float_Representation;
+
+         -----------
+         -- Ident --
+         -----------
+
+         --  pragma Ident (static_string_EXPRESSION)
+
+         --  Note: pragma Comment shares this processing. Pragma Comment
+         --  is identical to Ident, except that the restriction of the
+         --  argument to 31 characters and the placement restrictions
+         --  are not enforced for pragma Comment.
+
+         when Pragma_Ident | Pragma_Comment => Ident : declare
+            Str : Node_Id;
+
+         begin
+            GNAT_Pragma;
+            Check_Arg_Count (1);
+            Check_No_Identifiers;
+            Check_Arg_Is_Static_Expression (Arg1, Standard_String);
+
+            --  For pragma Ident, preserve DEC compatibility by requiring
+            --  the pragma to appear in a declarative part or package spec.
+
+            if Prag_Id = Pragma_Ident then
+               Check_Is_In_Decl_Part_Or_Package_Spec;
+            end if;
+
+            Str := Expr_Value_S (Expression (Arg1));
+
+            --  For pragma Ident, preserve DEC compatibility by limiting
+            --  the length to 31 characters.
+
+            if Prag_Id = Pragma_Ident
+              and then String_Length (Strval (Str)) > 31
+            then
+               Error_Pragma_Arg
+                 ("argument for pragma% is too long, maximum is 31", Arg1);
+            end if;
+
+            declare
+               CS : Node_Id;
+               GP : Node_Id;
+
+            begin
+               GP := Parent (Parent (N));
+
+               if Nkind (GP) = N_Package_Declaration
+                    or else
+                  Nkind (GP) = N_Generic_Package_Declaration
+               then
+                  GP := Parent (GP);
+               end if;
+
+               --  If we have a compilation unit, then record the ident
+               --  value, checking for improper duplication.
+
+               if Nkind (GP) = N_Compilation_Unit then
+                  CS := Ident_String (Current_Sem_Unit);
+
+                  if Present (CS) then
+
+                     --  For Ident, we do not permit multiple instances
+
+                     if Prag_Id = Pragma_Ident then
+                        Error_Pragma ("duplicate% pragma not permitted");
+
+                     --  For Comment, we concatenate the string, unless we
+                     --  want to preserve the tree structure for ASIS.
+
+                     elsif not Tree_Output then
+                        Start_String (Strval (CS));
+                        Store_String_Char (' ');
+                        Store_String_Chars (Strval (Str));
+                        Set_Strval (CS, End_String);
+                     end if;
+
+                  else
+                     --  In VMS, the effect of IDENT is achieved by passing
+                     --  IDENTIFICATION=name as a --for-linker switch.
+
+                     if OpenVMS_On_Target then
+                        Start_String;
+                        Store_String_Chars
+                          ("--for-linker=IDENTIFICATION=");
+                        String_To_Name_Buffer (Strval (Str));
+                        Store_String_Chars (Name_Buffer (1 .. Name_Len));
+
+                        --  Only the last processed IDENT is saved. The main
+                        --  purpose is so an IDENT associated with a main
+                        --  procedure will be used in preference to an IDENT
+                        --  associated with a with'd package.
+
+                        Replace_Linker_Option_String
+                          (End_String, "--for-linker=IDENTIFICATION=");
+                     end if;
+
+                     Set_Ident_String (Current_Sem_Unit, Str);
+                  end if;
+
+               --  For subunits, we just ignore the Ident, since in GNAT
+               --  these are not separate object files, and hence not
+               --  separate units in the unit table.
+
+               elsif Nkind (GP) = N_Subunit then
+                  null;
+
+               --  Otherwise we have a misplaced pragma Ident, but we ignore
+               --  this if we are in an instantiation, since it comes from
+               --  a generic, and has no relevance to the instantiation.
+
+               elsif Prag_Id = Pragma_Ident then
+                  if Instantiation_Location (Loc) = No_Location then
+                     Error_Pragma ("pragma% only allowed at outer level");
+                  end if;
+               end if;
+            end;
+         end Ident;
+
+         ------------
+         -- Import --
+         ------------
+
+         --  pragma Import (
+         --    [   Convention    =>] convention_IDENTIFIER,
+         --    [   Entity        =>] local_NAME
+         --    [, [External_Name =>] static_string_EXPRESSION ]
+         --    [, [Link_Name     =>] static_string_EXPRESSION ]);
+
+         when Pragma_Import =>
+            Check_Ada_83_Warning;
+            Check_At_Least_N_Arguments (2);
+            Check_At_Most_N_Arguments  (4);
+            Process_Import_Or_Interface;
+
+         ----------------------
+         -- Import_Exception --
+         ----------------------
+
+         --  pragma Import_Exception (
+         --        [Internal         =>] LOCAL_NAME,
+         --     [, [External         =>] EXTERNAL_SYMBOL,]
+         --     [, [Form     =>] Ada | VMS]
+         --     [, [Code     =>] static_integer_EXPRESSION]);
+
+         when Pragma_Import_Exception => Import_Exception : declare
+            Args  : Args_List (1 .. 4);
+            Names : Name_List (1 .. 4) := (
+                      Name_Internal,
+                      Name_External,
+                      Name_Form,
+                      Name_Code);
+
+            Internal : Node_Id renames Args (1);
+            External : Node_Id renames Args (2);
+            Form     : Node_Id renames Args (3);
+            Code     : Node_Id renames Args (4);
+
+         begin
+            GNAT_Pragma;
+            Gather_Associations (Names, Args);
+
+            if Present (External) and then Present (Code) then
+               Error_Pragma
+                 ("cannot give both External and Code options for pragma%");
+            end if;
+
+            Process_Extended_Import_Export_Exception_Pragma (
+              Arg_Internal => Internal,
+              Arg_External => External,
+              Arg_Form     => Form,
+              Arg_Code     => Code);
+
+            if not Is_VMS_Exception (Entity (Internal)) then
+               Set_Imported (Entity (Internal));
+            end if;
+
+         end Import_Exception;
+
+         ---------------------
+         -- Import_Function --
+         ---------------------
+
+         --  pragma Import_Function (
+         --        [Internal                 =>] LOCAL_NAME,
+         --     [, [External                 =>] EXTERNAL_SYMBOL]
+         --     [, [Parameter_Types          =>] (PARAMETER_TYPES)]
+         --     [, [Result_Type              =>] SUBTYPE_MARK]
+         --     [, [Mechanism                =>] MECHANISM]
+         --     [, [Result_Mechanism         =>] MECHANISM_NAME]
+         --     [, [First_Optional_Parameter =>] IDENTIFIER]);
+
+         when Pragma_Import_Function => Import_Function : declare
+            Args  : Args_List (1 .. 7);
+            Names : Name_List (1 .. 7) := (
+                      Name_Internal,
+                      Name_External,
+                      Name_Parameter_Types,
+                      Name_Result_Type,
+                      Name_Mechanism,
+                      Name_Result_Mechanism,
+                      Name_First_Optional_Parameter);
+
+            Internal                 : Node_Id renames Args (1);
+            External                 : Node_Id renames Args (2);
+            Parameter_Types          : Node_Id renames Args (3);
+            Result_Type              : Node_Id renames Args (4);
+            Mechanism                : Node_Id renames Args (5);
+            Result_Mechanism         : Node_Id renames Args (6);
+            First_Optional_Parameter : Node_Id renames Args (7);
+
+         begin
+            GNAT_Pragma;
+            Gather_Associations (Names, Args);
+            Process_Extended_Import_Export_Subprogram_Pragma (
+              Arg_Internal                 => Internal,
+              Arg_External                 => External,
+              Arg_Parameter_Types          => Parameter_Types,
+              Arg_Result_Type              => Result_Type,
+              Arg_Mechanism                => Mechanism,
+              Arg_Result_Mechanism         => Result_Mechanism,
+              Arg_First_Optional_Parameter => First_Optional_Parameter);
+         end Import_Function;
+
+         -------------------
+         -- Import_Object --
+         -------------------
+
+         --  pragma Import_Object (
+         --        [Internal =>] LOCAL_NAME,
+         --     [, [External =>] EXTERNAL_SYMBOL]
+         --     [, [Size     =>] EXTERNAL_SYMBOL]);
+
+         when Pragma_Import_Object => Import_Object : declare
+            Args  : Args_List (1 .. 3);
+            Names : Name_List (1 .. 3) := (
+                      Name_Internal,
+                      Name_External,
+                      Name_Size);
+
+            Internal : Node_Id renames Args (1);
+            External : Node_Id renames Args (2);
+            Size     : Node_Id renames Args (3);
+
+         begin
+            GNAT_Pragma;
+            Gather_Associations (Names, Args);
+            Process_Extended_Import_Export_Object_Pragma (
+              Arg_Internal => Internal,
+              Arg_External => External,
+              Arg_Size     => Size);
+         end Import_Object;
+
+         ----------------------
+         -- Import_Procedure --
+         ----------------------
+
+         --  pragma Import_Procedure (
+         --        [Internal                 =>] LOCAL_NAME,
+         --     [, [External                 =>] EXTERNAL_SYMBOL]
+         --     [, [Parameter_Types          =>] (PARAMETER_TYPES)]
+         --     [, [Mechanism                =>] MECHANISM]
+         --     [, [First_Optional_Parameter =>] IDENTIFIER]);
+
+         when Pragma_Import_Procedure => Import_Procedure : declare
+            Args  : Args_List (1 .. 5);
+            Names : Name_List (1 .. 5) := (
+                      Name_Internal,
+                      Name_External,
+                      Name_Parameter_Types,
+                      Name_Mechanism,
+                      Name_First_Optional_Parameter);
+
+            Internal                 : Node_Id renames Args (1);
+            External                 : Node_Id renames Args (2);
+            Parameter_Types          : Node_Id renames Args (3);
+            Mechanism                : Node_Id renames Args (4);
+            First_Optional_Parameter : Node_Id renames Args (5);
+
+         begin
+            GNAT_Pragma;
+            Gather_Associations (Names, Args);
+            Process_Extended_Import_Export_Subprogram_Pragma (
+              Arg_Internal                 => Internal,
+              Arg_External                 => External,
+              Arg_Parameter_Types          => Parameter_Types,
+              Arg_Mechanism                => Mechanism,
+              Arg_First_Optional_Parameter => First_Optional_Parameter);
+         end Import_Procedure;
+
+         -----------------------------
+         -- Import_Valued_Procedure --
+         -----------------------------
+
+         --  pragma Import_Valued_Procedure (
+         --        [Internal                 =>] LOCAL_NAME,
+         --     [, [External                 =>] EXTERNAL_SYMBOL]
+         --     [, [Parameter_Types          =>] (PARAMETER_TYPES)]
+         --     [, [Mechanism                =>] MECHANISM]
+         --     [, [First_Optional_Parameter =>] IDENTIFIER]);
+
+         when Pragma_Import_Valued_Procedure =>
+         Import_Valued_Procedure : declare
+            Args  : Args_List (1 .. 5);
+            Names : Name_List (1 .. 5) := (
+                      Name_Internal,
+                      Name_External,
+                      Name_Parameter_Types,
+                      Name_Mechanism,
+                      Name_First_Optional_Parameter);
+
+            Internal                 : Node_Id renames Args (1);
+            External                 : Node_Id renames Args (2);
+            Parameter_Types          : Node_Id renames Args (3);
+            Mechanism                : Node_Id renames Args (4);
+            First_Optional_Parameter : Node_Id renames Args (5);
+
+         begin
+            GNAT_Pragma;
+            Gather_Associations (Names, Args);
+            Process_Extended_Import_Export_Subprogram_Pragma (
+              Arg_Internal                 => Internal,
+              Arg_External                 => External,
+              Arg_Parameter_Types          => Parameter_Types,
+              Arg_Mechanism                => Mechanism,
+              Arg_First_Optional_Parameter => First_Optional_Parameter);
+         end Import_Valued_Procedure;
+
+         ------------------------
+         -- Initialize_Scalars --
+         ------------------------
+
+         --  pragma Initialize_Scalars;
+
+         when Pragma_Initialize_Scalars =>
+            GNAT_Pragma;
+            Check_Arg_Count (0);
+            Check_Valid_Configuration_Pragma;
+            Init_Or_Norm_Scalars := True;
+            Initialize_Scalars := True;
+
+         ------------
+         -- Inline --
+         ------------
+
+         --  pragma Inline ( NAME {, NAME} );
+
+         when Pragma_Inline =>
+
+            --  Pragma is active if inlining option is active
+
+            if Inline_Active then
+               Process_Inline (True);
+
+            --  Pragma is active in a predefined file in no run time mode
+
+            elsif No_Run_Time
+              and then
+                Is_Predefined_File_Name (Unit_File_Name (Current_Sem_Unit))
+            then
+               Process_Inline (True);
+
+            else
+               Process_Inline (False);
+            end if;
+
+         -------------------
+         -- Inline_Always --
+         -------------------
+
+         --  pragma Inline_Always ( NAME {, NAME} );
+
+         when Pragma_Inline_Always =>
+            Process_Inline (True);
+
+         --------------------
+         -- Inline_Generic --
+         --------------------
+
+         --  pragma Inline_Generic (NAME {, NAME});
+
+         when Pragma_Inline_Generic =>
+            Process_Generic_List;
+
+         ----------------------
+         -- Inspection_Point --
+         ----------------------
+
+         --  pragma Inspection_Point [(object_NAME {, object_NAME})];
+
+         when Pragma_Inspection_Point => Inspection_Point : declare
+            Arg : Node_Id;
+            Exp : Node_Id;
+
+         begin
+            if Arg_Count > 0 then
+               Arg := Arg1;
+               loop
+                  Exp := Expression (Arg);
+                  Analyze (Exp);
+
+                  if not Is_Entity_Name (Exp)
+                    or else not Is_Object (Entity (Exp))
+                  then
+                     Error_Pragma_Arg ("object name required", Arg);
+                  end if;
+
+                  Next (Arg);
+                  exit when No (Arg);
+               end loop;
+            end if;
+         end Inspection_Point;
+
+         ---------------
+         -- Interface --
+         ---------------
+
+         --  pragma Interface (
+         --    convention_IDENTIFIER,
+         --    local_NAME );
+
+         when Pragma_Interface =>
+            GNAT_Pragma;
+            Check_Arg_Count (2);
+            Check_No_Identifiers;
+            Process_Import_Or_Interface;
+
+         --------------------
+         -- Interface_Name --
+         --------------------
+
+         --  pragma Interface_Name (
+         --    [  Entity        =>] local_NAME
+         --    [,[External_Name =>] static_string_EXPRESSION ]
+         --    [,[Link_Name     =>] static_string_EXPRESSION ]);
+
+         when Pragma_Interface_Name => Interface_Name : declare
+            Id     : Node_Id;
+            Def_Id : Entity_Id;
+            Hom_Id : Entity_Id;
+            Found  : Boolean;
+
+         begin
+            GNAT_Pragma;
+            Check_At_Least_N_Arguments (2);
+            Check_At_Most_N_Arguments  (3);
+            Id := Expression (Arg1);
+            Analyze (Id);
+
+            if not Is_Entity_Name (Id) then
+               Error_Pragma_Arg
+                 ("first argument for pragma% must be entity name", Arg1);
+            elsif Etype (Id) = Any_Type then
+               return;
+            else
+               Def_Id := Entity (Id);
+            end if;
+
+            --  Special DEC-compatible processing for the object case,
+            --  forces object to be imported.
+
+            if Ekind (Def_Id) = E_Variable then
+               Kill_Size_Check_Code (Def_Id);
+               Note_Possible_Modification (Id);
+
+               --  Initialization is not allowed for imported variable
+
+               if Present (Expression (Parent (Def_Id)))
+                 and then Comes_From_Source (Expression (Parent (Def_Id)))
+               then
+                  Error_Msg_Sloc := Sloc (Def_Id);
+                  Error_Pragma_Arg
+                    ("no initialization allowed for declaration of& #",
+                     Arg2);
+
+               else
+                  --  For compatibility, support VADS usage of providing both
+                  --  pragmas Interface and Interface_Name to obtain the effect
+                  --  of a single Import pragma.
+
+                  if Is_Imported (Def_Id)
+                    and then Present (First_Rep_Item (Def_Id))
+                    and then Nkind (First_Rep_Item (Def_Id)) = N_Pragma
+                    and then Chars (First_Rep_Item (Def_Id)) = Name_Interface
+                  then
+                     null;
+                  else
+                     Set_Imported (Def_Id);
+                  end if;
+
+                  Set_Is_Public (Def_Id);
+                  Process_Interface_Name (Def_Id, Arg2, Arg3);
+               end if;
+
+            --  Otherwise must be subprogram
+
+            elsif not Is_Subprogram (Def_Id) then
+               Error_Pragma_Arg
+                 ("argument of pragma% is not subprogram", Arg1);
+
+            else
+               Check_At_Most_N_Arguments (3);
+               Hom_Id := Def_Id;
+               Found := False;
+
+               --  Loop through homonyms
+
+               loop
+                  Def_Id := Get_Base_Subprogram (Hom_Id);
+
+                  if Is_Imported (Def_Id) then
+                     Process_Interface_Name (Def_Id, Arg2, Arg3);
+                     Found := True;
+                  end if;
+
+                  Hom_Id := Homonym (Hom_Id);
+
+                  exit when No (Hom_Id)
+                    or else Scope (Hom_Id) /= Current_Scope;
+               end loop;
+
+               if not Found then
+                  Error_Pragma_Arg
+                    ("argument of pragma% is not imported subprogram",
+                     Arg1);
+               end if;
+            end if;
+         end Interface_Name;
+
+         -----------------------
+         -- Interrupt_Handler --
+         -----------------------
+
+         --  pragma Interrupt_Handler (handler_NAME);
+
+         when Pragma_Interrupt_Handler =>
+            Check_Ada_83_Warning;
+            Check_Arg_Count (1);
+            Check_No_Identifiers;
+            Check_Interrupt_Or_Attach_Handler;
+            Process_Interrupt_Or_Attach_Handler;
+
+         ------------------------
+         -- Interrupt_Priority --
+         ------------------------
+
+         --  pragma Interrupt_Priority [(EXPRESSION)];
+
+         when Pragma_Interrupt_Priority => Interrupt_Priority : declare
+            P   : constant Node_Id := Parent (N);
+            Arg : Node_Id;
+
+         begin
+            Check_Ada_83_Warning;
+
+            if Arg_Count /= 0 then
+               Arg := Expression (Arg1);
+               Check_Arg_Count (1);
+               Check_No_Identifiers;
+
+               --  Set In_Default_Expression for per-object case???
+
+               Analyze_And_Resolve (Arg, Standard_Integer);
+               if Expander_Active then
+                  Rewrite (Arg,
+                    Convert_To (RTE (RE_Interrupt_Priority), Arg));
+               end if;
+            end if;
+
+            if Nkind (P) /= N_Task_Definition
+              and then Nkind (P) /= N_Protected_Definition
+            then
+               Pragma_Misplaced;
+               return;
+
+            elsif Has_Priority_Pragma (P) then
+               Error_Pragma ("duplicate pragma% not allowed");
+
+            else
+               Set_Has_Priority_Pragma (P, True);
+               Record_Rep_Item (Defining_Identifier (Parent (P)), N);
+            end if;
+         end Interrupt_Priority;
+
+         ----------------------
+         -- Java_Constructor --
+         ----------------------
+
+         --  pragma Java_Constructor ([Entity =>] LOCAL_NAME);
+
+         when Pragma_Java_Constructor => Java_Constructor : declare
+            Id     : Entity_Id;
+            Def_Id : Entity_Id;
+            Hom_Id : Entity_Id;
+
+         begin
+            GNAT_Pragma;
+            Check_Arg_Count (1);
+            Check_Optional_Identifier (Arg1, Name_Entity);
+            Check_Arg_Is_Local_Name (Arg1);
+
+            Id := Expression (Arg1);
+            Find_Program_Unit_Name (Id);
+
+            --  If we did not find the name, we are done
+
+            if Etype (Id) = Any_Type then
+               return;
+            end if;
+
+            Hom_Id := Entity (Id);
+
+            --  Loop through homonyms
+
+            loop
+               Def_Id := Get_Base_Subprogram (Hom_Id);
+
+               --  The constructor is required to be a function returning
+               --  an access type whose designated type has convention Java.
+
+               if Ekind (Def_Id) = E_Function
+                 and then Ekind (Etype (Def_Id)) in Access_Kind
+                 and then
+                   (Atree.Convention
+                      (Designated_Type (Etype (Def_Id))) = Convention_Java
+                   or else
+                     Atree.Convention
+                      (Root_Type (Designated_Type (Etype (Def_Id))))
+                        = Convention_Java)
+               then
+                  Set_Is_Constructor (Def_Id);
+                  Set_Convention     (Def_Id, Convention_Java);
+
+               else
+                  Error_Pragma_Arg
+                    ("pragma% requires function returning a 'Java access type",
+                      Arg1);
+               end if;
+
+               Hom_Id := Homonym (Hom_Id);
+
+               exit when No (Hom_Id) or else Scope (Hom_Id) /= Current_Scope;
+            end loop;
+         end Java_Constructor;
+
+         ----------------------
+         -- Java_Interface --
+         ----------------------
+
+         --  pragma Java_Interface ([Entity =>] LOCAL_NAME);
+
+         when Pragma_Java_Interface => Java_Interface : declare
+            Arg : Node_Id;
+            Typ : Entity_Id;
+
+         begin
+            GNAT_Pragma;
+            Check_Arg_Count (1);
+            Check_Optional_Identifier (Arg1, Name_Entity);
+            Check_Arg_Is_Local_Name (Arg1);
+
+            Arg := Expression (Arg1);
+            Analyze (Arg);
+
+            if Etype (Arg) = Any_Type then
+               return;
+            end if;
+
+            if not Is_Entity_Name (Arg)
+              or else not Is_Type (Entity (Arg))
+            then
+               Error_Pragma_Arg ("pragma% requires a type mark", Arg1);
+            end if;
+
+            Typ := Underlying_Type (Entity (Arg));
+
+            --  For now we simply check some of the semantic constraints
+            --  on the type. This currently leaves out some restrictions
+            --  on interface types, namely that the parent type must be
+            --  java.lang.Object.Typ and that all primitives of the type
+            --  should be declared abstract. ???
+
+            if not Is_Tagged_Type (Typ) or else not Is_Abstract (Typ) then
+               Error_Pragma_Arg ("pragma% requires an abstract "
+                 & "tagged type", Arg1);
+
+            elsif not Has_Discriminants (Typ)
+              or else Ekind (Etype (First_Discriminant (Typ)))
+                        /= E_Anonymous_Access_Type
+              or else
+                not Is_Class_Wide_Type
+                      (Designated_Type (Etype (First_Discriminant (Typ))))
+            then
+               Error_Pragma_Arg
+                 ("type must have a class-wide access discriminant", Arg1);
+            end if;
+         end Java_Interface;
+
+         -------------
+         -- License --
+         -------------
+
+         --  pragma License (RESTRICTED | UNRESRICTED | GPL | MODIFIED_GPL);
+
+         when Pragma_License =>
+            GNAT_Pragma;
+            Check_Arg_Count (1);
+            Check_No_Identifiers;
+            Check_Valid_Configuration_Pragma;
+            Check_Arg_Is_Identifier (Arg1);
+
+            declare
+               Sind : constant Source_File_Index :=
+                        Source_Index (Current_Sem_Unit);
+
+            begin
+               case Chars (Get_Pragma_Arg (Arg1)) is
+                  when Name_GPL =>
+                     Set_License (Sind, GPL);
+
+                  when Name_Modified_GPL =>
+                     Set_License (Sind, Modified_GPL);
+
+                  when Name_Restricted =>
+                     Set_License (Sind, Restricted);
+
+                  when Name_Unrestricted =>
+                     Set_License (Sind, Unrestricted);
+
+                  when others =>
+                     Error_Pragma_Arg ("invalid license name", Arg1);
+               end case;
+            end;
+
+         ---------------
+         -- Link_With --
+         ---------------
+
+         --  pragma Link_With (string_EXPRESSION {, string_EXPRESSION});
+
+         when Pragma_Link_With => Link_With : declare
+            Arg : Node_Id;
+
+         begin
+            GNAT_Pragma;
+
+            if Operating_Mode = Generate_Code
+              and then In_Extended_Main_Source_Unit (N)
+            then
+               Check_At_Least_N_Arguments (1);
+               Check_No_Identifiers;
+               Check_Is_In_Decl_Part_Or_Package_Spec;
+               Check_Arg_Is_Static_Expression (Arg1, Standard_String);
+               Start_String;
+
+               Arg := Arg1;
+               while Present (Arg) loop
+                  Check_Arg_Is_Static_Expression (Arg, Standard_String);
+
+                  --  Store argument, converting sequences of spaces to
+                  --  a single null character (this is the difference in
+                  --  processing between Link_With, and Linker_Options).
+
+                  declare
+                     C : constant Char_Code := Get_Char_Code (' ');
+                     S : constant String_Id :=
+                           Strval (Expr_Value_S (Expression (Arg)));
+
+                     F : Nat := 1;
+                     L : Nat := String_Length (S);
+
+                     procedure Skip_Spaces;
+                     --  Advance F past any spaces
+
+                     procedure Skip_Spaces is
+                     begin
+                        while F <= L and then Get_String_Char (S, F) = C loop
+                           F := F + 1;
+                        end loop;
+                     end Skip_Spaces;
+
+                  begin
+                     Skip_Spaces; -- skip leading spaces
+
+                     --  Loop through characters, changing any embedded
+                     --  sequence of spaces to a single null character
+                     --  (this is how Link_With/Linker_Options differ)
+
+                     while F <= L loop
+                        if Get_String_Char (S, F) = C then
+                           Skip_Spaces;
+                           exit when F > L;
+                           Store_String_Char (ASCII.NUL);
+
+                        else
+                           Store_String_Char (Get_String_Char (S, F));
+                           F := F + 1;
+                        end if;
+                     end loop;
+                  end;
+
+                  Arg := Next (Arg);
+
+                  if Present (Arg) then
+                     Store_String_Char (ASCII.NUL);
+                  end if;
+               end loop;
+
+               Store_Linker_Option_String (End_String);
+            end if;
+         end Link_With;
+
+         ------------------
+         -- Linker_Alias --
+         ------------------
+
+         --  pragma Linker_Alias (
+         --      [Entity =>]  LOCAL_NAME
+         --      [Alias  =>]  static_string_EXPRESSION);
+
+         when Pragma_Linker_Alias =>
+            GNAT_Pragma;
+            Check_Arg_Count (2);
+            Check_Optional_Identifier (Arg1, Name_Entity);
+            Check_Optional_Identifier (Arg2, "alias");
+            Check_Arg_Is_Library_Level_Local_Name (Arg1);
+            Check_Arg_Is_Static_Expression (Arg2, Standard_String);
+
+            --  The only processing required is to link this item on to the
+            --  list of rep items for the given entity. This is accomplished
+            --  by the call to Rep_Item_Too_Late (when no error is detected
+            --  and False is returned).
+
+            if Rep_Item_Too_Late (Entity (Expression (Arg1)), N) then
+               return;
+            else
+               Set_Has_Gigi_Rep_Item (Entity (Expression (Arg1)));
+            end if;
+
+         --------------------
+         -- Linker_Options --
+         --------------------
+
+         --  pragma Linker_Options (string_EXPRESSION {, string_EXPRESSION});
+
+         --  Note: the use of multiple arguments is a GNAT extension
+
+         when Pragma_Linker_Options => Linker_Options : declare
+            Arg : Node_Id;
+
+         begin
+            if Operating_Mode = Generate_Code
+              and then In_Extended_Main_Source_Unit (N)
+            then
+               Check_Ada_83_Warning;
+               Check_At_Least_N_Arguments (1);
+               Check_No_Identifiers;
+               Check_Is_In_Decl_Part_Or_Package_Spec;
+               Check_Arg_Is_Static_Expression (Arg1, Standard_String);
+               Start_String (Strval (Expr_Value_S (Expression (Arg1))));
+
+               Arg := Arg2;
+               while Present (Arg) loop
+                  Check_Arg_Is_Static_Expression (Arg, Standard_String);
+                  Store_String_Char (ASCII.NUL);
+                  Store_String_Chars
+                    (Strval (Expr_Value_S (Expression (Arg))));
+                  Arg := Next (Arg);
+               end loop;
+
+               Store_Linker_Option_String (End_String);
+            end if;
+         end Linker_Options;
+
+         --------------------
+         -- Linker_Section --
+         --------------------
+
+         --  pragma Linker_Section (
+         --      [Entity  =>]  LOCAL_NAME
+         --      [Section =>]  static_string_EXPRESSION);
+
+         when Pragma_Linker_Section =>
+            GNAT_Pragma;
+            Check_Arg_Count (2);
+            Check_Optional_Identifier (Arg1, Name_Entity);
+            Check_Optional_Identifier (Arg2, Name_Section);
+            Check_Arg_Is_Library_Level_Local_Name (Arg1);
+            Check_Arg_Is_Static_Expression (Arg2, Standard_String);
+
+            --  The only processing required is to link this item on to the
+            --  list of rep items for the given entity. This is accomplished
+            --  by the call to Rep_Item_Too_Late (when no error is detected
+            --  and False is returned).
+
+            if Rep_Item_Too_Late (Entity (Expression (Arg1)), N) then
+               return;
+            else
+               Set_Has_Gigi_Rep_Item (Entity (Expression (Arg1)));
+            end if;
+
+         ----------
+         -- List --
+         ----------
+
+         --  pragma List (On | Off)
+
+         --  There is nothing to do here, since we did all the processing
+         --  for this pragma in Par.Prag (so that it works properly even in
+         --  syntax only mode)
+
+         when Pragma_List =>
+            null;
+
+         --------------------
+         -- Locking_Policy --
+         --------------------
+
+         --  pragma Locking_Policy (policy_IDENTIFIER);
+
+         when Pragma_Locking_Policy => declare
+            LP : Character;
+
+         begin
+            Check_Ada_83_Warning;
+            Check_Arg_Count (1);
+            Check_No_Identifiers;
+            Check_Arg_Is_Locking_Policy (Arg1);
+            Check_Valid_Configuration_Pragma;
+            Get_Name_String (Chars (Expression (Arg1)));
+            LP := Fold_Upper (Name_Buffer (1));
+
+            if Locking_Policy /= ' '
+              and then Locking_Policy /= LP
+            then
+               Error_Msg_Sloc := Locking_Policy_Sloc;
+               Error_Pragma ("locking policy incompatible with policy#");
+            else
+               Locking_Policy := LP;
+               Locking_Policy_Sloc := Loc;
+            end if;
+         end;
+
+         ----------------
+         -- Long_Float --
+         ----------------
+
+         --  pragma Long_Float (D_Float | G_Float);
+
+         when Pragma_Long_Float =>
+            GNAT_Pragma;
+            Check_Valid_Configuration_Pragma;
+            Check_Arg_Count (1);
+            Check_No_Identifier (Arg1);
+            Check_Arg_Is_One_Of (Arg1, Name_D_Float, Name_G_Float);
+
+            if not OpenVMS_On_Target then
+               Error_Pragma ("?pragma% ignored (applies only to Open'V'M'S)");
+            end if;
+
+            --  D_Float case
+
+            if Chars (Expression (Arg1)) = Name_D_Float then
+               if Opt.Float_Format_Long = 'G' then
+                  Error_Pragma ("G_Float previously specified");
+               end if;
+
+               Opt.Float_Format_Long := 'D';
+
+            --  G_Float case (this is the default, does not need overriding)
+
+            else
+               if Opt.Float_Format_Long = 'D' then
+                  Error_Pragma ("D_Float previously specified");
+               end if;
+
+               Opt.Float_Format_Long := 'G';
+            end if;
+
+            Set_Standard_Fpt_Formats;
+
+         -----------------------
+         -- Machine_Attribute --
+         -----------------------
+
+         --  pragma Machine_Attribute (
+         --    [Entity         =>] LOCAL_NAME,
+         --    [Attribute_Name =>] static_string_EXPRESSION
+         --  [,[Info           =>] static_string_EXPRESSION] );
+
+         when Pragma_Machine_Attribute => Machine_Attribute : declare
+            Def_Id : Entity_Id;
+
+         begin
+            GNAT_Pragma;
+
+            if Arg_Count = 3 then
+               Check_Optional_Identifier (Arg3, "info");
+               Check_Arg_Is_Static_Expression (Arg3, Standard_String);
+            else
+               Check_Arg_Count (2);
+            end if;
+
+            Check_Arg_Is_Local_Name (Arg1);
+            Check_Optional_Identifier (Arg2, "attribute_name");
+            Check_Optional_Identifier (Arg1, Name_Entity);
+            Check_Arg_Is_Static_Expression (Arg2, Standard_String);
+            Def_Id := Entity (Expression (Arg1));
+
+            if Is_Access_Type (Def_Id) then
+               Def_Id := Designated_Type (Def_Id);
+            end if;
+
+            if Rep_Item_Too_Early (Def_Id, N) then
+               return;
+            end if;
+
+            Def_Id := Underlying_Type (Def_Id);
+
+            --  The only processing required is to link this item on to the
+            --  list of rep items for the given entity. This is accomplished
+            --  by the call to Rep_Item_Too_Late (when no error is detected
+            --  and False is returned).
+
+            if Rep_Item_Too_Late (Def_Id, N) then
+               return;
+            else
+               Set_Has_Gigi_Rep_Item (Entity (Expression (Arg1)));
+            end if;
+         end Machine_Attribute;
+
+         ----------
+         -- Main --
+         ----------
+
+         --  pragma Main_Storage
+         --   (MAIN_STORAGE_OPTION [, MAIN_STORAGE_OPTION]);
+
+         --  MAIN_STORAGE_OPTION ::=
+         --    [WORKING_STORAGE =>] static_SIMPLE_EXPRESSION
+         --  | [TOP_GUARD =>] static_SIMPLE_EXPRESSION
+
+         when Pragma_Main => Main : declare
+            Args  : Args_List (1 .. 3);
+            Names : Name_List (1 .. 3) := (
+                      Name_Stack_Size,
+                      Name_Task_Stack_Size_Default,
+                      Name_Time_Slicing_Enabled);
+
+            Nod : Node_Id;
+
+         begin
+            GNAT_Pragma;
+            Gather_Associations (Names, Args);
+
+            for J in 1 .. 2 loop
+               if Present (Args (J)) then
+                  Check_Arg_Is_Static_Expression (Args (J), Any_Integer);
+               end if;
+            end loop;
+
+            if Present (Args (3)) then
+               Check_Arg_Is_Static_Expression (Args (3), Standard_Boolean);
+            end if;
+
+            Nod := Next (N);
+            while Present (Nod) loop
+               if Nkind (Nod) = N_Pragma
+                 and then Chars (Nod) = Name_Main
+               then
+                  Error_Msg_Name_1 := Chars (N);
+                  Error_Msg_N ("duplicate pragma% not permitted", Nod);
+               end if;
+
+               Next (Nod);
+            end loop;
+         end Main;
+
+         ------------------
+         -- Main_Storage --
+         ------------------
+
+         --  pragma Main_Storage
+         --   (MAIN_STORAGE_OPTION [, MAIN_STORAGE_OPTION]);
+
+         --  MAIN_STORAGE_OPTION ::=
+         --    [WORKING_STORAGE =>] static_SIMPLE_EXPRESSION
+         --  | [TOP_GUARD =>] static_SIMPLE_EXPRESSION
+
+         when Pragma_Main_Storage => Main_Storage : declare
+            Args  : Args_List (1 .. 2);
+            Names : Name_List (1 .. 2) := (
+                      Name_Working_Storage,
+                      Name_Top_Guard);
+
+            Nod : Node_Id;
+
+         begin
+            GNAT_Pragma;
+            Gather_Associations (Names, Args);
+
+            for J in 1 .. 2 loop
+               if Present (Args (J)) then
+                  Check_Arg_Is_Static_Expression (Args (J), Any_Integer);
+               end if;
+            end loop;
+
+            Check_In_Main_Program;
+
+            Nod := Next (N);
+            while Present (Nod) loop
+               if Nkind (Nod) = N_Pragma
+                 and then Chars (Nod) = Name_Main_Storage
+               then
+                  Error_Msg_Name_1 := Chars (N);
+                  Error_Msg_N ("duplicate pragma% not permitted", Nod);
+               end if;
+
+               Next (Nod);
+            end loop;
+
+         end Main_Storage;
+
+         -----------------
+         -- Memory_Size --
+         -----------------
+
+         --  pragma Memory_Size (NUMERIC_LITERAL)
+
+         when Pragma_Memory_Size =>
+            GNAT_Pragma;
+
+            --  Memory size is simply ignored
+
+            Check_No_Identifiers;
+            Check_Arg_Count (1);
+            Check_Arg_Is_Integer_Literal (Arg1);
+
+         ---------------
+         -- No_Return --
+         ---------------
+
+         --  pragma No_Return (procedure_LOCAL_NAME);
+
+         when Pragma_No_Return => declare
+            Id    : Node_Id;
+            E     : Entity_Id;
+            Found : Boolean;
+
+         begin
+            GNAT_Pragma;
+            Check_Arg_Count (1);
+            Check_No_Identifiers;
+            Check_Arg_Is_Local_Name (Arg1);
+            Id := Expression (Arg1);
+            Analyze (Id);
+
+            if not Is_Entity_Name (Id) then
+               Error_Pragma_Arg ("entity name required", Arg1);
+            end if;
+
+            if Etype (Id) = Any_Type then
+               raise Pragma_Exit;
+            end if;
+
+            E := Entity (Id);
+
+            Found := False;
+            while Present (E)
+              and then Scope (E) = Current_Scope
+            loop
+               if Ekind (E) = E_Procedure
+                 or else Ekind (E) = E_Generic_Procedure
+               then
+                  Set_No_Return (E);
+                  Found := True;
+               end if;
+
+               E := Homonym (E);
+            end loop;
+
+            if not Found then
+               Error_Pragma ("no procedures found for pragma%");
+            end if;
+         end;
+
+         -----------------
+         -- No_Run_Time --
+         -----------------
+
+         --  pragma No_Run_Time
+
+         when Pragma_No_Run_Time =>
+            GNAT_Pragma;
+            Check_Valid_Configuration_Pragma;
+            Check_Arg_Count (0);
+            Set_No_Run_Time_Mode;
+
+         -----------------------
+         -- Normalize_Scalars --
+         -----------------------
+
+         --  pragma Normalize_Scalars;
+
+         when Pragma_Normalize_Scalars =>
+            Check_Ada_83_Warning;
+            Check_Arg_Count (0);
+            Check_Valid_Configuration_Pragma;
+            Normalize_Scalars := True;
+            Init_Or_Norm_Scalars := True;
+
+         --------------
+         -- Optimize --
+         --------------
+
+         --  pragma Optimize (Time | Space);
+
+         --  The actual check for optimize is done in Gigi. Note that this
+         --  pragma does not actually change the optimization setting, it
+         --  simply checks that it is consistent with the pragma.
+
+         when Pragma_Optimize =>
+            Check_No_Identifiers;
+            Check_Arg_Count (1);
+            Check_Arg_Is_One_Of (Arg1, Name_Time, Name_Space, Name_Off);
+
+         ----------
+         -- Pack --
+         ----------
+
+         --  pragma Pack (first_subtype_LOCAL_NAME);
+
+         when Pragma_Pack => Pack : declare
+            Assoc   : Node_Id := Arg1;
+            Type_Id : Node_Id;
+            Typ     : Entity_Id;
+
+         begin
+            Check_No_Identifiers;
+            Check_Arg_Count (1);
+            Check_Arg_Is_Local_Name (Arg1);
+
+            Type_Id := Expression (Assoc);
+            Find_Type (Type_Id);
+            Typ := Entity (Type_Id);
+
+            if Typ = Any_Type
+              or else Rep_Item_Too_Early (Typ, N)
+            then
+               return;
+            else
+               Typ := Underlying_Type (Typ);
+            end if;
+
+            if not Is_Array_Type (Typ) and then not Is_Record_Type (Typ) then
+               Error_Pragma ("pragma% must specify array or record type");
+            end if;
+
+            Check_First_Subtype (Arg1);
+
+            if Has_Pragma_Pack (Typ) then
+               Error_Pragma ("duplicate pragma%, only one allowed");
+
+            --  Array type. We set the Has_Pragma_Pack flag, and Is_Packed,
+            --  but not Has_Non_Standard_Rep, because we don't actually know
+            --  till freeze time if the array can have packed representation.
+            --  That's because in the general case we do not know enough about
+            --  the component type until it in turn is frozen, which certainly
+            --  happens before the array type is frozen, but not necessarily
+            --  till that point (i.e. right now it may be unfrozen).
+
+            elsif Is_Array_Type (Typ) then
+
+               if Has_Aliased_Components (Base_Type (Typ)) then
+                  Error_Pragma
+                    ("pragma% ignored, cannot pack aliased components?");
+
+               elsif Has_Atomic_Components (Typ) then
+                  Error_Pragma
+                    ("?pragma% ignored, cannot pack atomic components");
+
+               elsif not Rep_Item_Too_Late (Typ, N) then
+                  Set_Is_Packed            (Base_Type (Typ));
+                  Set_Has_Pragma_Pack      (Base_Type (Typ));
+                  Set_Has_Non_Standard_Rep (Base_Type (Typ));
+               end if;
+
+            --  Record type. For record types, the pack is always effective
+
+            else -- Is_Record_Type (Typ)
+               if not Rep_Item_Too_Late (Typ, N) then
+                  Set_Has_Pragma_Pack      (Base_Type (Typ));
+                  Set_Is_Packed            (Base_Type (Typ));
+                  Set_Has_Non_Standard_Rep (Base_Type (Typ));
+               end if;
+            end if;
+         end Pack;
+
+         ----------
+         -- Page --
+         ----------
+
+         --  pragma Page;
+
+         --  There is nothing to do here, since we did all the processing
+         --  for this pragma in Par.Prag (so that it works properly even in
+         --  syntax only mode)
+
+         when Pragma_Page =>
+            null;
+
+         -------------
+         -- Passive --
+         -------------
+
+         --  pragma Passive [(PASSIVE_FORM)];
+
+         --   PASSIVE_FORM ::= Semaphore | No
+
+         when Pragma_Passive =>
+            GNAT_Pragma;
+
+            if Nkind (Parent (N)) /= N_Task_Definition then
+               Error_Pragma ("pragma% must be within task definition");
+            end if;
+
+            if Arg_Count /= 0 then
+               Check_Arg_Count (1);
+               Check_Arg_Is_One_Of (Arg1, Name_Semaphore, Name_No);
+            end if;
+
+         -------------
+         -- Polling --
+         -------------
+
+         --  pragma Polling (ON | OFF);
+
+         when Pragma_Polling =>
+            GNAT_Pragma;
+            Check_Arg_Count (1);
+            Check_No_Identifiers;
+            Check_Arg_Is_One_Of (Arg1, Name_On, Name_Off);
+            Polling_Required := (Chars (Expression (Arg1)) = Name_On);
+
+         ------------------
+         -- Preelaborate --
+         ------------------
+
+         --  pragma Preelaborate [(library_unit_NAME)];
+
+         --  Set the flag Is_Preelaborated of program unit name entity
+
+         when Pragma_Preelaborate => Preelaborate : declare
+            Ent : Entity_Id;
+            Pa  : Node_Id   := Parent (N);
+            Pk  : Node_Kind := Nkind (Pa);
+
+         begin
+            Check_Ada_83_Warning;
+            Check_Valid_Library_Unit_Pragma;
+
+            if Nkind (N) = N_Null_Statement then
+               return;
+            end if;
+
+            Ent := Find_Lib_Unit_Name;
+
+            --  This filters out pragmas inside generic parent then
+            --  show up inside instantiation
+
+            if Present (Ent)
+              and then not (Pk = N_Package_Specification
+                             and then Present (Generic_Parent (Pa)))
+            then
+               if not Debug_Flag_U then
+                  Set_Is_Preelaborated (Ent);
+                  Set_Suppress_Elaboration_Warnings (Ent);
+               end if;
+            end if;
+         end Preelaborate;
+
+         --------------
+         -- Priority --
+         --------------
+
+         --  pragma Priority (EXPRESSION);
+
+         when Pragma_Priority => Priority : declare
+            P   : constant Node_Id := Parent (N);
+            Arg : Node_Id;
+
+         begin
+            Check_No_Identifiers;
+            Check_Arg_Count (1);
+
+            Arg := Expression (Arg1);
+            Analyze_And_Resolve (Arg, Standard_Integer);
+
+            if not Is_Static_Expression (Arg) then
+               Check_Restriction (Static_Priorities, Arg);
+            end if;
+
+            --  Subprogram case
+
+            if Nkind (P) = N_Subprogram_Body then
+               Check_In_Main_Program;
+
+               --  Must be static
+
+               if not Is_Static_Expression (Arg) then
+                  Error_Pragma_Arg
+                    ("main subprogram priority is not static", Arg1);
+
+               --  If constraint error, then we already signalled an error
+
+               elsif Raises_Constraint_Error (Arg) then
+                  null;
+
+               --  Otherwise check in range
+
+               else
+                  declare
+                     Val : constant Uint := Expr_Value (Arg);
+
+                  begin
+                     if Val < 0
+                       or else Val > Expr_Value (Expression
+                                       (Parent (RTE (RE_Max_Priority))))
+                     then
+                        Error_Pragma_Arg
+                          ("main subprogram priority is out of range", Arg1);
+                     end if;
+                  end;
+               end if;
+
+               Set_Main_Priority
+                 (Current_Sem_Unit, UI_To_Int (Expr_Value (Arg)));
+
+            --  Task or Protected, must be of type Integer
+
+            elsif Nkind (P) = N_Protected_Definition
+                    or else
+                  Nkind (P) = N_Task_Definition
+            then
+               if Expander_Active then
+                  Rewrite (Arg,
+                    Convert_To (RTE (RE_Any_Priority), Arg));
+               end if;
+
+            --  Anything else is incorrect
+
+            else
+               Pragma_Misplaced;
+            end if;
+
+            if Has_Priority_Pragma (P) then
+               Error_Pragma ("duplicate pragma% not allowed");
+            else
+               Set_Has_Priority_Pragma (P, True);
+
+               if Nkind (P) = N_Protected_Definition
+                    or else
+                  Nkind (P) = N_Task_Definition
+               then
+                  Record_Rep_Item (Defining_Identifier (Parent (P)), N);
+                  --  exp_ch9 should use this ???
+               end if;
+            end if;
+
+         end Priority;
+
+         --------------------------
+         -- Propagate_Exceptions --
+         --------------------------
+
+         --  pragma Propagate_Exceptions;
+
+         when Pragma_Propagate_Exceptions =>
+            GNAT_Pragma;
+            Check_Arg_Count (0);
+
+            if In_Extended_Main_Source_Unit (N) then
+               Propagate_Exceptions := True;
+            end if;
+
+         ------------------
+         -- Psect_Object --
+         ------------------
+
+         --  pragma Psect_Object (
+         --        [Internal =>] LOCAL_NAME,
+         --     [, [External =>] EXTERNAL_SYMBOL]
+         --     [, [Size     =>] EXTERNAL_SYMBOL]);
+
+         when Pragma_Psect_Object | Pragma_Common_Object =>
+         Psect_Object : declare
+            Args  : Args_List (1 .. 3);
+            Names : Name_List (1 .. 3) := (
+                      Name_Internal,
+                      Name_External,
+                      Name_Size);
+
+            Internal : Node_Id renames Args (1);
+            External : Node_Id renames Args (2);
+            Size     : Node_Id renames Args (3);
+
+            R_Internal : Node_Id;
+            R_External : Node_Id;
+
+            MA       : Node_Id;
+            Str      : String_Id;
+
+            Def_Id   : Entity_Id;
+
+            procedure Check_Too_Long (Arg : Node_Id);
+            --  Posts message if the argument is an identifier with more
+            --  than 31 characters, or a string literal with more than
+            --  31 characters, and we are operating under VMS
+
+            procedure Check_Too_Long (Arg : Node_Id) is
+               X : Node_Id := Original_Node (Arg);
+
+            begin
+               if Nkind (X) /= N_String_Literal
+                    and then
+                  Nkind (X) /= N_Identifier
+               then
+                  Error_Pragma_Arg
+                    ("inappropriate argument for pragma %", Arg);
+               end if;
+
+               if OpenVMS_On_Target then
+                  if (Nkind (X) = N_String_Literal
+                       and then String_Length (Strval (X)) > 31)
+                    or else
+                     (Nkind (X) = N_Identifier
+                       and then Length_Of_Name (Chars (X)) > 31)
+                  then
+                     Error_Pragma_Arg
+                       ("argument for pragma % is longer than 31 characters",
+                        Arg);
+                  end if;
+               end if;
+            end Check_Too_Long;
+
+         --  Start of processing for Common_Object/Psect_Object
+
+         begin
+            GNAT_Pragma;
+            Gather_Associations (Names, Args);
+            Process_Extended_Import_Export_Internal_Arg (Internal);
+
+            R_Internal := Relocate_Node (Internal);
+
+            Def_Id := Entity (R_Internal);
+
+            if Ekind (Def_Id) /= E_Constant
+              and then Ekind (Def_Id) /= E_Variable
+            then
+               Error_Pragma_Arg
+                 ("pragma% must designate an object", Internal);
+            end if;
+
+            Check_Too_Long (R_Internal);
+
+            if Is_Imported (Def_Id) or else Is_Exported (Def_Id) then
+               Error_Pragma_Arg
+                 ("cannot use pragma% for imported/exported object",
+                  R_Internal);
+            end if;
+
+            if Is_Concurrent_Type (Etype (R_Internal)) then
+               Error_Pragma_Arg
+                 ("cannot specify pragma % for task/protected object",
+                  R_Internal);
+            end if;
+
+            if Is_Psected (Def_Id) then
+               Error_Msg_N ("?duplicate Psect_Object pragma", N);
+            else
+               Set_Is_Psected (Def_Id);
+            end if;
+
+            if Ekind (Def_Id) = E_Constant then
+               Error_Pragma_Arg
+                 ("cannot specify pragma % for a constant", R_Internal);
+            end if;
+
+            if Is_Record_Type (Etype (R_Internal)) then
+               declare
+                  Ent  : Entity_Id;
+                  Decl : Entity_Id;
+
+               begin
+                  Ent := First_Entity (Etype (R_Internal));
+                  while Present (Ent) loop
+                     Decl := Declaration_Node (Ent);
+
+                     if Ekind (Ent) = E_Component
+                       and then Nkind (Decl) = N_Component_Declaration
+                       and then Present (Expression (Decl))
+                     then
+                        Error_Msg_N
+                          ("?object for pragma % has defaults", R_Internal);
+                        exit;
+
+                     else
+                        Next_Entity (Ent);
+                     end if;
+                  end loop;
+               end;
+            end if;
+
+            if Present (Size) then
+               Check_Too_Long (Size);
+            end if;
+
+            --  Make Psect case-insensitive.
+
+            if Present (External) then
+               Check_Too_Long (External);
+
+               if Nkind (External) = N_String_Literal then
+                  String_To_Name_Buffer (Strval (External));
+               else
+                  Get_Name_String (Chars (External));
+               end if;
+
+               Set_All_Upper_Case;
+               Start_String;
+               Store_String_Chars (Name_Buffer (1 .. Name_Len));
+               Str := End_String;
+               R_External := Make_String_Literal
+                 (Sloc => Sloc (External), Strval => Str);
+            else
+               Get_Name_String (Chars (Internal));
+               Set_All_Upper_Case;
+               Start_String;
+               Store_String_Chars (Name_Buffer (1 .. Name_Len));
+               Str := End_String;
+               R_External := Make_String_Literal
+                 (Sloc => Sloc (Internal), Strval => Str);
+            end if;
+
+            --  Transform into pragma Linker_Section, add attributes to
+            --  match what DEC Ada does. Ignore size for now?
+
+            Rewrite (N,
+               Make_Pragma
+                 (Sloc (N),
+                  Name_Linker_Section,
+                  New_List
+                    (Make_Pragma_Argument_Association
+                       (Sloc => Sloc (R_Internal),
+                        Expression => R_Internal),
+                     Make_Pragma_Argument_Association
+                       (Sloc => Sloc (R_External),
+                        Expression => R_External))));
+
+            Analyze (N);
+
+            --  Add Machine_Attribute of "overlaid", so the section overlays
+            --  other sections of the same name.
+
+            Start_String;
+            Store_String_Chars ("overlaid");
+            Str := End_String;
+
+            MA :=
+               Make_Pragma
+                 (Sloc (N),
+                  Name_Machine_Attribute,
+                  New_List
+                    (Make_Pragma_Argument_Association
+                       (Sloc => Sloc (R_Internal),
+                        Expression => R_Internal),
+                     Make_Pragma_Argument_Association
+                       (Sloc => Sloc (R_External),
+                        Expression =>
+                          Make_String_Literal
+                            (Sloc => Sloc (R_External),
+                             Strval => Str))));
+            Analyze (MA);
+
+            --  Add Machine_Attribute of "global", so the section is visible
+            --  everywhere
+
+            Start_String;
+            Store_String_Chars ("global");
+            Str := End_String;
+
+            MA :=
+               Make_Pragma
+                 (Sloc (N),
+                  Name_Machine_Attribute,
+                  New_List
+                    (Make_Pragma_Argument_Association
+                       (Sloc => Sloc (R_Internal),
+                        Expression => R_Internal),
+                     Make_Pragma_Argument_Association
+                       (Sloc => Sloc (R_External),
+                        Expression =>
+                          Make_String_Literal
+                            (Sloc => Sloc (R_External),
+                             Strval => Str))));
+            Analyze (MA);
+
+            --  Add Machine_Attribute of "initialize", so the section is
+            --  demand zeroed.
+
+            Start_String;
+            Store_String_Chars ("initialize");
+            Str := End_String;
+
+            MA :=
+               Make_Pragma
+                 (Sloc (N),
+                  Name_Machine_Attribute,
+                  New_List
+                    (Make_Pragma_Argument_Association
+                       (Sloc => Sloc (R_Internal),
+                        Expression => R_Internal),
+                     Make_Pragma_Argument_Association
+                       (Sloc => Sloc (R_External),
+                        Expression =>
+                          Make_String_Literal
+                            (Sloc => Sloc (R_External),
+                             Strval => Str))));
+            Analyze (MA);
+
+         end Psect_Object;
+
+         ----------
+         -- Pure --
+         ----------
+
+         --  pragma Pure [(library_unit_NAME)];
+
+         when Pragma_Pure => Pure : declare
+            Ent : Entity_Id;
+         begin
+            Check_Ada_83_Warning;
+            Check_Valid_Library_Unit_Pragma;
+
+            if Nkind (N) = N_Null_Statement then
+               return;
+            end if;
+
+            Ent := Find_Lib_Unit_Name;
+            Set_Is_Pure (Ent);
+            Set_Suppress_Elaboration_Warnings (Ent);
+         end Pure;
+
+         -------------------
+         -- Pure_Function --
+         -------------------
+
+         --  pragma Pure_Function ([Entity =>] function_LOCAL_NAME);
+
+         when Pragma_Pure_Function => Pure_Function : declare
+            E_Id   : Node_Id;
+            E      : Entity_Id;
+            Def_Id : Entity_Id;
+
+         begin
+            GNAT_Pragma;
+            Check_Arg_Count (1);
+            Check_Optional_Identifier (Arg1, Name_Entity);
+            Check_Arg_Is_Local_Name (Arg1);
+            E_Id := Expression (Arg1);
+
+            if Error_Posted (E_Id) then
+               return;
+            end if;
+
+            --  Loop through homonyms (overloadings) of referenced entity
+
+            E := Entity (E_Id);
+            while Present (E) loop
+               Def_Id := Get_Base_Subprogram (E);
+
+               if Ekind (Def_Id) /= E_Function
+                 and then Ekind (Def_Id) /= E_Generic_Function
+                 and then Ekind (Def_Id) /= E_Operator
+               then
+                  Error_Pragma_Arg ("pragma% requires a function name", Arg1);
+               end if;
+
+               Set_Is_Pure (Def_Id);
+               E := Homonym (E);
+            end loop;
+         end Pure_Function;
+
+         --------------------
+         -- Queuing_Policy --
+         --------------------
+
+         --  pragma Queuing_Policy (policy_IDENTIFIER);
+
+         when Pragma_Queuing_Policy => declare
+            QP : Character;
+
+         begin
+            Check_Ada_83_Warning;
+            Check_Arg_Count (1);
+            Check_No_Identifiers;
+            Check_Arg_Is_Queuing_Policy (Arg1);
+            Check_Valid_Configuration_Pragma;
+            Get_Name_String (Chars (Expression (Arg1)));
+            QP := Fold_Upper (Name_Buffer (1));
+
+            if Queuing_Policy /= ' '
+              and then Queuing_Policy /= QP
+            then
+               Error_Msg_Sloc := Queuing_Policy_Sloc;
+               Error_Pragma ("queuing policy incompatible with policy#");
+            else
+               Queuing_Policy := QP;
+               Queuing_Policy_Sloc := Loc;
+            end if;
+         end;
+
+         ---------------------------
+         -- Remote_Call_Interface --
+         ---------------------------
+
+         --  pragma Remote_Call_Interface [(library_unit_NAME)];
+
+         when Pragma_Remote_Call_Interface => Remote_Call_Interface : declare
+            Cunit_Node : Node_Id;
+            Cunit_Ent  : Entity_Id;
+            K          : Node_Kind;
+
+         begin
+            Check_Ada_83_Warning;
+            Check_Valid_Library_Unit_Pragma;
+
+            if Nkind (N) = N_Null_Statement then
+               return;
+            end if;
+
+            Cunit_Node := Cunit (Current_Sem_Unit);
+            K          := Nkind (Unit (Cunit_Node));
+            Cunit_Ent  := Cunit_Entity (Current_Sem_Unit);
+
+            if K = N_Package_Declaration
+              or else K = N_Generic_Package_Declaration
+              or else K = N_Subprogram_Declaration
+              or else K = N_Generic_Subprogram_Declaration
+              or else (K = N_Subprogram_Body
+                         and then Acts_As_Spec (Unit (Cunit_Node)))
+            then
+               null;
+            else
+               Error_Pragma (
+                 "pragma% must apply to package or subprogram declaration");
+            end if;
+
+            Set_Is_Remote_Call_Interface (Cunit_Ent);
+         end Remote_Call_Interface;
+
+         ------------------
+         -- Remote_Types --
+         ------------------
+
+         --  pragma Remote_Types [(library_unit_NAME)];
+
+         when Pragma_Remote_Types => Remote_Types : declare
+            Cunit_Node : Node_Id;
+            Cunit_Ent  : Entity_Id;
+
+         begin
+            Check_Ada_83_Warning;
+            Check_Valid_Library_Unit_Pragma;
+
+            if Nkind (N) = N_Null_Statement then
+               return;
+            end if;
+
+            Cunit_Node := Cunit (Current_Sem_Unit);
+            Cunit_Ent  := Cunit_Entity (Current_Sem_Unit);
+
+            if Nkind (Unit (Cunit_Node)) /= N_Package_Declaration
+              and then
+              Nkind (Unit (Cunit_Node)) /= N_Generic_Package_Declaration
+            then
+               Error_Pragma (
+                 "pragma% can only apply to a package declaration");
+            end if;
+
+            Set_Is_Remote_Types (Cunit_Ent);
+         end Remote_Types;
+
+         ---------------
+         -- Ravenscar --
+         ---------------
+
+         when Pragma_Ravenscar =>
+            GNAT_Pragma;
+            Check_Arg_Count (0);
+            Check_Valid_Configuration_Pragma;
+            Set_Ravenscar;
+
+         -------------------------
+         -- Restricted_Run_Time --
+         -------------------------
+
+         when Pragma_Restricted_Run_Time =>
+            GNAT_Pragma;
+            Check_Arg_Count (0);
+            Check_Valid_Configuration_Pragma;
+            Set_Restricted_Profile;
+
+         ------------------
+         -- Restrictions --
+         ------------------
+
+         --  pragma Restrictions (RESTRICTION {, RESTRICTION});
+
+         --  RESTRICTION ::=
+         --    restriction_IDENTIFIER
+         --  | restriction_parameter_IDENTIFIER => EXPRESSION
+
+         when Pragma_Restrictions => Restrictions_Pragma : declare
+            Arg   : Node_Id;
+            R_Id  : Restriction_Id;
+            RP_Id : Restriction_Parameter_Id;
+            Id    : Name_Id;
+            Expr  : Node_Id;
+            Val   : Uint;
+
+         begin
+            Check_Ada_83_Warning;
+            Check_At_Least_N_Arguments (1);
+            Check_Valid_Configuration_Pragma;
+
+            Arg := Arg1;
+
+            while Present (Arg) loop
+               Id := Chars (Arg);
+               Expr := Expression (Arg);
+
+               --  Case of no restriction identifier
+
+               if Id = No_Name then
+                  if Nkind (Expr) /= N_Identifier then
+                     Error_Pragma_Arg
+                       ("invalid form for restriction", Arg);
+
+                  else
+                     R_Id := Get_Restriction_Id (Chars (Expr));
+
+                     if R_Id = Not_A_Restriction_Id then
+                        Error_Pragma_Arg
+                          ("invalid restriction identifier", Arg);
+
+                     --  Restriction is active
+
+                     else
+                        Restrictions (R_Id) := True;
+                        Restrictions_Loc (R_Id) := Sloc (N);
+
+                        --  Record the restriction if we are in the main unit,
+                        --  or in the extended main unit. The reason that we
+                        --  test separately for Main_Unit is that gnat.adc is
+                        --  processed with Current_Sem_Unit = Main_Unit, but
+                        --  nodes in gnat.adc do not appear to be the extended
+                        --  main source unit (they probably should do ???)
+
+                        if Current_Sem_Unit = Main_Unit
+                          or else In_Extended_Main_Source_Unit (N)
+                        then
+                           Main_Restrictions (R_Id) := True;
+                        end if;
+
+                        --  A very special case that must be processed here:
+                        --  pragma Restrictions (No_Exceptions) turns off all
+                        --  run-time checking. This is a bit dubious in terms
+                        --  of the formal language definition, but it is what
+                        --  is intended by the wording of RM H.4(12).
+
+                        if R_Id = No_Exceptions then
+                           Scope_Suppress := (others => True);
+                        end if;
+                     end if;
+                  end if;
+
+               --  Case of restriction identifier present
+
+               else
+                  RP_Id := Get_Restriction_Parameter_Id (Id);
+                  Analyze_And_Resolve (Expr, Any_Integer);
+
+                  if RP_Id = Not_A_Restriction_Parameter_Id then
+                     Error_Pragma_Arg
+                       ("invalid restriction parameter identifier", Arg);
+
+                  elsif not Is_OK_Static_Expression (Expr)
+                    or else not Is_Integer_Type (Etype (Expr))
+                    or else Expr_Value (Expr) < 0
+                  then
+                     Error_Pragma_Arg
+                       ("value must be non-negative static integer", Arg);
+
+                  --  Restriction pragma is active
+
+                  else
+                     Val := Expr_Value (Expr);
+
+                     --  Record pragma if most restrictive so far
+
+                     if Restriction_Parameters (RP_Id) = No_Uint
+                       or else Val < Restriction_Parameters (RP_Id)
+                     then
+                        Restriction_Parameters (RP_Id) := Expr_Value (Expr);
+                        Restriction_Parameters_Loc (RP_Id) := Sloc (N);
+                     end if;
+                  end if;
+               end if;
+
+               Next (Arg);
+            end loop;
+         end Restrictions_Pragma;
+
+         ----------------
+         -- Reviewable --
+         ----------------
+
+         --  pragma Reviewable;
+
+         when Pragma_Reviewable =>
+            Check_Ada_83_Warning;
+            Check_Arg_Count (0);
+
+         -------------------
+         -- Share_Generic --
+         -------------------
+
+         --  pragma Share_Generic (NAME {, NAME});
+
+         when Pragma_Share_Generic =>
+            GNAT_Pragma;
+            Process_Generic_List;
+
+         ------------
+         -- Shared --
+         ------------
+
+         --  pragma Shared (LOCAL_NAME);
+
+         when Pragma_Shared =>
+            Process_Atomic_Shared_Volatile;
+
+         --------------------
+         -- Shared_Passive --
+         --------------------
+
+         --  pragma Shared_Passive [(library_unit_NAME)];
+
+         --  Set the flag Is_Shared_Passive of program unit name entity
+
+         when Pragma_Shared_Passive => Shared_Passive : declare
+            Cunit_Node : Node_Id;
+            Cunit_Ent  : Entity_Id;
+
+         begin
+            Check_Ada_83_Warning;
+            Check_Valid_Library_Unit_Pragma;
+
+            if Nkind (N) = N_Null_Statement then
+               return;
+            end if;
+
+            Cunit_Node := Cunit (Current_Sem_Unit);
+            Cunit_Ent  := Cunit_Entity (Current_Sem_Unit);
+
+            if Nkind (Unit (Cunit_Node)) /= N_Package_Declaration
+              and then
+              Nkind (Unit (Cunit_Node)) /= N_Generic_Package_Declaration
+            then
+               Error_Pragma (
+                 "pragma% can only apply to a package declaration");
+            end if;
+
+            Set_Is_Shared_Passive (Cunit_Ent);
+         end Shared_Passive;
+
+         ----------------------
+         -- Source_File_Name --
+         ----------------------
+
+         --  pragma Source_File_Name (
+         --    [UNIT_NAME =>] unit_NAME,
+         --    [BODY_FILE_NAME | SPEC_FILE_NAME] => STRING_LITERAL);
+
+         --  No processing here. Processing was completed during parsing,
+         --  since we need to have file names set as early as possible.
+         --  Units are loaded well before semantic processing starts.
+
+         --  The only processing we defer to this point is the check
+         --  for correct placement.
+
+         when Pragma_Source_File_Name =>
+            GNAT_Pragma;
+            Check_Valid_Configuration_Pragma;
+
+         ----------------------
+         -- Source_Reference --
+         ----------------------
+
+         --  pragma Source_Reference (INTEGER_LITERAL [, STRING_LITERAL]);
+
+         --  Nothing to do, all processing completed in Par.Prag, since we
+         --  need the information for possible parser messages that are output
+
+         when Pragma_Source_Reference =>
+            GNAT_Pragma;
+
+         ------------------
+         -- Storage_Size --
+         ------------------
+
+         --  pragma Storage_Size (EXPRESSION);
+
+         when Pragma_Storage_Size => Storage_Size : declare
+            P : constant Node_Id := Parent (N);
+            X : Node_Id;
+
+         begin
+            Check_No_Identifiers;
+            Check_Arg_Count (1);
+
+            --  Set In_Default_Expression for per-object case???
+
+            X := Expression (Arg1);
+            Analyze_And_Resolve (X, Any_Integer);
+
+            if not Is_Static_Expression (X) then
+               Check_Restriction (Static_Storage_Size, X);
+            end if;
+
+            if Nkind (P) /= N_Task_Definition then
+               Pragma_Misplaced;
+               return;
+
+            else
+               if Has_Storage_Size_Pragma (P) then
+                  Error_Pragma ("duplicate pragma% not allowed");
+               else
+                  Set_Has_Storage_Size_Pragma (P, True);
+               end if;
+
+               Record_Rep_Item (Defining_Identifier (Parent (P)), N);
+               --  ???  exp_ch9 should use this!
+            end if;
+         end Storage_Size;
+
+         ------------------
+         -- Storage_Unit --
+         ------------------
+
+         --  pragma Storage_Unit (NUMERIC_LITERAL);
+
+         --  Only permitted argument is System'Storage_Unit value
+
+         when Pragma_Storage_Unit =>
+            Check_No_Identifiers;
+            Check_Arg_Count (1);
+            Check_Arg_Is_Integer_Literal (Arg1);
+
+            if Intval (Expression (Arg1)) /=
+              UI_From_Int (Ttypes.System_Storage_Unit)
+            then
+               Error_Msg_Uint_1 := UI_From_Int (Ttypes.System_Storage_Unit);
+               Error_Pragma_Arg
+                 ("the only allowed argument for pragma% is ^", Arg1);
+            end if;
+
+         --------------------
+         -- Stream_Convert --
+         --------------------
+
+         --  pragma Stream_Convert (
+         --    [Entity =>] type_LOCAL_NAME,
+         --    [Read   =>] function_NAME,
+         --    [Write  =>] function NAME);
+
+         when Pragma_Stream_Convert => Stream_Convert : begin
+            GNAT_Pragma;
+            Check_Arg_Count (3);
+            Check_Optional_Identifier (Arg1, Name_Entity);
+            Check_Optional_Identifier (Arg2, Name_Read);
+            Check_Optional_Identifier (Arg3, Name_Write);
+            Check_Arg_Is_Local_Name (Arg1);
+            Check_Non_Overloaded_Function (Arg2);
+            Check_Non_Overloaded_Function (Arg3);
+
+            declare
+               Typ   : constant Entity_Id :=
+                         Underlying_Type (Entity (Expression (Arg1)));
+               Read  : constant Entity_Id := Entity (Expression (Arg2));
+               Write : constant Entity_Id := Entity (Expression (Arg3));
+
+            begin
+               if Etype (Typ) = Any_Type
+                    or else
+                  Etype (Read) = Any_Type
+                    or else
+                  Etype (Write) = Any_Type
+               then
+                  return;
+               end if;
+
+               Check_First_Subtype (Arg1);
+
+               if Rep_Item_Too_Early (Typ, N)
+                    or else
+                  Rep_Item_Too_Late (Typ, N)
+               then
+                  return;
+               end if;
+
+               if Underlying_Type (Etype (Read)) /= Typ then
+                  Error_Pragma_Arg
+                    ("incorrect return type for function&", Arg2);
+               end if;
+
+               if Underlying_Type (Etype (First_Formal (Write))) /= Typ then
+                  Error_Pragma_Arg
+                    ("incorrect parameter type for function&", Arg3);
+               end if;
+
+               if Underlying_Type (Etype (First_Formal (Read))) /=
+                  Underlying_Type (Etype (Write))
+               then
+                  Error_Pragma_Arg
+                    ("result type of & does not match Read parameter type",
+                     Arg3);
+               end if;
+            end;
+         end Stream_Convert;
+
+         -------------------------
+         -- Style_Checks (GNAT) --
+         -------------------------
+
+         --  pragma Style_Checks (On | Off | ALL_CHECKS | STRING_LITERAL);
+
+         --  This is processed by the parser since some of the style
+         --  checks take place during source scanning and parsing. This
+         --  means that we don't need to issue error messages here.
+
+         when Pragma_Style_Checks => Style_Checks : declare
+            A  : constant Node_Id   := Expression (Arg1);
+            S  : String_Id;
+            C  : Char_Code;
+
+         begin
+            GNAT_Pragma;
+            Check_No_Identifiers;
+
+            --  Two argument form
+
+            if Arg_Count = 2 then
+               Check_Arg_Is_One_Of (Arg1, Name_On, Name_Off);
+
+               declare
+                  E_Id : Node_Id;
+                  E    : Entity_Id;
+
+               begin
+                  E_Id := Expression (Arg2);
+                  Analyze (E_Id);
+
+                  if not Is_Entity_Name (E_Id) then
+                     Error_Pragma_Arg
+                       ("second argument of pragma% must be entity name",
+                        Arg2);
+                  end if;
+
+                  E := Entity (E_Id);
+
+                  if E = Any_Id then
+                     return;
+                  else
+                     loop
+                        Set_Suppress_Style_Checks (E,
+                          (Chars (Expression (Arg1)) = Name_Off));
+                        exit when No (Homonym (E));
+                        E := Homonym (E);
+                     end loop;
+                  end if;
+               end;
+
+            --  One argument form
+
+            else
+               Check_Arg_Count (1);
+
+               if Nkind (A) = N_String_Literal then
+                  S   := Strval (A);
+
+                  declare
+                     Slen    : Natural := Natural (String_Length (S));
+                     Options : String (1 .. Slen);
+                     J       : Natural;
+
+                  begin
+                     J := 1;
+                     loop
+                        C := Get_String_Char (S, Int (J));
+                        exit when not In_Character_Range (C);
+                        Options (J) := Get_Character (C);
+
+                        if J = Slen then
+                           Set_Style_Check_Options (Options);
+                           exit;
+                        else
+                           J := J + 1;
+                        end if;
+                     end loop;
+                  end;
+
+               elsif Nkind (A) = N_Identifier then
+
+                  if Chars (A) = Name_All_Checks then
+                     Set_Default_Style_Check_Options;
+
+                  elsif Chars (A) = Name_On then
+                     Style_Check := True;
+
+                  elsif Chars (A) = Name_Off then
+                     Style_Check := False;
+
+                  end if;
+               end if;
+            end if;
+         end Style_Checks;
+
+         --------------
+         -- Subtitle --
+         --------------
+
+         --  pragma Subtitle ([Subtitle =>] STRING_LITERAL);
+
+         when Pragma_Subtitle =>
+            GNAT_Pragma;
+            Check_Arg_Count (1);
+            Check_Optional_Identifier (Arg1, Name_Subtitle);
+            Check_Arg_Is_String_Literal (Arg1);
+
+         --------------
+         -- Suppress --
+         --------------
+
+         --  pragma Suppress (IDENTIFIER [, [On =>] NAME]);
+
+         when Pragma_Suppress =>
+            Process_Suppress_Unsuppress (True);
+
+         ------------------
+         -- Suppress_All --
+         ------------------
+
+         --  pragma Suppress_All;
+
+         --  The only check made here is that the pragma appears in the
+         --  proper place, i.e. following a compilation unit. If indeed
+         --  it appears in this context, then the parser has already
+         --  inserted an equivalent pragma Suppress (All_Checks) to get
+         --  the required effect.
+
+         when Pragma_Suppress_All =>
+            GNAT_Pragma;
+            Check_Arg_Count (0);
+
+            if Nkind (Parent (N)) /= N_Compilation_Unit_Aux
+              or else not Is_List_Member (N)
+              or else List_Containing (N) /= Pragmas_After (Parent (N))
+            then
+               Error_Pragma
+                 ("misplaced pragma%, must follow compilation unit");
+            end if;
+
+         -------------------------
+         -- Suppress_Debug_Info --
+         -------------------------
+
+         --  pragma Suppress_Debug_Info ([Entity =>] LOCAL_NAME);
+
+         when Pragma_Suppress_Debug_Info =>
+            GNAT_Pragma;
+            Check_Arg_Count (1);
+            Check_Arg_Is_Local_Name (Arg1);
+            Check_Optional_Identifier (Arg1, Name_Entity);
+            Set_Debug_Info_Off (Entity (Get_Pragma_Arg (Arg1)));
+
+         -----------------------------
+         -- Suppress_Initialization --
+         -----------------------------
+
+         --  pragma Suppress_Initialization ([Entity =>] type_Name);
+
+         when Pragma_Suppress_Initialization => Suppress_Init : declare
+            E_Id : Node_Id;
+            E    : Entity_Id;
+
+         begin
+            GNAT_Pragma;
+            Check_Arg_Count (1);
+            Check_Optional_Identifier (Arg1, Name_Entity);
+            Check_Arg_Is_Local_Name (Arg1);
+
+            E_Id := Expression (Arg1);
+
+            if Etype (E_Id) = Any_Type then
+               return;
+            end if;
+
+            E := Entity (E_Id);
+
+            if Is_Type (E) then
+               if Is_Incomplete_Or_Private_Type (E) then
+                  if No (Full_View (Base_Type (E))) then
+                     Error_Pragma_Arg
+                       ("argument of pragma% cannot be an incomplete type",
+                         Arg1);
+                  else
+                     Set_Suppress_Init_Proc (Full_View (Base_Type (E)));
+                  end if;
+               else
+                  Set_Suppress_Init_Proc (Base_Type (E));
+               end if;
+
+            else
+               Error_Pragma_Arg
+                 ("pragma% requires argument that is a type name", Arg1);
+            end if;
+         end Suppress_Init;
+
+         -----------------
+         -- System_Name --
+         -----------------
+
+         --  pragma System_Name (DIRECT_NAME);
+
+         --  Syntax check: one argument, which must be the identifier GNAT
+         --  or the identifier GCC, no other identifiers are acceptable.
+
+         when Pragma_System_Name =>
+            Check_No_Identifiers;
+            Check_Arg_Count (1);
+            Check_Arg_Is_One_Of (Arg1, Name_Gcc, Name_Gnat);
+
+         -----------------------------
+         -- Task_Dispatching_Policy --
+         -----------------------------
+
+         --  pragma Task_Dispatching_Policy (policy_IDENTIFIER);
+
+         when Pragma_Task_Dispatching_Policy => declare
+            DP : Character;
+
+         begin
+            Check_Ada_83_Warning;
+            Check_Arg_Count (1);
+            Check_No_Identifiers;
+            Check_Arg_Is_Task_Dispatching_Policy (Arg1);
+            Check_Valid_Configuration_Pragma;
+            Get_Name_String (Chars (Expression (Arg1)));
+            DP := Fold_Upper (Name_Buffer (1));
+
+            if Task_Dispatching_Policy /= ' '
+              and then Task_Dispatching_Policy /= DP
+            then
+               Error_Msg_Sloc := Task_Dispatching_Policy_Sloc;
+               Error_Pragma
+                 ("task dispatching policy incompatible with policy#");
+            else
+               Task_Dispatching_Policy := DP;
+               Task_Dispatching_Policy_Sloc := Loc;
+            end if;
+         end;
+
+         --------------
+         -- Task_Info --
+         --------------
+
+         --  pragma Task_Info (EXPRESSION);
+
+         when Pragma_Task_Info => Task_Info : declare
+            P : constant Node_Id := Parent (N);
+
+         begin
+            GNAT_Pragma;
+
+            if Nkind (P) /= N_Task_Definition then
+               Error_Pragma ("pragma% must appear in task definition");
+            end if;
+
+            Check_No_Identifiers;
+            Check_Arg_Count (1);
+
+            Analyze_And_Resolve (Expression (Arg1), RTE (RE_Task_Info_Type));
+
+            if Etype (Expression (Arg1)) = Any_Type then
+               return;
+            end if;
+
+            if Has_Task_Info_Pragma (P) then
+               Error_Pragma ("duplicate pragma% not allowed");
+            else
+               Set_Has_Task_Info_Pragma (P, True);
+            end if;
+
+         end Task_Info;
+
+         ---------------
+         -- Task_Name --
+         ---------------
+
+         --  pragma Task_Name (string_EXPRESSION);
+
+         when Pragma_Task_Name => Task_Name : declare
+         --  pragma Priority (EXPRESSION);
+
+            P   : constant Node_Id := Parent (N);
+            Arg : Node_Id;
+
+         begin
+            Check_No_Identifiers;
+            Check_Arg_Count (1);
+
+            Arg := Expression (Arg1);
+            Analyze_And_Resolve (Arg, Standard_String);
+
+            if Nkind (P) /= N_Task_Definition then
+               Pragma_Misplaced;
+            end if;
+
+            if Has_Task_Name_Pragma (P) then
+               Error_Pragma ("duplicate pragma% not allowed");
+            else
+               Set_Has_Task_Name_Pragma (P, True);
+               Record_Rep_Item (Defining_Identifier (Parent (P)), N);
+            end if;
+
+         end Task_Name;
+
+         ------------------
+         -- Task_Storage --
+         ------------------
+
+         --  pragma Task_Storage (
+         --     [Task_Type =>] LOCAL_NAME,
+         --     [Top_Guard =>] static_integer_EXPRESSION);
+
+         when Pragma_Task_Storage => Task_Storage : declare
+            Args  : Args_List (1 .. 2);
+            Names : Name_List (1 .. 2) := (
+                      Name_Task_Type,
+                      Name_Top_Guard);
+
+            Task_Type : Node_Id renames Args (1);
+            Top_Guard : Node_Id renames Args (2);
+
+            Ent : Entity_Id;
+
+         begin
+            GNAT_Pragma;
+            Gather_Associations (Names, Args);
+            Check_Arg_Is_Local_Name (Task_Type);
+
+            Ent := Entity (Task_Type);
+
+            if not Is_Task_Type (Ent) then
+               Error_Pragma_Arg
+                 ("argument for pragma% must be task type", Task_Type);
+            end if;
+
+            if No (Top_Guard) then
+               Error_Pragma_Arg
+                 ("pragma% takes two arguments", Task_Type);
+            else
+               Check_Arg_Is_Static_Expression (Top_Guard, Any_Integer);
+            end if;
+
+            Check_First_Subtype (Task_Type);
+
+            if Rep_Item_Too_Late (Ent, N) then
+               raise Pragma_Exit;
+            end if;
+
+         end Task_Storage;
+
+         ----------------
+         -- Time_Slice --
+         ----------------
+
+         --  pragma Time_Slice (static_duration_EXPRESSION);
+
+         when Pragma_Time_Slice => Time_Slice : declare
+            Val : Ureal;
+            Nod : Node_Id;
+
+         begin
+            GNAT_Pragma;
+            Check_Arg_Count (1);
+            Check_No_Identifiers;
+            Check_In_Main_Program;
+            Check_Arg_Is_Static_Expression (Arg1, Standard_Duration);
+
+            if not Error_Posted (Arg1) then
+               Nod := Next (N);
+               while Present (Nod) loop
+                  if Nkind (Nod) = N_Pragma
+                    and then Chars (Nod) = Name_Time_Slice
+                  then
+                     Error_Msg_Name_1 := Chars (N);
+                     Error_Msg_N ("duplicate pragma% not permitted", Nod);
+                  end if;
+
+                  Next (Nod);
+               end loop;
+            end if;
+
+            --  Process only if in main unit
+
+            if Get_Source_Unit (Loc) = Main_Unit then
+               Opt.Time_Slice_Set := True;
+               Val := Expr_Value_R (Expression (Arg1));
+
+               if Val <= Ureal_0 then
+                  Opt.Time_Slice_Value := 0;
+
+               elsif Val > UR_From_Uint (UI_From_Int (1000)) then
+                  Opt.Time_Slice_Value := 1_000_000_000;
+
+               else
+                  Opt.Time_Slice_Value :=
+                    UI_To_Int (UR_To_Uint (Val * UI_From_Int (1_000_000)));
+               end if;
+            end if;
+         end Time_Slice;
+
+         -----------
+         -- Title --
+         -----------
+
+         --  pragma Title (TITLING_OPTION [, TITLING OPTION]);
+
+         --   TITLING_OPTION ::=
+         --     [Title =>] STRING_LITERAL
+         --   | [Subtitle =>] STRING_LITERAL
+
+         when Pragma_Title => Title : declare
+            Args  : Args_List (1 .. 2);
+            Names : Name_List (1 .. 2) := (
+                      Name_Title,
+                      Name_Subtitle);
+
+         begin
+            GNAT_Pragma;
+            Gather_Associations (Names, Args);
+
+            for J in 1 .. 2 loop
+               if Present (Args (J)) then
+                  Check_Arg_Is_String_Literal (Args (J));
+               end if;
+            end loop;
+         end Title;
+
+         ---------------------
+         -- Unchecked_Union --
+         ---------------------
+
+         --  pragma Unchecked_Union (first_subtype_LOCAL_NAME)
+
+         when Pragma_Unchecked_Union => Unchecked_Union : declare
+            Assoc   : Node_Id := Arg1;
+            Type_Id : Node_Id := Expression (Assoc);
+            Typ     : Entity_Id;
+            Discr   : Entity_Id;
+            Tdef    : Node_Id;
+            Clist   : Node_Id;
+            Vpart   : Node_Id;
+            Comp    : Node_Id;
+            Variant : Node_Id;
+
+         begin
+            GNAT_Pragma;
+            Check_No_Identifiers;
+            Check_Arg_Count (1);
+            Check_Arg_Is_Local_Name (Arg1);
+
+            Find_Type (Type_Id);
+            Typ := Entity (Type_Id);
+
+            if Typ = Any_Type
+              or else Rep_Item_Too_Early (Typ, N)
+            then
+               return;
+            else
+               Typ := Underlying_Type (Typ);
+            end if;
+
+            if Rep_Item_Too_Late (Typ, N) then
+               return;
+            end if;
+
+            Check_First_Subtype (Arg1);
+
+            --  Note remaining cases are references to a type in the current
+            --  declarative part. If we find an error, we post the error on
+            --  the relevant type declaration at an appropriate point.
+
+            if not Is_Record_Type (Typ) then
+               Error_Msg_N ("Unchecked_Union must be record type", Typ);
+               return;
+
+            elsif Is_Tagged_Type (Typ) then
+               Error_Msg_N ("Unchecked_Union must not be tagged", Typ);
+               return;
+
+            elsif Is_Limited_Type (Typ) then
+               Error_Msg_N
+                 ("Unchecked_Union must not be limited record type", Typ);
+               return;
+
+            else
+               if not Has_Discriminants (Typ) then
+                  Error_Msg_N
+                    ("Unchecked_Union must have one discriminant", Typ);
+                  return;
+               end if;
+
+               Discr := First_Discriminant (Typ);
+
+               if Present (Next_Discriminant (Discr)) then
+                  Error_Msg_N
+                    ("Unchecked_Union must have exactly one discriminant",
+                     Next_Discriminant (Discr));
+                  return;
+               end if;
+
+               if No (Discriminant_Default_Value (Discr)) then
+                  Error_Msg_N
+                    ("Unchecked_Union discriminant must have default value",
+                     Discr);
+               end if;
+
+               Tdef  := Type_Definition (Declaration_Node (Typ));
+               Clist := Component_List (Tdef);
+
+               if No (Clist) or else No (Variant_Part (Clist)) then
+                  Error_Msg_N
+                    ("Unchecked_Union must have variant part",
+                     Tdef);
+                  return;
+               end if;
+
+               Vpart := Variant_Part (Clist);
+
+               if Is_Non_Empty_List (Component_Items (Clist)) then
+                  Error_Msg_N
+                    ("components before variant not allowed " &
+                     "in Unchecked_Union",
+                     First (Component_Items (Clist)));
+               end if;
+
+               Variant := First (Variants (Vpart));
+               while Present (Variant) loop
+                  Clist := Component_List (Variant);
+
+                  if Present (Variant_Part (Clist)) then
+                     Error_Msg_N
+                       ("Unchecked_Union may not have nested variants",
+                        Variant_Part (Clist));
+                  end if;
+
+                  if not Is_Non_Empty_List (Component_Items (Clist)) then
+                     Error_Msg_N
+                       ("Unchecked_Union may not have empty component list",
+                        Variant);
+                     return;
+                  end if;
+
+                  Comp := First (Component_Items (Clist));
+
+                  if Nkind (Comp) = N_Component_Declaration then
+
+                     if Present (Expression (Comp)) then
+                        Error_Msg_N
+                          ("default initialization not allowed " &
+                           "in Unchecked_Union",
+                           Expression (Comp));
+                     end if;
+
+                     declare
+                        Sindic : constant Node_Id :=
+                                   Subtype_Indication (Comp);
+
+                     begin
+                        if Nkind (Sindic) = N_Subtype_Indication then
+                           Check_Static_Constraint (Constraint (Sindic));
+                        end if;
+                     end;
+                  end if;
+
+                  if Present (Next (Comp)) then
+                     Error_Msg_N
+                       ("Unchecked_Union variant can have only one component",
+                        Next (Comp));
+                  end if;
+
+                  Next (Variant);
+               end loop;
+            end if;
+
+            Set_Is_Unchecked_Union           (Typ, True);
+            Set_Suppress_Discriminant_Checks (Typ, True);
+            Set_Convention                   (Typ, Convention_C);
+
+            Set_Has_Unchecked_Union (Base_Type (Typ), True);
+            Set_Is_Unchecked_Union  (Base_Type (Typ), True);
+
+         end Unchecked_Union;
+
+         ------------------------
+         -- Unimplemented_Unit --
+         ------------------------
+
+         --  pragma Unimplemented_Unit;
+
+         --  Note: this only gives an error if we are generating code,
+         --  or if we are in a generic library unit (where the pragma
+         --  appears in the body, not in the spec).
+
+         when Pragma_Unimplemented_Unit => Unimplemented_Unit : declare
+            Cunitent : Entity_Id := Cunit_Entity (Get_Source_Unit (Loc));
+            Ent_Kind : Entity_Kind := Ekind (Cunitent);
+
+         begin
+            GNAT_Pragma;
+            Check_Arg_Count (0);
+
+            if Operating_Mode = Generate_Code
+              or else Ent_Kind = E_Generic_Function
+              or else Ent_Kind = E_Generic_Procedure
+              or else Ent_Kind = E_Generic_Package
+            then
+               Get_Name_String (Chars (Cunitent));
+               Set_Casing (Mixed_Case);
+               Write_Str (Name_Buffer (1 .. Name_Len));
+               Write_Str (" is not implemented");
+               Write_Eol;
+               raise Unrecoverable_Error;
+            end if;
+         end Unimplemented_Unit;
+
+         ------------------------------
+         -- Unreserve_All_Interrupts --
+         ------------------------------
+
+         --  pragma Unreserve_All_Interrupts;
+
+         when Pragma_Unreserve_All_Interrupts =>
+            GNAT_Pragma;
+            Check_Arg_Count (0);
+
+            if In_Extended_Main_Code_Unit (Main_Unit_Entity) then
+               Unreserve_All_Interrupts := True;
+            end if;
+
+         ----------------
+         -- Unsuppress --
+         ----------------
+
+         --  pragma Unsuppress (IDENTIFIER [, [On =>] NAME]);
+
+         when Pragma_Unsuppress =>
+            GNAT_Pragma;
+            Process_Suppress_Unsuppress (False);
+
+         -------------------
+         -- Use_VADS_Size --
+         -------------------
+
+         --  pragma Use_VADS_Size;
+
+         when Pragma_Use_VADS_Size =>
+            GNAT_Pragma;
+            Check_Arg_Count (0);
+            Check_Valid_Configuration_Pragma;
+            Use_VADS_Size := True;
+
+         ---------------------
+         -- Validity_Checks --
+         ---------------------
+
+         --  pragma Validity_Checks (On | Off | ALL_CHECKS | STRING_LITERAL);
+
+         when Pragma_Validity_Checks => Validity_Checks : declare
+            A  : constant Node_Id   := Expression (Arg1);
+            S  : String_Id;
+            C  : Char_Code;
+
+         begin
+            GNAT_Pragma;
+            Check_Arg_Count (1);
+            Check_Valid_Configuration_Pragma;
+            Check_No_Identifiers;
+
+            if Nkind (A) = N_String_Literal then
+               S   := Strval (A);
+
+               declare
+                  Slen    : Natural := Natural (String_Length (S));
+                  Options : String (1 .. Slen);
+                  J       : Natural;
+
+               begin
+                  J := 1;
+                  loop
+                     C := Get_String_Char (S, Int (J));
+                     exit when not In_Character_Range (C);
+                     Options (J) := Get_Character (C);
+
+                     if J = Slen then
+                        Set_Validity_Check_Options (Options);
+                        exit;
+                     else
+                        J := J + 1;
+                     end if;
+                  end loop;
+               end;
+
+            elsif Nkind (A) = N_Identifier then
+
+               if Chars (A) = Name_All_Checks then
+                  Set_Validity_Check_Options ("a");
+
+               elsif Chars (A) = Name_On then
+                  Validity_Checks_On := True;
+
+               elsif Chars (A) = Name_Off then
+                  Validity_Checks_On := False;
+
+               end if;
+            end if;
+         end Validity_Checks;
+
+         --------------
+         -- Volatile --
+         --------------
+
+         --  pragma Volatile (LOCAL_NAME);
+
+         when Pragma_Volatile =>
+            Process_Atomic_Shared_Volatile;
+
+         -------------------------
+         -- Volatile_Components --
+         -------------------------
+
+         --  pragma Volatile_Components (array_LOCAL_NAME);
+
+         --  Volatile is handled by the same circuit as Atomic_Components
+
+         --------------
+         -- Warnings --
+         --------------
+
+         --  pragma Warnings (On | Off, [LOCAL_NAME])
+
+         when Pragma_Warnings =>
+            GNAT_Pragma;
+            Check_At_Least_N_Arguments (1);
+            Check_At_Most_N_Arguments (2);
+            Check_No_Identifiers;
+
+            --  One argument case was processed by parser in Par.Prag
+
+            if Arg_Count /= 1 then
+               Check_Arg_Is_One_Of (Arg1, Name_On, Name_Off);
+               Check_Arg_Count (2);
+
+               declare
+                  E_Id : Node_Id;
+                  E    : Entity_Id;
+
+               begin
+                  E_Id := Expression (Arg2);
+                  Analyze (E_Id);
+
+                  if not Is_Entity_Name (E_Id) then
+                     Error_Pragma_Arg
+                       ("second argument of pragma% must be entity name",
+                        Arg2);
+                  end if;
+
+                  E := Entity (E_Id);
+
+                  if E = Any_Id then
+                     return;
+                  else
+                     loop
+                        Set_Warnings_Off (E,
+                          (Chars (Expression (Arg1)) = Name_Off));
+
+                        if Is_Enumeration_Type (E) then
+                           declare
+                              Lit : Entity_Id := First_Literal (E);
+
+                           begin
+                              while Present (Lit) loop
+                                 Set_Warnings_Off (Lit);
+                                 Next_Literal (Lit);
+                              end loop;
+                           end;
+                        end if;
+
+                        exit when No (Homonym (E));
+                        E := Homonym (E);
+                     end loop;
+                  end if;
+               end;
+            end if;
+
+         -------------------
+         -- Weak_External --
+         -------------------
+
+         --  pragma Weak_External ([Entity =>] LOCAL_NAME);
+
+         when Pragma_Weak_External => Weak_External : declare
+            Ent : Entity_Id;
+
+         begin
+            GNAT_Pragma;
+            Check_Arg_Count (1);
+            Check_Optional_Identifier (Arg1, Name_Entity);
+            Check_Arg_Is_Library_Level_Local_Name (Arg1);
+            Ent := Entity (Expression (Arg1));
+
+            if Rep_Item_Too_Early (Ent, N) then
+               return;
+            else
+               Ent := Underlying_Type (Ent);
+            end if;
+
+            --  The only processing required is to link this item on to the
+            --  list of rep items for the given entity. This is accomplished
+            --  by the call to Rep_Item_Too_Late (when no error is detected
+            --  and False is returned).
+
+            if Rep_Item_Too_Late (Ent, N) then
+               return;
+            else
+               Set_Has_Gigi_Rep_Item (Ent);
+            end if;
+         end Weak_External;
+
+      end case;
+
+   exception
+      when Pragma_Exit => null;
+
+   end Analyze_Pragma;
+
+   -------------------------
+   -- Get_Base_Subprogram --
+   -------------------------
+
+   function Get_Base_Subprogram (Def_Id : Entity_Id) return Entity_Id is
+      Result : Entity_Id;
+
+   begin
+      Result := Def_Id;
+
+      --  Follow subprogram renaming chain
+
+      while Is_Subprogram (Result)
+        and then
+          (Is_Generic_Instance (Result)
+            or else Nkind (Parent (Declaration_Node (Result))) =
+              N_Subprogram_Renaming_Declaration)
+        and then Present (Alias (Result))
+      loop
+         Result := Alias (Result);
+      end loop;
+
+      return Result;
+   end Get_Base_Subprogram;
+
+   ---------------------------
+   -- Is_Generic_Subprogram --
+   ---------------------------
+
+   function Is_Generic_Subprogram (Id : Entity_Id) return Boolean is
+   begin
+      return  Ekind (Id) = E_Generic_Procedure
+        or else Ekind (Id) = E_Generic_Function;
+   end Is_Generic_Subprogram;
+
+   ------------------------------
+   -- Is_Pragma_String_Literal --
+   ------------------------------
+
+   --  This function returns true if the corresponding pragma argument is
+   --  a static string expression. These are the only cases in which string
+   --  literals can appear as pragma arguments. We also allow a string
+   --  literal as the first argument to pragma Assert (although it will
+   --  of course always generate a type error).
+
+   function Is_Pragma_String_Literal (Par : Node_Id) return Boolean is
+      Pragn : constant Node_Id := Parent (Par);
+      Assoc : constant List_Id := Pragma_Argument_Associations (Pragn);
+      Pname : constant Name_Id := Chars (Pragn);
+      Argn  : Natural;
+      N     : Node_Id;
+
+   begin
+      Argn := 1;
+      N := First (Assoc);
+      loop
+         exit when N = Par;
+         Argn := Argn + 1;
+         Next (N);
+      end loop;
+
+      if Pname = Name_Assert then
+         return True;
+
+      elsif Pname = Name_Export then
+         return Argn > 2;
+
+      elsif Pname = Name_Ident then
+         return Argn = 1;
+
+      elsif Pname = Name_Import then
+         return Argn > 2;
+
+      elsif Pname = Name_Interface_Name then
+         return Argn > 1;
+
+      elsif Pname = Name_Linker_Alias then
+         return Argn = 2;
+
+      elsif Pname = Name_Linker_Section then
+         return Argn = 2;
+
+      elsif Pname = Name_Machine_Attribute then
+         return Argn = 2;
+
+      elsif Pname = Name_Source_File_Name then
+         return True;
+
+      elsif Pname = Name_Source_Reference then
+         return Argn = 2;
+
+      elsif Pname = Name_Title then
+         return True;
+
+      elsif Pname = Name_Subtitle then
+         return True;
+
+      else
+         return False;
+      end if;
+
+   end Is_Pragma_String_Literal;
+
+   --------------------------------------
+   -- Process_Compilation_Unit_Pragmas --
+   --------------------------------------
+
+   procedure Process_Compilation_Unit_Pragmas (N : Node_Id) is
+   begin
+      --  A special check for pragma Suppress_All. This is a strange DEC
+      --  pragma, strange because it comes at the end of the unit. If we
+      --  have a pragma Suppress_All in the Pragmas_After of the current
+      --  unit, then we insert a pragma Suppress (All_Checks) at the start
+      --  of the context clause to ensure the correct processing.
+
+      declare
+         PA : constant List_Id := Pragmas_After (Aux_Decls_Node (N));
+         P  : Node_Id;
+
+      begin
+         if Present (PA) then
+            P := First (PA);
+            while Present (P) loop
+               if Chars (P) = Name_Suppress_All then
+                  Prepend_To (Context_Items (N),
+                    Make_Pragma (Sloc (P),
+                      Chars => Name_Suppress,
+                      Pragma_Argument_Associations => New_List (
+                        Make_Pragma_Argument_Association (Sloc (P),
+                          Expression =>
+                            Make_Identifier (Sloc (P),
+                              Chars => Name_All_Checks)))));
+                  exit;
+               end if;
+
+               Next (P);
+            end loop;
+         end if;
+      end;
+   end Process_Compilation_Unit_Pragmas;
+
+   --------------------------------
+   -- Set_Encoded_Interface_Name --
+   --------------------------------
+
+   procedure Set_Encoded_Interface_Name (E : Entity_Id; S : Node_Id) is
+      Str : constant String_Id := Strval (S);
+      Len : constant Int       := String_Length (Str);
+      CC  : Char_Code;
+      C   : Character;
+      J   : Int;
+
+      Hex : constant array (0 .. 15) of Character := "0123456789abcdef";
+
+      procedure Encode;
+      --  Stores encoded value of character code CC. The encoding we
+      --  use an underscore followed by four lower case hex digits.
+
+      procedure Encode is
+      begin
+         Store_String_Char (Get_Char_Code ('_'));
+         Store_String_Char
+           (Get_Char_Code (Hex (Integer (CC / 2 ** 12))));
+         Store_String_Char
+           (Get_Char_Code (Hex (Integer (CC / 2 ** 8 and 16#0F#))));
+         Store_String_Char
+           (Get_Char_Code (Hex (Integer (CC / 2 ** 4 and 16#0F#))));
+         Store_String_Char
+           (Get_Char_Code (Hex (Integer (CC and 16#0F#))));
+      end Encode;
+
+   --  Start of processing for Set_Encoded_Interface_Name
+
+   begin
+      --  If first character is asterisk, this is a link name, and we
+      --  leave it completely unmodified. We also ignore null strings
+      --  (the latter case happens only in error cases) and no encoding
+      --  should occur for Java interface names.
+
+      if Len = 0
+        or else Get_String_Char (Str, 1) = Get_Char_Code ('*')
+        or else Java_VM
+      then
+         Set_Interface_Name (E, S);
+
+      else
+         J := 1;
+         loop
+            CC := Get_String_Char (Str, J);
+
+            exit when not In_Character_Range (CC);
+
+            C := Get_Character (CC);
+
+            exit when C /= '_' and then C /= '$'
+              and then C not in '0' .. '9'
+              and then C not in 'a' .. 'z'
+              and then C not in 'A' .. 'Z';
+
+            if J = Len then
+               Set_Interface_Name (E, S);
+               return;
+
+            else
+               J := J + 1;
+            end if;
+         end loop;
+
+         --  Here we need to encode. The encoding we use as follows:
+         --     three underscores  + four hex digits (lower case)
+
+         Start_String;
+
+         for J in 1 .. String_Length (Str) loop
+            CC := Get_String_Char (Str, J);
+
+            if not In_Character_Range (CC) then
+               Encode;
+            else
+               C := Get_Character (CC);
+
+               if C = '_' or else C = '$'
+                 or else C in '0' .. '9'
+                 or else C in 'a' .. 'z'
+                 or else C in 'A' .. 'Z'
+               then
+                  Store_String_Char (CC);
+               else
+                  Encode;
+               end if;
+            end if;
+         end loop;
+
+         Set_Interface_Name (E,
+           Make_String_Literal (Sloc (S),
+             Strval => End_String));
+      end if;
+   end Set_Encoded_Interface_Name;
+
+   -------------------
+   -- Set_Unit_Name --
+   -------------------
+
+   procedure Set_Unit_Name (N : Node_Id; With_Item : Node_Id) is
+      Pref : Node_Id;
+      Scop : Entity_Id;
+
+   begin
+      if Nkind (N) = N_Identifier
+        and then Nkind (With_Item) = N_Identifier
+      then
+         Set_Entity (N, Entity (With_Item));
+
+      elsif Nkind (N) = N_Selected_Component then
+         Change_Selected_Component_To_Expanded_Name (N);
+         Set_Entity (N, Entity (With_Item));
+         Set_Entity (Selector_Name (N), Entity (N));
+
+         Pref := Prefix (N);
+         Scop := Scope (Entity (N));
+
+         while Nkind (Pref) = N_Selected_Component loop
+            Change_Selected_Component_To_Expanded_Name (Pref);
+            Set_Entity (Selector_Name (Pref), Scop);
+            Set_Entity (Pref, Scop);
+            Pref := Prefix (Pref);
+            Scop := Scope (Scop);
+         end loop;
+
+         Set_Entity (Pref, Scop);
+      end if;
+   end Set_Unit_Name;
+
+end Sem_Prag;
diff --git a/gcc/ada/sem_prag.ads b/gcc/ada/sem_prag.ads
new file mode 100644 (file)
index 0000000..fca13a6
--- /dev/null
@@ -0,0 +1,62 @@
+------------------------------------------------------------------------------
+--                                                                          --
+--                         GNAT COMPILER COMPONENTS                         --
+--                                                                          --
+--                             S E M _ P R A G                              --
+--                                                                          --
+--                                 S p e c                                  --
+--                                                                          --
+--                            $Revision: 1.6 $                              --
+--                                                                          --
+--          Copyright (C) 1992-1997 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- --
+-- ware  Foundation;  either version 2,  or (at your option) any later ver- --
+-- sion.  GNAT is distributed in the hope that it will be useful, but WITH- --
+-- OUT ANY WARRANTY;  without even the  implied warranty of MERCHANTABILITY --
+-- or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License --
+-- for  more details.  You should have  received  a copy of the GNU General --
+-- Public License  distributed with GNAT;  see file COPYING.  If not, write --
+-- to  the Free Software Foundation,  59 Temple Place - Suite 330,  Boston, --
+-- MA 02111-1307, USA.                                                      --
+--                                                                          --
+-- GNAT was originally developed  by the GNAT team at  New York University. --
+-- It is now maintained by Ada Core Technologies Inc (http://www.gnat.com). --
+--                                                                          --
+------------------------------------------------------------------------------
+
+--  Pragma handling is isolated in a separate package
+--  (logically this processing belongs in chapter 4)
+
+with Types; use Types;
+package Sem_Prag is
+
+   procedure Analyze_Pragma (N : Node_Id);
+   --  Analyze procedure for pragma reference node N
+
+   function Is_Pragma_String_Literal (Par : Node_Id) return Boolean;
+   --  Given an N_Pragma_Argument_Association node, Par, which has the form
+   --  of an operator symbol, determines whether or not it should be treated
+   --  as an string literal. This is called by Sem_Ch6.Analyze_Operator_Symbol.
+   --  If True is returned, the argument is converted to a string literal. If
+   --  False is returned, then the argument is treated as an entity reference
+   --  to the operator.
+
+   procedure Process_Compilation_Unit_Pragmas (N : Node_Id);
+   --  Called at the start of processing compilation unit N to deal with
+   --  any special issues regarding pragmas. In particular, we have to
+   --  deal with Suppress_All at this stage, since it appears after the
+   --  unit instead of before.
+
+   procedure Set_Encoded_Interface_Name (E : Entity_Id; S : Node_Id);
+   --  This routine is used to set an encoded interface name. The node
+   --  S is an N_String_Literal node for the external name to be set, and
+   --  E is an entity whose Interface_Name field is to be set. In the
+   --  normal case where S contains a name that is a valid C identifier,
+   --  then S is simply set as the value of the Interface_Name. Otherwise
+   --  it is encoded. See the body for details of the encoding. This
+   --  encoding is only done on VMS systems, since it seems pretty silly,
+   --  but is needed to pass some dubious tests in the test suite.
+
+end Sem_Prag;
diff --git a/gcc/ada/sem_res.adb b/gcc/ada/sem_res.adb
new file mode 100644 (file)
index 0000000..641b120
--- /dev/null
@@ -0,0 +1,6403 @@
+------------------------------------------------------------------------------
+--                                                                          --
+--                         GNAT COMPILER COMPONENTS                         --
+--                                                                          --
+--                              S E M _ R E S                               --
+--                                                                          --
+--                                 B o d y                                  --
+--                                                                          --
+--                            $Revision: 1.717 $
+--                                                                          --
+--          Copyright (C) 1992-2001, 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- --
+-- ware  Foundation;  either version 2,  or (at your option) any later ver- --
+-- sion.  GNAT is distributed in the hope that it will be useful, but WITH- --
+-- OUT ANY WARRANTY;  without even the  implied warranty of MERCHANTABILITY --
+-- or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License --
+-- for  more details.  You should have  received  a copy of the GNU General --
+-- Public License  distributed with GNAT;  see file COPYING.  If not, write --
+-- to  the Free Software Foundation,  59 Temple Place - Suite 330,  Boston, --
+-- MA 02111-1307, USA.                                                      --
+--                                                                          --
+-- GNAT was originally developed  by the GNAT team at  New York University. --
+-- It is now maintained by Ada Core Technologies Inc (http://www.gnat.com). --
+--                                                                          --
+------------------------------------------------------------------------------
+
+with Atree;    use Atree;
+with Checks;   use Checks;
+with Debug;    use Debug;
+with Debug_A;  use Debug_A;
+with Einfo;    use Einfo;
+with Errout;   use Errout;
+with Expander; use Expander;
+with Exp_Ch7;  use Exp_Ch7;
+with Exp_Util; use Exp_Util;
+with Freeze;   use Freeze;
+with Itypes;   use Itypes;
+with Lib;      use Lib;
+with Lib.Xref; use Lib.Xref;
+with Namet;    use Namet;
+with Nmake;    use Nmake;
+with Nlists;   use Nlists;
+with Opt;      use Opt;
+with Output;   use Output;
+with Restrict; use Restrict;
+with Rtsfind;  use Rtsfind;
+with Sem;      use Sem;
+with Sem_Aggr; use Sem_Aggr;
+with Sem_Attr; use Sem_Attr;
+with Sem_Cat;  use Sem_Cat;
+with Sem_Ch4;  use Sem_Ch4;
+with Sem_Ch6;  use Sem_Ch6;
+with Sem_Ch8;  use Sem_Ch8;
+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_Intr; use Sem_Intr;
+with Sem_Util; use Sem_Util;
+with Sem_Type; use Sem_Type;
+with Sem_Warn; use Sem_Warn;
+with Sinfo;    use Sinfo;
+with Stand;    use Stand;
+with Stringt;  use Stringt;
+with Targparm; use Targparm;
+with Tbuild;   use Tbuild;
+with Uintp;    use Uintp;
+with Urealp;   use Urealp;
+
+package body Sem_Res is
+
+   -----------------------
+   -- Local Subprograms --
+   -----------------------
+
+   --  Second pass (top-down) type checking and overload resolution procedures
+   --  Typ is the type required by context. These procedures propagate the
+   --  type information recursively to the descendants of N. If the node
+   --  is not overloaded, its Etype is established in the first pass. If
+   --  overloaded,  the Resolve routines set the correct type. For arith.
+   --  operators, the Etype is the base type of the context.
+
+   --  Note that Resolve_Attribute is separated off in Sem_Attr
+
+   procedure Ambiguous_Character (C : Node_Id);
+   --  Give list of candidate interpretations when a character literal cannot
+   --  be resolved.
+
+   procedure Check_Discriminant_Use (N : Node_Id);
+   --  Enforce the restrictions on the use of discriminants when constraining
+   --  a component of a discriminated type (record or concurrent type).
+
+   procedure Check_For_Visible_Operator (N : Node_Id; T : Entity_Id);
+   --  Given a node for an operator associated with type T, check that
+   --  the operator is visible. Operators all of whose operands are
+   --  universal must be checked for visibility during resolution
+   --  because their type is not determinable based on their operands.
+
+   function Check_Infinite_Recursion (N : Node_Id) return Boolean;
+   --  Given a call node, N, which is known to occur immediately within the
+   --  subprogram being called, determines whether it is a detectable case of
+   --  an infinite recursion, and if so, outputs appropriate messages. Returns
+   --  True if an infinite recursion is detected, and False otherwise.
+
+   procedure Check_Initialization_Call (N : Entity_Id; Nam : Entity_Id);
+   --  If the type of the object being initialized uses the secondary stack
+   --  directly or indirectly, create a transient scope for the call to the
+   --  Init_Proc. This is because we do not create transient scopes for the
+   --  initialization of individual components within the init_proc itself.
+   --  Could be optimized away perhaps?
+
+   function Is_Predefined_Op (Nam : Entity_Id) return Boolean;
+   --  Utility to check whether the name in the call is a predefined
+   --  operator, in which case the call is made into an operator node.
+   --  An instance of an intrinsic conversion operation may be given
+   --  an operator name, but is not treated like an operator.
+
+   procedure Replace_Actual_Discriminants (N : Node_Id; Default : Node_Id);
+   --  If a default expression in entry call N depends on the discriminants
+   --  of the task, it must be replaced with a reference to the discriminant
+   --  of the task being called.
+
+   procedure Resolve_Allocator                 (N : Node_Id; Typ : Entity_Id);
+   procedure Resolve_Arithmetic_Op             (N : Node_Id; Typ : Entity_Id);
+   procedure Resolve_Call                      (N : Node_Id; Typ : Entity_Id);
+   procedure Resolve_Character_Literal         (N : Node_Id; Typ : Entity_Id);
+   procedure Resolve_Comparison_Op             (N : Node_Id; Typ : Entity_Id);
+   procedure Resolve_Conditional_Expression    (N : Node_Id; Typ : Entity_Id);
+   procedure Resolve_Equality_Op               (N : Node_Id; Typ : Entity_Id);
+   procedure Resolve_Explicit_Dereference      (N : Node_Id; Typ : Entity_Id);
+   procedure Resolve_Entity_Name               (N : Node_Id; Typ : Entity_Id);
+   procedure Resolve_Indexed_Component         (N : Node_Id; Typ : Entity_Id);
+   procedure Resolve_Integer_Literal           (N : Node_Id; Typ : Entity_Id);
+   procedure Resolve_Logical_Op                (N : Node_Id; Typ : Entity_Id);
+   procedure Resolve_Membership_Op             (N : Node_Id; Typ : Entity_Id);
+   procedure Resolve_Null                      (N : Node_Id; Typ : Entity_Id);
+   procedure Resolve_Operator_Symbol           (N : Node_Id; Typ : Entity_Id);
+   procedure Resolve_Op_Concat                 (N : Node_Id; Typ : Entity_Id);
+   procedure Resolve_Op_Expon                  (N : Node_Id; Typ : Entity_Id);
+   procedure Resolve_Op_Not                    (N : Node_Id; Typ : Entity_Id);
+   procedure Resolve_Qualified_Expression      (N : Node_Id; Typ : Entity_Id);
+   procedure Resolve_Range                     (N : Node_Id; Typ : Entity_Id);
+   procedure Resolve_Real_Literal              (N : Node_Id; Typ : Entity_Id);
+   procedure Resolve_Reference                 (N : Node_Id; Typ : Entity_Id);
+   procedure Resolve_Selected_Component        (N : Node_Id; Typ : Entity_Id);
+   procedure Resolve_Shift                     (N : Node_Id; Typ : Entity_Id);
+   procedure Resolve_Short_Circuit             (N : Node_Id; Typ : Entity_Id);
+   procedure Resolve_Slice                     (N : Node_Id; Typ : Entity_Id);
+   procedure Resolve_String_Literal            (N : Node_Id; Typ : Entity_Id);
+   procedure Resolve_Subprogram_Info           (N : Node_Id; Typ : Entity_Id);
+   procedure Resolve_Type_Conversion           (N : Node_Id; Typ : Entity_Id);
+   procedure Resolve_Unary_Op                  (N : Node_Id; Typ : Entity_Id);
+   procedure Resolve_Unchecked_Expression      (N : Node_Id; Typ : Entity_Id);
+   procedure Resolve_Unchecked_Type_Conversion (N : Node_Id; Typ : Entity_Id);
+
+   function Operator_Kind
+     (Op_Name   : Name_Id;
+      Is_Binary : Boolean)
+      return      Node_Kind;
+   --  Utility to map the name of an operator into the corresponding Node. Used
+   --  by other node rewriting procedures.
+
+   procedure Resolve_Actuals (N : Node_Id; Nam : Entity_Id);
+   --  Resolve actuals of call, and add default expressions for missing ones.
+
+   procedure Resolve_Entry_Call (N : Node_Id; Typ : Entity_Id);
+   --  Called from Resolve_Call, when the prefix denotes an entry or element
+   --  of entry family. Actuals are resolved as for subprograms, and the node
+   --  is rebuilt as an entry call. Also called for protected operations. Typ
+   --  is the context type, which is used when the operation is a protected
+   --  function with no arguments, and the return value is indexed.
+
+   procedure Resolve_Intrinsic_Operator (N : Node_Id; Typ : Entity_Id);
+   --  A call to a user-defined intrinsic operator is rewritten as a call
+   --  to the corresponding predefined operator, with suitable conversions.
+
+   procedure Rewrite_Operator_As_Call (N : Node_Id; Nam : Entity_Id);
+   --  If an operator node resolves to a call to a user-defined operator,
+   --  rewrite the node as a function call.
+
+   procedure Make_Call_Into_Operator
+     (N     : Node_Id;
+      Typ   : Entity_Id;
+      Op_Id : Entity_Id);
+   --  Inverse transformation: if an operator is given in functional notation,
+   --  then after resolving the node, transform into an operator node, so
+   --  that operands are resolved properly. Recall that predefined operators
+   --  do not have a full signature and special resolution rules apply.
+
+   procedure Rewrite_Renamed_Operator (N : Node_Id; Op : Entity_Id);
+   --  An operator can rename another, e.g. in  an instantiation. In that
+   --  case, the proper operator node must be constructed.
+
+   procedure Set_String_Literal_Subtype (N : Node_Id; Typ : Entity_Id);
+   --  The String_Literal_Subtype is built for all strings that are not
+   --  operands of a static concatenation operation. If the argument is not
+   --  a String the function is a no-op.
+
+   procedure Set_Slice_Subtype (N : Node_Id);
+   --  Build subtype of array type, with the range specified by the slice.
+
+   function Unique_Fixed_Point_Type (N : Node_Id) return Entity_Id;
+   --  A universal_fixed expression in an universal context is unambiguous if
+   --  there is only one applicable fixed point type. Determining whether
+   --  there is only one requires a search over all visible entities, and
+   --  happens only in very pathological cases (see 6115-006).
+
+   function Valid_Conversion
+     (N       : Node_Id;
+      Target  : Entity_Id;
+      Operand : Node_Id)
+      return    Boolean;
+   --  Verify legality rules given in 4.6 (8-23). Target is the target
+   --  type of the conversion, which may be an implicit conversion of
+   --  an actual parameter to an anonymous access type (in which case
+   --  N denotes the actual parameter and N = Operand).
+
+   -------------------------
+   -- Ambiguous_Character --
+   -------------------------
+
+   procedure Ambiguous_Character (C : Node_Id) is
+      E : Entity_Id;
+
+   begin
+      if Nkind (C) = N_Character_Literal then
+         Error_Msg_N ("ambiguous character literal", C);
+         Error_Msg_N
+           ("\possible interpretations: Character, Wide_Character!", C);
+
+         E := Current_Entity (C);
+
+         if Present (E) then
+
+            while Present (E) loop
+               Error_Msg_NE ("\possible interpretation:}!", C, Etype (E));
+               E := Homonym (E);
+            end loop;
+         end if;
+      end if;
+   end Ambiguous_Character;
+
+   -------------------------
+   -- Analyze_And_Resolve --
+   -------------------------
+
+   procedure Analyze_And_Resolve (N : Node_Id) is
+   begin
+      Analyze (N);
+      Resolve (N, Etype (N));
+   end Analyze_And_Resolve;
+
+   procedure Analyze_And_Resolve (N : Node_Id; Typ : Entity_Id) is
+   begin
+      Analyze (N);
+      Resolve (N, Typ);
+   end Analyze_And_Resolve;
+
+   --  Version withs check(s) suppressed
+
+   procedure Analyze_And_Resolve
+     (N        : Node_Id;
+      Typ      : Entity_Id;
+      Suppress : Check_Id)
+   is
+      Scop : Entity_Id := Current_Scope;
+
+   begin
+      if Suppress = All_Checks then
+         declare
+            Svg : constant Suppress_Record := Scope_Suppress;
+
+         begin
+            Scope_Suppress := (others => True);
+            Analyze_And_Resolve (N, Typ);
+            Scope_Suppress := Svg;
+         end;
+
+      else
+         declare
+            Svg : constant Boolean := Get_Scope_Suppress (Suppress);
+
+         begin
+            Set_Scope_Suppress (Suppress, True);
+            Analyze_And_Resolve (N, Typ);
+            Set_Scope_Suppress (Suppress, Svg);
+         end;
+      end if;
+
+      if Current_Scope /= Scop
+        and then Scope_Is_Transient
+      then
+         --  This can only happen if a transient scope was created
+         --  for an inner expression, which will be removed upon
+         --  completion of the analysis of an enclosing construct.
+         --  The transient scope must have the suppress status of
+         --  the enclosing environment, not of this Analyze call.
+
+         Scope_Stack.Table (Scope_Stack.Last).Save_Scope_Suppress :=
+           Scope_Suppress;
+      end if;
+   end Analyze_And_Resolve;
+
+   procedure Analyze_And_Resolve
+     (N        : Node_Id;
+      Suppress : Check_Id)
+   is
+      Scop : Entity_Id := Current_Scope;
+
+   begin
+      if Suppress = All_Checks then
+         declare
+            Svg : constant Suppress_Record := Scope_Suppress;
+
+         begin
+            Scope_Suppress := (others => True);
+            Analyze_And_Resolve (N);
+            Scope_Suppress := Svg;
+         end;
+
+      else
+         declare
+            Svg : constant Boolean := Get_Scope_Suppress (Suppress);
+
+         begin
+            Set_Scope_Suppress (Suppress, True);
+            Analyze_And_Resolve (N);
+            Set_Scope_Suppress (Suppress, Svg);
+         end;
+      end if;
+
+      if Current_Scope /= Scop
+        and then Scope_Is_Transient
+      then
+         Scope_Stack.Table (Scope_Stack.Last).Save_Scope_Suppress :=
+           Scope_Suppress;
+      end if;
+   end Analyze_And_Resolve;
+
+   ----------------------------
+   -- Check_Discriminant_Use --
+   ----------------------------
+
+   procedure Check_Discriminant_Use (N : Node_Id) is
+      PN   : constant Node_Id   := Parent (N);
+      Disc : constant Entity_Id := Entity (N);
+      P    : Node_Id;
+      D    : Node_Id;
+
+   begin
+      --  Any use in a default expression is legal.
+
+      if In_Default_Expression then
+         null;
+
+      elsif Nkind (PN) = N_Range then
+
+         --  Discriminant cannot be used to constrain a scalar type.
+
+         P := Parent (PN);
+
+         if Nkind (P) = N_Range_Constraint
+           and then Nkind (Parent (P)) = N_Subtype_Indication
+           and then Nkind (Parent (Parent (P))) = N_Component_Declaration
+         then
+            Error_Msg_N ("discriminant cannot constrain scalar type", N);
+
+         elsif Nkind (P) = N_Index_Or_Discriminant_Constraint then
+
+            --  The following check catches the unusual case where
+            --  a discriminant appears within an index constraint
+            --  that is part of a larger expression within a constraint
+            --  on a component, e.g. "C : Int range 1 .. F (new A(1 .. D))".
+            --  For now we only check case of record components, and
+            --  note that a similar check should also apply in the
+            --  case of discriminant constraints below. ???
+
+            --  Note that the check for N_Subtype_Declaration below is to
+            --  detect the valid use of discriminants in the constraints of a
+            --  subtype declaration when this subtype declaration appears
+            --  inside the scope of a record type (which is syntactically
+            --  illegal, but which may be created as part of derived type
+            --  processing for records). See Sem_Ch3.Build_Derived_Record_Type
+            --  for more info.
+
+            if Ekind (Current_Scope) = E_Record_Type
+              and then Scope (Disc) = Current_Scope
+              and then not
+                (Nkind (Parent (P)) = N_Subtype_Indication
+                 and then
+                  (Nkind (Parent (Parent (P))) = N_Component_Declaration
+                   or else Nkind (Parent (Parent (P))) = N_Subtype_Declaration)
+                  and then Paren_Count (N) = 0)
+            then
+               Error_Msg_N
+                 ("discriminant must appear alone in component constraint", N);
+               return;
+            end if;
+
+            --   Detect a common beginner error:
+            --   type R (D : Positive := 100) is record
+            --     Name: String (1 .. D);
+            --   end record;
+
+            --  The default value causes an object of type R to be
+            --  allocated with room for Positive'Last characters.
+
+            declare
+               SI : Node_Id;
+               T  : Entity_Id;
+               TB : Node_Id;
+               CB : Entity_Id;
+
+               function Large_Storage_Type (T : Entity_Id) return Boolean;
+               --  Return True if type T has a large enough range that
+               --  any array whose index type covered the whole range of
+               --  the type would likely raise Storage_Error.
+
+               function Large_Storage_Type (T : Entity_Id) return Boolean is
+               begin
+                  return
+                    T = Standard_Integer
+                      or else
+                    T = Standard_Positive
+                      or else
+                    T = Standard_Natural;
+               end Large_Storage_Type;
+
+            begin
+               --  Check that the Disc has a large range
+
+               if not Large_Storage_Type (Etype (Disc)) then
+                  goto No_Danger;
+               end if;
+
+               --  If the enclosing type is limited, we allocate only the
+               --  default value, not the maximum, and there is no need for
+               --  a warning.
+
+               if Is_Limited_Type (Scope (Disc)) then
+                  goto No_Danger;
+               end if;
+
+               --  Check that it is the high bound
+
+               if N /= High_Bound (PN)
+                 or else not Present (Discriminant_Default_Value (Disc))
+               then
+                  goto No_Danger;
+               end if;
+
+               --  Check the array allows a large range at this bound.
+               --  First find the array
+
+               SI := Parent (P);
+
+               if Nkind (SI) /= N_Subtype_Indication then
+                  goto No_Danger;
+               end if;
+
+               T := Entity (Subtype_Mark (SI));
+
+               if not Is_Array_Type (T) then
+                  goto No_Danger;
+               end if;
+
+               --  Next, find the dimension
+
+               TB := First_Index (T);
+               CB := First (Constraints (P));
+               while True
+                 and then Present (TB)
+                 and then Present (CB)
+                 and then CB /= PN
+               loop
+                  Next_Index (TB);
+                  Next (CB);
+               end loop;
+
+               if CB /= PN then
+                  goto No_Danger;
+               end if;
+
+               --  Now, check the dimension has a large range
+
+               if not Large_Storage_Type (Etype (TB)) then
+                  goto No_Danger;
+               end if;
+
+               --  Warn about the danger
+
+               Error_Msg_N
+                 ("creation of object of this type may raise Storage_Error?",
+                  N);
+
+               <<No_Danger>>
+                  null;
+
+            end;
+         end if;
+
+      --  Legal case is in index or discriminant constraint
+
+      elsif Nkind (PN) = N_Index_Or_Discriminant_Constraint
+        or else Nkind (PN) = N_Discriminant_Association
+      then
+         if Paren_Count (N) > 0 then
+            Error_Msg_N
+              ("discriminant in constraint must appear alone",  N);
+         end if;
+
+         return;
+
+      --  Otherwise, context is an expression. It should not be within
+      --  (i.e. a subexpression of) a constraint for a component.
+
+      else
+         D := PN;
+         P := Parent (PN);
+
+         while Nkind (P) /= N_Component_Declaration
+           and then Nkind (P) /= N_Subtype_Indication
+           and then Nkind (P) /= N_Entry_Declaration
+         loop
+            D := P;
+            P := Parent (P);
+            exit when No (P);
+         end loop;
+
+         --  If the discriminant is used in an expression that is a bound
+         --  of a scalar type, an Itype is created and the bounds are attached
+         --  to its range,  not to the original subtype indication. Such use
+         --  is of course a double fault.
+
+         if (Nkind (P) = N_Subtype_Indication
+              and then
+                (Nkind (Parent (P)) = N_Component_Declaration
+                  or else Nkind (Parent (P)) = N_Derived_Type_Definition)
+              and then D = Constraint (P))
+
+         --  The constraint itself may be given by a subtype indication,
+         --  rather than by a more common discrete range.
+
+           or else (Nkind (P) = N_Subtype_Indication
+             and then Nkind (Parent (P)) = N_Index_Or_Discriminant_Constraint)
+
+           or else Nkind (P) = N_Entry_Declaration
+           or else Nkind (D) = N_Defining_Identifier
+         then
+            Error_Msg_N
+              ("discriminant in constraint must appear alone",  N);
+         end if;
+      end if;
+   end Check_Discriminant_Use;
+
+   --------------------------------
+   -- Check_For_Visible_Operator --
+   --------------------------------
+
+   procedure Check_For_Visible_Operator (N : Node_Id; T : Entity_Id) is
+      Orig_Node : Node_Id := Original_Node (N);
+
+   begin
+      if Comes_From_Source (Orig_Node)
+        and then not In_Open_Scopes (Scope (T))
+        and then not Is_Potentially_Use_Visible (T)
+        and then not In_Use (T)
+        and then not In_Use (Scope (T))
+        and then (not Present (Entity (N))
+                   or else Ekind (Entity (N)) /= E_Function)
+        and then (Nkind (Orig_Node) /= N_Function_Call
+                   or else Nkind (Name (Orig_Node)) /= N_Expanded_Name
+                   or else Entity (Prefix (Name (Orig_Node))) /= Scope (T))
+        and then not In_Instance
+      then
+         Error_Msg_NE
+           ("operator for} is not directly visible!", N, First_Subtype (T));
+         Error_Msg_N ("use clause would make operation legal!", N);
+      end if;
+   end Check_For_Visible_Operator;
+
+   ------------------------------
+   -- Check_Infinite_Recursion --
+   ------------------------------
+
+   function Check_Infinite_Recursion (N : Node_Id) return Boolean is
+      P : Node_Id;
+      C : Node_Id;
+
+   begin
+      --  Loop moving up tree, quitting if something tells us we are
+      --  definitely not in an infinite recursion situation.
+
+      C := N;
+      loop
+         P := Parent (C);
+         exit when Nkind (P) = N_Subprogram_Body;
+
+         if Nkind (P) = N_Or_Else        or else
+            Nkind (P) = N_And_Then       or else
+            Nkind (P) = N_If_Statement   or else
+            Nkind (P) = N_Case_Statement
+         then
+            return False;
+
+         elsif Nkind (P) = N_Handled_Sequence_Of_Statements
+           and then C /= First (Statements (P))
+         then
+            return False;
+
+         else
+            C := P;
+         end if;
+      end loop;
+
+      Warn_On_Instance := True;
+      Error_Msg_N ("possible infinite recursion?", N);
+      Error_Msg_N ("\Storage_Error may be raised at run time?", N);
+      Warn_On_Instance := False;
+
+      return True;
+   end Check_Infinite_Recursion;
+
+   -------------------------------
+   -- Check_Initialization_Call --
+   -------------------------------
+
+   procedure Check_Initialization_Call (N : Entity_Id; Nam : Entity_Id) is
+      Typ : Entity_Id := Etype (First_Formal (Nam));
+
+      function Uses_SS (T : Entity_Id) return Boolean;
+
+      function Uses_SS (T : Entity_Id) return Boolean is
+         Comp : Entity_Id;
+         Expr : Node_Id;
+
+      begin
+         if Is_Controlled (T)
+           or else Has_Controlled_Component (T)
+           or else Functions_Return_By_DSP_On_Target
+         then
+            return False;
+
+         elsif Is_Array_Type (T) then
+            return Uses_SS (Component_Type (T));
+
+         elsif Is_Record_Type (T) then
+            Comp := First_Component (T);
+
+            while Present (Comp) loop
+
+               if Ekind (Comp) = E_Component
+                 and then Nkind (Parent (Comp)) = N_Component_Declaration
+               then
+                  Expr := Expression (Parent (Comp));
+
+                  if Nkind (Expr) = N_Function_Call
+                    and then Requires_Transient_Scope (Etype (Expr))
+                  then
+                     return True;
+
+                  elsif Uses_SS (Etype (Comp)) then
+                     return True;
+                  end if;
+               end if;
+
+               Next_Component (Comp);
+            end loop;
+
+            return False;
+
+         else
+            return False;
+         end if;
+      end Uses_SS;
+
+   begin
+      if Uses_SS (Typ) then
+         Establish_Transient_Scope (First_Actual (N), Sec_Stack => True);
+      end if;
+   end Check_Initialization_Call;
+
+   ------------------------------
+   -- Check_Parameterless_Call --
+   ------------------------------
+
+   procedure Check_Parameterless_Call (N : Node_Id) is
+      Nam : Node_Id;
+
+   begin
+      if Nkind (N) in N_Has_Etype and then Etype (N) = Any_Type then
+         return;
+      end if;
+
+      --  Rewrite as call if overloadable entity that is (or could be, in
+      --  the overloaded case) a function call. If we know for sure that
+      --  the entity is an enumeration literal, we do not rewrite it.
+
+      if (Is_Entity_Name (N)
+            and then Is_Overloadable (Entity (N))
+            and then (Ekind (Entity (N)) /= E_Enumeration_Literal
+                        or else Is_Overloaded (N)))
+
+      --  Rewrite as call if it is an explicit deference of an expression of
+      --  a subprogram access type, and the suprogram type is not that of a
+      --  procedure or entry.
+
+      or else
+        (Nkind (N) = N_Explicit_Dereference
+          and then Ekind (Etype (N)) = E_Subprogram_Type
+          and then Base_Type (Etype (Etype (N))) /= Standard_Void_Type)
+
+      --  Rewrite as call if it is a selected component which is a function,
+      --  this is the case of a call to a protected function (which may be
+      --  overloaded with other protected operations).
+
+      or else
+        (Nkind (N) = N_Selected_Component
+          and then (Ekind (Entity (Selector_Name (N))) = E_Function
+            or else ((Ekind (Entity (Selector_Name (N))) = E_Entry
+                       or else
+                      Ekind (Entity (Selector_Name (N))) = E_Procedure)
+              and then Is_Overloaded (Selector_Name (N)))))
+
+      --  If one of the above three conditions is met, rewrite as call.
+      --  Apply the rewriting only once.
+
+      then
+         if Nkind (Parent (N)) /= N_Function_Call
+           or else N /= Name (Parent (N))
+         then
+            Nam := New_Copy (N);
+
+            --  If overloaded, overload set belongs to new copy.
+
+            Save_Interps (N, Nam);
+
+            --  Change node to parameterless function call (note that the
+            --  Parameter_Associations associations field is left set to Empty,
+            --  its normal default value since there are no parameters)
+
+            Change_Node (N, N_Function_Call);
+            Set_Name (N, Nam);
+            Set_Sloc (N, Sloc (Nam));
+            Analyze_Call (N);
+         end if;
+
+      elsif Nkind (N) = N_Parameter_Association then
+         Check_Parameterless_Call (Explicit_Actual_Parameter (N));
+      end if;
+   end Check_Parameterless_Call;
+
+   ----------------------
+   -- Is_Predefined_Op --
+   ----------------------
+
+   function Is_Predefined_Op (Nam : Entity_Id) return Boolean is
+   begin
+      return Is_Intrinsic_Subprogram (Nam)
+        and then not Is_Generic_Instance (Nam)
+        and then Chars (Nam) in Any_Operator_Name
+        and then (No (Alias (Nam))
+                   or else Is_Predefined_Op (Alias (Nam)));
+   end Is_Predefined_Op;
+
+   -----------------------------
+   -- Make_Call_Into_Operator --
+   -----------------------------
+
+   procedure Make_Call_Into_Operator
+     (N     : Node_Id;
+      Typ   : Entity_Id;
+      Op_Id : Entity_Id)
+   is
+      Op_Name   : constant Name_Id := Chars (Op_Id);
+      Act1      : Node_Id := First_Actual (N);
+      Act2      : Node_Id := Next_Actual (Act1);
+      Error     : Boolean := False;
+      Is_Binary : constant Boolean := Present (Act2);
+      Op_Node   : Node_Id;
+      Opnd_Type : Entity_Id;
+      Orig_Type : Entity_Id := Empty;
+      Pack      : Entity_Id;
+
+      type Kind_Test is access function (E : Entity_Id) return Boolean;
+
+      function Is_Definite_Access_Type (E : Entity_Id) return Boolean;
+      --  Determine whether E is an acess type declared by an access decla-
+      --  ration, and  not an (anonymous) allocator type.
+
+      function Operand_Type_In_Scope (S : Entity_Id) return Boolean;
+      --  If the operand is not universal, and the operator is given by a
+      --  expanded name,  verify that the operand has an interpretation with
+      --  a type defined in the given scope of the operator.
+
+      function Type_In_P (Test : Kind_Test) return Entity_Id;
+      --  Find a type of the given class in the package Pack that contains
+      --  the operator.
+
+      -----------------------------
+      -- Is_Definite_Access_Type --
+      -----------------------------
+
+      function Is_Definite_Access_Type (E : Entity_Id) return Boolean is
+         Btyp : constant Entity_Id := Base_Type (E);
+      begin
+         return Ekind (Btyp) = E_Access_Type
+           or else (Ekind (Btyp) = E_Access_Subprogram_Type
+                     and then Comes_From_Source (Btyp));
+      end Is_Definite_Access_Type;
+
+      ---------------------------
+      -- Operand_Type_In_Scope --
+      ---------------------------
+
+      function Operand_Type_In_Scope (S : Entity_Id) return Boolean is
+         Nod : constant Node_Id := Right_Opnd (Op_Node);
+         I   : Interp_Index;
+         It  : Interp;
+
+      begin
+         if not Is_Overloaded (Nod) then
+            return Scope (Base_Type (Etype (Nod))) = S;
+
+         else
+            Get_First_Interp (Nod, I, It);
+
+            while Present (It.Typ) loop
+
+               if Scope (Base_Type (It.Typ)) = S then
+                  return True;
+               end if;
+
+               Get_Next_Interp (I, It);
+            end loop;
+
+            return False;
+         end if;
+      end Operand_Type_In_Scope;
+
+      ---------------
+      -- Type_In_P --
+      ---------------
+
+      function Type_In_P (Test : Kind_Test) return Entity_Id is
+         E : Entity_Id;
+
+         function In_Decl return Boolean;
+         --  Verify that node is not part of the type declaration for the
+         --  candidate type, which would otherwise be invisible.
+
+         -------------
+         -- In_Decl --
+         -------------
+
+         function In_Decl return Boolean is
+            Decl_Node : constant Node_Id := Parent (E);
+            N2        : Node_Id;
+
+         begin
+            N2 := N;
+
+            if Etype (E) = Any_Type then
+               return True;
+
+            elsif No (Decl_Node) then
+               return False;
+
+            else
+               while Present (N2)
+                 and then Nkind (N2) /= N_Compilation_Unit
+               loop
+                  if N2 = Decl_Node then
+                     return True;
+                  else
+                     N2 := Parent (N2);
+                  end if;
+               end loop;
+
+               return False;
+            end if;
+         end In_Decl;
+
+      --  Start of processing for Type_In_P
+
+      begin
+         --  If the context type is declared in the prefix package, this
+         --  is the desired base type.
+
+         if Scope (Base_Type (Typ)) = Pack
+           and then Test (Typ)
+         then
+            return Base_Type (Typ);
+
+         else
+            E := First_Entity (Pack);
+
+            while Present (E) loop
+
+               if Test (E)
+                 and then not In_Decl
+               then
+                  return E;
+               end if;
+
+               Next_Entity (E);
+            end loop;
+
+            return Empty;
+         end if;
+      end Type_In_P;
+
+      ---------------------------
+      -- Operand_Type_In_Scope --
+      ---------------------------
+
+   --  Start of processing for Make_Call_Into_Operator
+
+   begin
+      Op_Node := New_Node (Operator_Kind (Op_Name, Is_Binary), Sloc (N));
+
+      --  Binary operator
+
+      if Is_Binary then
+         Set_Left_Opnd  (Op_Node, Relocate_Node (Act1));
+         Set_Right_Opnd (Op_Node, Relocate_Node (Act2));
+         Save_Interps (Act1, Left_Opnd  (Op_Node));
+         Save_Interps (Act2, Right_Opnd (Op_Node));
+         Act1 := Left_Opnd (Op_Node);
+         Act2 := Right_Opnd (Op_Node);
+
+      --  Unary operator
+
+      else
+         Set_Right_Opnd (Op_Node, Relocate_Node (Act1));
+         Save_Interps (Act1, Right_Opnd (Op_Node));
+         Act1 := Right_Opnd (Op_Node);
+      end if;
+
+      --  If the operator is denoted by an expanded name, and the prefix is
+      --  not Standard, but the operator is a predefined one whose scope is
+      --  Standard, then this is an implicit_operator, inserted as an
+      --  interpretation by the procedure of the same name. This procedure
+      --  overestimates the presence of implicit operators, because it does
+      --  not examine the type of the operands. Verify now that the operand
+      --  type appears in the given scope. If right operand is universal,
+      --  check the other operand. In the case of concatenation, either
+      --  argument can be the component type, so check the type of the result.
+      --  If both arguments are literals, look for a type of the right kind
+      --  defined in the given scope. This elaborate nonsense is brought to
+      --  you courtesy of b33302a. The type itself must be frozen, so we must
+      --  find the type of the proper class in the given scope.
+
+      --  A final wrinkle is the multiplication operator for fixed point
+      --  types, which is defined in Standard only, and not in the scope of
+      --  the fixed_point type itself.
+
+      if Nkind (Name (N)) = N_Expanded_Name then
+         Pack := Entity (Prefix (Name (N)));
+
+         --  If the entity being called is defined in the given package,
+         --  it is a renaming of a predefined operator, and known to be
+         --  legal.
+
+         if Scope (Entity (Name (N))) = Pack
+            and then Pack /= Standard_Standard
+         then
+            null;
+
+         elsif (Op_Name =  Name_Op_Multiply
+              or else Op_Name = Name_Op_Divide)
+           and then Is_Fixed_Point_Type (Etype (Left_Opnd  (Op_Node)))
+           and then Is_Fixed_Point_Type (Etype (Right_Opnd (Op_Node)))
+         then
+            if Pack /= Standard_Standard then
+               Error := True;
+            end if;
+
+         else
+            Opnd_Type := Base_Type (Etype (Right_Opnd (Op_Node)));
+
+            if Op_Name = Name_Op_Concat then
+               Opnd_Type := Base_Type (Typ);
+
+            elsif (Scope (Opnd_Type) = Standard_Standard
+                     and then Is_Binary)
+              or else (Nkind (Right_Opnd (Op_Node)) = N_Attribute_Reference
+                        and then Is_Binary
+                        and then not Comes_From_Source (Opnd_Type))
+            then
+               Opnd_Type := Base_Type (Etype (Left_Opnd (Op_Node)));
+            end if;
+
+            if Scope (Opnd_Type) = Standard_Standard then
+
+               --  Verify that the scope contains a type that corresponds to
+               --  the given literal. Optimize the case where Pack is Standard.
+
+               if Pack /= Standard_Standard then
+
+                  if Opnd_Type = Universal_Integer then
+                     Orig_Type :=  Type_In_P (Is_Integer_Type'Access);
+
+                  elsif Opnd_Type = Universal_Real then
+                     Orig_Type := Type_In_P (Is_Real_Type'Access);
+
+                  elsif Opnd_Type = Any_String then
+                     Orig_Type := Type_In_P (Is_String_Type'Access);
+
+                  elsif Opnd_Type = Any_Access then
+                     Orig_Type :=  Type_In_P (Is_Definite_Access_Type'Access);
+
+                  elsif Opnd_Type = Any_Composite then
+                     Orig_Type := Type_In_P (Is_Composite_Type'Access);
+
+                     if Present (Orig_Type) then
+                        if Has_Private_Component (Orig_Type) then
+                           Orig_Type := Empty;
+                        else
+                           Set_Etype (Act1, Orig_Type);
+
+                           if Is_Binary then
+                              Set_Etype (Act2, Orig_Type);
+                           end if;
+                        end if;
+                     end if;
+
+                  else
+                     Orig_Type := Empty;
+                  end if;
+
+                  Error := No (Orig_Type);
+               end if;
+
+            elsif Ekind (Opnd_Type) = E_Allocator_Type
+               and then No (Type_In_P (Is_Definite_Access_Type'Access))
+            then
+               Error := True;
+
+            --  If the type is defined elsewhere, and the operator is not
+            --  defined in the given scope (by a renaming declaration, e.g.)
+            --  then this is an error as well. If an extension of System is
+            --  present, and the type may be defined there, Pack must be
+            --  System itself.
+
+            elsif Scope (Opnd_Type) /= Pack
+              and then Scope (Op_Id) /= Pack
+              and then (No (System_Aux_Id)
+                         or else Scope (Opnd_Type) /= System_Aux_Id
+                         or else Pack /= Scope (System_Aux_Id))
+            then
+               Error := True;
+
+            elsif Pack = Standard_Standard
+              and then not Operand_Type_In_Scope (Standard_Standard)
+            then
+               Error := True;
+            end if;
+         end if;
+
+         if Error then
+            Error_Msg_Node_2 := Pack;
+            Error_Msg_NE
+              ("& not declared in&", N, Selector_Name (Name (N)));
+            Set_Etype (N, Any_Type);
+            return;
+         end if;
+      end if;
+
+      Set_Chars  (Op_Node, Op_Name);
+      Set_Etype  (Op_Node, Base_Type (Etype (N)));
+      Set_Entity (Op_Node, Op_Id);
+      Generate_Reference (Op_Id, N, ' ');
+      Rewrite (N,  Op_Node);
+      Resolve (N, Typ);
+
+      --  For predefined operators on literals, the operation freezes
+      --  their type.
+
+      if Present (Orig_Type) then
+         Set_Etype (Act1, Orig_Type);
+         Freeze_Expression (Act1);
+      end if;
+   end Make_Call_Into_Operator;
+
+   -------------------
+   -- Operator_Kind --
+   -------------------
+
+   function Operator_Kind
+     (Op_Name   : Name_Id;
+      Is_Binary : Boolean)
+      return      Node_Kind
+   is
+      Kind : Node_Kind;
+
+   begin
+      if Is_Binary then
+         if    Op_Name =  Name_Op_And      then Kind := N_Op_And;
+         elsif Op_Name =  Name_Op_Or       then Kind := N_Op_Or;
+         elsif Op_Name =  Name_Op_Xor      then Kind := N_Op_Xor;
+         elsif Op_Name =  Name_Op_Eq       then Kind := N_Op_Eq;
+         elsif Op_Name =  Name_Op_Ne       then Kind := N_Op_Ne;
+         elsif Op_Name =  Name_Op_Lt       then Kind := N_Op_Lt;
+         elsif Op_Name =  Name_Op_Le       then Kind := N_Op_Le;
+         elsif Op_Name =  Name_Op_Gt       then Kind := N_Op_Gt;
+         elsif Op_Name =  Name_Op_Ge       then Kind := N_Op_Ge;
+         elsif Op_Name =  Name_Op_Add      then Kind := N_Op_Add;
+         elsif Op_Name =  Name_Op_Subtract then Kind := N_Op_Subtract;
+         elsif Op_Name =  Name_Op_Concat   then Kind := N_Op_Concat;
+         elsif Op_Name =  Name_Op_Multiply then Kind := N_Op_Multiply;
+         elsif Op_Name =  Name_Op_Divide   then Kind := N_Op_Divide;
+         elsif Op_Name =  Name_Op_Mod      then Kind := N_Op_Mod;
+         elsif Op_Name =  Name_Op_Rem      then Kind := N_Op_Rem;
+         elsif Op_Name =  Name_Op_Expon    then Kind := N_Op_Expon;
+         else
+            raise Program_Error;
+         end if;
+
+      --  Unary operators
+
+      else
+         if    Op_Name =  Name_Op_Add      then Kind := N_Op_Plus;
+         elsif Op_Name =  Name_Op_Subtract then Kind := N_Op_Minus;
+         elsif Op_Name =  Name_Op_Abs      then Kind := N_Op_Abs;
+         elsif Op_Name =  Name_Op_Not      then Kind := N_Op_Not;
+         else
+            raise Program_Error;
+         end if;
+      end if;
+
+      return Kind;
+   end Operator_Kind;
+
+   -----------------------------
+   -- Pre_Analyze_And_Resolve --
+   -----------------------------
+
+   procedure Pre_Analyze_And_Resolve (N : Node_Id; T : Entity_Id) is
+      Save_Full_Analysis : constant Boolean := Full_Analysis;
+
+   begin
+      Full_Analysis := False;
+      Expander_Mode_Save_And_Set (False);
+
+      --  We suppress all checks for this analysis, since the checks will
+      --  be applied properly, and in the right location, when the default
+      --  expression is reanalyzed and reexpanded later on.
+
+      Analyze_And_Resolve (N, T, Suppress => All_Checks);
+
+      Expander_Mode_Restore;
+      Full_Analysis := Save_Full_Analysis;
+   end Pre_Analyze_And_Resolve;
+
+   --  Version without context type.
+
+   procedure Pre_Analyze_And_Resolve (N : Node_Id) is
+      Save_Full_Analysis : constant Boolean := Full_Analysis;
+
+   begin
+      Full_Analysis := False;
+      Expander_Mode_Save_And_Set (False);
+
+      Analyze (N);
+      Resolve (N, Etype (N), Suppress => All_Checks);
+
+      Expander_Mode_Restore;
+      Full_Analysis := Save_Full_Analysis;
+   end Pre_Analyze_And_Resolve;
+
+   ----------------------------------
+   -- Replace_Actual_Discriminants --
+   ----------------------------------
+
+   procedure Replace_Actual_Discriminants (N : Node_Id; Default : Node_Id) is
+      Loc : constant Source_Ptr := Sloc (N);
+      Tsk : Node_Id := Empty;
+
+      function Process_Discr (Nod : Node_Id) return Traverse_Result;
+
+      -------------------
+      -- Process_Discr --
+      -------------------
+
+      function Process_Discr (Nod : Node_Id) return Traverse_Result is
+         Ent : Entity_Id;
+
+      begin
+         if Nkind (Nod) = N_Identifier then
+            Ent := Entity (Nod);
+
+            if Present (Ent)
+              and then Ekind (Ent) = E_Discriminant
+            then
+               Rewrite (Nod,
+                 Make_Selected_Component (Loc,
+                   Prefix        => New_Copy_Tree (Tsk, New_Sloc => Loc),
+                   Selector_Name => Make_Identifier (Loc, Chars (Ent))));
+
+               Set_Etype (Nod, Etype (Ent));
+            end if;
+
+         end if;
+
+         return OK;
+      end Process_Discr;
+
+      procedure Replace_Discrs is new Traverse_Proc (Process_Discr);
+
+   --  Start of processing for Replace_Actual_Discriminants
+
+   begin
+      if not Expander_Active then
+         return;
+      end if;
+
+      if Nkind (Name (N)) = N_Selected_Component then
+         Tsk := Prefix (Name (N));
+
+      elsif Nkind (Name (N)) = N_Indexed_Component then
+         Tsk := Prefix (Prefix (Name (N)));
+      end if;
+
+      if No (Tsk) then
+         return;
+      else
+         Replace_Discrs (Default);
+      end if;
+   end Replace_Actual_Discriminants;
+
+   -------------
+   -- Resolve --
+   -------------
+
+   procedure Resolve (N : Node_Id; Typ : Entity_Id) is
+      I         : Interp_Index;
+      I1        : Interp_Index := 0; -- prevent junk warning
+      It        : Interp;
+      It1       : Interp;
+      Found     : Boolean   := False;
+      Seen      : Entity_Id := Empty; -- prevent junk warning
+      Ctx_Type  : Entity_Id := Typ;
+      Expr_Type : Entity_Id := Empty; -- prevent junk warning
+      Ambiguous : Boolean   := False;
+
+      procedure Patch_Up_Value (N : Node_Id; Typ : Entity_Id);
+      --  Try and fix up a literal so that it matches its expected type. New
+      --  literals are manufactured if necessary to avoid cascaded errors.
+
+      procedure Resolution_Failed;
+      --  Called when attempt at resolving current expression fails
+
+      --------------------
+      -- Patch_Up_Value --
+      --------------------
+
+      procedure Patch_Up_Value (N : Node_Id; Typ : Entity_Id) is
+      begin
+         if Nkind (N) = N_Integer_Literal
+           and then Is_Real_Type (Typ)
+         then
+            Rewrite (N,
+              Make_Real_Literal (Sloc (N),
+                Realval => UR_From_Uint (Intval (N))));
+            Set_Etype (N, Universal_Real);
+            Set_Is_Static_Expression (N);
+
+         elsif Nkind (N) = N_Real_Literal
+           and then Is_Integer_Type (Typ)
+         then
+            Rewrite (N,
+              Make_Integer_Literal (Sloc (N),
+                Intval => UR_To_Uint (Realval (N))));
+            Set_Etype (N, Universal_Integer);
+            Set_Is_Static_Expression (N);
+         elsif Nkind (N) = N_String_Literal
+           and then Is_Character_Type (Typ)
+         then
+            Set_Character_Literal_Name (Char_Code (Character'Pos ('A')));
+            Rewrite (N,
+              Make_Character_Literal (Sloc (N),
+                Chars => Name_Find,
+                Char_Literal_Value => Char_Code (Character'Pos ('A'))));
+            Set_Etype (N, Any_Character);
+            Set_Is_Static_Expression (N);
+
+         elsif Nkind (N) /= N_String_Literal
+           and then Is_String_Type (Typ)
+         then
+            Rewrite (N,
+              Make_String_Literal (Sloc (N),
+                Strval => End_String));
+
+         elsif Nkind (N) = N_Range then
+            Patch_Up_Value (Low_Bound (N), Typ);
+            Patch_Up_Value (High_Bound (N), Typ);
+         end if;
+      end Patch_Up_Value;
+
+      -----------------------
+      -- Resolution_Failed --
+      -----------------------
+
+      procedure Resolution_Failed is
+      begin
+         Patch_Up_Value (N, Typ);
+         Set_Etype (N, Typ);
+         Debug_A_Exit ("resolving  ", N, " (done, resolution failed)");
+         Set_Is_Overloaded (N, False);
+
+         --  The caller will return without calling the expander, so we need
+         --  to set the analyzed flag. Note that it is fine to set Analyzed
+         --  to True even if we are in the middle of a shallow analysis,
+         --  (see the spec of sem for more details) since this is an error
+         --  situation anyway, and there is no point in repeating the
+         --  analysis later (indeed it won't work to repeat it later, since
+         --  we haven't got a clear resolution of which entity is being
+         --  referenced.)
+
+         Set_Analyzed (N, True);
+         return;
+      end Resolution_Failed;
+
+   --  Start of processing for Resolve
+
+   begin
+      --  Access attribute on remote subprogram cannot be used for
+      --  a non-remote access-to-subprogram type.
+
+      if Nkind (N) = N_Attribute_Reference
+        and then (Attribute_Name (N) = Name_Access
+          or else Attribute_Name (N) = Name_Unrestricted_Access
+          or else Attribute_Name (N) = Name_Unchecked_Access)
+        and then Comes_From_Source (N)
+        and then Is_Entity_Name (Prefix (N))
+        and then Is_Subprogram (Entity (Prefix (N)))
+        and then Is_Remote_Call_Interface (Entity (Prefix (N)))
+        and then not Is_Remote_Access_To_Subprogram_Type (Typ)
+      then
+         Error_Msg_N
+           ("prefix must statically denote a non-remote subprogram", N);
+      end if;
+
+      --  If the context is a Remote_Access_To_Subprogram, access attributes
+      --  must be resolved with the corresponding fat pointer. There is no need
+      --  to check for the attribute name since the return type of an
+      --  attribute is never a remote type.
+
+      if Nkind (N) = N_Attribute_Reference
+        and then Comes_From_Source (N)
+        and then (Is_Remote_Call_Interface (Typ)
+                    or else Is_Remote_Types (Typ))
+      then
+         declare
+            Attr      : constant Attribute_Id :=
+                          Get_Attribute_Id (Attribute_Name (N));
+            Pref      : constant Node_Id      := Prefix (N);
+            Decl      : Node_Id;
+            Spec      : Node_Id;
+            Is_Remote : Boolean := True;
+
+         begin
+            --  Check that Typ is a fat pointer with a reference to a RAS as
+            --  original access type.
+
+            if
+              (Ekind (Typ) = E_Access_Subprogram_Type
+                 and then Present (Equivalent_Type (Typ)))
+              or else
+                (Ekind (Typ) = E_Record_Type
+                   and then Present (Corresponding_Remote_Type (Typ)))
+
+            then
+               --  Prefix (N) must statically denote a remote subprogram
+               --  declared in a package specification.
+
+               if Attr = Attribute_Access then
+                  Decl := Unit_Declaration_Node (Entity (Pref));
+
+                  if Nkind (Decl) = N_Subprogram_Body then
+                     Spec := Corresponding_Spec (Decl);
+
+                     if not No (Spec) then
+                        Decl := Unit_Declaration_Node (Spec);
+                     end if;
+                  end if;
+
+                  Spec := Parent (Decl);
+
+                  if not Is_Entity_Name (Prefix (N))
+                    or else Nkind (Spec) /= N_Package_Specification
+                    or else
+                      not Is_Remote_Call_Interface (Defining_Entity (Spec))
+                  then
+                     Is_Remote := False;
+                     Error_Msg_N
+                       ("prefix must statically denote a remote subprogram ",
+                        N);
+                  end if;
+               end if;
+
+               if Attr = Attribute_Access
+                 or else Attr = Attribute_Unchecked_Access
+                 or else Attr = Attribute_Unrestricted_Access
+               then
+                  Check_Subtype_Conformant
+                    (New_Id  => Entity (Prefix (N)),
+                     Old_Id  => Designated_Type
+                       (Corresponding_Remote_Type (Typ)),
+                     Err_Loc => N);
+                  if Is_Remote then
+                     Process_Remote_AST_Attribute (N, Typ);
+                  end if;
+               end if;
+            end if;
+         end;
+      end if;
+
+      Debug_A_Entry ("resolving  ", N);
+
+      if Is_Fixed_Point_Type (Typ) then
+         Check_Restriction (No_Fixed_Point, N);
+
+      elsif Is_Floating_Point_Type (Typ)
+        and then Typ /= Universal_Real
+        and then Typ /= Any_Real
+      then
+         Check_Restriction (No_Floating_Point, N);
+      end if;
+
+      --  Return if already analyzed
+
+      if Analyzed (N) then
+         Debug_A_Exit ("resolving  ", N, "  (done, already analyzed)");
+         return;
+
+      --  Return if type = Any_Type (previous error encountered)
+
+      elsif Etype (N) = Any_Type then
+         Debug_A_Exit ("resolving  ", N, "  (done, Etype = Any_Type)");
+         return;
+      end if;
+
+      Check_Parameterless_Call (N);
+
+      --  If not overloaded, then we know the type, and all that needs doing
+      --  is to check that this type is compatible with the context.
+
+      if not Is_Overloaded (N) then
+         Found := Covers (Typ, Etype (N));
+         Expr_Type := Etype (N);
+
+      --  In the overloaded case, we must select the interpretation that
+      --  is compatible with the context (i.e. the type passed to Resolve)
+
+      else
+         Get_First_Interp (N, I, It);
+
+         --  Loop through possible interpretations
+
+         Interp_Loop : while Present (It.Typ) loop
+
+            --  We are only interested in interpretations that are compatible
+            --  with the expected type, any other interpretations are ignored
+
+            if Covers (Typ, It.Typ) then
+
+               --  First matching interpretation
+
+               if not Found then
+                  Found := True;
+                  I1    := I;
+                  Seen  := It.Nam;
+                  Expr_Type := It.Typ;
+
+               --  Matching intepretation that is not the first, maybe an
+               --  error, but there are some cases where preference rules are
+               --  used to choose between the two possibilities. These and
+               --  some more obscure cases are handled in Disambiguate.
+
+               else
+                  Error_Msg_Sloc := Sloc (Seen);
+                  It1 := Disambiguate (N, I1, I, Typ);
+
+                  if It1 = No_Interp then
+
+                     --  Before we issue an ambiguity complaint, check for
+                     --  the case of a subprogram call where at least one
+                     --  of the arguments is Any_Type, and if so, suppress
+                     --  the message, since it is a cascaded error.
+
+                     if Nkind (N) = N_Function_Call
+                       or else Nkind (N) = N_Procedure_Call_Statement
+                     then
+                        declare
+                           A : Node_Id := First_Actual (N);
+                           E : Node_Id;
+
+                        begin
+                           while Present (A) loop
+                              E := A;
+
+                              if Nkind (E) = N_Parameter_Association then
+                                 E := Explicit_Actual_Parameter (E);
+                              end if;
+
+                              if Etype (E) = Any_Type then
+                                 if Debug_Flag_V then
+                                    Write_Str ("Any_Type in call");
+                                    Write_Eol;
+                                 end if;
+
+                                 exit Interp_Loop;
+                              end if;
+
+                              Next_Actual (A);
+                           end loop;
+                        end;
+
+                     elsif Nkind (N) in  N_Binary_Op
+                       and then (Etype (Left_Opnd (N)) = Any_Type
+                                  or else Etype (Right_Opnd (N)) = Any_Type)
+                     then
+                        exit Interp_Loop;
+
+                     elsif Nkind (N) in  N_Unary_Op
+                       and then Etype (Right_Opnd (N)) = Any_Type
+                     then
+                        exit Interp_Loop;
+                     end if;
+
+                     --  Not that special case, so issue message using the
+                     --  flag Ambiguous to control printing of the header
+                     --  message only at the start of an ambiguous set.
+
+                     if not Ambiguous then
+                        Error_Msg_NE
+                          ("ambiguous expression (cannot resolve&)!",
+                           N, It.Nam);
+                        Error_Msg_N
+                          ("possible interpretation#!", N);
+                        Ambiguous := True;
+                     end if;
+
+                     Error_Msg_Sloc := Sloc (It.Nam);
+                     Error_Msg_N ("possible interpretation#!", N);
+
+                  --  Disambiguation has succeeded. Skip the remaining
+                  --  interpretations.
+                  else
+                     Seen := It1.Nam;
+                     Expr_Type := It1.Typ;
+
+                     while Present (It.Typ) loop
+                        Get_Next_Interp (I, It);
+                     end loop;
+                  end if;
+               end if;
+
+               --  We have a matching interpretation, Expr_Type is the
+               --  type from this interpretation, and Seen is the entity.
+
+               --  For an operator, just set the entity name. The type will
+               --  be set by the specific operator resolution routine.
+
+               if Nkind (N) in N_Op then
+                  Set_Entity (N, Seen);
+                  Generate_Reference (Seen, N);
+
+               elsif Nkind (N) = N_Character_Literal then
+                  Set_Etype (N, Expr_Type);
+
+               --  For an explicit dereference, attribute reference, range,
+               --  short-circuit form (which is not an operator node),
+               --  or a call with a name that is an explicit dereference,
+               --  there is nothing to be done at this point.
+
+               elsif     Nkind (N) = N_Explicit_Dereference
+                 or else Nkind (N) = N_Attribute_Reference
+                 or else Nkind (N) = N_And_Then
+                 or else Nkind (N) = N_Indexed_Component
+                 or else Nkind (N) = N_Or_Else
+                 or else Nkind (N) = N_Range
+                 or else Nkind (N) = N_Selected_Component
+                 or else Nkind (N) = N_Slice
+                 or else Nkind (Name (N)) = N_Explicit_Dereference
+               then
+                  null;
+
+               --  For procedure or function calls, set the type of the
+               --  name, and also the entity pointer for the prefix
+
+               elsif (Nkind (N) = N_Procedure_Call_Statement
+                       or else Nkind (N) = N_Function_Call)
+                 and then (Is_Entity_Name (Name (N))
+                            or else Nkind (Name (N)) = N_Operator_Symbol)
+               then
+                  Set_Etype  (Name (N), Expr_Type);
+                  Set_Entity (Name (N), Seen);
+                  Generate_Reference (Seen, Name (N));
+
+               elsif Nkind (N) = N_Function_Call
+                 and then Nkind (Name (N)) = N_Selected_Component
+               then
+                  Set_Etype (Name (N), Expr_Type);
+                  Set_Entity (Selector_Name (Name (N)), Seen);
+                  Generate_Reference (Seen, Selector_Name (Name (N)));
+
+               --  For all other cases, just set the type of the Name
+
+               else
+                  Set_Etype (Name (N), Expr_Type);
+               end if;
+
+            --  Here if interpetation is incompatible with context type
+
+            else
+               if Debug_Flag_V then
+                  Write_Str ("    intepretation incompatible with context");
+                  Write_Eol;
+               end if;
+            end if;
+
+            --  Move to next interpretation
+
+            exit Interp_Loop when not Present (It.Typ);
+
+            Get_Next_Interp (I, It);
+         end loop Interp_Loop;
+      end if;
+
+      --  At this stage Found indicates whether or not an acceptable
+      --  interpretation exists. If not, then we have an error, except
+      --  that if the context is Any_Type as a result of some other error,
+      --  then we suppress the error report.
+
+      if not Found then
+         if Typ /= Any_Type then
+
+            --  If type we are looking for is Void, then this is the
+            --  procedure call case, and the error is simply that what
+            --  we gave is not a procedure name (we think of procedure
+            --  calls as expressions with types internally, but the user
+            --  doesn't think of them this way!)
+
+            if Typ = Standard_Void_Type then
+               Error_Msg_N ("expect procedure name in procedure call", N);
+               Found := True;
+
+            --  Otherwise we do have a subexpression with the wrong type
+
+            --  Check for the case of an allocator which uses an access
+            --  type instead of the designated type. This is a common
+            --  error and we specialize the message, posting an error
+            --  on the operand of the allocator, complaining that we
+            --  expected the designated type of the allocator.
+
+            elsif Nkind (N) = N_Allocator
+              and then Ekind (Typ) in Access_Kind
+              and then Ekind (Etype (N)) in Access_Kind
+              and then Designated_Type (Etype (N)) = Typ
+            then
+               Wrong_Type (Expression (N), Designated_Type (Typ));
+               Found := True;
+
+            --  Check for an aggregate. Sometimes we can get bogus
+            --  aggregates from misuse of parentheses, and we are
+            --  about to complain about the aggregate without even
+            --  looking inside it.
+
+            --  Instead, if we have an aggregate of type Any_Composite,
+            --  then analyze and resolve the component fields, and then
+            --  only issue another message if we get no errors doing
+            --  this (otherwise assume that the errors in the aggregate
+            --  caused the problem).
+
+            elsif Nkind (N) = N_Aggregate
+              and then Etype (N) = Any_Composite
+            then
+
+               --  Disable expansion in any case. If there is a type mismatch
+               --  it may be fatal to try to expand the aggregate. The flag
+               --  would otherwise be set to false when the error is posted.
+
+               Expander_Active := False;
+
+               declare
+                  procedure Check_Aggr (Aggr : Node_Id);
+                  --  Check one aggregate, and set Found to True if we
+                  --  have a definite error in any of its elements
+
+                  procedure Check_Elmt (Aelmt : Node_Id);
+                  --  Check one element of aggregate and set Found to
+                  --  True if we definitely have an error in the element.
+
+                  procedure Check_Aggr (Aggr : Node_Id) is
+                     Elmt : Node_Id;
+
+                  begin
+                     if Present (Expressions (Aggr)) then
+                        Elmt := First (Expressions (Aggr));
+                        while Present (Elmt) loop
+                           Check_Elmt (Elmt);
+                           Next (Elmt);
+                        end loop;
+                     end if;
+
+                     if Present (Component_Associations (Aggr)) then
+                        Elmt := First (Component_Associations (Aggr));
+                        while Present (Elmt) loop
+                           Check_Elmt (Expression (Elmt));
+                           Next (Elmt);
+                        end loop;
+                     end if;
+                  end Check_Aggr;
+
+                  procedure Check_Elmt (Aelmt : Node_Id) is
+                  begin
+                     --  If we have a nested aggregate, go inside it (to
+                     --  attempt a naked analyze-resolve of the aggregate
+                     --  can cause undesirable cascaded errors). Do not
+                     --  resolve expression if it needs a type from context,
+                     --  as for integer * fixed expression.
+
+                     if Nkind (Aelmt) = N_Aggregate then
+                        Check_Aggr (Aelmt);
+
+                     else
+                        Analyze (Aelmt);
+
+                        if not Is_Overloaded (Aelmt)
+                          and then Etype (Aelmt) /= Any_Fixed
+                        then
+                           Resolve (Aelmt, Etype (Aelmt));
+                        end if;
+
+                        if Etype (Aelmt) = Any_Type then
+                           Found := True;
+                        end if;
+                     end if;
+                  end Check_Elmt;
+
+               begin
+                  Check_Aggr (N);
+               end;
+            end if;
+
+            --  If an error message was issued already, Found got reset
+            --  to True, so if it is still False, issue the standard
+            --  Wrong_Type message.
+
+            if not Found then
+               if Is_Overloaded (N)
+                 and then Nkind (N) = N_Function_Call
+               then
+                  Error_Msg_Node_2 := Typ;
+                  Error_Msg_NE ("no visible interpretation of&" &
+                    " matches expected type&", N, Name (N));
+
+                  if All_Errors_Mode then
+                     declare
+                        Index : Interp_Index;
+                        It    : Interp;
+
+                     begin
+                        Error_Msg_N ("\possible interpretations:", N);
+                        Get_First_Interp (Name (N), Index, It);
+
+                        while Present (It.Nam) loop
+
+                              Error_Msg_Sloc := Sloc (It.Nam);
+                              Error_Msg_Node_2 := It.Typ;
+                              Error_Msg_NE ("\&  declared#, type&",
+                                N, It.Nam);
+
+                           Get_Next_Interp (Index, It);
+                        end loop;
+                     end;
+                  else
+                     Error_Msg_N ("\use -gnatf for details", N);
+                  end if;
+               else
+                  Wrong_Type (N, Typ);
+               end if;
+            end if;
+         end if;
+
+         Resolution_Failed;
+         return;
+
+      --  Test if we have more than one interpretation for the context
+
+      elsif Ambiguous then
+         Resolution_Failed;
+         return;
+
+      --  Here we have an acceptable interpretation for the context
+
+      else
+         --  A user-defined operator is tranformed into a function call at
+         --  this point, so that further processing knows that operators are
+         --  really operators (i.e. are predefined operators). User-defined
+         --  operators that are intrinsic are just renamings of the predefined
+         --  ones, and need not be turned into calls either, but if they rename
+         --  a different operator, we must transform the node accordingly.
+         --  Instantiations of Unchecked_Conversion are intrinsic but are
+         --  treated as functions, even if given an operator designator.
+
+         if Nkind (N) in N_Op
+           and then Present (Entity (N))
+           and then Ekind (Entity (N)) /= E_Operator
+         then
+
+            if not Is_Predefined_Op (Entity (N)) then
+               Rewrite_Operator_As_Call (N, Entity (N));
+
+            elsif Present (Alias (Entity (N))) then
+               Rewrite_Renamed_Operator (N, Alias (Entity (N)));
+            end if;
+         end if;
+
+         --  Propagate type information and normalize tree for various
+         --  predefined operations. If the context only imposes a class of
+         --  types, rather than a specific type, propagate the actual type
+         --  downward.
+
+         if Typ = Any_Integer
+           or else Typ = Any_Boolean
+           or else Typ = Any_Modular
+           or else Typ = Any_Real
+           or else Typ = Any_Discrete
+         then
+            Ctx_Type := Expr_Type;
+
+            --  Any_Fixed is legal in a real context only if a specific
+            --  fixed point type is imposed. If Norman Cohen can be
+            --  confused by this, it deserves a separate message.
+
+            if Typ = Any_Real
+              and then Expr_Type = Any_Fixed
+            then
+               Error_Msg_N ("Illegal context for mixed mode operation", N);
+               Set_Etype (N, Universal_Real);
+               Ctx_Type := Universal_Real;
+            end if;
+         end if;
+
+         case N_Subexpr'(Nkind (N)) is
+
+            when N_Aggregate => Resolve_Aggregate                (N, Ctx_Type);
+
+            when N_Allocator => Resolve_Allocator                (N, Ctx_Type);
+
+            when N_And_Then | N_Or_Else
+                             => Resolve_Short_Circuit            (N, Ctx_Type);
+
+            when N_Attribute_Reference
+                             => Resolve_Attribute                (N, Ctx_Type);
+
+            when N_Character_Literal
+                             => Resolve_Character_Literal        (N, Ctx_Type);
+
+            when N_Conditional_Expression
+                             => Resolve_Conditional_Expression   (N, Ctx_Type);
+
+            when N_Expanded_Name
+                             => Resolve_Entity_Name              (N, Ctx_Type);
+
+            when N_Extension_Aggregate
+                             => Resolve_Extension_Aggregate      (N, Ctx_Type);
+
+            when N_Explicit_Dereference
+                             => Resolve_Explicit_Dereference     (N, Ctx_Type);
+
+            when N_Function_Call
+                             => Resolve_Call                     (N, Ctx_Type);
+
+            when N_Identifier
+                             => Resolve_Entity_Name              (N, Ctx_Type);
+
+            when N_In | N_Not_In
+                             => Resolve_Membership_Op            (N, Ctx_Type);
+
+            when N_Indexed_Component
+                             => Resolve_Indexed_Component        (N, Ctx_Type);
+
+            when N_Integer_Literal
+                             => Resolve_Integer_Literal          (N, Ctx_Type);
+
+            when N_Null      => Resolve_Null                     (N, Ctx_Type);
+
+            when N_Op_And | N_Op_Or | N_Op_Xor
+                             => Resolve_Logical_Op               (N, Ctx_Type);
+
+            when N_Op_Eq | N_Op_Ne
+                             => Resolve_Equality_Op              (N, Ctx_Type);
+
+            when N_Op_Lt | N_Op_Le | N_Op_Gt | N_Op_Ge
+                             => Resolve_Comparison_Op            (N, Ctx_Type);
+
+            when N_Op_Not    => Resolve_Op_Not                   (N, Ctx_Type);
+
+            when N_Op_Add    | N_Op_Subtract | N_Op_Multiply |
+                 N_Op_Divide | N_Op_Mod      | N_Op_Rem
+
+                             => Resolve_Arithmetic_Op            (N, Ctx_Type);
+
+            when N_Op_Concat => Resolve_Op_Concat                (N, Ctx_Type);
+
+            when N_Op_Expon  => Resolve_Op_Expon                 (N, Ctx_Type);
+
+            when N_Op_Plus | N_Op_Minus  | N_Op_Abs
+                             => Resolve_Unary_Op                 (N, Ctx_Type);
+
+            when N_Op_Shift  => Resolve_Shift                    (N, Ctx_Type);
+
+            when N_Procedure_Call_Statement
+                             => Resolve_Call                     (N, Ctx_Type);
+
+            when N_Operator_Symbol
+                             => Resolve_Operator_Symbol          (N, Ctx_Type);
+
+            when N_Qualified_Expression
+                             => Resolve_Qualified_Expression     (N, Ctx_Type);
+
+            when N_Raise_xxx_Error
+                             => Set_Etype (N, Ctx_Type);
+
+            when N_Range     => Resolve_Range                    (N, Ctx_Type);
+
+            when N_Real_Literal
+                             => Resolve_Real_Literal             (N, Ctx_Type);
+
+            when N_Reference => Resolve_Reference                (N, Ctx_Type);
+
+            when N_Selected_Component
+                             => Resolve_Selected_Component       (N, Ctx_Type);
+
+            when N_Slice     => Resolve_Slice                    (N, Ctx_Type);
+
+            when N_String_Literal
+                             => Resolve_String_Literal           (N, Ctx_Type);
+
+            when N_Subprogram_Info
+                             => Resolve_Subprogram_Info          (N, Ctx_Type);
+
+            when N_Type_Conversion
+                             => Resolve_Type_Conversion          (N, Ctx_Type);
+
+            when N_Unchecked_Expression =>
+               Resolve_Unchecked_Expression                      (N, Ctx_Type);
+
+            when N_Unchecked_Type_Conversion =>
+               Resolve_Unchecked_Type_Conversion                 (N, Ctx_Type);
+
+         end case;
+
+         --  If the subexpression was replaced by a non-subexpression, then
+         --  all we do is to expand it. The only legitimate case we know of
+         --  is converting procedure call statement to entry call statements,
+         --  but there may be others, so we are making this test general.
+
+         if Nkind (N) not in N_Subexpr then
+            Debug_A_Exit ("resolving  ", N, "  (done)");
+            Expand (N);
+            return;
+         end if;
+
+         --  The expression is definitely NOT overloaded at this point, so
+         --  we reset the Is_Overloaded flag to avoid any confusion when
+         --  reanalyzing the node.
+
+         Set_Is_Overloaded (N, False);
+
+         --  Freeze expression type, entity if it is a name, and designated
+         --  type if it is an allocator (RM 13.14(9,10)).
+
+         --  Now that the resolution of the type of the node is complete,
+         --  and we did not detect an error, we can expand this node. We
+         --  skip the expand call if we are in a default expression, see
+         --  section "Handling of Default Expressions" in Sem spec.
+
+         Debug_A_Exit ("resolving  ", N, "  (done)");
+
+         --  We unconditionally freeze the expression, even if we are in
+         --  default expression mode (the Freeze_Expression routine tests
+         --  this flag and only freezes static types if it is set).
+
+         Freeze_Expression (N);
+
+         --  Now we can do the expansion
+
+         Expand (N);
+      end if;
+
+   end Resolve;
+
+   --  Version with check(s) suppressed
+
+   procedure Resolve (N : Node_Id; Typ : Entity_Id; Suppress : Check_Id) is
+   begin
+      if Suppress = All_Checks then
+         declare
+            Svg : constant Suppress_Record := Scope_Suppress;
+
+         begin
+            Scope_Suppress := (others => True);
+            Resolve (N, Typ);
+            Scope_Suppress := Svg;
+         end;
+
+      else
+         declare
+            Svg : constant Boolean := Get_Scope_Suppress (Suppress);
+
+         begin
+            Set_Scope_Suppress (Suppress, True);
+            Resolve (N, Typ);
+            Set_Scope_Suppress (Suppress, Svg);
+         end;
+      end if;
+   end Resolve;
+
+   ---------------------
+   -- Resolve_Actuals --
+   ---------------------
+
+   procedure Resolve_Actuals (N : Node_Id; Nam : Entity_Id) is
+      Loc    : constant Source_Ptr := Sloc (N);
+      A      : Node_Id;
+      F      : Entity_Id;
+      A_Typ  : Entity_Id;
+      F_Typ  : Entity_Id;
+      Prev   : Node_Id := Empty;
+
+      procedure Insert_Default;
+      --  If the actual is missing in a call, insert in the actuals list
+      --  an instance of the default expression. The insertion is always
+      --  a named association.
+
+      --------------------
+      -- Insert_Default --
+      --------------------
+
+      procedure Insert_Default is
+         Actval : Node_Id;
+         Assoc  : Node_Id;
+
+      begin
+         --  Note that we do a full New_Copy_Tree, so that any associated
+         --  Itypes are properly copied. This may not be needed any more,
+         --  but it does no harm as a safety measure! Defaults of a generic
+         --  formal may be out of bounds of the corresponding actual (see
+         --  cc1311b) and an additional check may be required.
+
+         if Present (Default_Value (F)) then
+
+            Actval := New_Copy_Tree (Default_Value (F),
+                        New_Scope => Current_Scope, New_Sloc => Loc);
+
+            if Is_Concurrent_Type (Scope (Nam))
+              and then Has_Discriminants (Scope (Nam))
+            then
+               Replace_Actual_Discriminants (N, Actval);
+            end if;
+
+            if Is_Overloadable (Nam)
+              and then Present (Alias (Nam))
+            then
+               if Base_Type (Etype (F)) /= Base_Type (Etype (Actval))
+                 and then not Is_Tagged_Type (Etype (F))
+               then
+                  --  If default is a real literal, do not introduce a
+                  --  conversion whose effect may depend on the run-time
+                  --  size of universal real.
+
+                  if Nkind (Actval) = N_Real_Literal then
+                     Set_Etype (Actval, Base_Type (Etype (F)));
+                  else
+                     Actval := Unchecked_Convert_To (Etype (F), Actval);
+                  end if;
+               end if;
+
+               if Is_Scalar_Type (Etype (F)) then
+                  Enable_Range_Check (Actval);
+               end if;
+
+               Set_Parent (Actval, N);
+               Analyze_And_Resolve (Actval, Etype (Actval));
+            else
+               Set_Parent (Actval, N);
+
+               --  Resolve aggregates with their base type, to avoid scope
+               --  anomalies: the subtype was first built in the suprogram
+               --  declaration, and the current call may be nested.
+
+               if Nkind (Actval) = N_Aggregate
+                 and then Has_Discriminants (Etype (Actval))
+               then
+                  Analyze_And_Resolve (Actval, Base_Type (Etype (Actval)));
+               else
+                  Analyze_And_Resolve (Actval, Etype (Actval));
+               end if;
+            end if;
+
+            --  If default is a tag indeterminate function call, propagate
+            --  tag to obtain proper dispatching.
+
+            if Is_Controlling_Formal (F)
+              and then Nkind (Default_Value (F)) = N_Function_Call
+            then
+               Set_Is_Controlling_Actual (Actval);
+            end if;
+
+         else
+            --  Missing argument in call, nothing to insert.
+            return;
+         end if;
+
+         --  If the default expression raises constraint error, then just
+         --  silently replace it with an N_Raise_Constraint_Error node,
+         --  since we already gave the warning on the subprogram spec.
+
+         if Raises_Constraint_Error (Actval) then
+            Rewrite (Actval,
+              Make_Raise_Constraint_Error (Loc));
+            Set_Raises_Constraint_Error (Actval);
+            Set_Etype (Actval, Etype (F));
+         end if;
+
+         Assoc :=
+           Make_Parameter_Association (Loc,
+             Explicit_Actual_Parameter => Actval,
+             Selector_Name => Make_Identifier (Loc, Chars (F)));
+
+         --  Case of insertion is first named actual
+
+         if No (Prev) or else
+            Nkind (Parent (Prev)) /= N_Parameter_Association
+         then
+            Set_Next_Named_Actual (Assoc, First_Named_Actual (N));
+            Set_First_Named_Actual (N, Actval);
+
+            if No (Prev) then
+               if not Present (Parameter_Associations (N)) then
+                  Set_Parameter_Associations (N, New_List (Assoc));
+               else
+                  Append (Assoc, Parameter_Associations (N));
+               end if;
+
+            else
+               Insert_After (Prev, Assoc);
+            end if;
+
+         --  Case of insertion is not first named actual
+
+         else
+            Set_Next_Named_Actual
+              (Assoc, Next_Named_Actual (Parent (Prev)));
+            Set_Next_Named_Actual (Parent (Prev), Actval);
+            Append (Assoc, Parameter_Associations (N));
+         end if;
+
+         Mark_Rewrite_Insertion (Assoc);
+         Mark_Rewrite_Insertion (Actval);
+
+         Prev := Actval;
+      end Insert_Default;
+
+   --  Start of processing for Resolve_Actuals
+
+   begin
+      A := First_Actual (N);
+      F := First_Formal (Nam);
+
+      while Present (F) loop
+
+         if Present (A)
+           and then (Nkind (Parent (A)) /= N_Parameter_Association
+                       or else
+                     Chars (Selector_Name (Parent (A))) = Chars (F))
+         then
+            --  If the formal is Out or In_Out, do not resolve and expand the
+            --  conversion, because it is subsequently expanded into explicit
+            --  temporaries and assignments. However, the object of the
+            --  conversion can be resolved. An exception is the case of
+            --  a tagged type conversion with a class-wide actual. In that
+            --  case we want the tag check to occur and no temporary will
+            --  will be needed (no representation change can occur) and
+            --  the parameter is passed by reference, so we go ahead and
+            --  resolve the type conversion.
+
+            if Ekind (F) /= E_In_Parameter
+              and then Nkind (A) = N_Type_Conversion
+              and then not Is_Class_Wide_Type (Etype (Expression (A)))
+            then
+               if Conversion_OK (A)
+                 or else Valid_Conversion (A, Etype (A), Expression (A))
+               then
+                  Resolve (Expression (A), Etype (Expression (A)));
+               end if;
+
+            else
+               Resolve (A, Etype (F));
+            end if;
+
+            A_Typ := Etype (A);
+            F_Typ := Etype (F);
+
+            if Ekind (F) /= E_In_Parameter
+              and then not Is_OK_Variable_For_Out_Formal (A)
+            then
+               --  Specialize error message for protected procedure call
+               --  within function call of the same protected object.
+
+               if Is_Entity_Name (A)
+                 and then Chars (Entity (A)) = Name_uObject
+                 and then Ekind (Current_Scope) = E_Function
+                 and then Convention (Current_Scope) = Convention_Protected
+                 and then Ekind (Nam) /= E_Function
+               then
+                  Error_Msg_N ("within protected function, protected " &
+                    "object is constant", A);
+                  Error_Msg_N ("\cannot call operation that may modify it", A);
+               else
+                  Error_Msg_NE ("actual for& must be a variable", A, F);
+               end if;
+            end if;
+
+            if Ekind (F) /= E_Out_Parameter then
+               Check_Unset_Reference (A);
+
+               if Ada_83
+                 and then Is_Entity_Name (A)
+                 and then Ekind (Entity (A)) = E_Out_Parameter
+               then
+                  Error_Msg_N ("(Ada 83) illegal reading of out parameter", A);
+               end if;
+            end if;
+
+            --  Apply appropriate range checks for in, out, and in-out
+            --  parameters. Out and in-out parameters also need a separate
+            --  check, if there is a type conversion, to make sure the return
+            --  value meets the constraints of the variable before the
+            --  conversion.
+
+            --  Gigi looks at the check flag and uses the appropriate types.
+            --  For now since one flag is used there is an optimization which
+            --  might not be done in the In Out case since Gigi does not do
+            --  any analysis. More thought required about this ???
+
+            if Ekind (F) = E_In_Parameter
+              or else Ekind (F) = E_In_Out_Parameter
+            then
+               if Is_Scalar_Type (Etype (A)) then
+                  Apply_Scalar_Range_Check (A, F_Typ);
+
+               elsif Is_Array_Type (Etype (A)) then
+                  Apply_Length_Check (A, F_Typ);
+
+               elsif Is_Record_Type (F_Typ)
+                 and then Has_Discriminants (F_Typ)
+                 and then Is_Constrained (F_Typ)
+                 and then (not Is_Derived_Type (F_Typ)
+                             or else Comes_From_Source (Nam))
+               then
+                  Apply_Discriminant_Check (A, F_Typ);
+
+               elsif Is_Access_Type (F_Typ)
+                 and then Is_Array_Type (Designated_Type (F_Typ))
+                 and then Is_Constrained (Designated_Type (F_Typ))
+               then
+                  Apply_Length_Check (A, F_Typ);
+
+               elsif Is_Access_Type (F_Typ)
+                 and then Has_Discriminants (Designated_Type (F_Typ))
+                 and then Is_Constrained (Designated_Type (F_Typ))
+               then
+                  Apply_Discriminant_Check (A, F_Typ);
+
+               else
+                  Apply_Range_Check (A, F_Typ);
+               end if;
+            end if;
+
+            if Ekind (F) = E_Out_Parameter
+              or else Ekind (F) = E_In_Out_Parameter
+            then
+
+               if Nkind (A) = N_Type_Conversion then
+                  if Is_Scalar_Type (A_Typ) then
+                     Apply_Scalar_Range_Check
+                       (Expression (A), Etype (Expression (A)), A_Typ);
+                  else
+                     Apply_Range_Check
+                       (Expression (A), Etype (Expression (A)), A_Typ);
+                  end if;
+
+               else
+                  if Is_Scalar_Type (F_Typ) then
+                     Apply_Scalar_Range_Check (A, A_Typ, F_Typ);
+
+                  elsif Is_Array_Type (F_Typ)
+                    and then Ekind (F) = E_Out_Parameter
+                  then
+                     Apply_Length_Check (A, F_Typ);
+
+                  else
+                     Apply_Range_Check (A, A_Typ, F_Typ);
+                  end if;
+               end if;
+            end if;
+
+            --  An actual associated with an access parameter is implicitly
+            --  converted to the anonymous access type of the formal and
+            --  must satisfy the legality checks for access conversions.
+
+            if Ekind (F_Typ) = E_Anonymous_Access_Type then
+               if not Valid_Conversion (A, F_Typ, A) then
+                  Error_Msg_N
+                    ("invalid implicit conversion for access parameter", A);
+               end if;
+            end if;
+
+            --  Check bad case of atomic/volatile argument (RM C.6(12))
+
+            if Is_By_Reference_Type (Etype (F))
+              and then Comes_From_Source (N)
+            then
+               if Is_Atomic_Object (A)
+                 and then not Is_Atomic (Etype (F))
+               then
+                  Error_Msg_N
+                    ("cannot pass atomic argument to non-atomic formal",
+                     N);
+
+               elsif Is_Volatile_Object (A)
+                 and then not Is_Volatile (Etype (F))
+               then
+                  Error_Msg_N
+                    ("cannot pass volatile argument to non-volatile formal",
+                     N);
+               end if;
+            end if;
+
+            --  Check that subprograms don't have improper controlling
+            --  arguments (RM 3.9.2 (9))
+
+            if Is_Controlling_Formal (F) then
+               Set_Is_Controlling_Actual (A);
+            elsif Nkind (A) = N_Explicit_Dereference then
+               Validate_Remote_Access_To_Class_Wide_Type (A);
+            end if;
+
+            if (Is_Class_Wide_Type (A_Typ) or else Is_Dynamically_Tagged (A))
+              and then not Is_Class_Wide_Type (F_Typ)
+              and then not Is_Controlling_Formal (F)
+            then
+               Error_Msg_N ("class-wide argument not allowed here!", A);
+               if Is_Subprogram (Nam) then
+                  Error_Msg_Node_2 := F_Typ;
+                  Error_Msg_NE
+                    ("& is not a primitive operation of &!", A, Nam);
+               end if;
+
+            elsif Is_Access_Type (A_Typ)
+              and then Is_Access_Type (F_Typ)
+              and then Ekind (F_Typ) /= E_Access_Subprogram_Type
+              and then (Is_Class_Wide_Type (Designated_Type (A_Typ))
+                or else (Nkind (A) = N_Attribute_Reference
+                          and then Is_Class_Wide_Type (Etype (Prefix (A)))))
+              and then not Is_Class_Wide_Type (Designated_Type (F_Typ))
+              and then not Is_Controlling_Formal (F)
+            then
+               Error_Msg_N
+                 ("access to class-wide argument not allowed here!", A);
+               if Is_Subprogram (Nam) then
+                  Error_Msg_Node_2 := Designated_Type (F_Typ);
+                  Error_Msg_NE
+                    ("& is not a primitive operation of &!", A, Nam);
+               end if;
+            end if;
+
+            Eval_Actual (A);
+
+            --  If it is a named association, treat the selector_name as
+            --  a proper identifier, and mark the corresponding entity.
+
+            if Nkind (Parent (A)) = N_Parameter_Association then
+               Set_Entity (Selector_Name (Parent (A)), F);
+               Generate_Reference (F, Selector_Name (Parent (A)));
+               Set_Etype (Selector_Name (Parent (A)), F_Typ);
+               Generate_Reference (F_Typ, N, ' ');
+            end if;
+
+            Prev := A;
+            Next_Actual (A);
+
+         else
+            Insert_Default;
+         end if;
+
+         Next_Formal (F);
+      end loop;
+
+   end Resolve_Actuals;
+
+   -----------------------
+   -- Resolve_Allocator --
+   -----------------------
+
+   procedure Resolve_Allocator (N : Node_Id; Typ : Entity_Id) is
+      E        : constant Node_Id := Expression (N);
+      Subtyp   : Entity_Id;
+      Discrim  : Entity_Id;
+      Constr   : Node_Id;
+      Disc_Exp : Node_Id;
+
+   begin
+      --  Replace general access with specific type
+
+      if Ekind (Etype (N)) = E_Allocator_Type then
+         Set_Etype (N, Base_Type (Typ));
+      end if;
+
+      if Is_Abstract (Typ) then
+         Error_Msg_N ("type of allocator cannot be abstract",  N);
+      end if;
+
+      --  For qualified expression, resolve the expression using the
+      --  given subtype (nothing to do for type mark, subtype indication)
+
+      if Nkind (E) = N_Qualified_Expression then
+         if Is_Class_Wide_Type (Etype (E))
+           and then not Is_Class_Wide_Type (Designated_Type (Typ))
+         then
+            Error_Msg_N
+              ("class-wide allocator not allowed for this access type", N);
+         end if;
+
+         Resolve (Expression (E), Etype (E));
+         Check_Unset_Reference (Expression (E));
+
+      --  For a subtype mark or subtype indication, freeze the subtype
+
+      else
+         Freeze_Expression (E);
+
+         if Is_Access_Constant (Typ) and then not No_Initialization (N) then
+            Error_Msg_N
+              ("initialization required for access-to-constant allocator", N);
+         end if;
+
+         --  A special accessibility check is needed for allocators that
+         --  constrain access discriminants. The level of the type of the
+         --  expression used to contrain an access discriminant cannot be
+         --  deeper than the type of the allocator (in constrast to access
+         --  parameters, where the level of the actual can be arbitrary).
+         --  We can't use Valid_Conversion to perform this check because
+         --  in general the type of the allocator is unrelated to the type
+         --  of the access discriminant. Note that specialized checks are
+         --  needed for the cases of a constraint expression which is an
+         --  access attribute or an access discriminant.
+
+         if Nkind (Original_Node (E)) = N_Subtype_Indication
+           and then Ekind (Typ) /= E_Anonymous_Access_Type
+         then
+            Subtyp := Entity (Subtype_Mark (Original_Node (E)));
+
+            if Has_Discriminants (Subtyp) then
+               Discrim := First_Discriminant (Base_Type (Subtyp));
+               Constr := First (Constraints (Constraint (Original_Node (E))));
+
+               while Present (Discrim) and then Present (Constr) loop
+                  if Ekind (Etype (Discrim)) = E_Anonymous_Access_Type then
+                     if Nkind (Constr) = N_Discriminant_Association then
+                        Disc_Exp := Original_Node (Expression (Constr));
+                     else
+                        Disc_Exp := Original_Node (Constr);
+                     end if;
+
+                     if Type_Access_Level (Etype (Disc_Exp))
+                       > Type_Access_Level (Typ)
+                     then
+                        Error_Msg_N
+                          ("operand type has deeper level than allocator type",
+                           Disc_Exp);
+
+                     elsif Nkind (Disc_Exp) = N_Attribute_Reference
+                       and then Get_Attribute_Id (Attribute_Name (Disc_Exp))
+                                  = Attribute_Access
+                       and then Object_Access_Level (Prefix (Disc_Exp))
+                                  > Type_Access_Level (Typ)
+                     then
+                        Error_Msg_N
+                          ("prefix of attribute has deeper level than"
+                              & " allocator type", Disc_Exp);
+
+                     --  When the operand is an access discriminant the check
+                     --  is against the level of the prefix object.
+
+                     elsif Ekind (Etype (Disc_Exp)) = E_Anonymous_Access_Type
+                       and then Nkind (Disc_Exp) = N_Selected_Component
+                       and then Object_Access_Level (Prefix (Disc_Exp))
+                                  > Type_Access_Level (Typ)
+                     then
+                        Error_Msg_N
+                          ("access discriminant has deeper level than"
+                              & " allocator type", Disc_Exp);
+                     end if;
+                  end if;
+                  Next_Discriminant (Discrim);
+                  Next (Constr);
+               end loop;
+            end if;
+         end if;
+      end if;
+
+      --  Check for allocation from an empty storage pool
+
+      if No_Pool_Assigned (Typ) then
+         declare
+            Loc : constant Source_Ptr := Sloc (N);
+
+         begin
+            Error_Msg_N ("?allocation from empty storage pool!", N);
+            Error_Msg_N ("?Storage_Error will be raised at run time!", N);
+            Insert_Action (N,
+              Make_Raise_Storage_Error (Loc));
+         end;
+      end if;
+   end Resolve_Allocator;
+
+   ---------------------------
+   -- Resolve_Arithmetic_Op --
+   ---------------------------
+
+   --  Used for resolving all arithmetic operators except exponentiation
+
+   procedure Resolve_Arithmetic_Op (N : Node_Id; Typ : Entity_Id) is
+      L  : constant Node_Id := Left_Opnd (N);
+      R  : constant Node_Id := Right_Opnd (N);
+      T  : Entity_Id;
+      TL : Entity_Id := Base_Type (Etype (L));
+      TR : Entity_Id := Base_Type (Etype (R));
+
+      B_Typ : constant Entity_Id := Base_Type (Typ);
+      --  We do the resolution using the base type, because intermediate values
+      --  in expressions always are of the base type, not a subtype of it.
+
+      function Is_Integer_Or_Universal (N : Node_Id) return Boolean;
+      --  Return True iff given type is Integer or universal real/integer
+
+      procedure Set_Mixed_Mode_Operand (N : Node_Id; T : Entity_Id);
+      --  Choose type of integer literal in fixed-point operation to conform
+      --  to available fixed-point type. T is the type of the other operand,
+      --  which is needed to determine the expected type of N.
+
+      procedure Set_Operand_Type (N : Node_Id);
+      --  Set operand type to T if universal
+
+      function Universal_Interpretation (N : Node_Id) return Entity_Id;
+      --  Find universal type of operand, if any.
+
+      -----------------------------
+      -- Is_Integer_Or_Universal --
+      -----------------------------
+
+      function Is_Integer_Or_Universal (N : Node_Id) return Boolean is
+         T     : Entity_Id;
+         Index : Interp_Index;
+         It    : Interp;
+
+      begin
+         if not Is_Overloaded (N) then
+            T := Etype (N);
+            return Base_Type (T) = Base_Type (Standard_Integer)
+              or else T = Universal_Integer
+              or else T = Universal_Real;
+         else
+            Get_First_Interp (N, Index, It);
+
+            while Present (It.Typ) loop
+
+               if Base_Type (It.Typ) = Base_Type (Standard_Integer)
+                 or else It.Typ = Universal_Integer
+                 or else It.Typ = Universal_Real
+               then
+                  return True;
+               end if;
+
+               Get_Next_Interp (Index, It);
+            end loop;
+         end if;
+
+         return False;
+      end Is_Integer_Or_Universal;
+
+      ----------------------------
+      -- Set_Mixed_Mode_Operand --
+      ----------------------------
+
+      procedure Set_Mixed_Mode_Operand (N : Node_Id; T : Entity_Id) is
+         Index : Interp_Index;
+         It    : Interp;
+
+      begin
+         if Universal_Interpretation (N) = Universal_Integer then
+
+            --  A universal integer literal is resolved as standard integer
+            --  except in the case of a fixed-point result, where we leave
+            --  it as universal (to be handled by Exp_Fixd later on)
+
+            if Is_Fixed_Point_Type (T) then
+               Resolve (N, Universal_Integer);
+            else
+               Resolve (N, Standard_Integer);
+            end if;
+
+         elsif Universal_Interpretation (N) = Universal_Real
+           and then (T = Base_Type (Standard_Integer)
+                      or else T = Universal_Integer
+                      or else T = Universal_Real)
+         then
+            --  A universal real can appear in a fixed-type context. We resolve
+            --  the literal with that context, even though this might raise an
+            --  exception prematurely (the other operand may be zero).
+
+            Resolve (N, B_Typ);
+
+         elsif Etype (N) = Base_Type (Standard_Integer)
+           and then T = Universal_Real
+           and then Is_Overloaded (N)
+         then
+            --  Integer arg in mixed-mode operation. Resolve with universal
+            --  type, in case preference rule must be applied.
+
+            Resolve (N, Universal_Integer);
+
+         elsif Etype (N) = T
+           and then B_Typ /= Universal_Fixed
+         then
+            --  Not a mixed-mode operation. Resolve with context.
+
+            Resolve (N, B_Typ);
+
+         elsif Etype (N) = Any_Fixed then
+
+            --  N may itself be a mixed-mode operation, so use context type.
+
+            Resolve (N, B_Typ);
+
+         elsif Is_Fixed_Point_Type (T)
+           and then B_Typ = Universal_Fixed
+           and then Is_Overloaded (N)
+         then
+            --  Must be (fixed * fixed) operation, operand must have one
+            --  compatible interpretation.
+
+            Resolve (N, Any_Fixed);
+
+         elsif Is_Fixed_Point_Type (B_Typ)
+           and then (T = Universal_Real
+                      or else Is_Fixed_Point_Type (T))
+           and then Is_Overloaded (N)
+         then
+            --  C * F(X) in a fixed context, where C is a real literal or a
+            --  fixed-point expression. F must have either a fixed type
+            --  interpretation or an integer interpretation, but not both.
+
+            Get_First_Interp (N, Index, It);
+
+            while Present (It.Typ) loop
+
+               if Base_Type (It.Typ) = Base_Type (Standard_Integer) then
+
+                  if Analyzed (N) then
+                     Error_Msg_N ("ambiguous operand in fixed operation", N);
+                  else
+                     Resolve (N, Standard_Integer);
+                  end if;
+
+               elsif Is_Fixed_Point_Type (It.Typ) then
+
+                  if Analyzed (N) then
+                     Error_Msg_N ("ambiguous operand in fixed operation", N);
+                  else
+                     Resolve (N, It.Typ);
+                  end if;
+               end if;
+
+               Get_Next_Interp (Index, It);
+            end loop;
+
+            --  Reanalyze the literal with the fixed type of the context.
+
+            if N = L then
+               Set_Analyzed (R, False);
+               Resolve (R, B_Typ);
+            else
+               Set_Analyzed (L, False);
+               Resolve (L, B_Typ);
+            end if;
+
+         else
+            Resolve (N, Etype (N));
+         end if;
+      end Set_Mixed_Mode_Operand;
+
+      ----------------------
+      -- Set_Operand_Type --
+      ----------------------
+
+      procedure Set_Operand_Type (N : Node_Id) is
+      begin
+         if Etype (N) = Universal_Integer
+           or else Etype (N) = Universal_Real
+         then
+            Set_Etype (N, T);
+         end if;
+      end Set_Operand_Type;
+
+      ------------------------------
+      -- Universal_Interpretation --
+      ------------------------------
+
+      function Universal_Interpretation (N : Node_Id) return Entity_Id is
+         Index : Interp_Index;
+         It    : Interp;
+
+      begin
+         if not Is_Overloaded (N) then
+
+            if Etype (N) = Universal_Integer
+               or else Etype (N) = Universal_Real
+            then
+               return Etype (N);
+            else
+               return Empty;
+            end if;
+
+         else
+            Get_First_Interp (N, Index, It);
+
+            while Present (It.Typ) loop
+
+               if It.Typ = Universal_Integer
+                  or else It.Typ = Universal_Real
+               then
+                  return It.Typ;
+               end if;
+
+               Get_Next_Interp (Index, It);
+            end loop;
+
+            return Empty;
+         end if;
+      end Universal_Interpretation;
+
+   --  Start of processing for Resolve_Arithmetic_Op
+
+   begin
+      if Comes_From_Source (N)
+        and then Ekind (Entity (N)) = E_Function
+        and then Is_Imported (Entity (N))
+        and then Present (First_Rep_Item (Entity (N)))
+      then
+         Resolve_Intrinsic_Operator (N, Typ);
+         return;
+
+      --  Special-case for mixed-mode universal expressions or fixed point
+      --  type operation: each argument is resolved separately. The same
+      --  treatment is required if one of the operands of a fixed point
+      --  operation is universal real, since in this case we don't do a
+      --  conversion to a specific fixed-point type (instead the expander
+      --  takes care of the case).
+
+      elsif (B_Typ = Universal_Integer
+           or else B_Typ = Universal_Real)
+        and then Present (Universal_Interpretation (L))
+        and then Present (Universal_Interpretation (R))
+      then
+         Resolve (L, Universal_Interpretation (L));
+         Resolve (R, Universal_Interpretation (R));
+         Set_Etype (N, B_Typ);
+
+      elsif (B_Typ = Universal_Real
+           or else Etype (N) = Universal_Fixed
+           or else (Etype (N) = Any_Fixed
+                     and then Is_Fixed_Point_Type (B_Typ))
+           or else (Is_Fixed_Point_Type (B_Typ)
+                     and then (Is_Integer_Or_Universal (L)
+                                 or else
+                               Is_Integer_Or_Universal (R))))
+        and then (Nkind (N) = N_Op_Multiply or else
+                  Nkind (N) = N_Op_Divide)
+      then
+         if TL = Universal_Integer or else TR = Universal_Integer then
+            Check_For_Visible_Operator (N, B_Typ);
+         end if;
+
+         --  If context is a fixed type and one operand is integer, the
+         --  other is resolved with the type of the context.
+
+         if Is_Fixed_Point_Type (B_Typ)
+           and then (Base_Type (TL) = Base_Type (Standard_Integer)
+                      or else TL = Universal_Integer)
+         then
+            Resolve (R, B_Typ);
+            Resolve (L, TL);
+
+         elsif Is_Fixed_Point_Type (B_Typ)
+           and then (Base_Type (TR) = Base_Type (Standard_Integer)
+                      or else TR = Universal_Integer)
+         then
+            Resolve (L, B_Typ);
+            Resolve (R, TR);
+
+         else
+            Set_Mixed_Mode_Operand (L, TR);
+            Set_Mixed_Mode_Operand (R, TL);
+         end if;
+
+         if Etype (N) = Universal_Fixed
+           or else Etype (N) = Any_Fixed
+         then
+            if B_Typ = Universal_Fixed
+              and then Nkind (Parent (N)) /= N_Type_Conversion
+              and then Nkind (Parent (N)) /= N_Unchecked_Type_Conversion
+            then
+               Error_Msg_N
+                 ("type cannot be determined from context!", N);
+               Error_Msg_N
+                 ("\explicit conversion to result type required", N);
+
+               Set_Etype (L, Any_Type);
+               Set_Etype (R, Any_Type);
+
+            else
+               if Ada_83
+                  and then Etype (N) = Universal_Fixed
+                  and then Nkind (Parent (N)) /= N_Type_Conversion
+                  and then Nkind (Parent (N)) /= N_Unchecked_Type_Conversion
+               then
+                  Error_Msg_N
+                    ("(Ada 83) fixed-point operation " &
+                     "needs explicit conversion",
+                     N);
+               end if;
+
+               Set_Etype (N, B_Typ);
+            end if;
+
+         elsif Is_Fixed_Point_Type (B_Typ)
+           and then (Is_Integer_Or_Universal (L)
+                       or else Nkind (L) = N_Real_Literal
+                       or else Nkind (R) = N_Real_Literal
+                       or else
+                     Is_Integer_Or_Universal (R))
+         then
+            Set_Etype (N, B_Typ);
+
+         elsif Etype (N) = Any_Fixed then
+
+            --  If no previous errors, this is only possible if one operand
+            --  is overloaded and the context is universal. Resolve as such.
+
+            Set_Etype (N, B_Typ);
+         end if;
+
+      else
+         if (TL = Universal_Integer or else TL = Universal_Real)
+           and then (TR = Universal_Integer or else TR = Universal_Real)
+         then
+            Check_For_Visible_Operator (N, B_Typ);
+         end if;
+
+         --  If the context is Universal_Fixed and the operands are also
+         --  universal fixed, this is an error, unless there is only one
+         --  applicable fixed_point type (usually duration).
+
+         if B_Typ = Universal_Fixed
+           and then Etype (L) = Universal_Fixed
+         then
+            T := Unique_Fixed_Point_Type (N);
+
+            if T  = Any_Type then
+               Set_Etype (N, T);
+               return;
+            else
+               Resolve (L, T);
+               Resolve (R, T);
+            end if;
+
+         else
+            Resolve (L, B_Typ);
+            Resolve (R, B_Typ);
+         end if;
+
+         --  If one of the arguments was resolved to a non-universal type.
+         --  label the result of the operation itself with the same type.
+         --  Do the same for the universal argument, if any.
+
+         T := Intersect_Types (L, R);
+         Set_Etype (N, Base_Type (T));
+         Set_Operand_Type (L);
+         Set_Operand_Type (R);
+      end if;
+
+      Generate_Operator_Reference (N);
+      Eval_Arithmetic_Op (N);
+
+      --  Set overflow and division checking bit. Much cleverer code needed
+      --  here eventually and perhaps the Resolve routines should be separated
+      --  for the various arithmetic operations, since they will need
+      --  different processing. ???
+
+      if Nkind (N) in N_Op then
+         if not Overflow_Checks_Suppressed (Etype (N)) then
+            Set_Do_Overflow_Check (N);
+         end if;
+
+         if (Nkind (N) = N_Op_Divide
+             or else Nkind (N) = N_Op_Rem
+             or else Nkind (N) = N_Op_Mod)
+           and then not Division_Checks_Suppressed (Etype (N))
+         then
+            Set_Do_Division_Check (N);
+         end if;
+      end if;
+
+      Check_Unset_Reference (L);
+      Check_Unset_Reference (R);
+
+   end Resolve_Arithmetic_Op;
+
+   ------------------
+   -- Resolve_Call --
+   ------------------
+
+   procedure Resolve_Call (N : Node_Id; Typ : Entity_Id) is
+      Loc     : constant Source_Ptr := Sloc (N);
+      Subp    : constant Node_Id    := Name (N);
+      Nam     : Entity_Id;
+      I       : Interp_Index;
+      It      : Interp;
+      Norm_OK : Boolean;
+      Scop    : Entity_Id;
+
+   begin
+      --  The context imposes a unique interpretation with type Typ on
+      --  a procedure or function call. Find the entity of the subprogram
+      --  that yields the expected type, and propagate the corresponding
+      --  formal constraints on the actuals. The caller has established
+      --  that an interpretation exists, and emitted an error if not unique.
+
+      --  First deal with the case of a call to an access-to-subprogram,
+      --  dereference made explicit in Analyze_Call.
+
+      if Ekind (Etype (Subp)) = E_Subprogram_Type then
+
+         if not Is_Overloaded (Subp) then
+            Nam := Etype (Subp);
+
+         else
+            --  Find the interpretation whose type (a subprogram type)
+            --  has a return type that is compatible with the context.
+            --  Analysis of the node has established that one exists.
+
+            Get_First_Interp (Subp,  I, It);
+            Nam := Empty;
+
+            while Present (It.Typ) loop
+
+               if Covers (Typ, Etype (It.Typ)) then
+                  Nam := It.Typ;
+                  exit;
+               end if;
+
+               Get_Next_Interp (I, It);
+            end loop;
+
+            if No (Nam) then
+               raise Program_Error;
+            end if;
+         end if;
+
+         --  If the prefix is not an entity, then resolve it
+
+         if not Is_Entity_Name (Subp) then
+            Resolve (Subp, Nam);
+         end if;
+
+      --  If this is a procedure call which is really an entry call, do
+      --  the conversion of the procedure call to an entry call. Protected
+      --  operations use the same circuitry because the name in the call
+      --  can be an arbitrary expression with special resolution rules.
+
+      elsif Nkind (Subp) = N_Selected_Component
+        or else Nkind (Subp) = N_Indexed_Component
+        or else (Is_Entity_Name (Subp)
+                  and then Ekind (Entity (Subp)) = E_Entry)
+      then
+         Resolve_Entry_Call (N, Typ);
+         Check_Elab_Call (N);
+         return;
+
+      --  Normal subprogram call with name established in Resolve
+
+      elsif not (Is_Type (Entity (Subp))) then
+         Nam := Entity (Subp);
+         Set_Entity_With_Style_Check (Subp, Nam);
+         Generate_Reference (Nam, Subp);
+
+      --  Otherwise we must have the case of an overloaded call
+
+      else
+         pragma Assert (Is_Overloaded (Subp));
+         Nam := Empty;  --  We know that it will be assigned in loop below.
+
+         Get_First_Interp (Subp,  I, It);
+
+         while Present (It.Typ) loop
+            if Covers (Typ, It.Typ) then
+               Nam := It.Nam;
+               Set_Entity_With_Style_Check (Subp, Nam);
+               Generate_Reference (Nam, Subp);
+               exit;
+            end if;
+
+            Get_Next_Interp (I, It);
+         end loop;
+      end if;
+
+      --  Check that a call to Current_Task does not occur in an entry body
+
+      if Is_RTE (Nam, RE_Current_Task) then
+         declare
+            P : Node_Id;
+
+         begin
+            P := N;
+            loop
+               P := Parent (P);
+               exit when No (P);
+
+               if Nkind (P) = N_Entry_Body then
+                  Error_Msg_NE
+                    ("& should not be used in entry body ('R'M C.7(17))",
+                     N, Nam);
+                  exit;
+               end if;
+            end loop;
+         end;
+      end if;
+
+      --  Check that a procedure call does not occur in the context
+      --  of the entry call statement of a conditional or timed
+      --  entry call. Note that the case of a call to a subprogram
+      --  renaming of an entry will also be rejected. The test
+      --  for N not being an N_Entry_Call_Statement is defensive,
+      --  covering the possibility that the processing of entry
+      --  calls might reach this point due to later modifications
+      --  of the code above.
+
+      if Nkind (Parent (N)) = N_Entry_Call_Alternative
+        and then Nkind (N) /= N_Entry_Call_Statement
+        and then Entry_Call_Statement (Parent (N)) = N
+      then
+         Error_Msg_N ("entry call required in select statement", N);
+      end if;
+
+      --  Freeze the subprogram name if not in default expression. Note
+      --  that we freeze procedure calls as well as function calls.
+      --  Procedure calls are not frozen according to the rules (RM
+      --  13.14(14)) because it is impossible to have a procedure call to
+      --  a non-frozen procedure in pure Ada, but in the code that we
+      --  generate in the expander, this rule needs extending because we
+      --  can generate procedure calls that need freezing.
+
+      if Is_Entity_Name (Subp) and then not In_Default_Expression then
+         Freeze_Expression (Subp);
+      end if;
+
+      --  For a predefined operator, the type of the result is the type
+      --  imposed by context, except for a predefined operation on universal
+      --  fixed. Otherwise The type of the call is the type returned by the
+      --  subprogram being called.
+
+      if Is_Predefined_Op (Nam) then
+
+         if Etype (N) /= Universal_Fixed then
+            Set_Etype (N, Typ);
+         end if;
+
+      --  If the subprogram returns an array type, and the context
+      --  requires the component type of that array type, the node is
+      --  really an indexing of the parameterless call. Resolve as such.
+
+      elsif Needs_No_Actuals (Nam)
+        and then
+          ((Is_Array_Type (Etype (Nam))
+                   and then Covers (Typ, Component_Type (Etype (Nam))))
+             or else (Is_Access_Type (Etype (Nam))
+                        and then Is_Array_Type (Designated_Type (Etype (Nam)))
+                        and then
+                          Covers (Typ,
+                            Component_Type (Designated_Type (Etype (Nam))))))
+      then
+         declare
+            Index_Node : Node_Id;
+
+         begin
+            Check_Elab_Call (N);
+
+            if Component_Type (Etype (Nam)) /= Any_Type then
+               Index_Node :=
+                 Make_Indexed_Component (Loc,
+                   Prefix =>
+                     Make_Function_Call (Loc,
+                       Name => New_Occurrence_Of (Nam, Loc)),
+                   Expressions => Parameter_Associations (N));
+
+               --  Since we are correcting a node classification error made by
+               --  the parser, we call Replace rather than Rewrite.
+
+               Replace (N, Index_Node);
+               Set_Etype (Prefix (N), Etype (Nam));
+               Set_Etype (N, Typ);
+               Resolve_Indexed_Component (N, Typ);
+            end if;
+
+            return;
+         end;
+
+      else
+         Set_Etype (N, Etype (Nam));
+      end if;
+
+      --  In the case where the call is to an overloaded subprogram, Analyze
+      --  calls Normalize_Actuals once per overloaded subprogram. Therefore in
+      --  such a case Normalize_Actuals needs to be called once more to order
+      --  the actuals correctly. Otherwise the call will have the ordering
+      --  given by the last overloaded subprogram whether this is the correct
+      --  one being called or not.
+
+      if Is_Overloaded (Subp) then
+         Normalize_Actuals (N, Nam, False, Norm_OK);
+         pragma Assert (Norm_OK);
+      end if;
+
+      --  In any case, call is fully resolved now. Reset Overload flag, to
+      --  prevent subsequent overload resolution if node is analyzed again
+
+      Set_Is_Overloaded (Subp, False);
+      Set_Is_Overloaded (N, False);
+
+      --  If we are calling the current subprogram from immediately within
+      --  its body, then that is the case where we can sometimes detect
+      --  cases of infinite recursion statically. Do not try this in case
+      --  restriction No_Recursion is in effect anyway.
+
+      Scop := Current_Scope;
+
+      if Nam = Scop
+        and then not Restrictions (No_Recursion)
+        and then Check_Infinite_Recursion (N)
+      then
+         --  Here we detected and flagged an infinite recursion, so we do
+         --  not need to test the case below for further warnings.
+
+         null;
+
+      --  If call is to immediately containing subprogram, then check for
+      --  the case of a possible run-time detectable infinite recursion.
+
+      else
+         while Scop /= Standard_Standard loop
+            if Nam = Scop then
+               --  Although in general recursion is not statically checkable,
+               --  the case of calling an immediately containing subprogram
+               --  is easy to catch.
+
+               Check_Restriction (No_Recursion, N);
+
+               --  If the recursive call is to a parameterless procedure, then
+               --  even if we can't statically detect infinite recursion, this
+               --  is pretty suspicious, and we output a warning. Furthermore,
+               --  we will try later to detect some cases here at run time by
+               --  expanding checking code (see Detect_Infinite_Recursion in
+               --  package Exp_Ch6).
+               --  If the recursive call is within a handler we do not emit a
+               --  warning, because this is a common idiom: loop until input
+               --  is correct, catch illegal input in handler and restart.
+
+               if No (First_Formal (Nam))
+                 and then Etype (Nam) = Standard_Void_Type
+                 and then not Error_Posted (N)
+                 and then Nkind (Parent (N)) /= N_Exception_Handler
+               then
+                  Set_Has_Recursive_Call (Nam);
+                  Error_Msg_N ("possible infinite recursion?", N);
+                  Error_Msg_N ("Storage_Error may be raised at run time?", N);
+               end if;
+
+               exit;
+            end if;
+
+            Scop := Scope (Scop);
+         end loop;
+      end if;
+
+      --  If subprogram name is a predefined operator, it was given in
+      --  functional notation. Replace call node with operator node, so
+      --  that actuals can be resolved appropriately.
+
+      if Is_Predefined_Op (Nam) or else Ekind (Nam) = E_Operator then
+         Make_Call_Into_Operator (N, Typ, Entity (Name (N)));
+         return;
+
+      elsif Present (Alias (Nam))
+        and then Is_Predefined_Op (Alias (Nam))
+      then
+         Resolve_Actuals (N, Nam);
+         Make_Call_Into_Operator (N, Typ, Alias (Nam));
+         return;
+      end if;
+
+      --  Create a transient scope if the resulting type requires it.
+      --  There are 3 notable exceptions: in init_procs, the transient scope
+      --  overhead is not needed and even incorrect due to the actual expansion
+      --  of adjust calls; the second case is enumeration literal pseudo calls,
+      --  the other case is intrinsic subprograms (Unchecked_Conversion and
+      --  source information functions) that do not use the secondary stack
+      --  even though the return type is unconstrained.
+
+      --  If this is an initialization call for a type whose initialization
+      --  uses the secondary stack, we also need to create a transient scope
+      --  for it, precisely because we will not do it within the init_proc
+      --  itself.
+
+      if Expander_Active
+        and then Is_Type (Etype (Nam))
+        and then Requires_Transient_Scope (Etype (Nam))
+        and then Ekind (Nam) /= E_Enumeration_Literal
+        and then not Within_Init_Proc
+        and then not Is_Intrinsic_Subprogram (Nam)
+      then
+         Establish_Transient_Scope
+           (N, Sec_Stack => not Functions_Return_By_DSP_On_Target);
+
+      elsif Chars (Nam) = Name_uInit_Proc
+        and then not Within_Init_Proc
+      then
+         Check_Initialization_Call (N, Nam);
+      end if;
+
+      --  A protected function cannot be called within the definition of the
+      --  enclosing protected type.
+
+      if Is_Protected_Type (Scope (Nam))
+        and then In_Open_Scopes (Scope (Nam))
+        and then not Has_Completion (Scope (Nam))
+      then
+         Error_Msg_NE
+           ("& cannot be called before end of protected definition", N, Nam);
+      end if;
+
+      --  Propagate interpretation to actuals, and add default expressions
+      --  where needed.
+
+      if Present (First_Formal (Nam)) then
+         Resolve_Actuals (N, Nam);
+
+         --  Overloaded literals are rewritten as function calls, for
+         --  purpose of resolution. After resolution, we can replace
+         --  the call with the literal itself.
+
+      elsif Ekind (Nam) = E_Enumeration_Literal then
+         Copy_Node (Subp, N);
+         Resolve_Entity_Name (N, Typ);
+
+         --  Avoid validation, since it is a static function call.
+
+         return;
+      end if;
+
+      --  If the subprogram is a primitive operation, check whether or not
+      --  it is a correct dispatching call.
+
+      if Is_Overloadable (Nam)
+        and then Is_Dispatching_Operation (Nam)
+      then
+         Check_Dispatching_Call (N);
+
+            --  If the subprogram is abstract, check that the call has a
+            --  controlling argument (i.e. is dispatching) or is disptaching on
+            --  result
+
+         if Is_Abstract (Nam)
+           and then No (Controlling_Argument (N))
+           and then not Is_Class_Wide_Type (Typ)
+           and then not Is_Tag_Indeterminate (N)
+         then
+            Error_Msg_N ("call to abstract subprogram must be dispatching", N);
+         end if;
+
+      elsif Is_Abstract (Nam)
+        and then not In_Instance
+      then
+         Error_Msg_NE ("cannot call abstract subprogram &!", N, Nam);
+      end if;
+
+      if Is_Intrinsic_Subprogram (Nam) then
+         Check_Intrinsic_Call (N);
+      end if;
+
+      --  If we fall through we definitely have a non-static call
+
+      Check_Elab_Call (N);
+
+   end Resolve_Call;
+
+   -------------------------------
+   -- Resolve_Character_Literal --
+   -------------------------------
+
+   procedure Resolve_Character_Literal (N : Node_Id; Typ : Entity_Id) is
+      B_Typ : constant Entity_Id := Base_Type (Typ);
+      C     : Entity_Id;
+
+   begin
+      --  Verify that the character does belong to the type of the context
+
+      Set_Etype (N, B_Typ);
+      Eval_Character_Literal (N);
+
+      --  Wide_Character literals must always be defined, since the set of
+      --  wide character literals is complete, i.e. if a character literal
+      --  is accepted by the parser, then it is OK for wide character.
+
+      if Root_Type (B_Typ) = Standard_Wide_Character then
+         return;
+
+      --  Always accept character literal for type Any_Character, which
+      --  occurs in error situations and in comparisons of literals, both
+      --  of which should accept all literals.
+
+      elsif B_Typ = Any_Character then
+         return;
+
+      --  For Standard.Character or a type derived from it, check that
+      --  the literal is in range
+
+      elsif Root_Type (B_Typ) = Standard_Character then
+         if In_Character_Range (Char_Literal_Value (N)) then
+            return;
+         end if;
+
+      --  If the entity is already set, this has already been resolved in
+      --  a generic context, or comes from expansion. Nothing else to do.
+
+      elsif Present (Entity (N)) then
+         return;
+
+      --  Otherwise we have a user defined character type, and we can use
+      --  the standard visibility mechanisms to locate the referenced entity
+
+      else
+         C := Current_Entity (N);
+
+         while Present (C) loop
+            if Etype (C) = B_Typ then
+               Set_Entity_With_Style_Check (N, C);
+               Generate_Reference (C, N);
+               return;
+            end if;
+
+            C := Homonym (C);
+         end loop;
+      end if;
+
+      --  If we fall through, then the literal does not match any of the
+      --  entries of the enumeration type. This isn't just a constraint
+      --  error situation, it is an illegality (see RM 4.2).
+
+      Error_Msg_NE
+        ("character not defined for }", N, First_Subtype (B_Typ));
+
+   end Resolve_Character_Literal;
+
+   ---------------------------
+   -- Resolve_Comparison_Op --
+   ---------------------------
+
+   --  Context requires a boolean type, and plays no role in resolution.
+   --  Processing identical to that for equality operators.
+
+   procedure Resolve_Comparison_Op (N : Node_Id; Typ : Entity_Id) is
+      L : constant Node_Id := Left_Opnd (N);
+      R : constant Node_Id := Right_Opnd (N);
+      T : Entity_Id;
+
+   begin
+      --  If this is an intrinsic operation which is not predefined, use
+      --  the types of its declared arguments to resolve the possibly
+      --  overloaded operands. Otherwise the operands are unambiguous and
+      --  specify the expected type.
+
+      if Scope (Entity (N)) /= Standard_Standard then
+         T := Etype (First_Entity (Entity (N)));
+      else
+         T := Find_Unique_Type (L, R);
+
+         if T = Any_Fixed then
+            T := Unique_Fixed_Point_Type (L);
+         end if;
+      end if;
+
+      Set_Etype (N, Typ);
+      Generate_Reference (T, N, ' ');
+
+      if T /= Any_Type then
+
+         if T = Any_String
+           or else T = Any_Composite
+           or else T = Any_Character
+         then
+            if T = Any_Character then
+               Ambiguous_Character (L);
+            else
+               Error_Msg_N ("ambiguous operands for comparison", N);
+            end if;
+
+            Set_Etype (N, Any_Type);
+            return;
+
+         else
+            if Comes_From_Source (N)
+              and then Has_Unchecked_Union (T)
+            then
+               Error_Msg_N
+                ("cannot compare Unchecked_Union values", N);
+            end if;
+
+            Resolve (L, T);
+            Resolve (R, T);
+            Check_Unset_Reference (L);
+            Check_Unset_Reference (R);
+            Generate_Operator_Reference (N);
+            Eval_Relational_Op (N);
+         end if;
+      end if;
+
+   end Resolve_Comparison_Op;
+
+   ------------------------------------
+   -- Resolve_Conditional_Expression --
+   ------------------------------------
+
+   procedure Resolve_Conditional_Expression (N : Node_Id; Typ : Entity_Id) is
+      Condition : constant Node_Id := First (Expressions (N));
+      Then_Expr : constant Node_Id := Next (Condition);
+      Else_Expr : constant Node_Id := Next (Then_Expr);
+
+   begin
+      Resolve (Condition, Standard_Boolean);
+      Resolve (Then_Expr, Typ);
+      Resolve (Else_Expr, Typ);
+
+      Set_Etype (N, Typ);
+      Eval_Conditional_Expression (N);
+   end Resolve_Conditional_Expression;
+
+   -----------------------------------------
+   -- Resolve_Discrete_Subtype_Indication --
+   -----------------------------------------
+
+   procedure Resolve_Discrete_Subtype_Indication
+     (N   : Node_Id;
+      Typ : Entity_Id)
+   is
+      R : Node_Id;
+      S : Entity_Id;
+
+   begin
+      Analyze (Subtype_Mark (N));
+      S := Entity (Subtype_Mark (N));
+
+      if Nkind (Constraint (N)) /= N_Range_Constraint then
+         Error_Msg_N ("expect range constraint for discrete type", N);
+         Set_Etype (N, Any_Type);
+
+      else
+         R := Range_Expression (Constraint (N));
+         Analyze (R);
+
+         if Base_Type (S) /= Base_Type (Typ) then
+            Error_Msg_NE
+              ("expect subtype of }", N, First_Subtype (Typ));
+
+            --  Rewrite the constraint as a range of Typ
+            --  to allow compilation to proceed further.
+
+            Set_Etype (N, Typ);
+            Rewrite (Low_Bound (R),
+              Make_Attribute_Reference (Sloc (Low_Bound (R)),
+                Prefix =>         New_Occurrence_Of (Typ, Sloc (R)),
+                Attribute_Name => Name_First));
+            Rewrite (High_Bound (R),
+              Make_Attribute_Reference (Sloc (High_Bound (R)),
+                Prefix =>         New_Occurrence_Of (Typ, Sloc (R)),
+                Attribute_Name => Name_First));
+
+         else
+            Resolve (R, Typ);
+            Set_Etype (N, Etype (R));
+
+            --  Additionally, we must check that the bounds are compatible
+            --  with the given subtype, which might be different from the
+            --  type of the context.
+
+            Apply_Range_Check (R, S);
+
+            --  ??? If the above check statically detects a Constraint_Error
+            --  it replaces the offending bound(s) of the range R with a
+            --  Constraint_Error node. When the itype which uses these bounds
+            --  is frozen the resulting call to Duplicate_Subexpr generates
+            --  a new temporary for the bounds.
+
+            --  Unfortunately there are other itypes that are also made depend
+            --  on these bounds, so when Duplicate_Subexpr is called they get
+            --  a forward reference to the newly created temporaries and Gigi
+            --  aborts on such forward references. This is probably sign of a
+            --  more fundamental problem somewhere else in either the order of
+            --  itype freezing or the way certain itypes are constructed.
+
+            --  To get around this problem we call Remove_Side_Effects right
+            --  away if either bounds of R are a Constraint_Error.
+
+            declare
+               L : Node_Id := Low_Bound (R);
+               H : Node_Id := High_Bound (R);
+
+            begin
+               if Nkind (L) = N_Raise_Constraint_Error then
+                  Remove_Side_Effects (L);
+               end if;
+
+               if Nkind (H) = N_Raise_Constraint_Error then
+                  Remove_Side_Effects (H);
+               end if;
+            end;
+
+            Check_Unset_Reference (Low_Bound  (R));
+            Check_Unset_Reference (High_Bound (R));
+         end if;
+      end if;
+   end Resolve_Discrete_Subtype_Indication;
+
+   -------------------------
+   -- Resolve_Entity_Name --
+   -------------------------
+
+   --  Used to resolve identifiers and expanded names
+
+   procedure Resolve_Entity_Name (N : Node_Id; Typ : Entity_Id) is
+      E : constant Entity_Id := Entity (N);
+
+   begin
+      --  Replace named numbers by corresponding literals. Note that this is
+      --  the one case where Resolve_Entity_Name must reset the Etype, since
+      --  it is currently marked as universal.
+
+      if Ekind (E) = E_Named_Integer then
+         Set_Etype (N, Typ);
+         Eval_Named_Integer (N);
+
+      elsif Ekind (E) = E_Named_Real then
+         Set_Etype (N, Typ);
+         Eval_Named_Real (N);
+
+      --  Allow use of subtype only if it is a concurrent type where we are
+      --  currently inside the body. This will eventually be expanded
+      --  into a call to Self (for tasks) or _object (for protected
+      --  objects). Any other use of a subtype is invalid.
+
+      elsif Is_Type (E) then
+         if Is_Concurrent_Type (E)
+           and then In_Open_Scopes (E)
+         then
+            null;
+         else
+            Error_Msg_N
+               ("Invalid use of subtype mark in expression or call", N);
+         end if;
+
+      --  Check discriminant use if entity is discriminant in current scope,
+      --  i.e. discriminant of record or concurrent type currently being
+      --  analyzed. Uses in corresponding body are unrestricted.
+
+      elsif Ekind (E) = E_Discriminant
+        and then Scope (E) = Current_Scope
+        and then not Has_Completion (Current_Scope)
+      then
+         Check_Discriminant_Use (N);
+
+      --  A parameterless generic function cannot appear in a context that
+      --  requires resolution.
+
+      elsif Ekind (E) = E_Generic_Function then
+         Error_Msg_N ("illegal use of generic function", N);
+
+      elsif Ekind (E) = E_Out_Parameter
+        and then Ada_83
+        and then (Nkind (Parent (N)) in N_Op
+                    or else (Nkind (Parent (N)) = N_Assignment_Statement
+                              and then N = Expression (Parent (N)))
+                    or else Nkind (Parent (N)) = N_Explicit_Dereference)
+      then
+         Error_Msg_N ("(Ada 83) illegal reading of out parameter", N);
+
+      --  In all other cases, just do the possible static evaluation
+
+      else
+         --  A deferred constant that appears in an expression must have
+         --  a completion, unless it has been removed by in-place expansion
+         --  of an aggregate.
+
+         if Ekind (E) = E_Constant
+           and then Comes_From_Source (E)
+           and then No (Constant_Value (E))
+           and then Is_Frozen (Etype (E))
+           and then not In_Default_Expression
+           and then not Is_Imported (E)
+         then
+
+            if No_Initialization (Parent (E))
+              or else (Present (Full_View (E))
+                        and then No_Initialization (Parent (Full_View (E))))
+            then
+               null;
+            else
+               Error_Msg_N (
+                 "deferred constant is frozen before completion", N);
+            end if;
+         end if;
+
+         Eval_Entity_Name (N);
+      end if;
+   end Resolve_Entity_Name;
+
+   -------------------
+   -- Resolve_Entry --
+   -------------------
+
+   procedure Resolve_Entry (Entry_Name : Node_Id) is
+      Loc    : constant Source_Ptr := Sloc (Entry_Name);
+      Nam    : Entity_Id;
+      New_N  : Node_Id;
+      S      : Entity_Id;
+      Tsk    : Entity_Id;
+      E_Name : Node_Id;
+      Index  : Node_Id;
+
+      function Actual_Index_Type (E : Entity_Id) return Entity_Id;
+      --  If the bounds of the entry family being called depend on task
+      --  discriminants, build a new index subtype where a discriminant is
+      --  replaced with the value of the discriminant of the target task.
+      --  The target task is the prefix of the entry name in the call.
+
+      -----------------------
+      -- Actual_Index_Type --
+      -----------------------
+
+      function Actual_Index_Type (E : Entity_Id) return Entity_Id is
+         Typ   : Entity_Id := Entry_Index_Type (E);
+         Tsk   : Entity_Id := Scope (E);
+         Lo    : Node_Id := Type_Low_Bound  (Typ);
+         Hi    : Node_Id := Type_High_Bound (Typ);
+         New_T : Entity_Id;
+
+         function Actual_Discriminant_Ref (Bound : Node_Id) return Node_Id;
+         --  If the bound is given by a discriminant, replace with a reference
+         --  to the discriminant of the same name in the target task.
+         --  If the entry name is the target of a requeue statement and the
+         --  entry is in the current protected object, the bound to be used
+         --  is the discriminal of the object (see apply_range_checks for
+         --  details of the transformation).
+
+         -----------------------------
+         -- Actual_Discriminant_Ref --
+         -----------------------------
+
+         function Actual_Discriminant_Ref (Bound : Node_Id) return Node_Id is
+            Typ : Entity_Id := Etype (Bound);
+            Ref : Node_Id;
+
+         begin
+            Remove_Side_Effects (Bound);
+
+            if not Is_Entity_Name (Bound)
+              or else Ekind (Entity (Bound)) /= E_Discriminant
+            then
+               return Bound;
+
+            elsif Is_Protected_Type (Tsk)
+              and then In_Open_Scopes (Tsk)
+              and then Nkind (Parent (Entry_Name)) = N_Requeue_Statement
+            then
+               return New_Occurrence_Of (Discriminal (Entity (Bound)), Loc);
+
+            else
+               Ref :=
+                 Make_Selected_Component (Loc,
+                   Prefix => New_Copy_Tree (Prefix (Prefix (Entry_Name))),
+                   Selector_Name => New_Occurrence_Of (Entity (Bound), Loc));
+               Analyze (Ref);
+               Resolve (Ref, Typ);
+               return Ref;
+            end if;
+         end Actual_Discriminant_Ref;
+
+      --  Start of processing for Actual_Index_Type
+
+      begin
+         if not Has_Discriminants (Tsk)
+           or else (not Is_Entity_Name (Lo)
+                     and then not Is_Entity_Name (Hi))
+         then
+            return Entry_Index_Type (E);
+
+         else
+            New_T := Create_Itype (Ekind (Typ), Parent (Entry_Name));
+            Set_Etype        (New_T, Base_Type (Typ));
+            Set_Size_Info    (New_T, Typ);
+            Set_RM_Size      (New_T, RM_Size (Typ));
+            Set_Scalar_Range (New_T,
+              Make_Range (Sloc (Entry_Name),
+                Low_Bound  => Actual_Discriminant_Ref (Lo),
+                High_Bound => Actual_Discriminant_Ref (Hi)));
+
+            return New_T;
+         end if;
+      end Actual_Index_Type;
+
+   --  Start of processing of Resolve_Entry
+
+   begin
+      --  Find name of entry being called, and resolve prefix of name
+      --  with its own type. The prefix can be overloaded, and the name
+      --  and signature of the entry must be taken into account.
+
+      if Nkind (Entry_Name) = N_Indexed_Component then
+
+         --  Case of dealing with entry family within the current tasks
+
+         E_Name := Prefix (Entry_Name);
+
+      else
+         E_Name := Entry_Name;
+      end if;
+
+      if Is_Entity_Name (E_Name) then
+         --  Entry call to an entry (or entry family) in the current task.
+         --  This is legal even though the task will deadlock. Rewrite as
+         --  call to current task.
+
+         --  This can also be a call to an entry in  an enclosing task.
+         --  If this is a single task, we have to retrieve its name,
+         --  because the scope of the entry is the task type, not the
+         --  object. If the enclosing task is a task type, the identity
+         --  of the task is given by its own self variable.
+
+         --  Finally this can be a requeue on an entry of the same task
+         --  or protected object.
+
+         S := Scope (Entity (E_Name));
+
+         for J in reverse 0 .. Scope_Stack.Last loop
+
+            if Is_Task_Type (Scope_Stack.Table (J).Entity)
+              and then not Comes_From_Source (S)
+            then
+               --  S is an enclosing task or protected object. The concurrent
+               --  declaration has been converted into a type declaration, and
+               --  the object itself has an object declaration that follows
+               --  the type in the same declarative part.
+
+               Tsk := Next_Entity (S);
+
+               while Etype (Tsk) /= S loop
+                  Next_Entity (Tsk);
+               end loop;
+
+               S := Tsk;
+               exit;
+
+            elsif S = Scope_Stack.Table (J).Entity then
+
+               --  Call to current task. Will be transformed into call to Self
+
+               exit;
+
+            end if;
+         end loop;
+
+         New_N :=
+           Make_Selected_Component (Loc,
+             Prefix => New_Occurrence_Of (S, Loc),
+             Selector_Name =>
+               New_Occurrence_Of (Entity (E_Name), Loc));
+         Rewrite (E_Name, New_N);
+         Analyze (E_Name);
+
+      elsif Nkind (Entry_Name) = N_Selected_Component
+        and then Is_Overloaded (Prefix (Entry_Name))
+      then
+         --  Use the entry name (which must be unique at this point) to
+         --  find the prefix that returns the corresponding task type or
+         --  protected type.
+
+         declare
+            Pref : Node_Id := Prefix (Entry_Name);
+            I    : Interp_Index;
+            It   : Interp;
+            Ent  : Entity_Id :=  Entity (Selector_Name (Entry_Name));
+
+         begin
+            Get_First_Interp (Pref, I, It);
+
+            while Present (It.Typ) loop
+
+               if Scope (Ent) = It.Typ then
+                  Set_Etype (Pref, It.Typ);
+                  exit;
+               end if;
+
+               Get_Next_Interp (I, It);
+            end loop;
+         end;
+      end if;
+
+      if Nkind (Entry_Name) = N_Selected_Component then
+         Resolve (Prefix (Entry_Name), Etype (Prefix (Entry_Name)));
+
+      else pragma Assert (Nkind (Entry_Name) = N_Indexed_Component);
+         Nam := Entity (Selector_Name (Prefix (Entry_Name)));
+         Resolve (Prefix (Prefix (Entry_Name)),
+                   Etype (Prefix (Prefix (Entry_Name))));
+
+         Index :=  First (Expressions (Entry_Name));
+         Resolve (Index, Entry_Index_Type (Nam));
+
+         --  Up to this point the expression could have been the actual
+         --  in a simple entry call, and be given by a named association.
+
+         if Nkind (Index) = N_Parameter_Association then
+            Error_Msg_N ("expect expression for entry index", Index);
+         else
+            Apply_Range_Check (Index, Actual_Index_Type (Nam));
+         end if;
+      end if;
+
+   end Resolve_Entry;
+
+   ------------------------
+   -- Resolve_Entry_Call --
+   ------------------------
+
+   procedure Resolve_Entry_Call (N : Node_Id; Typ : Entity_Id) is
+      Entry_Name  : constant Node_Id    := Name (N);
+      Loc         : constant Source_Ptr := Sloc (Entry_Name);
+      Actuals     : List_Id;
+      First_Named : Node_Id;
+      Nam         : Entity_Id;
+      Norm_OK     : Boolean;
+      Obj         : Node_Id;
+      Was_Over    : Boolean;
+
+   begin
+      --  Processing of the name is similar for entry calls and protected
+      --  operation calls. Once the entity is determined, we can complete
+      --  the resolution of the actuals.
+
+      --  The selector may be overloaded, in the case of a protected object
+      --  with overloaded functions. The type of the context is used for
+      --  resolution.
+
+      if Nkind (Entry_Name) = N_Selected_Component
+        and then Is_Overloaded (Selector_Name (Entry_Name))
+        and then Typ /= Standard_Void_Type
+      then
+         declare
+            I  : Interp_Index;
+            It : Interp;
+
+         begin
+            Get_First_Interp (Selector_Name (Entry_Name), I, It);
+
+            while Present (It.Typ) loop
+
+               if Covers (Typ, It.Typ) then
+                  Set_Entity (Selector_Name (Entry_Name), It.Nam);
+                  Set_Etype  (Entry_Name, It.Typ);
+
+                  Generate_Reference (It.Typ, N, ' ');
+               end if;
+
+               Get_Next_Interp (I, It);
+            end loop;
+         end;
+      end if;
+
+      Resolve_Entry (Entry_Name);
+
+      if Nkind (Entry_Name) = N_Selected_Component then
+
+         --  Simple entry call.
+
+         Nam := Entity (Selector_Name (Entry_Name));
+         Obj := Prefix (Entry_Name);
+         Was_Over := Is_Overloaded (Selector_Name (Entry_Name));
+
+      else pragma Assert (Nkind (Entry_Name) = N_Indexed_Component);
+
+         --  Call to member of entry family.
+
+         Nam := Entity (Selector_Name (Prefix (Entry_Name)));
+         Obj := Prefix (Prefix (Entry_Name));
+         Was_Over := Is_Overloaded (Selector_Name (Prefix (Entry_Name)));
+      end if;
+
+      --  Use context type to disambiguate a protected function that can be
+      --  called without actuals and that returns an array type, and where
+      --  the argument list may be an indexing of the returned value.
+
+      if Ekind (Nam) = E_Function
+        and then Needs_No_Actuals (Nam)
+        and then Present (Parameter_Associations (N))
+        and then
+          ((Is_Array_Type (Etype (Nam))
+             and then Covers (Typ, Component_Type (Etype (Nam))))
+
+            or else (Is_Access_Type (Etype (Nam))
+                      and then Is_Array_Type (Designated_Type (Etype (Nam)))
+                      and then Covers (Typ,
+                        Component_Type (Designated_Type (Etype (Nam))))))
+      then
+         declare
+            Index_Node : Node_Id;
+
+         begin
+            Index_Node :=
+              Make_Indexed_Component (Loc,
+                Prefix =>
+                  Make_Function_Call (Loc,
+                    Name => Relocate_Node (Entry_Name)),
+                Expressions => Parameter_Associations (N));
+
+            --  Since we are correcting a node classification error made by
+            --  the parser, we call Replace rather than Rewrite.
+
+            Replace (N, Index_Node);
+            Set_Etype (Prefix (N), Etype (Nam));
+            Set_Etype (N, Typ);
+            Resolve_Indexed_Component (N, Typ);
+            return;
+         end;
+      end if;
+
+      --  The operation name may have been overloaded. Order the actuals
+      --  according to the formals of the resolved entity.
+
+      if Was_Over then
+         Normalize_Actuals (N, Nam, False, Norm_OK);
+         pragma Assert (Norm_OK);
+      end if;
+
+      Resolve_Actuals (N, Nam);
+      Generate_Reference (Nam, Entry_Name);
+
+      if Ekind (Nam) = E_Entry
+        or else Ekind (Nam) = E_Entry_Family
+      then
+         Check_Potentially_Blocking_Operation (N);
+      end if;
+
+      --  Verify that a procedure call cannot masquerade as an entry
+      --  call where an entry call is expected.
+
+      if Ekind (Nam) = E_Procedure then
+
+         if Nkind (Parent (N)) = N_Entry_Call_Alternative
+           and then N = Entry_Call_Statement (Parent (N))
+         then
+            Error_Msg_N ("entry call required in select statement", N);
+
+         elsif Nkind (Parent (N)) = N_Triggering_Alternative
+           and then N = Triggering_Statement (Parent (N))
+         then
+            Error_Msg_N ("triggering statement cannot be procedure call", N);
+
+         elsif Ekind (Scope (Nam)) = E_Task_Type
+           and then not In_Open_Scopes (Scope (Nam))
+         then
+            Error_Msg_N ("Task has no entry with this name", Entry_Name);
+         end if;
+      end if;
+
+      --  After resolution, entry calls and protected procedure calls
+      --  are changed into entry calls, for expansion. The structure
+      --  of the node does not change, so it can safely be done in place.
+      --  Protected function calls must keep their structure because they
+      --  are subexpressions.
+
+      if Ekind (Nam) /= E_Function then
+
+         --  A protected operation that is not a function may modify the
+         --  corresponding object, and cannot apply to a constant.
+         --  If this is an internal call, the prefix is the type itself.
+
+         if Is_Protected_Type (Scope (Nam))
+           and then not Is_Variable (Obj)
+           and then (not Is_Entity_Name (Obj)
+                       or else not Is_Type (Entity (Obj)))
+         then
+            Error_Msg_N
+              ("prefix of protected procedure or entry call must be variable",
+               Entry_Name);
+         end if;
+
+         Actuals := Parameter_Associations (N);
+         First_Named := First_Named_Actual (N);
+
+         Rewrite (N,
+           Make_Entry_Call_Statement (Loc,
+             Name                   => Entry_Name,
+             Parameter_Associations => Actuals));
+
+         Set_First_Named_Actual (N, First_Named);
+         Set_Analyzed (N, True);
+
+      --  Protected functions can return on the secondary stack, in which
+      --  case we must trigger the transient scope mechanism
+
+      elsif Expander_Active
+        and then Requires_Transient_Scope (Etype (Nam))
+      then
+         Establish_Transient_Scope (N,
+           Sec_Stack => not Functions_Return_By_DSP_On_Target);
+      end if;
+
+   end Resolve_Entry_Call;
+
+   -------------------------
+   -- Resolve_Equality_Op --
+   -------------------------
+
+   --  Both arguments must have the same type, and the boolean context
+   --  does not participate in the resolution. The first pass verifies
+   --  that the interpretation is not ambiguous, and the type of the left
+   --  argument is correctly set, or is Any_Type in case of ambiguity.
+   --  If both arguments are strings or aggregates, allocators, or Null,
+   --  they are ambiguous even though they carry a single (universal) type.
+   --  Diagnose this case here.
+
+   procedure Resolve_Equality_Op (N : Node_Id; Typ : Entity_Id) is
+      L : constant Node_Id   := Left_Opnd (N);
+      R : constant Node_Id   := Right_Opnd (N);
+      T : Entity_Id := Find_Unique_Type (L, R);
+
+      function Find_Unique_Access_Type return Entity_Id;
+      --  In the case of allocators, make a last-ditch attempt to find a single
+      --  access type with the right designated type. This is semantically
+      --  dubious, and of no interest to any real code, but c48008a makes it
+      --  all worthwhile.
+
+      -----------------------------
+      -- Find_Unique_Access_Type --
+      -----------------------------
+
+      function Find_Unique_Access_Type return Entity_Id is
+         Acc : Entity_Id;
+         E   : Entity_Id;
+         S   : Entity_Id := Current_Scope;
+
+      begin
+         if Ekind (Etype (R)) =  E_Allocator_Type then
+            Acc := Designated_Type (Etype (R));
+
+         elsif Ekind (Etype (L)) =  E_Allocator_Type then
+            Acc := Designated_Type (Etype (L));
+
+         else
+            return Empty;
+         end if;
+
+         while S /= Standard_Standard loop
+            E := First_Entity (S);
+
+            while Present (E) loop
+
+               if Is_Type (E)
+                 and then Is_Access_Type (E)
+                 and then Ekind (E) /= E_Allocator_Type
+                 and then Designated_Type (E) = Base_Type (Acc)
+               then
+                  return E;
+               end if;
+
+               Next_Entity (E);
+            end loop;
+
+            S := Scope (S);
+         end loop;
+
+         return Empty;
+      end Find_Unique_Access_Type;
+
+   --  Start of processing for Resolve_Equality_Op
+
+   begin
+      Set_Etype (N, Base_Type (Typ));
+      Generate_Reference (T, N, ' ');
+
+      if T = Any_Fixed then
+         T := Unique_Fixed_Point_Type (L);
+      end if;
+
+      if T /= Any_Type then
+
+         if T = Any_String
+           or else T = Any_Composite
+           or else T = Any_Character
+         then
+
+            if T = Any_Character then
+               Ambiguous_Character (L);
+            else
+               Error_Msg_N ("ambiguous operands for equality", N);
+            end if;
+
+            Set_Etype (N, Any_Type);
+            return;
+
+         elsif T = Any_Access
+           or else Ekind (T) = E_Allocator_Type
+         then
+            T := Find_Unique_Access_Type;
+
+            if No (T) then
+               Error_Msg_N ("ambiguous operands for equality", N);
+               Set_Etype (N, Any_Type);
+               return;
+            end if;
+         end if;
+
+         if Comes_From_Source (N)
+           and then Has_Unchecked_Union (T)
+         then
+            Error_Msg_N
+              ("cannot compare Unchecked_Union values", N);
+         end if;
+
+         Resolve (L, T);
+         Resolve (R, T);
+         Check_Unset_Reference (L);
+         Check_Unset_Reference (R);
+         Generate_Operator_Reference (N);
+
+         --  If this is an inequality, it may be the implicit inequality
+         --  created for a user-defined operation, in which case the corres-
+         --  ponding equality operation is not intrinsic, and the operation
+         --  cannot be constant-folded. Else fold.
+
+         if Nkind (N) = N_Op_Eq
+           or else Comes_From_Source (Entity (N))
+           or else Ekind (Entity (N)) = E_Operator
+           or else Is_Intrinsic_Subprogram
+             (Corresponding_Equality (Entity (N)))
+         then
+            Eval_Relational_Op (N);
+         elsif Nkind (N) = N_Op_Ne
+           and then Is_Abstract (Entity (N))
+         then
+            Error_Msg_NE ("cannot call abstract subprogram &!", N, Entity (N));
+         end if;
+      end if;
+   end Resolve_Equality_Op;
+
+   ----------------------------------
+   -- Resolve_Explicit_Dereference --
+   ----------------------------------
+
+   procedure Resolve_Explicit_Dereference (N : Node_Id; Typ : Entity_Id) is
+      P  : constant Node_Id := Prefix (N);
+      I  : Interp_Index;
+      It : Interp;
+
+   begin
+      --  Now that we know the type, check that this is not a
+      --  dereference of an uncompleted type. Note that this
+      --  is not entirely correct, because dereferences of
+      --  private types are legal in default expressions.
+      --  This consideration also applies to similar checks
+      --  for allocators, qualified expressions, and type
+      --  conversions. ???
+
+      Check_Fully_Declared (Typ, N);
+
+      if Is_Overloaded (P) then
+
+         --  Use the context type to select the prefix that has the
+         --  correct designated type.
+
+         Get_First_Interp (P, I, It);
+         while Present (It.Typ) loop
+            exit when Is_Access_Type (It.Typ)
+              and then Covers (Typ, Designated_Type (It.Typ));
+
+            Get_Next_Interp (I, It);
+         end loop;
+
+         Resolve (P, It.Typ);
+         Set_Etype (N, Designated_Type (It.Typ));
+
+      else
+         Resolve (P, Etype (P));
+      end if;
+
+      if Is_Access_Type (Etype (P)) then
+         Apply_Access_Check (N);
+      end if;
+
+      --  If the designated type is a packed unconstrained array type,
+      --  and the explicit dereference is not in the context of an
+      --  attribute reference, then we must compute and set the actual
+      --  subtype, since it is needed by Gigi. The reason we exclude
+      --  the attribute case is that this is handled fine by Gigi, and
+      --  in fact we use such attributes to build the actual subtype.
+      --  We also exclude generated code (which builds actual subtypes
+      --  directly if they are needed).
+
+      if Is_Array_Type (Etype (N))
+        and then Is_Packed (Etype (N))
+        and then not Is_Constrained (Etype (N))
+        and then Nkind (Parent (N)) /= N_Attribute_Reference
+        and then Comes_From_Source (N)
+      then
+         Set_Etype (N, Get_Actual_Subtype (N));
+      end if;
+
+      --  Note: there is no Eval processing required for an explicit
+      --  deference, because the type is known to be an allocators, and
+      --  allocator expressions can never be static.
+
+   end Resolve_Explicit_Dereference;
+
+   -------------------------------
+   -- Resolve_Indexed_Component --
+   -------------------------------
+
+   procedure Resolve_Indexed_Component (N : Node_Id; Typ : Entity_Id) is
+      Name       : constant Node_Id := Prefix  (N);
+      Expr       : Node_Id;
+      Array_Type : Entity_Id := Empty; -- to prevent junk warning
+      Index      : Node_Id;
+
+   begin
+      if Is_Overloaded (Name) then
+
+         --  Use the context type to select the prefix that yields the
+         --  correct component type.
+
+         declare
+            I     : Interp_Index;
+            It    : Interp;
+            I1    : Interp_Index := 0;
+            P     : constant Node_Id := Prefix (N);
+            Found : Boolean := False;
+
+         begin
+            Get_First_Interp (P, I, It);
+
+            while Present (It.Typ) loop
+
+               if (Is_Array_Type (It.Typ)
+                     and then Covers (Typ, Component_Type (It.Typ)))
+                 or else (Is_Access_Type (It.Typ)
+                            and then Is_Array_Type (Designated_Type (It.Typ))
+                            and then Covers
+                              (Typ, Component_Type (Designated_Type (It.Typ))))
+               then
+                  if Found then
+                     It := Disambiguate (P, I1, I, Any_Type);
+
+                     if It = No_Interp then
+                        Error_Msg_N ("ambiguous prefix for indexing",  N);
+                        Set_Etype (N, Typ);
+                        return;
+
+                     else
+                        Found := True;
+                        Array_Type := It.Typ;
+                        I1 := I;
+                     end if;
+
+                  else
+                     Found := True;
+                     Array_Type := It.Typ;
+                     I1 := I;
+                  end if;
+               end if;
+
+               Get_Next_Interp (I, It);
+            end loop;
+         end;
+
+      else
+         Array_Type := Etype (Name);
+      end if;
+
+      Resolve (Name, Array_Type);
+      Array_Type := Get_Actual_Subtype_If_Available (Name);
+
+      --  If prefix is access type, dereference to get real array type.
+      --  Note: we do not apply an access check because the expander always
+      --  introduces an explicit dereference, and the check will happen there.
+
+      if Is_Access_Type (Array_Type) then
+         Array_Type := Designated_Type (Array_Type);
+      end if;
+
+      --  If name was overloaded, set component type correctly now.
+
+      Set_Etype (N, Component_Type (Array_Type));
+
+      Index := First_Index (Array_Type);
+      Expr  := First (Expressions (N));
+
+      --  The prefix may have resolved to a string literal, in which case
+      --  its etype has a special representation. This is only possible
+      --  currently if the prefix is a static concatenation, written in
+      --  functional notation.
+
+      if Ekind (Array_Type) = E_String_Literal_Subtype then
+         Resolve (Expr, Standard_Positive);
+
+      else
+         while Present (Index) and Present (Expr) loop
+            Resolve (Expr, Etype (Index));
+            Check_Unset_Reference (Expr);
+
+            if Is_Scalar_Type (Etype (Expr)) then
+               Apply_Scalar_Range_Check (Expr, Etype (Index));
+            else
+               Apply_Range_Check (Expr, Get_Actual_Subtype (Index));
+            end if;
+
+            Next_Index (Index);
+            Next (Expr);
+         end loop;
+      end if;
+
+      Eval_Indexed_Component (N);
+
+   end Resolve_Indexed_Component;
+
+   -----------------------------
+   -- Resolve_Integer_Literal --
+   -----------------------------
+
+   procedure Resolve_Integer_Literal (N : Node_Id; Typ : Entity_Id) is
+   begin
+      Set_Etype (N, Typ);
+      Eval_Integer_Literal (N);
+   end Resolve_Integer_Literal;
+
+   ---------------------------------
+   --  Resolve_Intrinsic_Operator --
+   ---------------------------------
+
+   procedure Resolve_Intrinsic_Operator  (N : Node_Id; Typ : Entity_Id) is
+      Op : Entity_Id;
+      Arg1 : Node_Id := Left_Opnd  (N);
+      Arg2 : Node_Id := Right_Opnd (N);
+
+   begin
+      Op := Entity (N);
+
+      while Scope (Op) /= Standard_Standard loop
+         Op := Homonym (Op);
+         pragma Assert (Present (Op));
+      end loop;
+
+      Set_Entity (N, Op);
+
+      if Typ /= Etype (Arg1) or else Typ = Etype (Arg2) then
+         Rewrite (Left_Opnd  (N), Convert_To (Typ, Arg1));
+         Rewrite (Right_Opnd (N), Convert_To (Typ, Arg2));
+
+         Analyze (Left_Opnd  (N));
+         Analyze (Right_Opnd (N));
+      end if;
+
+      Resolve_Arithmetic_Op (N, Typ);
+   end Resolve_Intrinsic_Operator;
+
+   ------------------------
+   -- Resolve_Logical_Op --
+   ------------------------
+
+   procedure Resolve_Logical_Op (N : Node_Id; Typ : Entity_Id) is
+      B_Typ : Entity_Id;
+
+   begin
+      --  Predefined operations on scalar types yield the base type. On
+      --  the other hand, logical operations on arrays yield the type of
+      --  the arguments (and the context).
+
+      if Is_Array_Type (Typ) then
+         B_Typ := Typ;
+      else
+         B_Typ := Base_Type (Typ);
+      end if;
+
+      --  The following test is required because the operands of the operation
+      --  may be literals, in which case the resulting type appears to be
+      --  compatible with a signed integer type, when in fact it is compatible
+      --  only with modular types. If the context itself is universal, the
+      --  operation is illegal.
+
+      if not Valid_Boolean_Arg (Typ) then
+         Error_Msg_N ("invalid context for logical operation", N);
+         Set_Etype (N, Any_Type);
+         return;
+
+      elsif Typ = Any_Modular then
+         Error_Msg_N
+           ("no modular type available in this context", N);
+         Set_Etype (N, Any_Type);
+         return;
+      end if;
+
+      Resolve (Left_Opnd (N), B_Typ);
+      Resolve (Right_Opnd (N), B_Typ);
+
+      Check_Unset_Reference (Left_Opnd  (N));
+      Check_Unset_Reference (Right_Opnd (N));
+
+      Set_Etype (N, B_Typ);
+      Generate_Operator_Reference (N);
+      Eval_Logical_Op (N);
+   end Resolve_Logical_Op;
+
+   ---------------------------
+   -- Resolve_Membership_Op --
+   ---------------------------
+
+   --  The context can only be a boolean type, and does not determine
+   --  the arguments. Arguments should be unambiguous, but the preference
+   --  rule for universal types applies.
+
+   procedure Resolve_Membership_Op (N : Node_Id; Typ : Entity_Id) is
+      L : constant Node_Id   := Left_Opnd (N);
+      R : constant Node_Id   := Right_Opnd (N);
+      T : Entity_Id;
+
+   begin
+      if L = Error or else R = Error then
+         return;
+      end if;
+
+      if not Is_Overloaded (R)
+        and then
+          (Etype (R) = Universal_Integer or else
+           Etype (R) = Universal_Real)
+        and then Is_Overloaded (L)
+      then
+         T := Etype (R);
+      else
+         T := Intersect_Types (L, R);
+      end if;
+
+      Resolve (L, T);
+      Check_Unset_Reference (L);
+
+      if Nkind (R) = N_Range
+        and then not Is_Scalar_Type (T)
+      then
+         Error_Msg_N ("scalar type required for range", R);
+      end if;
+
+      if Is_Entity_Name (R) then
+         Freeze_Expression (R);
+      else
+         Resolve (R, T);
+         Check_Unset_Reference (R);
+      end if;
+
+      Eval_Membership_Op (N);
+   end Resolve_Membership_Op;
+
+   ------------------
+   -- Resolve_Null --
+   ------------------
+
+   procedure Resolve_Null (N : Node_Id; Typ : Entity_Id) is
+   begin
+      --  For now allow circumvention of the restriction against
+      --  anonymous null access values via a debug switch to allow
+      --  for easier trasition.
+
+      if not Debug_Flag_J
+        and then Ekind (Typ) = E_Anonymous_Access_Type
+        and then Comes_From_Source (N)
+      then
+         --  In the common case of a call which uses an explicitly null
+         --  value for an access parameter, give specialized error msg
+
+         if Nkind (Parent (N)) = N_Procedure_Call_Statement
+              or else
+            Nkind (Parent (N)) = N_Function_Call
+         then
+            Error_Msg_N
+              ("null is not allowed as argument for an access parameter", N);
+
+         --  Standard message for all other cases (are there any?)
+
+         else
+            Error_Msg_N
+              ("null cannot be of an anonymous access type", N);
+         end if;
+      end if;
+
+      --  In a distributed context, null for a remote access to subprogram
+      --  may need to be replaced with a special record aggregate. In this
+      --  case, return after having done the transformation.
+
+      if (Ekind (Typ) = E_Record_Type
+           or else Is_Remote_Access_To_Subprogram_Type (Typ))
+        and then Remote_AST_Null_Value (N, Typ)
+      then
+         return;
+      end if;
+
+      --  The null literal takes its type from the context.
+
+      Set_Etype (N, Typ);
+   end Resolve_Null;
+
+   -----------------------
+   -- Resolve_Op_Concat --
+   -----------------------
+
+   procedure Resolve_Op_Concat (N : Node_Id; Typ : Entity_Id) is
+      Btyp : constant Entity_Id := Base_Type (Typ);
+      Op1  : constant Node_Id := Left_Opnd (N);
+      Op2  : constant Node_Id := Right_Opnd (N);
+
+      procedure Resolve_Concatenation_Arg (Arg : Node_Id; Is_Comp : Boolean);
+      --  Internal procedure to resolve one operand of concatenation operator.
+      --  The operand is either of the array type or of the component type.
+      --  If the operand is an aggregate, and the component type is composite,
+      --  this is ambiguous if component type has aggregates.
+
+      -------------------------------
+      -- Resolve_Concatenation_Arg --
+      -------------------------------
+
+      procedure Resolve_Concatenation_Arg (Arg : Node_Id; Is_Comp : Boolean) is
+      begin
+         if In_Instance then
+            if Is_Comp
+              or else (not Is_Overloaded (Arg)
+               and then Etype (Arg) /= Any_Composite
+               and then Covers (Component_Type (Typ), Etype (Arg)))
+            then
+               Resolve (Arg, Component_Type (Typ));
+            else
+               Resolve (Arg, Btyp);
+            end if;
+
+         elsif Has_Compatible_Type (Arg, Component_Type (Typ)) then
+
+            if Nkind (Arg) = N_Aggregate
+              and then Is_Composite_Type (Component_Type (Typ))
+            then
+               if Is_Private_Type (Component_Type (Typ)) then
+                  Resolve (Arg, Btyp);
+
+               else
+                  Error_Msg_N ("ambiguous aggregate must be qualified", Arg);
+                  Set_Etype (Arg, Any_Type);
+               end if;
+
+            else
+               if Is_Overloaded (Arg)
+                 and then Has_Compatible_Type (Arg, Typ)
+                 and then Etype (Arg) /= Any_Type
+               then
+                  Error_Msg_N ("ambiguous operand for concatenation!", Arg);
+
+                  declare
+                     I  : Interp_Index;
+                     It : Interp;
+
+                  begin
+                     Get_First_Interp (Arg, I, It);
+
+                     while Present (It.Nam) loop
+
+                        if Base_Type (Etype (It.Nam)) = Base_Type (Typ)
+                          or else Base_Type (Etype (It.Nam)) =
+                            Base_Type (Component_Type (Typ))
+                        then
+                           Error_Msg_Sloc := Sloc (It.Nam);
+                           Error_Msg_N ("\possible interpretation#", Arg);
+                        end if;
+
+                        Get_Next_Interp (I, It);
+                     end loop;
+                  end;
+               end if;
+
+               Resolve (Arg, Component_Type (Typ));
+
+               if Arg = Left_Opnd (N) then
+                  Set_Is_Component_Left_Opnd (N);
+               else
+                  Set_Is_Component_Right_Opnd (N);
+               end if;
+            end if;
+
+         else
+            Resolve (Arg, Btyp);
+         end if;
+
+         Check_Unset_Reference (Arg);
+      end Resolve_Concatenation_Arg;
+
+   --  Start of processing for Resolve_Op_Concat
+
+   begin
+      Set_Etype (N, Btyp);
+
+      if Is_Limited_Composite (Btyp) then
+         Error_Msg_N ("concatenation not available for limited array", N);
+      end if;
+
+      --  If the operands are themselves concatenations, resolve them as
+      --  such directly. This removes several layers of recursion and allows
+      --  GNAT to handle larger multiple concatenations.
+
+      if Nkind (Op1) = N_Op_Concat
+        and then not Is_Array_Type (Component_Type (Typ))
+        and then Entity (Op1) = Entity (N)
+      then
+         Resolve_Op_Concat (Op1, Typ);
+      else
+         Resolve_Concatenation_Arg
+           (Op1,  Is_Component_Left_Opnd  (N));
+      end if;
+
+      if Nkind (Op2) = N_Op_Concat
+        and then not Is_Array_Type (Component_Type (Typ))
+        and then Entity (Op2) = Entity (N)
+      then
+         Resolve_Op_Concat (Op2, Typ);
+      else
+         Resolve_Concatenation_Arg
+           (Op2, Is_Component_Right_Opnd  (N));
+      end if;
+
+      Generate_Operator_Reference (N);
+
+      if Is_String_Type (Typ) then
+         Eval_Concatenation (N);
+      end if;
+
+      --  If this is not a static concatenation, but the result is a
+      --  string type (and not an array of strings) insure that static
+      --  string operands have their subtypes properly constructed.
+
+      if Nkind (N) /= N_String_Literal
+        and then Is_Character_Type (Component_Type (Typ))
+      then
+         Set_String_Literal_Subtype (Op1, Typ);
+         Set_String_Literal_Subtype (Op2, Typ);
+      end if;
+   end Resolve_Op_Concat;
+
+   ----------------------
+   -- Resolve_Op_Expon --
+   ----------------------
+
+   procedure Resolve_Op_Expon (N : Node_Id; Typ : Entity_Id) is
+      B_Typ : constant Entity_Id := Base_Type (Typ);
+
+   begin
+      --  Catch attempts to do fixed-point exponentation with universal
+      --  operands, which is a case where the illegality is not caught
+      --  during normal operator analysis.
+
+      if Is_Fixed_Point_Type (Typ) and then Comes_From_Source (N) then
+         Error_Msg_N ("exponentiation not available for fixed point", N);
+         return;
+      end if;
+
+      if Etype (Left_Opnd (N)) = Universal_Integer
+        or else Etype (Left_Opnd (N)) = Universal_Real
+      then
+         Check_For_Visible_Operator (N, B_Typ);
+      end if;
+
+      --  We do the resolution using the base type, because intermediate values
+      --  in expressions always are of the base type, not a subtype of it.
+
+      Resolve (Left_Opnd (N), B_Typ);
+      Resolve (Right_Opnd (N), Standard_Integer);
+
+      Check_Unset_Reference (Left_Opnd  (N));
+      Check_Unset_Reference (Right_Opnd (N));
+
+      Set_Etype (N, B_Typ);
+      Generate_Operator_Reference (N);
+      Eval_Op_Expon (N);
+
+      --  Set overflow checking bit. Much cleverer code needed here eventually
+      --  and perhaps the Resolve routines should be separated for the various
+      --  arithmetic operations, since they will need different processing. ???
+
+      if Nkind (N) in N_Op then
+         if not Overflow_Checks_Suppressed (Etype (N)) then
+            Set_Do_Overflow_Check (N, True);
+         end if;
+      end if;
+
+   end Resolve_Op_Expon;
+
+   --------------------
+   -- Resolve_Op_Not --
+   --------------------
+
+   procedure Resolve_Op_Not (N : Node_Id; Typ : Entity_Id) is
+      B_Typ : Entity_Id;
+
+      function Parent_Is_Boolean return Boolean;
+      --  This function determines if the parent node is a boolean operator
+      --  or operation (comparison op, membership test, or short circuit form)
+      --  and the not in question is the left operand of this operation.
+      --  Note that if the not is in parens, then false is returned.
+
+      function Parent_Is_Boolean return Boolean is
+      begin
+         if Paren_Count (N) /= 0 then
+            return False;
+
+         else
+            case Nkind (Parent (N)) is
+               when N_Op_And   |
+                    N_Op_Eq    |
+                    N_Op_Ge    |
+                    N_Op_Gt    |
+                    N_Op_Le    |
+                    N_Op_Lt    |
+                    N_Op_Ne    |
+                    N_Op_Or    |
+                    N_Op_Xor   |
+                    N_In       |
+                    N_Not_In   |
+                    N_And_Then |
+                    N_Or_Else =>
+
+                  return Left_Opnd (Parent (N)) = N;
+
+               when others =>
+                  return False;
+            end case;
+         end if;
+      end Parent_Is_Boolean;
+
+   --  Start of processing for Resolve_Op_Not
+
+   begin
+      --  Predefined operations on scalar types yield the base type. On
+      --  the other hand, logical operations on arrays yield the type of
+      --  the arguments (and the context).
+
+      if Is_Array_Type (Typ) then
+         B_Typ := Typ;
+      else
+         B_Typ := Base_Type (Typ);
+      end if;
+
+      if not Valid_Boolean_Arg (Typ) then
+         Error_Msg_N ("invalid operand type for operator&", N);
+         Set_Etype (N, Any_Type);
+         return;
+
+      elsif (Typ = Universal_Integer
+        or else Typ = Any_Modular)
+      then
+         if Parent_Is_Boolean then
+            Error_Msg_N
+              ("operand of not must be enclosed in parentheses",
+               Right_Opnd (N));
+         else
+            Error_Msg_N
+              ("no modular type available in this context", N);
+         end if;
+
+         Set_Etype (N, Any_Type);
+         return;
+
+      else
+         if not Is_Boolean_Type (Typ)
+           and then Parent_Is_Boolean
+         then
+            Error_Msg_N ("?not expression should be parenthesized here", N);
+         end if;
+
+         Resolve (Right_Opnd (N), B_Typ);
+         Check_Unset_Reference (Right_Opnd (N));
+         Set_Etype (N, B_Typ);
+         Generate_Operator_Reference (N);
+         Eval_Op_Not (N);
+      end if;
+   end Resolve_Op_Not;
+
+   -----------------------------
+   -- Resolve_Operator_Symbol --
+   -----------------------------
+
+   --  Nothing to be done, all resolved already
+
+   procedure Resolve_Operator_Symbol (N : Node_Id; Typ : Entity_Id) is
+   begin
+      null;
+   end Resolve_Operator_Symbol;
+
+   ----------------------------------
+   -- Resolve_Qualified_Expression --
+   ----------------------------------
+
+   procedure Resolve_Qualified_Expression (N : Node_Id; Typ : Entity_Id) is
+      Target_Typ : constant Entity_Id := Entity (Subtype_Mark (N));
+      Expr       : constant Node_Id   := Expression (N);
+
+   begin
+      Resolve (Expr, Target_Typ);
+
+      --  A qualified expression requires an exact match of the type,
+      --  class-wide matching is not allowed.
+
+      if Is_Class_Wide_Type (Target_Typ)
+        and then Base_Type (Etype (Expr)) /= Base_Type (Target_Typ)
+      then
+         Wrong_Type (Expr, Target_Typ);
+      end if;
+
+      --  If the target type is unconstrained, then we reset the type of
+      --  the result from the type of the expression. For other cases, the
+      --  actual subtype of the expression is the target type.
+
+      if Is_Composite_Type (Target_Typ)
+        and then not Is_Constrained (Target_Typ)
+      then
+         Set_Etype (N, Etype (Expr));
+      end if;
+
+      Eval_Qualified_Expression (N);
+   end Resolve_Qualified_Expression;
+
+   -------------------
+   -- Resolve_Range --
+   -------------------
+
+   procedure Resolve_Range (N : Node_Id; Typ : Entity_Id) is
+      L : constant Node_Id := Low_Bound (N);
+      H : constant Node_Id := High_Bound (N);
+
+   begin
+      Set_Etype (N, Typ);
+      Resolve (L, Typ);
+      Resolve (H, Typ);
+
+      Check_Unset_Reference (L);
+      Check_Unset_Reference (H);
+
+      --  We have to check the bounds for being within the base range as
+      --  required for a non-static context. Normally this is automatic
+      --  and done as part of evaluating expressions, but the N_Range
+      --  node is an exception, since in GNAT we consider this node to
+      --  be a subexpression, even though in Ada it is not. The circuit
+      --  in Sem_Eval could check for this, but that would put the test
+      --  on the main evaluation path for expressions.
+
+      Check_Non_Static_Context (L);
+      Check_Non_Static_Context (H);
+
+   end Resolve_Range;
+
+   --------------------------
+   -- Resolve_Real_Literal --
+   --------------------------
+
+   procedure Resolve_Real_Literal (N : Node_Id; Typ : Entity_Id) is
+      Actual_Typ : constant Entity_Id := Etype (N);
+
+   begin
+      --  Special processing for fixed-point literals to make sure that the
+      --  value is an exact multiple of small where this is required. We
+      --  skip this for the universal real case, and also for generic types.
+
+      if Is_Fixed_Point_Type (Typ)
+        and then Typ /= Universal_Fixed
+        and then Typ /= Any_Fixed
+        and then not Is_Generic_Type (Typ)
+      then
+         declare
+            Val   : constant Ureal := Realval (N);
+            Cintr : constant Ureal := Val / Small_Value (Typ);
+            Cint  : constant Uint  := UR_Trunc (Cintr);
+            Den   : constant Uint  := Norm_Den (Cintr);
+            Stat  : Boolean;
+
+         begin
+            --  Case of literal is not an exact multiple of the Small
+
+            if Den /= 1 then
+
+               --  For a source program literal for a decimal fixed-point
+               --  type, this is statically illegal (RM 4.9(36)).
+
+               if Is_Decimal_Fixed_Point_Type (Typ)
+                 and then Actual_Typ = Universal_Real
+                 and then Comes_From_Source (N)
+               then
+                  Error_Msg_N ("value has extraneous low order digits", N);
+               end if;
+
+               --  Replace literal by a value that is the exact representation
+               --  of a value of the type, i.e. a multiple of the small value,
+               --  by truncation, since Machine_Rounds is false for all GNAT
+               --  fixed-point types (RM 4.9(38)).
+
+               Stat := Is_Static_Expression (N);
+               Rewrite (N,
+                 Make_Real_Literal (Sloc (N),
+                   Realval => Small_Value (Typ) * Cint));
+
+               Set_Is_Static_Expression (N, Stat);
+            end if;
+
+            --  In all cases, set the corresponding integer field
+
+            Set_Corresponding_Integer_Value (N, Cint);
+         end;
+      end if;
+
+      --  Now replace the actual type by the expected type as usual
+
+      Set_Etype (N, Typ);
+      Eval_Real_Literal (N);
+   end Resolve_Real_Literal;
+
+   -----------------------
+   -- Resolve_Reference --
+   -----------------------
+
+   procedure Resolve_Reference (N : Node_Id; Typ : Entity_Id) is
+      P : constant Node_Id := Prefix (N);
+
+   begin
+      --  Replace general access with specific type
+
+      if Ekind (Etype (N)) = E_Allocator_Type then
+         Set_Etype (N, Base_Type (Typ));
+      end if;
+
+      Resolve (P, Designated_Type (Etype (N)));
+
+      --  If we are taking the reference of a volatile entity, then treat
+      --  it as a potential modification of this entity. This is much too
+      --  conservative, but is neccessary because remove side effects can
+      --  result in transformations of normal assignments into reference
+      --  sequences that otherwise fail to notice the modification.
+
+      if Is_Entity_Name (P) and then Is_Volatile (Entity (P)) then
+         Note_Possible_Modification (P);
+      end if;
+   end Resolve_Reference;
+
+   --------------------------------
+   -- Resolve_Selected_Component --
+   --------------------------------
+
+   procedure Resolve_Selected_Component (N : Node_Id; Typ : Entity_Id) is
+      Comp  : Entity_Id;
+      Comp1 : Entity_Id        := Empty; -- prevent junk warning
+      P     : constant Node_Id := Prefix  (N);
+      S     : constant Node_Id := Selector_Name (N);
+      T     : Entity_Id        := Etype (P);
+      I     : Interp_Index;
+      I1    : Interp_Index := 0; -- prevent junk warning
+      It    : Interp;
+      It1   : Interp;
+      Found : Boolean;
+
+   begin
+      if Is_Overloaded (P) then
+
+         --  Use the context type to select the prefix that has a selector
+         --  of the correct name and type.
+
+         Found := False;
+         Get_First_Interp (P, I, It);
+
+         Search : while Present (It.Typ) loop
+            if Is_Access_Type (It.Typ) then
+               T := Designated_Type (It.Typ);
+            else
+               T := It.Typ;
+            end if;
+
+            if Is_Record_Type (T) then
+               Comp := First_Entity (T);
+
+               while Present (Comp) loop
+
+                  if Chars (Comp) = Chars (S)
+                    and then Covers (Etype (Comp), Typ)
+                  then
+                     if not Found then
+                        Found := True;
+                        I1  := I;
+                        It1 := It;
+                        Comp1 := Comp;
+
+                     else
+                        It := Disambiguate (P, I1, I, Any_Type);
+
+                        if It = No_Interp then
+                           Error_Msg_N
+                             ("ambiguous prefix for selected component",  N);
+                           Set_Etype (N, Typ);
+                           return;
+
+                        else
+                           It1 := It;
+
+                           if Scope (Comp1) /= It1.Typ then
+
+                              --  Resolution chooses the new interpretation.
+                              --  Find the component with the right name.
+
+                              Comp1 := First_Entity (It1.Typ);
+
+                              while Present (Comp1)
+                                and then Chars (Comp1) /= Chars (S)
+                              loop
+                                 Comp1 := Next_Entity (Comp1);
+                              end loop;
+                           end if;
+
+                           exit Search;
+                        end if;
+                     end if;
+                  end if;
+
+                  Comp := Next_Entity (Comp);
+               end loop;
+
+            end if;
+
+            Get_Next_Interp (I, It);
+
+         end loop Search;
+
+         Resolve (P, It1.Typ);
+         Set_Etype (N, Typ);
+         Set_Entity (S, Comp1);
+
+      else
+         --  Resolve prefix with its type.
+
+         Resolve (P, T);
+      end if;
+
+      --  Deal with access type case
+
+      if Is_Access_Type (Etype (P)) then
+         Apply_Access_Check (N);
+         T := Designated_Type (Etype (P));
+      else
+         T := Etype (P);
+      end if;
+
+      if Has_Discriminants (T)
+        and then Present (Original_Record_Component (Entity (S)))
+        and then Ekind (Original_Record_Component (Entity (S))) = E_Component
+        and then Present (Discriminant_Checking_Func
+                           (Original_Record_Component (Entity (S))))
+        and then not Discriminant_Checks_Suppressed (T)
+      then
+         Set_Do_Discriminant_Check (N);
+      end if;
+
+      if Ekind (Entity (S)) = E_Void then
+         Error_Msg_N ("premature use of component", S);
+      end if;
+
+      --  If the prefix is a record conversion, this may be a renamed
+      --  discriminant whose bounds differ from those of the original
+      --  one, so we must ensure that a range check is performed.
+
+      if Nkind (P) = N_Type_Conversion
+        and then Ekind (Entity (S)) = E_Discriminant
+      then
+         Set_Etype (N, Base_Type (Typ));
+      end if;
+
+      --  Note: No Eval processing is required, because the prefix is of a
+      --  record type, or protected type, and neither can possibly be static.
+
+   end Resolve_Selected_Component;
+
+   -------------------
+   -- Resolve_Shift --
+   -------------------
+
+   procedure Resolve_Shift (N : Node_Id; Typ : Entity_Id) is
+      B_Typ : constant Entity_Id := Base_Type (Typ);
+      L     : constant Node_Id   := Left_Opnd  (N);
+      R     : constant Node_Id   := Right_Opnd (N);
+
+   begin
+      --  We do the resolution using the base type, because intermediate values
+      --  in expressions always are of the base type, not a subtype of it.
+
+      Resolve (L, B_Typ);
+      Resolve (R, Standard_Natural);
+
+      Check_Unset_Reference (L);
+      Check_Unset_Reference (R);
+
+      Set_Etype (N, B_Typ);
+      Generate_Operator_Reference (N);
+      Eval_Shift (N);
+   end Resolve_Shift;
+
+   ---------------------------
+   -- Resolve_Short_Circuit --
+   ---------------------------
+
+   procedure Resolve_Short_Circuit (N : Node_Id; Typ : Entity_Id) is
+      B_Typ : constant Entity_Id := Base_Type (Typ);
+      L     : constant Node_Id   := Left_Opnd  (N);
+      R     : constant Node_Id   := Right_Opnd (N);
+
+   begin
+      Resolve (L, B_Typ);
+      Resolve (R, B_Typ);
+
+      Check_Unset_Reference (L);
+      Check_Unset_Reference (R);
+
+      Set_Etype (N, B_Typ);
+      Eval_Short_Circuit (N);
+   end Resolve_Short_Circuit;
+
+   -------------------
+   -- Resolve_Slice --
+   -------------------
+
+   procedure Resolve_Slice (N : Node_Id; Typ : Entity_Id) is
+      Name       : constant Node_Id := Prefix (N);
+      Drange     : constant Node_Id := Discrete_Range (N);
+      Array_Type : Entity_Id        := Empty;
+      Index      : Node_Id;
+
+   begin
+      if Is_Overloaded (Name) then
+
+         --  Use the context type to select the prefix that yields the
+         --  correct array type.
+
+         declare
+            I      : Interp_Index;
+            I1     : Interp_Index := 0;
+            It     : Interp;
+            P      : constant Node_Id := Prefix (N);
+            Found  : Boolean := False;
+
+         begin
+            Get_First_Interp (P, I,  It);
+
+            while Present (It.Typ) loop
+
+               if (Is_Array_Type (It.Typ)
+                    and then Covers (Typ,  It.Typ))
+                 or else (Is_Access_Type (It.Typ)
+                           and then Is_Array_Type (Designated_Type (It.Typ))
+                           and then Covers (Typ, Designated_Type (It.Typ)))
+               then
+                  if Found then
+                     It := Disambiguate (P, I1, I, Any_Type);
+
+                     if It = No_Interp then
+                        Error_Msg_N ("ambiguous prefix for slicing",  N);
+                        Set_Etype (N, Typ);
+                        return;
+                     else
+                        Found := True;
+                        Array_Type := It.Typ;
+                        I1 := I;
+                     end if;
+                  else
+                     Found := True;
+                     Array_Type := It.Typ;
+                     I1 := I;
+                  end if;
+               end if;
+
+               Get_Next_Interp (I, It);
+            end loop;
+         end;
+
+      else
+         Array_Type := Etype (Name);
+      end if;
+
+      Resolve (Name, Array_Type);
+
+      if Is_Access_Type (Array_Type) then
+         Apply_Access_Check (N);
+         Array_Type := Designated_Type (Array_Type);
+
+      elsif Is_Entity_Name (Name)
+        or else (Nkind (Name) = N_Function_Call
+                  and then not Is_Constrained (Etype (Name)))
+      then
+         Array_Type := Get_Actual_Subtype (Name);
+      end if;
+
+      --  If name was overloaded, set slice type correctly now
+
+      Set_Etype (N, Array_Type);
+
+      --  If the range is specified by a subtype mark, no resolution
+      --  is necessary.
+
+      if not Is_Entity_Name (Drange) then
+         Index := First_Index (Array_Type);
+         Resolve (Drange, Base_Type (Etype (Index)));
+
+         if Nkind (Drange) = N_Range then
+            Apply_Range_Check (Drange, Etype (Index));
+         end if;
+      end if;
+
+      Set_Slice_Subtype (N);
+      Eval_Slice (N);
+
+   end Resolve_Slice;
+
+   ----------------------------
+   -- Resolve_String_Literal --
+   ----------------------------
+
+   procedure Resolve_String_Literal (N : Node_Id; Typ : Entity_Id) is
+      C_Typ      : constant Entity_Id  := Component_Type (Typ);
+      R_Typ      : constant Entity_Id  := Root_Type (C_Typ);
+      Loc        : constant Source_Ptr := Sloc (N);
+      Str        : constant String_Id  := Strval (N);
+      Strlen     : constant Nat        := String_Length (Str);
+      Subtype_Id : Entity_Id;
+      Need_Check : Boolean;
+
+   begin
+      --  For a string appearing in a concatenation, defer creation of the
+      --  string_literal_subtype until the end of the resolution of the
+      --  concatenation, because the literal may be constant-folded away.
+      --  This is a useful optimization for long concatenation expressions.
+
+      --  If the string is an aggregate built for a single character  (which
+      --  happens in a non-static context) or a is null string to which special
+      --  checks may apply, we build the subtype. Wide strings must also get
+      --  a string subtype if they come from a one character aggregate. Strings
+      --  generated by attributes might be static, but it is often hard to
+      --  determine whether the enclosing context is static, so we generate
+      --  subtypes for them as well, thus losing some rarer optimizations ???
+      --  Same for strings that come from a static conversion.
+
+      Need_Check :=
+        (Strlen = 0 and then Typ /= Standard_String)
+          or else Nkind (Parent (N)) /= N_Op_Concat
+          or else (N /= Left_Opnd (Parent (N))
+                    and then N /= Right_Opnd (Parent (N)))
+          or else (Typ = Standard_Wide_String
+                    and then Nkind (Original_Node (N)) /= N_String_Literal);
+
+      --  If the resolving type is itself a string literal subtype, we
+      --  can just reuse it, since there is no point in creating another.
+
+      if Ekind (Typ) = E_String_Literal_Subtype then
+         Subtype_Id := Typ;
+
+      elsif Nkind (Parent (N)) = N_Op_Concat
+        and then not Need_Check
+        and then Nkind (Original_Node (N)) /= N_Character_Literal
+        and then Nkind (Original_Node (N)) /= N_Attribute_Reference
+        and then Nkind (Original_Node (N)) /= N_Qualified_Expression
+        and then Nkind (Original_Node (N)) /= N_Type_Conversion
+      then
+         Subtype_Id := Typ;
+
+      --  Otherwise we must create a string literal subtype. Note that the
+      --  whole idea of string literal subtypes is simply to avoid the need
+      --  for building a full fledged array subtype for each literal.
+      else
+         Set_String_Literal_Subtype (N, Typ);
+         Subtype_Id := Etype (N);
+      end if;
+
+      if Nkind (Parent (N)) /= N_Op_Concat
+        or else Need_Check
+      then
+         Set_Etype (N, Subtype_Id);
+         Eval_String_Literal (N);
+      end if;
+
+      if Is_Limited_Composite (Typ)
+        or else Is_Private_Composite (Typ)
+      then
+         Error_Msg_N ("string literal not available for private array", N);
+         Set_Etype (N, Any_Type);
+         return;
+      end if;
+
+      --  The validity of a null string has been checked in the
+      --  call to  Eval_String_Literal.
+
+      if Strlen = 0 then
+         return;
+
+      --  Always accept string literal with component type Any_Character,
+      --  which occurs in error situations and in comparisons of literals,
+      --  both of which should accept all literals.
+
+      elsif R_Typ = Any_Character then
+         return;
+
+      --  If the type is bit-packed, then we always tranform the string
+      --  literal into a full fledged aggregate.
+
+      elsif Is_Bit_Packed_Array (Typ) then
+         null;
+
+      --  Deal with cases of Wide_String and String
+
+      else
+         --  For Standard.Wide_String, or any other type whose component
+         --  type is Standard.Wide_Character, we know that all the
+         --  characters in the string must be acceptable, since the parser
+         --  accepted the characters as valid character literals.
+
+         if R_Typ = Standard_Wide_Character then
+            null;
+
+         --  For the case of Standard.String, or any other type whose
+         --  component type is Standard.Character, we must make sure that
+         --  there are no wide characters in the string, i.e. that it is
+         --  entirely composed of characters in range of type String.
+
+         --  If the string literal is the result of a static concatenation,
+         --  the test has already been performed on the components, and need
+         --  not be repeated.
+
+         elsif R_Typ = Standard_Character
+           and then Nkind (Original_Node (N)) /= N_Op_Concat
+         then
+            for J in 1 .. Strlen loop
+               if not In_Character_Range (Get_String_Char (Str, J)) then
+
+                  --  If we are out of range, post error. This is one of the
+                  --  very few places that we place the flag in the middle of
+                  --  a token, right under the offending wide character.
+
+                  Error_Msg
+                    ("literal out of range of type Character",
+                     Source_Ptr (Int (Loc) + J));
+                  return;
+               end if;
+            end loop;
+
+         --  If the root type is not a standard character, then we will convert
+         --  the string into an aggregate and will let the aggregate code do
+         --  the checking.
+
+         else
+            null;
+
+         end if;
+
+         --  See if the component type of the array corresponding to the
+         --  string has compile time known bounds. If yes we can directly
+         --  check whether the evaluation of the string will raise constraint
+         --  error. Otherwise we need to transform the string literal into
+         --  the corresponding character aggregate and let the aggregate
+         --  code do the checking.
+
+         if R_Typ = Standard_Wide_Character
+           or else R_Typ = Standard_Character
+         then
+            --  Check for the case of full range, where we are definitely OK
+
+            if Component_Type (Typ) = Base_Type (Component_Type (Typ)) then
+               return;
+            end if;
+
+            --  Here the range is not the complete base type range, so check
+
+            declare
+               Comp_Typ_Lo : constant Node_Id :=
+                               Type_Low_Bound (Component_Type (Typ));
+               Comp_Typ_Hi : constant Node_Id :=
+                               Type_High_Bound (Component_Type (Typ));
+
+               Char_Val : Uint;
+
+            begin
+               if Compile_Time_Known_Value (Comp_Typ_Lo)
+                 and then Compile_Time_Known_Value (Comp_Typ_Hi)
+               then
+                  for J in 1 .. Strlen loop
+                     Char_Val := UI_From_Int (Int (Get_String_Char (Str, J)));
+
+                     if Char_Val < Expr_Value (Comp_Typ_Lo)
+                       or else Char_Val > Expr_Value (Comp_Typ_Hi)
+                     then
+                        Apply_Compile_Time_Constraint_Error
+                          (N, "character out of range?",
+                           Loc => Source_Ptr (Int (Loc) + J));
+                     end if;
+                  end loop;
+
+                  return;
+               end if;
+            end;
+         end if;
+      end if;
+
+      --  If we got here we meed to transform the string literal into the
+      --  equivalent qualified positional array aggregate. This is rather
+      --  heavy artillery for this situation, but it is hard work to avoid.
+
+      declare
+         Lits : List_Id    := New_List;
+         P    : Source_Ptr := Loc + 1;
+         C    : Char_Code;
+
+      begin
+         --  Build the character literals, we give them source locations
+         --  that correspond to the string positions, which is a bit tricky
+         --  given the possible presence of wide character escape sequences.
+
+         for J in 1 .. Strlen loop
+            C := Get_String_Char (Str, J);
+            Set_Character_Literal_Name (C);
+
+            Append_To (Lits,
+              Make_Character_Literal (P, Name_Find, C));
+
+            if In_Character_Range (C) then
+               P := P + 1;
+
+            --  Should we have a call to Skip_Wide here ???
+            --  ???     else
+            --             Skip_Wide (P);
+
+            end if;
+         end loop;
+
+         Rewrite (N,
+           Make_Qualified_Expression (Loc,
+             Subtype_Mark => New_Reference_To (Typ, Loc),
+             Expression   =>
+               Make_Aggregate (Loc, Expressions => Lits)));
+
+         Analyze_And_Resolve (N, Typ);
+      end;
+   end Resolve_String_Literal;
+
+   -----------------------------
+   -- Resolve_Subprogram_Info --
+   -----------------------------
+
+   procedure Resolve_Subprogram_Info (N : Node_Id; Typ : Entity_Id) is
+   begin
+      Set_Etype (N, Typ);
+   end Resolve_Subprogram_Info;
+
+   -----------------------------
+   -- Resolve_Type_Conversion --
+   -----------------------------
+
+   procedure Resolve_Type_Conversion (N : Node_Id; Typ : Entity_Id) is
+      Target_Type : constant Entity_Id := Etype (N);
+      Conv_OK     : constant Boolean   := Conversion_OK (N);
+      Operand     : Node_Id;
+      Opnd_Type   : Entity_Id;
+      Rop         : Node_Id;
+
+   begin
+      Operand := Expression (N);
+
+      if not Conv_OK
+        and then not Valid_Conversion (N, Target_Type, Operand)
+      then
+         return;
+      end if;
+
+      if Etype (Operand) = Any_Fixed then
+
+         --  Mixed-mode operation involving a literal. Context must be a fixed
+         --  type which is applied to the literal subsequently.
+
+         if Is_Fixed_Point_Type (Typ) then
+            Set_Etype (Operand, Universal_Real);
+
+         elsif Is_Numeric_Type (Typ)
+           and then (Nkind (Operand) = N_Op_Multiply
+                      or else Nkind (Operand) = N_Op_Divide)
+           and then (Etype (Right_Opnd (Operand)) = Universal_Real
+                     or else Etype (Left_Opnd (Operand)) = Universal_Real)
+         then
+            if Unique_Fixed_Point_Type (N) = Any_Type then
+               return;    --  expression is ambiguous.
+            else
+               Set_Etype (Operand, Standard_Duration);
+            end if;
+
+            if Etype (Right_Opnd (Operand)) = Universal_Real then
+               Rop := New_Copy_Tree (Right_Opnd (Operand));
+            else
+               Rop := New_Copy_Tree (Left_Opnd (Operand));
+            end if;
+
+            Resolve (Rop, Standard_Long_Long_Float);
+
+            if Realval (Rop) /= Ureal_0
+              and then abs (Realval (Rop)) < Delta_Value (Standard_Duration)
+            then
+               Error_Msg_N ("universal real operand can only be interpreted?",
+                 Rop);
+               Error_Msg_N ("\as Duration, and will lose precision?", Rop);
+            end if;
+
+         else
+            Error_Msg_N ("invalid context for mixed mode operation", N);
+            Set_Etype (Operand, Any_Type);
+            return;
+         end if;
+      end if;
+
+      Opnd_Type := Etype (Operand);
+      Resolve (Operand, Opnd_Type);
+
+      --  Note: we do the Eval_Type_Conversion call before applying the
+      --  required checks for a subtype conversion. This is important,
+      --  since both are prepared under certain circumstances to change
+      --  the type conversion to a constraint error node, but in the case
+      --  of Eval_Type_Conversion this may reflect an illegality in the
+      --  static case, and we would miss the illegality (getting only a
+      --  warning message), if we applied the type conversion checks first.
+
+      Eval_Type_Conversion (N);
+
+      --  If after evaluation, we still have a type conversion, then we
+      --  may need to apply checks required for a subtype conversion.
+
+      --  Skip these type conversion checks if universal fixed operands
+      --  operands involved, since range checks are handled separately for
+      --  these cases (in the appropriate Expand routines in unit Exp_Fixd).
+
+      if Nkind (N) = N_Type_Conversion
+        and then not Is_Generic_Type (Root_Type (Target_Type))
+        and then Target_Type /= Universal_Fixed
+        and then Opnd_Type /= Universal_Fixed
+      then
+         Apply_Type_Conversion_Checks (N);
+      end if;
+
+      --  Issue warning for conversion of simple object to its own type
+
+      if Warn_On_Redundant_Constructs
+        and then Comes_From_Source (N)
+        and then Nkind (N) = N_Type_Conversion
+        and then Is_Entity_Name (Expression (N))
+        and then Etype (Entity (Expression (N))) = Target_Type
+      then
+         Error_Msg_NE
+           ("?useless conversion, & has this type",
+            N, Entity (Expression (N)));
+      end if;
+   end Resolve_Type_Conversion;
+
+   ----------------------
+   -- Resolve_Unary_Op --
+   ----------------------
+
+   procedure Resolve_Unary_Op (N : Node_Id; Typ : Entity_Id) is
+      B_Typ : Entity_Id := Base_Type (Typ);
+      R     : constant Node_Id := Right_Opnd (N);
+
+   begin
+      --  Generate warning for expressions like -5 mod 3
+
+      if Paren_Count (N) = 0
+        and then Nkind (N) = N_Op_Minus
+        and then Nkind (Right_Opnd (N)) = N_Op_Mod
+      then
+         Error_Msg_N
+           ("?unary minus expression should be parenthesized here", N);
+      end if;
+
+      if Etype (R) = Universal_Integer
+        or else Etype (R) = Universal_Real
+      then
+         Check_For_Visible_Operator (N, B_Typ);
+      end if;
+
+      Set_Etype (N, B_Typ);
+      Resolve (R, B_Typ);
+      Check_Unset_Reference (R);
+      Generate_Operator_Reference (N);
+      Eval_Unary_Op (N);
+
+      --  Set overflow checking bit. Much cleverer code needed here eventually
+      --  and perhaps the Resolve routines should be separated for the various
+      --  arithmetic operations, since they will need different processing ???
+
+      if Nkind (N) in N_Op then
+         if not Overflow_Checks_Suppressed (Etype (N)) then
+            Set_Do_Overflow_Check (N, True);
+         end if;
+      end if;
+
+   end Resolve_Unary_Op;
+
+   ----------------------------------
+   -- Resolve_Unchecked_Expression --
+   ----------------------------------
+
+   procedure Resolve_Unchecked_Expression
+     (N   : Node_Id;
+      Typ : Entity_Id)
+   is
+   begin
+      Resolve (Expression (N), Typ, Suppress => All_Checks);
+      Set_Etype (N, Typ);
+   end Resolve_Unchecked_Expression;
+
+   ---------------------------------------
+   -- Resolve_Unchecked_Type_Conversion --
+   ---------------------------------------
+
+   procedure Resolve_Unchecked_Type_Conversion
+     (N   : Node_Id;
+      Typ : Entity_Id)
+   is
+      Operand   : constant Node_Id   := Expression (N);
+      Opnd_Type : constant Entity_Id := Etype (Operand);
+
+   begin
+      --  Resolve operand using its own type.
+
+      Resolve (Operand, Opnd_Type);
+      Eval_Unchecked_Conversion (N);
+
+   end Resolve_Unchecked_Type_Conversion;
+
+   ------------------------------
+   -- Rewrite_Operator_As_Call --
+   ------------------------------
+
+   procedure Rewrite_Operator_As_Call (N : Node_Id; Nam : Entity_Id) is
+      Loc     :  Source_Ptr := Sloc (N);
+      Actuals :  List_Id := New_List;
+      New_N   : Node_Id;
+
+   begin
+      if Nkind (N) in  N_Binary_Op then
+         Append (Left_Opnd (N), Actuals);
+      end if;
+
+      Append (Right_Opnd (N), Actuals);
+
+      New_N :=
+        Make_Function_Call (Sloc => Loc,
+          Name => New_Occurrence_Of (Nam, Loc),
+          Parameter_Associations => Actuals);
+
+      Preserve_Comes_From_Source (New_N, N);
+      Preserve_Comes_From_Source (Name (New_N), N);
+      Rewrite (N, New_N);
+      Set_Etype (N, Etype (Nam));
+   end Rewrite_Operator_As_Call;
+
+   ------------------------------
+   -- Rewrite_Renamed_Operator --
+   ------------------------------
+
+   procedure Rewrite_Renamed_Operator (N : Node_Id; Op : Entity_Id) is
+      Nam       : constant Name_Id := Chars (Op);
+      Is_Binary : constant Boolean := Nkind (N) in N_Binary_Op;
+      Op_Node   : Node_Id;
+
+   begin
+      if Chars (N) /= Nam then
+
+         --  Rewrite the operator node using the real operator, not its
+         --  renaming.
+
+         Op_Node := New_Node (Operator_Kind (Nam, Is_Binary), Sloc (N));
+         Set_Chars      (Op_Node, Nam);
+         Set_Etype      (Op_Node, Etype (N));
+         Set_Entity     (Op_Node, Op);
+         Set_Right_Opnd (Op_Node, Right_Opnd (N));
+
+         Generate_Reference (Op, N);
+
+         if Is_Binary then
+            Set_Left_Opnd  (Op_Node, Left_Opnd  (N));
+         end if;
+
+         Rewrite (N, Op_Node);
+      end if;
+   end Rewrite_Renamed_Operator;
+
+   -----------------------
+   -- Set_Slice_Subtype --
+   -----------------------
+
+   --  Build an implicit subtype declaration to represent the type delivered
+   --  by the slice. This is an abbreviated version of an array subtype. We
+   --  define an index subtype for the slice,  using either the subtype name
+   --  or the discrete range of the slice. To be consistent with index usage
+   --  elsewhere, we create a list header to hold the single index. This list
+   --  is not otherwise attached to the syntax tree.
+
+   procedure Set_Slice_Subtype (N : Node_Id) is
+      Loc           : constant Source_Ptr := Sloc (N);
+      Index         : Node_Id;
+      Index_List    : List_Id := New_List;
+      Index_Subtype : Entity_Id;
+      Index_Type    : Entity_Id;
+      Slice_Subtype : Entity_Id;
+      Drange        : constant Node_Id := Discrete_Range (N);
+
+   begin
+      if Is_Entity_Name (Drange) then
+         Index_Subtype := Entity (Drange);
+
+      else
+         --  We force the evaluation of a range. This is definitely needed in
+         --  the renamed case, and seems safer to do unconditionally. Note in
+         --  any case that since we will create and insert an Itype referring
+         --  to this range, we must make sure any side effect removal actions
+         --  are inserted before the Itype definition.
+
+         if Nkind (Drange) = N_Range then
+            Force_Evaluation (Low_Bound (Drange));
+            Force_Evaluation (High_Bound (Drange));
+         end if;
+
+         Index_Type := Base_Type (Etype (Drange));
+
+         Index_Subtype := Create_Itype (Subtype_Kind (Ekind (Index_Type)), N);
+
+         Set_Scalar_Range (Index_Subtype, Drange);
+         Set_Etype        (Index_Subtype, Index_Type);
+         Set_Size_Info    (Index_Subtype, Index_Type);
+         Set_RM_Size      (Index_Subtype, RM_Size (Index_Type));
+      end if;
+
+      Slice_Subtype := Create_Itype (E_Array_Subtype, N);
+
+      Index := New_Occurrence_Of (Index_Subtype, Loc);
+      Set_Etype (Index, Index_Subtype);
+      Append (Index, Index_List);
+
+      Set_Component_Type (Slice_Subtype, Component_Type (Etype (N)));
+      Set_First_Index    (Slice_Subtype, Index);
+      Set_Etype          (Slice_Subtype, Base_Type (Etype (N)));
+      Set_Is_Constrained (Slice_Subtype, True);
+      Init_Size_Align    (Slice_Subtype);
+
+      Check_Compile_Time_Size (Slice_Subtype);
+
+      --  The Etype of the existing Slice node is reset to this slice
+      --  subtype. Its bounds are obtained from its first index.
+
+      Set_Etype (N, Slice_Subtype);
+
+      --  In the packed case, this must be immediately frozen
+
+      --  Couldn't we always freeze here??? and if we did, then the above
+      --  call to Check_Compile_Time_Size could be eliminated, which would
+      --  be nice, because then that routine could be made private to Freeze.
+
+      if Is_Packed (Slice_Subtype) and not In_Default_Expression then
+         Freeze_Itype (Slice_Subtype, N);
+      end if;
+
+   end Set_Slice_Subtype;
+
+   --------------------------------
+   -- Set_String_Literal_Subtype --
+   --------------------------------
+
+   procedure Set_String_Literal_Subtype (N : Node_Id; Typ : Entity_Id) is
+      Subtype_Id : Entity_Id;
+
+   begin
+      if Nkind (N) /= N_String_Literal then
+         return;
+
+      else
+         Subtype_Id := Create_Itype (E_String_Literal_Subtype, N);
+      end if;
+
+      Set_Component_Type           (Subtype_Id, Component_Type (Typ));
+      Set_String_Literal_Length    (Subtype_Id,
+        UI_From_Int (String_Length (Strval (N))));
+      Set_Etype                    (Subtype_Id, Base_Type (Typ));
+      Set_Is_Constrained           (Subtype_Id);
+
+      --  The low bound is set from the low bound of the corresponding
+      --  index type. Note that we do not store the high bound in the
+      --  string literal subtype, but it can be deduced if necssary
+      --  from the length and the low bound.
+
+      Set_String_Literal_Low_Bound
+        (Subtype_Id, Type_Low_Bound (Etype (First_Index (Typ))));
+
+      Set_Etype (N, Subtype_Id);
+   end Set_String_Literal_Subtype;
+
+   -----------------------------
+   -- Unique_Fixed_Point_Type --
+   -----------------------------
+
+   function Unique_Fixed_Point_Type (N : Node_Id) return Entity_Id is
+      T1   : Entity_Id := Empty;
+      T2   : Entity_Id;
+      Item : Node_Id;
+      Scop : Entity_Id;
+
+      procedure Fixed_Point_Error;
+      --  If true ambiguity, give details.
+
+      procedure Fixed_Point_Error is
+      begin
+         Error_Msg_N ("ambiguous universal_fixed_expression", N);
+         Error_Msg_NE ("\possible interpretation as}", N, T1);
+         Error_Msg_NE ("\possible interpretation as}", N, T2);
+      end Fixed_Point_Error;
+
+   begin
+      --  The operations on Duration are visible, so Duration is always a
+      --  possible interpretation.
+
+      T1 := Standard_Duration;
+
+      Scop := Current_Scope;
+
+      --  Look for fixed-point types in enclosing scopes.
+
+      while Scop /= Standard_Standard loop
+         T2 := First_Entity (Scop);
+
+         while Present (T2) loop
+            if Is_Fixed_Point_Type (T2)
+              and then Current_Entity (T2) = T2
+              and then Scope (Base_Type (T2)) = Scop
+            then
+               if Present (T1) then
+                  Fixed_Point_Error;
+                  return Any_Type;
+               else
+                  T1 := T2;
+               end if;
+            end if;
+
+            Next_Entity (T2);
+         end loop;
+
+         Scop := Scope (Scop);
+      end loop;
+
+      --  Look for visible fixed type declarations in the context.
+
+      Item := First (Context_Items (Cunit (Current_Sem_Unit)));
+
+      while Present (Item) loop
+
+         if Nkind (Item) = N_With_Clause then
+            Scop := Entity (Name (Item));
+            T2 := First_Entity (Scop);
+
+            while Present (T2) loop
+               if Is_Fixed_Point_Type (T2)
+                 and then Scope (Base_Type (T2)) = Scop
+                 and then (Is_Potentially_Use_Visible (T2)
+                             or else In_Use (T2))
+               then
+                  if Present (T1) then
+                     Fixed_Point_Error;
+                     return Any_Type;
+                  else
+                     T1 := T2;
+                  end if;
+               end if;
+
+               Next_Entity (T2);
+            end loop;
+         end if;
+
+         Next (Item);
+      end loop;
+
+      if Nkind (N) = N_Real_Literal then
+         Error_Msg_NE ("real literal interpreted as }?", N, T1);
+
+      else
+         Error_Msg_NE ("universal_fixed expression interpreted as }?", N, T1);
+      end if;
+
+      return T1;
+   end Unique_Fixed_Point_Type;
+
+   ----------------------
+   -- Valid_Conversion --
+   ----------------------
+
+   function Valid_Conversion
+     (N       : Node_Id;
+      Target  : Entity_Id;
+      Operand : Node_Id)
+      return    Boolean
+   is
+      Target_Type : Entity_Id := Base_Type (Target);
+      Opnd_Type   : Entity_Id := Etype (Operand);
+
+      function Conversion_Check
+        (Valid : Boolean;
+         Msg   : String)
+         return  Boolean;
+      --  Little routine to post Msg if Valid is False, returns Valid value
+
+      function Valid_Tagged_Conversion
+        (Target_Type : Entity_Id;
+         Opnd_Type   : Entity_Id)
+         return        Boolean;
+      --  Specifically test for validity of tagged conversions
+
+      ----------------------
+      -- Conversion_Check --
+      ----------------------
+
+      function Conversion_Check
+        (Valid : Boolean;
+         Msg   : String)
+         return  Boolean
+      is
+      begin
+         if not Valid then
+            Error_Msg_N (Msg, Operand);
+         end if;
+
+         return Valid;
+      end Conversion_Check;
+
+      -----------------------------
+      -- Valid_Tagged_Conversion --
+      -----------------------------
+
+      function Valid_Tagged_Conversion
+        (Target_Type : Entity_Id;
+         Opnd_Type   : Entity_Id)
+         return        Boolean
+      is
+      begin
+         --  Upward conversions are allowed (RM 4.6(22)).
+
+         if Covers (Target_Type, Opnd_Type)
+           or else Is_Ancestor (Target_Type, Opnd_Type)
+         then
+            return True;
+
+         --  Downward conversion are allowed if the operand is
+         --  is class-wide (RM 4.6(23)).
+
+         elsif Is_Class_Wide_Type (Opnd_Type)
+              and then Covers (Opnd_Type, Target_Type)
+         then
+            return True;
+
+         elsif Covers (Opnd_Type, Target_Type)
+           or else Is_Ancestor (Opnd_Type, Target_Type)
+         then
+            return
+              Conversion_Check (False,
+                "downward conversion of tagged objects not allowed");
+         else
+            Error_Msg_NE
+              ("invalid tagged conversion, not compatible with}",
+               N, First_Subtype (Opnd_Type));
+            return False;
+         end if;
+      end Valid_Tagged_Conversion;
+
+   --  Start of processing for Valid_Conversion
+
+   begin
+      Check_Parameterless_Call (Operand);
+
+      if Is_Overloaded (Operand) then
+         declare
+            I   : Interp_Index;
+            I1  : Interp_Index;
+            It  : Interp;
+            It1 : Interp;
+            N1  : Entity_Id;
+
+         begin
+            --  Remove procedure calls, which syntactically cannot appear
+            --  in this context, but which cannot be removed by type checking,
+            --  because the context does not impose a type.
+
+            Get_First_Interp (Operand, I, It);
+
+            while Present (It.Typ) loop
+
+               if It.Typ = Standard_Void_Type then
+                  Remove_Interp (I);
+               end if;
+
+               Get_Next_Interp (I, It);
+            end loop;
+
+            Get_First_Interp (Operand, I, It);
+            I1  := I;
+            It1 := It;
+
+            if No (It.Typ) then
+               Error_Msg_N ("illegal operand in conversion", Operand);
+               return False;
+            end if;
+
+            Get_Next_Interp (I, It);
+
+            if Present (It.Typ) then
+               N1  := It1.Nam;
+               It1 :=  Disambiguate (Operand, I1, I, Any_Type);
+
+               if It1 = No_Interp then
+                  Error_Msg_N ("ambiguous operand in conversion", Operand);
+
+                  Error_Msg_Sloc := Sloc (It.Nam);
+                  Error_Msg_N ("possible interpretation#!", Operand);
+
+                  Error_Msg_Sloc := Sloc (N1);
+                  Error_Msg_N ("possible interpretation#!", Operand);
+
+                  return False;
+               end if;
+            end if;
+
+            Set_Etype (Operand, It1.Typ);
+            Opnd_Type := It1.Typ;
+         end;
+      end if;
+
+      if Chars (Current_Scope) = Name_Unchecked_Conversion then
+
+         --  This check is dubious, what if there were a user defined
+         --  scope whose name was Unchecked_Conversion ???
+
+         return True;
+
+      elsif Is_Numeric_Type (Target_Type)  then
+         if Opnd_Type = Universal_Fixed then
+            return True;
+         else
+            return Conversion_Check (Is_Numeric_Type (Opnd_Type),
+                             "illegal operand for numeric conversion");
+         end if;
+
+      elsif Is_Array_Type (Target_Type) then
+         if not Is_Array_Type (Opnd_Type)
+           or else Opnd_Type = Any_Composite
+           or else Opnd_Type = Any_String
+         then
+            Error_Msg_N
+              ("illegal operand for array conversion", Operand);
+            return False;
+
+         elsif Number_Dimensions (Target_Type) /=
+           Number_Dimensions (Opnd_Type)
+         then
+            Error_Msg_N
+              ("incompatible number of dimensions for conversion", Operand);
+            return False;
+
+         else
+            declare
+               Target_Index      : Node_Id := First_Index (Target_Type);
+               Opnd_Index        : Node_Id := First_Index (Opnd_Type);
+
+               Target_Index_Type : Entity_Id;
+               Opnd_Index_Type   : Entity_Id;
+
+               Target_Comp_Type  : Entity_Id := Component_Type (Target_Type);
+               Opnd_Comp_Type    : Entity_Id := Component_Type (Opnd_Type);
+
+            begin
+               while Present (Target_Index) and then Present (Opnd_Index) loop
+                  Target_Index_Type := Etype (Target_Index);
+                  Opnd_Index_Type   := Etype (Opnd_Index);
+
+                  if not (Is_Integer_Type (Target_Index_Type)
+                          and then Is_Integer_Type (Opnd_Index_Type))
+                    and then (Root_Type (Target_Index_Type)
+                              /= Root_Type (Opnd_Index_Type))
+                  then
+                     Error_Msg_N
+                       ("incompatible index types for array conversion",
+                        Operand);
+                     return False;
+                  end if;
+
+                  Next_Index (Target_Index);
+                  Next_Index (Opnd_Index);
+               end loop;
+
+               if Base_Type (Target_Comp_Type) /=
+                 Base_Type (Opnd_Comp_Type)
+               then
+                  Error_Msg_N
+                    ("incompatible component types for array conversion",
+                     Operand);
+                  return False;
+
+               elsif
+                  Is_Constrained (Target_Comp_Type)
+                    /= Is_Constrained (Opnd_Comp_Type)
+                  or else not Subtypes_Statically_Match
+                                (Target_Comp_Type, Opnd_Comp_Type)
+               then
+                  Error_Msg_N
+                    ("component subtypes must statically match", Operand);
+                  return False;
+
+               end if;
+            end;
+         end if;
+
+         return True;
+
+      elsif (Ekind (Target_Type) = E_General_Access_Type
+        or else Ekind (Target_Type) = E_Anonymous_Access_Type)
+          and then
+            Conversion_Check
+              (Is_Access_Type (Opnd_Type)
+                 and then Ekind (Opnd_Type) /=
+                   E_Access_Subprogram_Type
+                 and then Ekind (Opnd_Type) /=
+                   E_Access_Protected_Subprogram_Type,
+               "must be an access-to-object type")
+      then
+         if Is_Access_Constant (Opnd_Type)
+           and then not Is_Access_Constant (Target_Type)
+         then
+            Error_Msg_N
+              ("access-to-constant operand type not allowed", Operand);
+            return False;
+         end if;
+
+         --  Check the static accessibility rule of 4.6(17). Note that
+         --  the check is not enforced when within an instance body, since
+         --  the RM requires such cases to be caught at run time.
+
+         if Ekind (Target_Type) /= E_Anonymous_Access_Type then
+            if Type_Access_Level (Opnd_Type)
+              > Type_Access_Level (Target_Type)
+            then
+               --  In an instance, this is a run-time check, but one we
+               --  know will fail, so generate an appropriate warning.
+               --  The raise will be generated by Expand_N_Type_Conversion.
+
+               if In_Instance_Body then
+                  Error_Msg_N
+                    ("?cannot convert local pointer to non-local access type",
+                     Operand);
+                  Error_Msg_N
+                    ("?Program_Error will be raised at run time", Operand);
+
+               else
+                  Error_Msg_N
+                    ("cannot convert local pointer to non-local access type",
+                     Operand);
+                  return False;
+               end if;
+
+            elsif Ekind (Opnd_Type) = E_Anonymous_Access_Type then
+
+               --  When the operand is a selected access discriminant
+               --  the check needs to be made against the level of the
+               --  object denoted by the prefix of the selected name.
+               --  (Object_Access_Level handles checking the prefix
+               --  of the operand for this case.)
+
+               if Nkind (Operand) = N_Selected_Component
+                 and then Object_Access_Level (Operand)
+                   > Type_Access_Level (Target_Type)
+               then
+                  --  In an instance, this is a run-time check, but one we
+                  --  know will fail, so generate an appropriate warning.
+                  --  The raise will be generated by Expand_N_Type_Conversion.
+
+                  if In_Instance_Body then
+                     Error_Msg_N
+                       ("?cannot convert access discriminant to non-local" &
+                        " access type", Operand);
+                     Error_Msg_N
+                       ("?Program_Error will be raised at run time", Operand);
+
+                  else
+                     Error_Msg_N
+                       ("cannot convert access discriminant to non-local" &
+                        " access type", Operand);
+                     return False;
+                  end if;
+               end if;
+
+               --  The case of a reference to an access discriminant
+               --  from within a type declaration (which will appear
+               --  as a discriminal) is always illegal because the
+               --  level of the discriminant is considered to be
+               --  deeper than any (namable) access type.
+
+               if Is_Entity_Name (Operand)
+                 and then (Ekind (Entity (Operand)) = E_In_Parameter
+                            or else Ekind (Entity (Operand)) = E_Constant)
+                 and then Present (Discriminal_Link (Entity (Operand)))
+               then
+                  Error_Msg_N
+                    ("discriminant has deeper accessibility level than target",
+                     Operand);
+                  return False;
+               end if;
+            end if;
+         end if;
+
+         declare
+            Target : constant Entity_Id := Designated_Type (Target_Type);
+            Opnd   : constant Entity_Id := Designated_Type (Opnd_Type);
+
+         begin
+            if Is_Tagged_Type (Target) then
+               return Valid_Tagged_Conversion (Target, Opnd);
+
+            else
+               if Base_Type (Target) /= Base_Type (Opnd) then
+                  Error_Msg_NE
+                    ("target designated type not compatible with }",
+                     N, Base_Type (Opnd));
+                  return False;
+
+               elsif not Subtypes_Statically_Match (Target, Opnd)
+                  and then (not Has_Discriminants (Target)
+                             or else Is_Constrained (Target))
+               then
+                  Error_Msg_NE
+                    ("target designated subtype not compatible with }",
+                     N, Opnd);
+                  return False;
+
+               else
+                  return True;
+               end if;
+            end if;
+         end;
+
+      elsif Ekind (Target_Type) = E_Access_Subprogram_Type
+        and then Conversion_Check
+                   (Ekind (Base_Type (Opnd_Type)) = E_Access_Subprogram_Type,
+                    "illegal operand for access subprogram conversion")
+      then
+         --  Check that the designated types are subtype conformant
+
+         if not Subtype_Conformant (Designated_Type (Opnd_Type),
+                                    Designated_Type (Target_Type))
+         then
+            Error_Msg_N
+              ("operand type is not subtype conformant with target type",
+               Operand);
+         end if;
+
+         --  Check the static accessibility rule of 4.6(20)
+
+         if Type_Access_Level (Opnd_Type) >
+            Type_Access_Level (Target_Type)
+         then
+            Error_Msg_N
+              ("operand type has deeper accessibility level than target",
+               Operand);
+
+         --  Check that if the operand type is declared in a generic body,
+         --  then the target type must be declared within that same body
+         --  (enforces last sentence of 4.6(20)).
+
+         elsif Present (Enclosing_Generic_Body (Opnd_Type)) then
+            declare
+               O_Gen : constant Node_Id :=
+                         Enclosing_Generic_Body (Opnd_Type);
+
+               T_Gen : Node_Id :=
+                         Enclosing_Generic_Body (Target_Type);
+
+            begin
+               while Present (T_Gen) and then T_Gen /= O_Gen loop
+                  T_Gen := Enclosing_Generic_Body (T_Gen);
+               end loop;
+
+               if T_Gen /= O_Gen then
+                  Error_Msg_N
+                    ("target type must be declared in same generic body"
+                     & " as operand type", N);
+               end if;
+            end;
+         end if;
+
+         return True;
+
+      elsif Is_Remote_Access_To_Subprogram_Type (Target_Type)
+        and then Is_Remote_Access_To_Subprogram_Type (Opnd_Type)
+      then
+         --  It is valid to convert from one RAS type to another provided
+         --  that their specification statically match.
+
+         Check_Subtype_Conformant
+           (New_Id  =>
+              Designated_Type (Corresponding_Remote_Type (Target_Type)),
+            Old_Id  =>
+              Designated_Type (Corresponding_Remote_Type (Opnd_Type)),
+            Err_Loc =>
+              N);
+         return True;
+
+      elsif Is_Tagged_Type (Target_Type) then
+         return Valid_Tagged_Conversion (Target_Type, Opnd_Type);
+
+      --  Types derived from the same root type are convertible.
+
+      elsif Root_Type (Target_Type) = Root_Type (Opnd_Type) then
+         return True;
+
+      --  In an instance, there may be inconsistent views of the same
+      --  type, or types derived from the same type.
+
+      elsif In_Instance
+        and then Underlying_Type (Target_Type) = Underlying_Type (Opnd_Type)
+      then
+         return True;
+
+      --  Special check for common access type error case
+
+      elsif Ekind (Target_Type) = E_Access_Type
+         and then Is_Access_Type (Opnd_Type)
+      then
+         Error_Msg_N ("target type must be general access type!", N);
+         Error_Msg_NE ("add ALL to }!", N, Target_Type);
+
+         return False;
+
+      else
+         Error_Msg_NE ("invalid conversion, not compatible with }",
+           N, Opnd_Type);
+
+         return False;
+      end if;
+   end Valid_Conversion;
+
+end Sem_Res;
diff --git a/gcc/ada/sem_res.ads b/gcc/ada/sem_res.ads
new file mode 100644 (file)
index 0000000..5c92654
--- /dev/null
@@ -0,0 +1,118 @@
+------------------------------------------------------------------------------
+--                                                                          --
+--                         GNAT COMPILER COMPONENTS                         --
+--                                                                          --
+--                              S E M _ R E S                               --
+--                                                                          --
+--                                 S p e c                                  --
+--                                                                          --
+--                            $Revision: 1.19 $
+--                                                                          --
+--          Copyright (C) 1992-1999 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- --
+-- ware  Foundation;  either version 2,  or (at your option) any later ver- --
+-- sion.  GNAT is distributed in the hope that it will be useful, but WITH- --
+-- OUT ANY WARRANTY;  without even the  implied warranty of MERCHANTABILITY --
+-- or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License --
+-- for  more details.  You should have  received  a copy of the GNU General --
+-- Public License  distributed with GNAT;  see file COPYING.  If not, write --
+-- to  the Free Software Foundation,  59 Temple Place - Suite 330,  Boston, --
+-- MA 02111-1307, USA.                                                      --
+--                                                                          --
+-- GNAT was originally developed  by the GNAT team at  New York University. --
+-- It is now maintained by Ada Core Technologies Inc (http://www.gnat.com). --
+--                                                                          --
+------------------------------------------------------------------------------
+
+--  Resolution processing for all subexpression nodes. Note that the separate
+--  package Sem_Aggr contains the actual resolution routines for aggregates,
+--  which are separated off since aggregate processing is complex.
+
+with Snames; use Snames;
+with Types;  use Types;
+
+package Sem_Res is
+
+   --  As described in Sem_Ch4, the type resolution proceeds in two phases.
+   --  The first phase is a bottom up pass that is achieved during the
+   --  recursive traversal performed by the Analyze procedures. This phase
+   --  determines unambiguous types, and collects sets of possible types
+   --  where the interpretation is potentially ambiguous.
+
+   --  On completing this bottom up pass, which corresponds to a call to
+   --  Analyze on a complete context, the Resolve routine is called which
+   --  performs a top down resolution with recursive calls to itself to
+   --  resolve operands.
+
+   --  Since in practice a lot of semantic analysis has to be postponed until
+   --  types are known (e.g. static folding, setting of suppress flags), the
+   --  Resolve routines also complete the semantic analyze, and also call the
+   --  expander for possibly expansion of the completely type resolved node.
+
+   procedure Resolve (N : Node_Id; Typ : Entity_Id);
+   procedure Resolve (N : Node_Id; Typ : Entity_Id; Suppress : Check_Id);
+   --  Top level type-checking procedure, called in a complete context. The
+   --  construct N, which is a subexpression, has already been analyzed, and
+   --  is required to be of type Typ given the analysis of the context (which
+   --  uses the information gathered on the bottom up phase in Analyze). The
+   --  resolve routines do various other processing, e.g. static evaluation.
+   --  If a Suppress argument is present, then the resolution is done with the
+   --  specified check suppressed (can be All_Checks to suppress all checks).
+
+   procedure Resolve_Discrete_Subtype_Indication
+     (N   : Node_Id;
+      Typ : Entity_Id);
+   --  Resolve subtype indications in choices (case statements and
+   --  aggregates) and in index constraints. Note that the resulting Etype
+   --  of the subtype indication node is set to the Etype of the contained
+   --  range (i.e. an Itype is not constructed for the actual subtype).
+
+   procedure Resolve_Entry (Entry_Name : Node_Id);
+   --  Find name of entry being called, and resolve prefix of name with its
+   --  own type. For now we assume that the prefix cannot be overloaded and
+   --  the name of the entry plays no role in the resolution.
+
+   procedure Analyze_And_Resolve (N : Node_Id);
+   procedure Analyze_And_Resolve (N : Node_Id; Typ : Entity_Id);
+   procedure Analyze_And_Resolve
+     (N        : Node_Id;
+      Typ      : Entity_Id;
+      Suppress : Check_Id);
+   procedure Analyze_And_Resolve
+     (N        : Node_Id;
+      Suppress : Check_Id);
+   --  These routines combine the effect of Analyze and Resolve. If a Suppress
+   --  argument is present, then the analysis is done with the specified check
+   --  suppressed (can be All_Checks to suppress all checks). These checks are
+   --  suppressed for both the analysis and resolution. If the type argument
+   --  is not present, then the Etype of the expression after the Analyze
+   --  call is used for the Resolve.
+
+   procedure Check_Parameterless_Call (N : Node_Id);
+   --  Several forms of names can denote calls to entities without para-
+   --  meters. The context determines whether the name denotes the entity
+   --  or a call to it. When it is a call, the node must be rebuilt
+   --  accordingly (deprocedured, in A68 terms) and renalyzed to obtain
+   --  possible interpretations.
+   --
+   --  The name may be that of an overloadable construct, or it can be an
+   --  explicit dereference of a prefix that denotes an access to subprogram.
+   --  In that case, we want to convert the name into a call only if the
+   --  context requires the return type of the subprogram.  Finally, a
+   --  parameterless protected subprogram appears as a selected component.
+   --
+   --  The parameter T is the Typ for the corresponding resolve call.
+
+   procedure Pre_Analyze_And_Resolve (N : Node_Id; T : Entity_Id);
+   --  Performs a pre-analysis of expression node N. During pre-analysis
+   --  N is analyzed and then resolved against type T, but no expansion
+   --  is carried out for N or its children. For more info on pre-analysis
+   --  read the spec of Sem.
+
+   procedure Pre_Analyze_And_Resolve (N : Node_Id);
+   --  Same, but use type of node because context does not impose a single
+   --  type.
+
+end Sem_Res;
diff --git a/gcc/ada/sem_smem.adb b/gcc/ada/sem_smem.adb
new file mode 100644 (file)
index 0000000..5b0c29c
--- /dev/null
@@ -0,0 +1,150 @@
+------------------------------------------------------------------------------
+--                                                                          --
+--                         GNAT COMPILER COMPONENTS                         --
+--                                                                          --
+--                             S E M _ S M E M                              --
+--                                                                          --
+--                                 B o d y                                  --
+--                                                                          --
+--                            $Revision: 1.5 $
+--                                                                          --
+--          Copyright (C) 1998-2000, 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- --
+-- ware  Foundation;  either version 2,  or (at your option) any later ver- --
+-- sion.  GNAT is distributed in the hope that it will be useful, but WITH- --
+-- OUT ANY WARRANTY;  without even the  implied warranty of MERCHANTABILITY --
+-- or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License --
+-- for  more details.  You should have  received  a copy of the GNU General --
+-- Public License  distributed with GNAT;  see file COPYING.  If not, write --
+-- to  the Free Software Foundation,  59 Temple Place - Suite 330,  Boston, --
+-- MA 02111-1307, USA.                                                      --
+--                                                                          --
+-- GNAT was originally developed  by the GNAT team at  New York University. --
+-- It is now maintained by Ada Core Technologies Inc (http://www.gnat.com). --
+--                                                                          --
+------------------------------------------------------------------------------
+
+with Atree;  use Atree;
+with Einfo;  use Einfo;
+with Errout; use Errout;
+with Namet;  use Namet;
+with Sinfo;  use Sinfo;
+with Snames; use Snames;
+
+package body Sem_Smem is
+
+   function Contains_Access_Type (T : Entity_Id) return Boolean;
+   --  This function determines if type T is an access type, or contains
+   --  a component (array, record, protected type cases) that contains
+   --  an access type (recursively defined in the appropriate manner).
+
+   ----------------------
+   -- Check_Shared_Var --
+   ----------------------
+
+   procedure Check_Shared_Var
+     (Id : Entity_Id;
+      T  : Entity_Id;
+      N  : Node_Id)
+   is
+   begin
+      --  We cannot tolerate aliased variables, because they might be
+      --  modified via an aliased pointer, and we could not detect that
+      --  this was happening (to update the corresponding shared memory
+      --  file), so we must disallow all use of Aliased
+
+      if Aliased_Present (N) then
+         Error_Msg_N
+           ("aliased variables " &
+            "not supported in Shared_Passive partitions",
+            N);
+
+      --  We can't support access types at all, since they are local
+      --  pointers that cannot in any simple way be transmitted to other
+      --  partitions.
+
+      elsif Is_Access_Type (T) then
+         Error_Msg_N
+           ("access type variables " &
+            "not supported in Shared_Passive partitions",
+            Id);
+
+      --  We cannot tolerate types that contain access types, same reasons
+
+      elsif Contains_Access_Type (T) then
+         Error_Msg_N
+           ("types containing access components " &
+            "not supported in Shared_Passive partitions",
+            Id);
+
+      --  Currently we do not support unconstrained record types, since we
+      --  use 'Write to write out values. This could probably be special
+      --  cased and handled in the future if necessary.
+
+      elsif Is_Record_Type (T)
+        and then not Is_Constrained (T)
+      then
+         Error_Msg_N
+           ("unconstrained variant records " &
+            "not supported in Shared_Passive partitions",
+            Id);
+      end if;
+   end Check_Shared_Var;
+
+   --------------------------
+   -- Contains_Access_Type --
+   --------------------------
+
+   function Contains_Access_Type (T : Entity_Id) return Boolean is
+      C : Entity_Id;
+
+   begin
+      if Is_Access_Type (T) then
+         return True;
+
+      elsif Is_Array_Type (T) then
+         return Contains_Access_Type (Component_Type (T));
+
+      elsif Is_Record_Type (T) then
+         if Has_Discriminants (T) then
+            C := First_Discriminant (T);
+            while Present (C) loop
+               if Comes_From_Source (C) then
+                  return True;
+               else
+                  C := Next_Discriminant (C);
+               end if;
+            end loop;
+         end if;
+
+         C := First_Component (T);
+         while Present (C) loop
+
+            --  For components, ignore internal components other than _Parent
+
+            if Comes_From_Source (T)
+              and then
+                (Chars (C) = Name_uParent
+                  or else
+                 not Is_Internal_Name (Chars (C)))
+              and then Contains_Access_Type (Etype (C))
+            then
+               return True;
+            else
+               C := Next_Component (C);
+            end if;
+         end loop;
+
+         return False;
+
+      elsif Is_Protected_Type (T) then
+         return Contains_Access_Type (Corresponding_Record_Type (T));
+
+      else
+         return False;
+      end if;
+   end Contains_Access_Type;
+
+end Sem_Smem;
diff --git a/gcc/ada/sem_smem.ads b/gcc/ada/sem_smem.ads
new file mode 100644 (file)
index 0000000..a164659
--- /dev/null
@@ -0,0 +1,43 @@
+------------------------------------------------------------------------------
+--                                                                          --
+--                         GNAT COMPILER COMPONENTS                         --
+--                                                                          --
+--                             S E M _ S M E M                              --
+--                                                                          --
+--                                 S p e c                                  --
+--                                                                          --
+--                            $Revision: 1.2 $                              --
+--                                                                          --
+--           Copyright (C) 1998-2000, 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- --
+-- ware  Foundation;  either version 2,  or (at your option) any later ver- --
+-- sion.  GNAT is distributed in the hope that it will be useful, but WITH- --
+-- OUT ANY WARRANTY;  without even the  implied warranty of MERCHANTABILITY --
+-- or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License --
+-- for  more details.  You should have  received  a copy of the GNU General --
+-- Public License  distributed with GNAT;  see file COPYING.  If not, write --
+-- to  the Free Software Foundation,  59 Temple Place - Suite 330,  Boston, --
+-- MA 02111-1307, USA.                                                      --
+--                                                                          --
+-- GNAT was originally developed  by the GNAT team at  New York University. --
+-- It is now maintained by Ada Core Technologies Inc (http://www.gnat.com). --
+--                                                                          --
+------------------------------------------------------------------------------
+
+--  This package contains routines involved in processing of shared memory
+--  variables, i.e. variables declared in shared passive partitions.
+
+with Types; use Types;
+package Sem_Smem is
+
+   procedure Check_Shared_Var
+     (Id : Entity_Id;
+      T  : Entity_Id;
+      N  : Node_Id);
+   --  This routine checks that the object declaration, N, for identifier,
+   --  Id, of type, T, is valid, i.e. that it does not violate restrictions
+   --  on the kind of variables we support in shared passive partitions.
+
+end Sem_Smem;
diff --git a/gcc/ada/sem_type.adb b/gcc/ada/sem_type.adb
new file mode 100644 (file)
index 0000000..9c335e6
--- /dev/null
@@ -0,0 +1,2028 @@
+------------------------------------------------------------------------------
+--                                                                          --
+--                         GNAT COMPILER COMPONENTS                         --
+--                                                                          --
+--                             S E M _ T Y P E                              --
+--                                                                          --
+--                                 B o d y                                  --
+--                                                                          --
+--                            $Revision: 1.198 $
+--                                                                          --
+--          Copyright (C) 1992-2001 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- --
+-- ware  Foundation;  either version 2,  or (at your option) any later ver- --
+-- sion.  GNAT is distributed in the hope that it will be useful, but WITH- --
+-- OUT ANY WARRANTY;  without even the  implied warranty of MERCHANTABILITY --
+-- or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License --
+-- for  more details.  You should have  received  a copy of the GNU General --
+-- Public License  distributed with GNAT;  see file COPYING.  If not, write --
+-- to  the Free Software Foundation,  59 Temple Place - Suite 330,  Boston, --
+-- MA 02111-1307, USA.                                                      --
+--                                                                          --
+-- GNAT was originally developed  by the GNAT team at  New York University. --
+-- It is now maintained by Ada Core Technologies Inc (http://www.gnat.com). --
+--                                                                          --
+------------------------------------------------------------------------------
+
+with Atree;    use Atree;
+with Debug;    use Debug;
+with Einfo;    use Einfo;
+with Errout;   use Errout;
+with Lib;      use Lib;
+with Opt;      use Opt;
+with Output;   use Output;
+with Sem;      use Sem;
+with Sem_Ch6;  use Sem_Ch6;
+with Sem_Ch8;  use Sem_Ch8;
+with Sem_Util; use Sem_Util;
+with Stand;    use Stand;
+with Sinfo;    use Sinfo;
+with Snames;   use Snames;
+with Uintp;    use Uintp;
+
+package body Sem_Type is
+
+   -------------------------------------
+   -- Handling of Overload Resolution --
+   -------------------------------------
+
+   --  Overload resolution uses two passes over the syntax tree of a complete
+   --  context. In the first, bottom-up pass, the types of actuals in calls
+   --  are used to resolve possibly overloaded subprogram and operator names.
+   --  In the second top-down pass, the type of the context (for example the
+   --  condition in a while statement) is used to resolve a possibly ambiguous
+   --  call, and the unique subprogram name in turn imposes a specific context
+   --  on each of its actuals.
+
+   --  Most expressions are in fact unambiguous, and the bottom-up pass is
+   --  sufficient  to resolve most everything. To simplify the common case,
+   --  names and expressions carry a flag Is_Overloaded to indicate whether
+   --  they have more than one interpretation. If the flag is off, then each
+   --  name has already a unique meaning and type, and the bottom-up pass is
+   --  sufficient (and much simpler).
+
+   --------------------------
+   -- Operator Overloading --
+   --------------------------
+
+   --  The visibility of operators is handled differently from that of
+   --  other entities. We do not introduce explicit versions of primitive
+   --  operators for each type definition. As a result, there is only one
+   --  entity corresponding to predefined addition on all numeric types, etc.
+   --  The back-end resolves predefined operators according to their type.
+   --  The visibility of primitive operations then reduces to the visibility
+   --  of the resulting type:  (a + b) is a legal interpretation of some
+   --  primitive operator + if the type of the result (which must also be
+   --  the type of a and b) is directly visible (i.e. either immediately
+   --  visible or use-visible.)
+
+   --  User-defined operators are treated like other functions, but the
+   --  visibility of these user-defined operations must be special-cased
+   --  to determine whether they hide or are hidden by predefined operators.
+   --  The form P."+" (x, y) requires additional handling.
+   --
+   --  Concatenation is treated more conventionally: for every one-dimensional
+   --  array type we introduce a explicit concatenation operator. This is
+   --  necessary to handle the case of (element & element => array) which
+   --  cannot be handled conveniently if there is no explicit instance of
+   --  resulting type of the operation.
+
+   -----------------------
+   -- Local Subprograms --
+   -----------------------
+
+   procedure All_Overloads;
+   pragma Warnings (Off, All_Overloads);
+   --  Debugging procedure: list full contents of Overloads table.
+
+   function Universal_Interpretation (Opnd : Node_Id) return Entity_Id;
+   --  Yields universal_Integer or Universal_Real if this is a candidate.
+
+   function Specific_Type (T1, T2 : Entity_Id) return Entity_Id;
+   --  If T1 and T2 are compatible, return  the one that is not
+   --  universal or is not a "class" type (any_character,  etc).
+
+   --------------------
+   -- Add_One_Interp --
+   --------------------
+
+   procedure Add_One_Interp
+     (N         : Node_Id;
+      E         : Entity_Id;
+      T         : Entity_Id;
+      Opnd_Type : Entity_Id := Empty)
+   is
+      Vis_Type : Entity_Id;
+
+      procedure Add_Entry (Name :  Entity_Id; Typ : Entity_Id);
+      --  Add one interpretation to node. Node is already known to be
+      --  overloaded. Add new interpretation if not hidden by previous
+      --  one, and remove previous one if hidden by new one.
+
+      function Is_Universal_Operation (Op : Entity_Id) return Boolean;
+      --  True if the entity is a predefined operator and the operands have
+      --  a universal Interpretation.
+
+      ---------------
+      -- Add_Entry --
+      ---------------
+
+      procedure Add_Entry (Name :  Entity_Id; Typ : Entity_Id) is
+         Index : Interp_Index;
+         It    : Interp;
+
+      begin
+         Get_First_Interp (N, Index, It);
+
+         while Present (It.Nam) loop
+
+            --  A user-defined subprogram hides another declared at an outer
+            --  level, or one that is use-visible. So return if previous
+            --  definition hides new one (which is either in an outer
+            --  scope, or use-visible). Note that for functions use-visible
+            --  is the same as potentially use-visible. If new one hides
+            --  previous one, replace entry in table of interpretations.
+            --  If this is a universal operation, retain the operator in case
+            --  preference rule applies.
+
+            if (((Ekind (Name) = E_Function or else Ekind (Name) = E_Procedure)
+                 and then Ekind (Name) = Ekind (It.Nam))
+                or else (Ekind (Name) = E_Operator
+              and then Ekind (It.Nam) = E_Function))
+
+              and then Is_Immediately_Visible (It.Nam)
+              and then Type_Conformant (Name, It.Nam)
+              and then Base_Type (It.Typ) = Base_Type (T)
+            then
+               if Is_Universal_Operation (Name) then
+                  exit;
+
+               --  If node is an operator symbol, we have no actuals with
+               --  which to check hiding, and this is done in full in the
+               --  caller (Analyze_Subprogram_Renaming) so we include the
+               --  predefined operator in any case.
+
+               elsif Nkind (N) = N_Operator_Symbol
+                 or else (Nkind (N) = N_Expanded_Name
+                            and then
+                          Nkind (Selector_Name (N)) = N_Operator_Symbol)
+               then
+                  exit;
+
+               elsif not In_Open_Scopes (Scope (Name))
+                 or else Scope_Depth (Scope (Name))
+                   <= Scope_Depth (Scope (It.Nam))
+               then
+                  --  If ambiguity within instance, and entity is not an
+                  --  implicit operation, save for later disambiguation.
+
+                  if Scope (Name) = Scope (It.Nam)
+                    and then not Is_Inherited_Operation (Name)
+                    and then In_Instance
+                  then
+                     exit;
+                  else
+                     return;
+                  end if;
+
+               else
+                  All_Interp.Table (Index).Nam := Name;
+                  return;
+               end if;
+
+            --  Avoid making duplicate entries in overloads
+
+            elsif Name = It.Nam
+              and then Base_Type (It.Typ) = Base_Type (T)
+            then
+               return;
+
+            --  Otherwise keep going
+
+            else
+               Get_Next_Interp (Index, It);
+            end if;
+
+         end loop;
+
+         --  On exit, enter new interpretation. The context, or a preference
+         --  rule, will resolve the ambiguity on the second pass.
+
+         All_Interp.Table (All_Interp.Last) := (Name, Typ);
+         All_Interp.Increment_Last;
+         All_Interp.Table (All_Interp.Last) := No_Interp;
+
+      end Add_Entry;
+
+      ----------------------------
+      -- Is_Universal_Operation --
+      ----------------------------
+
+      function Is_Universal_Operation (Op : Entity_Id) return Boolean is
+         Arg : Node_Id;
+
+      begin
+         if Ekind (Op) /= E_Operator then
+            return False;
+
+         elsif Nkind (N) in N_Binary_Op then
+            return Present (Universal_Interpretation (Left_Opnd (N)))
+              and then Present (Universal_Interpretation (Right_Opnd (N)));
+
+         elsif Nkind (N) in N_Unary_Op then
+            return Present (Universal_Interpretation (Right_Opnd (N)));
+
+         elsif Nkind (N) = N_Function_Call then
+            Arg := First_Actual (N);
+
+            while Present (Arg) loop
+
+               if No (Universal_Interpretation (Arg)) then
+                  return False;
+               end if;
+
+               Next_Actual (Arg);
+            end loop;
+
+            return True;
+
+         else
+            return False;
+         end if;
+      end Is_Universal_Operation;
+
+   --  Start of processing for Add_One_Interp
+
+   begin
+      --  If the interpretation is a predefined operator, verify that the
+      --  result type is visible, or that the entity has already been
+      --  resolved (case of an instantiation node that refers to a predefined
+      --  operation, or an internally generated operator node, or an operator
+      --  given as an expanded name). If the operator is a comparison or
+      --  equality, it is the type of the operand that matters to determine
+      --  whether the operator is visible. In an instance, the check is not
+      --  performed, given that the operator was visible in the generic.
+
+      if Ekind (E) = E_Operator then
+
+         if Present (Opnd_Type) then
+            Vis_Type := Opnd_Type;
+         else
+            Vis_Type := Base_Type (T);
+         end if;
+
+         if In_Open_Scopes (Scope (Vis_Type))
+           or else Is_Potentially_Use_Visible (Vis_Type)
+           or else In_Use (Vis_Type)
+           or else (In_Use (Scope (Vis_Type))
+                     and then not Is_Hidden (Vis_Type))
+           or else Nkind (N) = N_Expanded_Name
+           or else (Nkind (N) in N_Op and then E = Entity (N))
+           or else In_Instance
+         then
+            null;
+
+         --  If the node is given in functional notation and the prefix
+         --  is an expanded name, then the operator is visible if the
+         --  prefix is the scope of the result type as well.
+
+         elsif Nkind (N) = N_Function_Call
+           and then Nkind (Name (N)) = N_Expanded_Name
+           and then (Entity (Prefix (Name (N))) = Scope (Base_Type (T))
+                      or else Entity (Prefix (Name (N))) = Scope (Vis_Type))
+         then
+            null;
+
+         --  Save type for subsequent error message, in case no other
+         --  interpretation is found.
+
+         else
+            Candidate_Type := Vis_Type;
+            return;
+         end if;
+
+      --  In an instance, an abstract non-dispatching operation cannot
+      --  be a candidate interpretation, because it could not have been
+      --  one in the generic (it may be a spurious overloading in the
+      --  instance).
+
+      elsif In_Instance
+        and then Is_Abstract (E)
+        and then not Is_Dispatching_Operation (E)
+      then
+         return;
+      end if;
+
+      --  If this is the first interpretation of N, N has type Any_Type.
+      --  In that case place the new type on the node. If one interpretation
+      --  already exists, indicate that the node is overloaded, and store
+      --  both the previous and the new interpretation in All_Interp. If
+      --  this is a later interpretation, just add it to the set.
+
+      if Etype (N) = Any_Type then
+         if Is_Type (E) then
+            Set_Etype (N, T);
+
+         else
+            --  Record both the operator or subprogram name, and its type.
+
+            if Nkind (N) in N_Op or else Is_Entity_Name (N) then
+               Set_Entity (N, E);
+            end if;
+
+            Set_Etype (N, T);
+         end if;
+
+      --  Either there is no current interpretation in the table for any
+      --  node or the interpretation that is present is for a different
+      --  node. In both cases add a new interpretation to the table.
+
+      elsif Interp_Map.Last < 0
+        or else Interp_Map.Table (Interp_Map.Last).Node /= N
+      then
+         New_Interps (N);
+
+         if (Nkind (N) in N_Op or else Is_Entity_Name (N))
+           and then Present (Entity (N))
+         then
+            Add_Entry (Entity (N), Etype (N));
+
+         elsif (Nkind (N) = N_Function_Call
+                 or else Nkind (N) = N_Procedure_Call_Statement)
+           and then (Nkind (Name (N)) = N_Operator_Symbol
+                      or else Is_Entity_Name (Name (N)))
+         then
+            Add_Entry (Entity (Name (N)), Etype (N));
+
+         else
+            --  Overloaded prefix in indexed or selected component,
+            --  or call whose name is an expresion or another call.
+
+            Add_Entry (Etype (N), Etype (N));
+         end if;
+
+         Add_Entry (E, T);
+
+      else
+         Add_Entry (E, T);
+      end if;
+   end Add_One_Interp;
+
+   -------------------
+   -- All_Overloads --
+   -------------------
+
+   procedure All_Overloads is
+   begin
+      for J in All_Interp.First .. All_Interp.Last loop
+
+         if Present (All_Interp.Table (J).Nam) then
+            Write_Entity_Info (All_Interp.Table (J). Nam, " ");
+         else
+            Write_Str ("No Interp");
+         end if;
+
+         Write_Str ("=================");
+         Write_Eol;
+      end loop;
+   end All_Overloads;
+
+   ---------------------
+   -- Collect_Interps --
+   ---------------------
+
+   procedure Collect_Interps (N : Node_Id) is
+      Ent          : constant Entity_Id := Entity (N);
+      H            : Entity_Id;
+      First_Interp : Interp_Index;
+
+   begin
+      New_Interps (N);
+
+      --  Unconditionally add the entity that was initially matched
+
+      First_Interp := All_Interp.Last;
+      Add_One_Interp (N, Ent, Etype (N));
+
+      --  For expanded name, pick up all additional entities from the
+      --  same scope, since these are obviously also visible. Note that
+      --  these are not necessarily contiguous on the homonym chain.
+
+      if Nkind (N) = N_Expanded_Name then
+         H := Homonym (Ent);
+         while Present (H) loop
+            if Scope (H) = Scope (Entity (N)) then
+               Add_One_Interp (N, H, Etype (H));
+            end if;
+
+            H := Homonym (H);
+         end loop;
+
+      --  Case of direct name
+
+      else
+         --  First, search the homonym chain for directly visible entities
+
+         H := Current_Entity (Ent);
+         while Present (H) loop
+            exit when (not Is_Overloadable (H))
+              and then Is_Immediately_Visible (H);
+
+            if Is_Immediately_Visible (H)
+              and then H /= Ent
+            then
+               --  Only add interpretation if not hidden by an inner
+               --  immediately visible one.
+
+               for J in First_Interp .. All_Interp.Last - 1 loop
+
+                  --  Current homograph is not hidden. Add to overloads.
+
+                  if not Is_Immediately_Visible (All_Interp.Table (J).Nam) then
+                     exit;
+
+                  --  Homograph is hidden, unless it is a predefined operator.
+
+                  elsif Type_Conformant (H, All_Interp.Table (J).Nam) then
+
+                     --  A homograph in the same scope can occur within an
+                     --  instantiation, the resulting ambiguity has to be
+                     --  resolved later.
+
+                     if Scope (H) = Scope (Ent)
+                        and then In_Instance
+                        and then not Is_Inherited_Operation (H)
+                     then
+                        All_Interp.Table (All_Interp.Last) := (H, Etype (H));
+                        All_Interp.Increment_Last;
+                        All_Interp.Table (All_Interp.Last) := No_Interp;
+                        goto Next_Homograph;
+
+                     elsif Scope (H) /= Standard_Standard then
+                        goto Next_Homograph;
+                     end if;
+                  end if;
+               end loop;
+
+               --  On exit, we know that current homograph is not hidden.
+
+               Add_One_Interp (N, H, Etype (H));
+
+               if Debug_Flag_E then
+                  Write_Str ("Add overloaded Interpretation ");
+                  Write_Int (Int (H));
+                  Write_Eol;
+               end if;
+            end if;
+
+            <<Next_Homograph>>
+               H := Homonym (H);
+         end loop;
+
+         --  Scan list of homographs for use-visible entities only.
+
+         H := Current_Entity (Ent);
+
+         while Present (H) loop
+            if Is_Potentially_Use_Visible (H)
+              and then H /= Ent
+              and then Is_Overloadable (H)
+            then
+               for J in First_Interp .. All_Interp.Last - 1 loop
+
+                  if not Is_Immediately_Visible (All_Interp.Table (J).Nam) then
+                     exit;
+
+                  elsif Type_Conformant (H, All_Interp.Table (J).Nam) then
+                     goto Next_Use_Homograph;
+                  end if;
+               end loop;
+
+               Add_One_Interp (N, H, Etype (H));
+            end if;
+
+            <<Next_Use_Homograph>>
+               H := Homonym (H);
+         end loop;
+      end if;
+
+      if All_Interp.Last = First_Interp + 1 then
+
+         --  The original interpretation is in fact not overloaded.
+
+         Set_Is_Overloaded (N, False);
+      end if;
+   end Collect_Interps;
+
+   ------------
+   -- Covers --
+   ------------
+
+   function Covers (T1, T2 : Entity_Id) return Boolean is
+   begin
+      pragma Assert (Present (T1) and Present (T2));
+
+      --  Simplest case: same types are compatible, and types that have the
+      --  same base type and are not generic actuals are compatible. Generic
+      --  actuals  belong to their class but are not compatible with other
+      --  types of their class, and in particular with other generic actuals.
+      --  They are however compatible with their own subtypes, and itypes
+      --  with the same base are compatible as well. Similary, constrained
+      --  subtypes obtained from expressions of an unconstrained nominal type
+      --  are compatible with the base type (may lead to spurious ambiguities
+      --  in obscure cases ???)
+
+      --  Generic actuals require special treatment to avoid spurious ambi-
+      --  guities in an instance, when two formal types are instantiated with
+      --  the same actual, so that different subprograms end up with the same
+      --  signature in the instance.
+
+      if T1 = T2 then
+         return True;
+
+      elsif Base_Type (T1) = Base_Type (T2) then
+         if not Is_Generic_Actual_Type (T1) then
+            return True;
+         else
+            return (not Is_Generic_Actual_Type (T2)
+                     or else Is_Itype (T1)
+                     or else Is_Itype (T2)
+                     or else Is_Constr_Subt_For_U_Nominal (T1)
+                     or else Is_Constr_Subt_For_U_Nominal (T2)
+                     or else Scope (T1) /= Scope (T2));
+         end if;
+
+      --  Literals are compatible with types in  a given "class"
+
+      elsif (T2 = Universal_Integer and then Is_Integer_Type (T1))
+        or else (T2 = Universal_Real    and then Is_Real_Type (T1))
+        or else (T2 = Universal_Fixed   and then Is_Fixed_Point_Type (T1))
+        or else (T2 = Any_Fixed         and then Is_Fixed_Point_Type (T1))
+        or else (T2 = Any_String        and then Is_String_Type (T1))
+        or else (T2 = Any_Character     and then Is_Character_Type (T1))
+        or else (T2 = Any_Access        and then Is_Access_Type (T1))
+      then
+         return True;
+
+      --  The context may be class wide.
+
+      elsif Is_Class_Wide_Type (T1)
+        and then Is_Ancestor (Root_Type (T1), T2)
+      then
+         return True;
+
+      elsif Is_Class_Wide_Type (T1)
+        and then Is_Class_Wide_Type (T2)
+        and then Base_Type (Etype (T1)) = Base_Type (Etype (T2))
+      then
+         return True;
+
+      --  In a dispatching call the actual may be class-wide
+
+      elsif Is_Class_Wide_Type (T2)
+        and then Base_Type (Root_Type (T2)) = Base_Type (T1)
+      then
+         return True;
+
+      --  Some contexts require a class of types rather than a specific type
+
+      elsif (T1 = Any_Integer and then Is_Integer_Type (T2))
+        or else (T1 = Any_Boolean and then Is_Boolean_Type (T2))
+        or else (T1 = Any_Real and then Is_Real_Type (T2))
+        or else (T1 = Any_Fixed and then Is_Fixed_Point_Type (T2))
+        or else (T1 = Any_Discrete and then Is_Discrete_Type (T2))
+      then
+         return True;
+
+      --  An aggregate is compatible with an array or record type
+
+      elsif T2 = Any_Composite
+        and then Ekind (T1) in E_Array_Type .. E_Record_Subtype
+      then
+         return True;
+
+      --  If the expected type is an anonymous access, the designated
+      --  type must cover that of the expression.
+
+      elsif Ekind (T1) = E_Anonymous_Access_Type
+        and then Is_Access_Type (T2)
+        and then Covers (Designated_Type (T1), Designated_Type (T2))
+      then
+         return True;
+
+      --  An Access_To_Subprogram is compatible with itself, or with an
+      --  anonymous type created for an attribute reference Access.
+
+      elsif (Ekind (Base_Type (T1)) = E_Access_Subprogram_Type
+               or else
+             Ekind (Base_Type (T1)) = E_Access_Protected_Subprogram_Type)
+        and then Is_Access_Type (T2)
+        and then (not Comes_From_Source (T1)
+                   or else not Comes_From_Source (T2))
+        and then (Is_Overloadable (Designated_Type (T2))
+                    or else
+                  Ekind (Designated_Type (T2)) = E_Subprogram_Type)
+        and then
+          Type_Conformant (Designated_Type (T1), Designated_Type (T2))
+        and then
+          Mode_Conformant (Designated_Type (T1), Designated_Type (T2))
+      then
+         return True;
+
+      elsif Is_Record_Type (T1)
+        and then (Is_Remote_Call_Interface (T1)
+                   or else Is_Remote_Types (T1))
+        and then Present (Corresponding_Remote_Type (T1))
+      then
+         return Covers (Corresponding_Remote_Type (T1), T2);
+
+      elsif Ekind (T2) = E_Access_Attribute_Type
+        and then (Ekind (Base_Type (T1)) = E_General_Access_Type
+              or else Ekind (Base_Type (T1)) = E_Access_Type)
+        and then Covers (Designated_Type (T1), Designated_Type (T2))
+      then
+         --  If the target type is a RACW type while the source is an access
+         --  attribute type, we are building a RACW that may be exported.
+
+         if Is_Remote_Access_To_Class_Wide_Type (Base_Type (T1)) then
+            Set_Has_RACW (Current_Sem_Unit);
+         end if;
+
+         return True;
+
+      elsif Ekind (T2) = E_Allocator_Type
+        and then Is_Access_Type (T1)
+        and then Covers (Designated_Type (T1), Designated_Type (T2))
+      then
+         return True;
+
+      --  A boolean operation on integer literals is compatible with a
+      --  modular context.
+
+      elsif T2 = Any_Modular
+        and then Is_Modular_Integer_Type (T1)
+      then
+         return True;
+
+      --  The actual type may be the result of a previous error
+
+      elsif Base_Type (T2) = Any_Type then
+         return True;
+
+      --  A packed array type covers its corresponding non-packed type.
+      --  This is not legitimate Ada, but allows the omission of a number
+      --  of otherwise useless unchecked conversions, and since this can
+      --  only arise in (known correct) expanded code, no harm is done
+
+      elsif Is_Array_Type (T2)
+        and then Is_Packed (T2)
+        and then T1 = Packed_Array_Type (T2)
+      then
+         return True;
+
+      --  Similarly an array type covers its corresponding packed array type
+
+      elsif Is_Array_Type (T1)
+        and then Is_Packed (T1)
+        and then T2 = Packed_Array_Type (T1)
+      then
+         return True;
+
+      --  In an instance the proper view may not always be correct for
+      --  private types, but private and full view are compatible. This
+      --  removes spurious errors from nested instantiations that involve,
+      --  among other things, types derived from privated types.
+
+      elsif In_Instance
+        and then Is_Private_Type (T1)
+        and then ((Present (Full_View (T1))
+                    and then Covers (Full_View (T1), T2))
+          or else Base_Type (T1) = T2
+          or else Base_Type (T2) = T1)
+      then
+         return True;
+
+      --  In the expansion of inlined bodies, types are compatible if they
+      --  are structurally equivalent.
+
+      elsif In_Inlined_Body
+        and then (Underlying_Type (T1) = Underlying_Type (T2)
+                   or else (Is_Access_Type (T1)
+                              and then Is_Access_Type (T2)
+                              and then
+                                Designated_Type (T1) = Designated_Type (T2))
+                   or else (T1 = Any_Access
+                              and then Is_Access_Type (Underlying_Type (T2))))
+      then
+         return True;
+
+      --  Otherwise it doesn't cover!
+
+      else
+         return False;
+      end if;
+   end Covers;
+
+   ------------------
+   -- Disambiguate --
+   ------------------
+
+   function Disambiguate
+     (N      : Node_Id;
+      I1, I2 : Interp_Index;
+      Typ    : Entity_Id)
+      return   Interp
+   is
+      I           : Interp_Index;
+      It          : Interp;
+      It1, It2    : Interp;
+      Nam1, Nam2  : Entity_Id;
+      Predef_Subp : Entity_Id;
+      User_Subp   : Entity_Id;
+
+      function Matches (Actual, Formal : Node_Id) return Boolean;
+      --  Look for exact type match in an instance, to remove spurious
+      --  ambiguities when two formal types have the same actual.
+
+      function Standard_Operator return Boolean;
+
+      function Remove_Conversions return Interp;
+      --  Last chance for pathological cases involving comparisons on
+      --  literals, and user overloadings of the same operator. Such
+      --  pathologies have been removed from the ACVC, but still appear in
+      --  two DEC tests, with the following notable quote from Ben Brosgol:
+      --
+      --  [Note: I disclaim all credit/responsibility/blame for coming up with
+      --  this example;  Robert Dewar brought it to our attention, since it
+      --  is apparently found in the ACVC 1.5. I did not attempt to find
+      --  the reason in the Reference Manual that makes the example legal,
+      --  since I was too nauseated by it to want to pursue it further.]
+      --
+      --  Accordingly, this is not a fully recursive solution, but it handles
+      --  DEC tests c460vsa, c460vsb. It also handles ai00136a, which pushes
+      --  pathology in the other direction with calls whose multiple overloaded
+      --  actuals make them truly unresolvable.
+
+      -------------
+      -- Matches --
+      -------------
+
+      function Matches (Actual, Formal : Node_Id) return Boolean is
+         T1 : constant Entity_Id := Etype (Actual);
+         T2 : constant Entity_Id := Etype (Formal);
+
+      begin
+         return T1 = T2
+           or else
+             (Is_Numeric_Type (T2)
+               and then
+             (T1 = Universal_Real or else T1 = Universal_Integer));
+      end Matches;
+
+      ------------------------
+      -- Remove_Conversions --
+      ------------------------
+
+      function Remove_Conversions return Interp is
+         I    : Interp_Index;
+         It   : Interp;
+         It1  : Interp;
+         F1   : Entity_Id;
+         Act1 : Node_Id;
+         Act2 : Node_Id;
+
+      begin
+         It1   := No_Interp;
+         Get_First_Interp (N, I, It);
+
+         while Present (It.Typ) loop
+
+            if not Is_Overloadable (It.Nam) then
+               return No_Interp;
+            end if;
+
+            F1 := First_Formal (It.Nam);
+
+            if No (F1) then
+               return It1;
+
+            else
+               if Nkind (N) = N_Function_Call
+                 or else Nkind (N) = N_Procedure_Call_Statement
+               then
+                  Act1 := First_Actual (N);
+
+                  if Present (Act1) then
+                     Act2 := Next_Actual (Act1);
+                  else
+                     Act2 := Empty;
+                  end if;
+
+               elsif Nkind (N) in N_Unary_Op then
+                  Act1 := Right_Opnd (N);
+                  Act2 := Empty;
+
+               elsif Nkind (N) in N_Binary_Op then
+                  Act1 := Left_Opnd (N);
+                  Act2 := Right_Opnd (N);
+
+               else
+                  return It1;
+               end if;
+
+               if Nkind (Act1) in N_Op
+                 and then Is_Overloaded (Act1)
+                 and then (Nkind (Right_Opnd (Act1)) = N_Integer_Literal
+                            or else Nkind (Right_Opnd (Act1)) = N_Real_Literal)
+                 and then Has_Compatible_Type (Act1, Standard_Boolean)
+                 and then Etype (F1) = Standard_Boolean
+               then
+
+                  if It1 /= No_Interp then
+                     return No_Interp;
+
+                  elsif Present (Act2)
+                    and then Nkind (Act2) in N_Op
+                    and then Is_Overloaded (Act2)
+                    and then (Nkind (Right_Opnd (Act1)) = N_Integer_Literal
+                                or else
+                              Nkind (Right_Opnd (Act1)) = N_Real_Literal)
+                    and then Has_Compatible_Type (Act2, Standard_Boolean)
+                  then
+                     --  The preference rule on the first actual is not
+                     --  sufficient to disambiguate.
+
+                     goto Next_Interp;
+
+                  else
+                     It1 := It;
+                  end if;
+               end if;
+            end if;
+
+            <<Next_Interp>>
+               Get_Next_Interp (I, It);
+         end loop;
+
+         if Errors_Detected > 0 then
+
+            --  After some error, a formal may have Any_Type and yield
+            --  a spurious match. To avoid cascaded errors if possible,
+            --  check for such a formal in either candidate.
+
+            declare
+               Formal : Entity_Id;
+
+            begin
+               Formal := First_Formal (Nam1);
+               while Present (Formal) loop
+                  if Etype (Formal) = Any_Type then
+                     return Disambiguate.It2;
+                  end if;
+
+                  Next_Formal (Formal);
+               end loop;
+
+               Formal := First_Formal (Nam2);
+               while Present (Formal) loop
+                  if Etype (Formal) = Any_Type then
+                     return Disambiguate.It1;
+                  end if;
+
+                  Next_Formal (Formal);
+               end loop;
+            end;
+         end if;
+
+         return It1;
+      end Remove_Conversions;
+
+      -----------------------
+      -- Standard_Operator --
+      -----------------------
+
+      function Standard_Operator return Boolean is
+         Nam : Node_Id;
+
+      begin
+         if Nkind (N) in N_Op then
+            return True;
+
+         elsif Nkind (N) = N_Function_Call then
+            Nam := Name (N);
+
+            if Nkind (Nam) /= N_Expanded_Name then
+               return True;
+            else
+               return Entity (Prefix (Nam)) = Standard_Standard;
+            end if;
+         else
+            return False;
+         end if;
+      end Standard_Operator;
+
+   --  Start of processing for Disambiguate
+
+   begin
+      --  Recover the two legal interpretations.
+
+      Get_First_Interp (N, I, It);
+
+      while I /= I1 loop
+         Get_Next_Interp (I, It);
+      end loop;
+
+      It1  := It;
+      Nam1 := It.Nam;
+
+      while I /= I2 loop
+         Get_Next_Interp (I, It);
+      end loop;
+
+      It2  := It;
+      Nam2 := It.Nam;
+
+      --  If the context is universal, the predefined operator is preferred.
+      --  This includes bounds in numeric type declarations, and expressions
+      --  in type conversions. If no interpretation yields a universal type,
+      --  then we must check whether the user-defined entity hides the prede-
+      --  fined one.
+
+      if Chars (Nam1) in  Any_Operator_Name
+        and then Standard_Operator
+      then
+         if        Typ = Universal_Integer
+           or else Typ = Universal_Real
+           or else Typ = Any_Integer
+           or else Typ = Any_Discrete
+           or else Typ = Any_Real
+           or else Typ = Any_Type
+         then
+            --  Find an interpretation that yields the universal type, or else
+            --  a predefined operator that yields a predefined numeric type.
+
+            declare
+               Candidate : Interp := No_Interp;
+            begin
+               Get_First_Interp (N, I, It);
+
+               while Present (It.Typ) loop
+                  if (Covers (Typ, It.Typ)
+                       or else Typ = Any_Type)
+                    and then
+                     (It.Typ = Universal_Integer
+                       or else It.Typ = Universal_Real)
+                  then
+                     return It;
+
+                  elsif Covers (Typ, It.Typ)
+                    and then Scope (It.Typ) = Standard_Standard
+                    and then Scope (It.Nam) = Standard_Standard
+                    and then Is_Numeric_Type (It.Typ)
+                  then
+                     Candidate := It;
+                  end if;
+
+                  Get_Next_Interp (I, It);
+               end loop;
+
+               if Candidate /= No_Interp then
+                  return Candidate;
+               end if;
+            end;
+
+         elsif Chars (Nam1) /= Name_Op_Not
+           and then (Typ = Standard_Boolean
+             or else Typ = Any_Boolean)
+         then
+            --  Equality or comparison operation. Choose predefined operator
+            --  if arguments are universal. The node may be an operator, a
+            --  name, or a function call, so unpack arguments accordingly.
+
+            declare
+               Arg1, Arg2 : Node_Id;
+
+            begin
+               if Nkind (N) in N_Op then
+                  Arg1 := Left_Opnd  (N);
+                  Arg2 := Right_Opnd (N);
+
+               elsif Is_Entity_Name (N)
+                 or else Nkind (N) = N_Operator_Symbol
+               then
+                  Arg1 := First_Entity (Entity (N));
+                  Arg2 := Next_Entity (Arg1);
+
+               else
+                  Arg1 := First_Actual (N);
+                  Arg2 := Next_Actual (Arg1);
+               end if;
+
+               if Present (Arg2)
+                 and then Present (Universal_Interpretation (Arg1))
+                 and then Universal_Interpretation (Arg2) =
+                          Universal_Interpretation (Arg1)
+               then
+                  Get_First_Interp (N, I, It);
+
+                  while Scope (It.Nam) /= Standard_Standard loop
+                     Get_Next_Interp (I, It);
+                  end loop;
+
+                  return It;
+               end if;
+            end;
+         end if;
+      end if;
+
+      --  If no universal interpretation, check whether user-defined operator
+      --  hides predefined one, as well as other special cases. If the node
+      --  is a range, then one or both bounds are ambiguous. Each will have
+      --  to be disambiguated w.r.t. the context type. The type of the range
+      --  itself is imposed by the context, so we can return either legal
+      --  interpretation.
+
+      if Ekind (Nam1) = E_Operator then
+         Predef_Subp := Nam1;
+         User_Subp   := Nam2;
+
+      elsif Ekind (Nam2) = E_Operator then
+         Predef_Subp := Nam2;
+         User_Subp   := Nam1;
+
+      elsif Nkind (N) = N_Range then
+         return It1;
+
+      --  If two user defined-subprograms are visible, it is a true ambiguity,
+      --  unless one of them is an entry and the context is a conditional or
+      --  timed entry call, or unless we are within an instance and this is
+      --  results from two formals types with the same actual.
+
+      else
+         if Nkind (N) = N_Procedure_Call_Statement
+           and then Nkind (Parent (N)) = N_Entry_Call_Alternative
+           and then N = Entry_Call_Statement (Parent (N))
+         then
+            if Ekind (Nam2) = E_Entry then
+               return It2;
+            elsif Ekind (Nam1) = E_Entry then
+               return It1;
+            else
+               return No_Interp;
+            end if;
+
+         --  If the ambiguity occurs within an instance, it is due to several
+         --  formal types with the same actual. Look for an exact match
+         --  between the types of the formals of the overloadable entities,
+         --  and the actuals in the call, to recover the unambiguous match
+         --  in the original generic.
+
+         elsif In_Instance then
+            if (Nkind (N) = N_Function_Call
+              or else Nkind (N) = N_Procedure_Call_Statement)
+            then
+               declare
+                  Actual : Node_Id;
+                  Formal : Entity_Id;
+
+               begin
+                  Actual := First_Actual (N);
+                  Formal := First_Formal (Nam1);
+                  while Present (Actual) loop
+                     if Etype (Actual) /= Etype (Formal) then
+                        return It2;
+                     end if;
+
+                     Next_Actual (Actual);
+                     Next_Formal (Formal);
+                  end loop;
+
+                  return It1;
+               end;
+
+            elsif Nkind (N) in N_Binary_Op then
+
+               if Matches (Left_Opnd (N), First_Formal (Nam1))
+                 and then
+                   Matches (Right_Opnd (N), Next_Formal (First_Formal (Nam1)))
+               then
+                  return It1;
+               else
+                  return It2;
+               end if;
+
+            elsif Nkind (N) in  N_Unary_Op then
+
+               if Etype (Right_Opnd (N)) = Etype (First_Formal (Nam1)) then
+                  return It1;
+               else
+                  return It2;
+               end if;
+
+            else
+               return Remove_Conversions;
+            end if;
+         else
+            return Remove_Conversions;
+         end if;
+      end if;
+
+      --  an implicit concatenation operator on a string type cannot be
+      --  disambiguated from the predefined concatenation. This can only
+      --  happen with concatenation of string literals.
+
+      if Chars (User_Subp) = Name_Op_Concat
+        and then Ekind (User_Subp) = E_Operator
+        and then Is_String_Type (Etype (First_Formal (User_Subp)))
+      then
+         return No_Interp;
+
+      --  If the user-defined operator is in  an open scope, or in the scope
+      --  of the resulting type, or given by an expanded name that names its
+      --  scope, it hides the predefined operator for the type. Exponentiation
+      --  has to be special-cased because the implicit operator does not have
+      --  a symmetric signature, and may not be hidden by the explicit one.
+
+      elsif (Nkind (N) = N_Function_Call
+              and then Nkind (Name (N)) = N_Expanded_Name
+              and then (Chars (Predef_Subp) /= Name_Op_Expon
+                          or else Hides_Op (User_Subp, Predef_Subp))
+              and then Scope (User_Subp) = Entity (Prefix (Name (N))))
+        or else Hides_Op (User_Subp, Predef_Subp)
+      then
+         if It1.Nam = User_Subp then
+            return It1;
+         else
+            return It2;
+         end if;
+
+      --  Otherwise, the predefined operator has precedence, or if the
+      --  user-defined operation is directly visible we have a true ambiguity.
+      --  If this is a fixed-point multiplication and division in Ada83 mode,
+      --  exclude the universal_fixed operator, which often causes ambiguities
+      --  in legacy code.
+
+      else
+         if (In_Open_Scopes (Scope (User_Subp))
+           or else Is_Potentially_Use_Visible (User_Subp))
+           and then not In_Instance
+         then
+            if Is_Fixed_Point_Type (Typ)
+              and then (Chars (Nam1) = Name_Op_Multiply
+                         or else Chars (Nam1) = Name_Op_Divide)
+              and then Ada_83
+            then
+               if It2.Nam = Predef_Subp then
+                  return It1;
+
+               else
+                  return It2;
+               end if;
+            else
+               return No_Interp;
+            end if;
+
+         elsif It1.Nam = Predef_Subp then
+            return It1;
+
+         else
+            return It2;
+         end if;
+      end if;
+
+   end Disambiguate;
+
+   ---------------------
+   -- End_Interp_List --
+   ---------------------
+
+   procedure End_Interp_List is
+   begin
+      All_Interp.Table (All_Interp.Last) := No_Interp;
+      All_Interp.Increment_Last;
+   end End_Interp_List;
+
+   -------------------------
+   -- Entity_Matches_Spec --
+   -------------------------
+
+   function Entity_Matches_Spec (Old_S, New_S : Entity_Id) return Boolean is
+   begin
+      --  Simple case: same entity kinds, type conformance is required.
+      --  A parameterless function can also rename a literal.
+
+      if Ekind (Old_S) = Ekind (New_S)
+        or else (Ekind (New_S) = E_Function
+                  and then Ekind (Old_S) = E_Enumeration_Literal)
+      then
+         return Type_Conformant (New_S, Old_S);
+
+      elsif Ekind (New_S) = E_Function
+        and then Ekind (Old_S) = E_Operator
+      then
+         return Operator_Matches_Spec (Old_S, New_S);
+
+      elsif Ekind (New_S) = E_Procedure
+        and then Is_Entry (Old_S)
+      then
+         return Type_Conformant (New_S, Old_S);
+
+      else
+         return False;
+      end if;
+   end Entity_Matches_Spec;
+
+   ----------------------
+   -- Find_Unique_Type --
+   ----------------------
+
+   function Find_Unique_Type (L : Node_Id; R : Node_Id) return Entity_Id is
+      I  : Interp_Index;
+      It : Interp;
+      T  : Entity_Id := Etype (L);
+      TR : Entity_Id := Any_Type;
+
+   begin
+      if Is_Overloaded (R) then
+         Get_First_Interp (R, I, It);
+
+         while Present (It.Typ) loop
+            if Covers (T, It.Typ) or else Covers (It.Typ, T) then
+
+               --  If several interpretations are possible and L is universal,
+               --  apply preference rule.
+
+               if TR /= Any_Type then
+
+                  if (T = Universal_Integer or else T = Universal_Real)
+                    and then It.Typ = T
+                  then
+                     TR := It.Typ;
+                  end if;
+
+               else
+                  TR := It.Typ;
+               end if;
+            end if;
+
+            Get_Next_Interp (I, It);
+         end loop;
+
+         Set_Etype (R, TR);
+
+      --  In the non-overloaded case, the Etype of R is already set
+      --  correctly.
+
+      else
+         null;
+      end if;
+
+      --  If one of the operands is Universal_Fixed, the type of the
+      --  other operand provides the context.
+
+      if Etype (R) = Universal_Fixed then
+         return T;
+
+      elsif T = Universal_Fixed then
+         return Etype (R);
+
+      else
+         return Specific_Type (T, Etype (R));
+      end if;
+
+   end Find_Unique_Type;
+
+   ----------------------
+   -- Get_First_Interp --
+   ----------------------
+
+   procedure Get_First_Interp
+     (N  : Node_Id;
+      I  : out Interp_Index;
+      It : out Interp)
+   is
+      Int_Ind : Interp_Index;
+      O_N     : Node_Id;
+
+   begin
+      --  If a selected component is overloaded because the selector has
+      --  multiple interpretations, the node is a call to a protected
+      --  operation or an indirect call. Retrieve the interpretation from
+      --  the selector name. The selected component may be overloaded as well
+      --  if the prefix is overloaded. That case is unchanged.
+
+      if Nkind (N) = N_Selected_Component
+        and then Is_Overloaded (Selector_Name (N))
+      then
+         O_N := Selector_Name (N);
+      else
+         O_N := N;
+      end if;
+
+      for Index in 0 .. Interp_Map.Last loop
+         if Interp_Map.Table (Index).Node = O_N then
+            Int_Ind := Interp_Map.Table (Index).Index;
+            It := All_Interp.Table (Int_Ind);
+            I := Int_Ind;
+            return;
+         end if;
+      end loop;
+
+      --  Procedure should never be called if the node has no interpretations
+
+      raise Program_Error;
+   end Get_First_Interp;
+
+   ----------------------
+   --  Get_Next_Interp --
+   ----------------------
+
+   procedure Get_Next_Interp (I : in out Interp_Index; It : out Interp) is
+   begin
+      I  := I + 1;
+      It := All_Interp.Table (I);
+   end Get_Next_Interp;
+
+   -------------------------
+   -- Has_Compatible_Type --
+   -------------------------
+
+   function Has_Compatible_Type
+     (N    : Node_Id;
+      Typ  : Entity_Id)
+      return Boolean
+   is
+      I  : Interp_Index;
+      It : Interp;
+
+   begin
+      if N = Error then
+         return False;
+      end if;
+
+      if Nkind (N) = N_Subtype_Indication
+        or else not Is_Overloaded (N)
+      then
+         return Covers (Typ, Etype (N))
+           or else (not Is_Tagged_Type (Typ)
+                     and then Ekind (Typ) /= E_Anonymous_Access_Type
+                     and then Covers (Etype (N), Typ));
+
+      else
+         Get_First_Interp (N, I, It);
+
+         while Present (It.Typ) loop
+            if Covers (Typ, It.Typ)
+              or else (not Is_Tagged_Type (Typ)
+                        and then Ekind (Typ) /= E_Anonymous_Access_Type
+                        and then Covers (It.Typ, Typ))
+            then
+               return True;
+            end if;
+
+            Get_Next_Interp (I, It);
+         end loop;
+
+         return False;
+      end if;
+   end Has_Compatible_Type;
+
+   --------------
+   -- Hides_Op --
+   --------------
+
+   function Hides_Op (F : Entity_Id; Op : Entity_Id) return Boolean is
+      Btyp : constant Entity_Id := Base_Type (Etype (First_Formal (F)));
+
+   begin
+      return Operator_Matches_Spec (Op, F)
+        and then (In_Open_Scopes (Scope (F))
+                    or else Scope (F) = Scope (Btyp)
+                    or else (not In_Open_Scopes (Scope (Btyp))
+                              and then not In_Use (Btyp)
+                              and then not In_Use (Scope (Btyp))));
+   end Hides_Op;
+
+   ------------------------
+   -- Init_Interp_Tables --
+   ------------------------
+
+   procedure Init_Interp_Tables is
+   begin
+      All_Interp.Init;
+      Interp_Map.Init;
+   end Init_Interp_Tables;
+
+   ---------------------
+   -- Intersect_Types --
+   ---------------------
+
+   function Intersect_Types (L, R : Node_Id) return Entity_Id is
+      Index : Interp_Index;
+      It    : Interp;
+      Typ   : Entity_Id;
+
+      function Check_Right_Argument (T : Entity_Id) return Entity_Id;
+      --  Find interpretation of right arg that has type compatible with T
+
+      --------------------------
+      -- Check_Right_Argument --
+      --------------------------
+
+      function Check_Right_Argument (T : Entity_Id) return Entity_Id is
+         Index : Interp_Index;
+         It    : Interp;
+         T2    : Entity_Id;
+
+      begin
+         if not Is_Overloaded (R) then
+            return Specific_Type (T, Etype (R));
+
+         else
+            Get_First_Interp (R, Index, It);
+
+            loop
+               T2 := Specific_Type (T, It.Typ);
+
+               if T2 /= Any_Type then
+                  return T2;
+               end if;
+
+               Get_Next_Interp (Index, It);
+               exit when No (It.Typ);
+            end loop;
+
+            return Any_Type;
+         end if;
+      end Check_Right_Argument;
+
+   --  Start processing for Intersect_Types
+
+   begin
+      if Etype (L) = Any_Type or else Etype (R) = Any_Type then
+         return Any_Type;
+      end if;
+
+      if not Is_Overloaded (L) then
+         Typ := Check_Right_Argument (Etype (L));
+
+      else
+         Typ := Any_Type;
+         Get_First_Interp (L, Index, It);
+
+         while Present (It.Typ) loop
+            Typ := Check_Right_Argument (It.Typ);
+            exit when Typ /= Any_Type;
+            Get_Next_Interp (Index, It);
+         end loop;
+
+      end if;
+
+      --  If Typ is Any_Type, it means no compatible pair of types was found
+
+      if Typ = Any_Type then
+
+         if Nkind (Parent (L)) in N_Op then
+            Error_Msg_N ("incompatible types for operator", Parent (L));
+
+         elsif Nkind (Parent (L)) = N_Range then
+            Error_Msg_N ("incompatible types given in constraint", Parent (L));
+
+         else
+            Error_Msg_N ("incompatible types", Parent (L));
+         end if;
+      end if;
+
+      return Typ;
+   end Intersect_Types;
+
+   -----------------
+   -- Is_Ancestor --
+   -----------------
+
+   function Is_Ancestor (T1, T2 : Entity_Id) return Boolean is
+      Par : Entity_Id;
+
+   begin
+      if Base_Type (T1) = Base_Type (T2) then
+         return True;
+
+      elsif Is_Private_Type (T1)
+        and then Present (Full_View (T1))
+        and then Base_Type (T2) = Base_Type (Full_View (T1))
+      then
+         return True;
+
+      else
+         Par := Etype (T2);
+
+         loop
+            if Base_Type (T1) = Base_Type (Par)
+              or else (Is_Private_Type (T1)
+                        and then Present (Full_View (T1))
+                        and then Base_Type (Par) = Base_Type (Full_View (T1)))
+            then
+               return True;
+
+            elsif Is_Private_Type (Par)
+              and then Present (Full_View (Par))
+              and then Full_View (Par) = Base_Type (T1)
+            then
+               return True;
+
+            elsif Etype (Par) /= Par then
+               Par := Etype (Par);
+            else
+               return False;
+            end if;
+         end loop;
+      end if;
+   end Is_Ancestor;
+
+   -------------------
+   -- Is_Subtype_Of --
+   -------------------
+
+   function Is_Subtype_Of (T1 : Entity_Id; T2 : Entity_Id) return Boolean is
+      S : Entity_Id;
+
+   begin
+      S := Ancestor_Subtype (T1);
+      while Present (S) loop
+         if S = T2 then
+            return True;
+         else
+            S := Ancestor_Subtype (S);
+         end if;
+      end loop;
+
+      return False;
+   end Is_Subtype_Of;
+
+   -----------------
+   -- New_Interps --
+   -----------------
+
+   procedure New_Interps (N : Node_Id)  is
+   begin
+      Interp_Map.Increment_Last;
+      All_Interp.Increment_Last;
+      Interp_Map.Table (Interp_Map.Last) := (N, All_Interp.Last);
+      All_Interp.Table (All_Interp.Last) := No_Interp;
+      Set_Is_Overloaded (N, True);
+   end New_Interps;
+
+   ---------------------------
+   -- Operator_Matches_Spec --
+   ---------------------------
+
+   function Operator_Matches_Spec (Op, New_S : Entity_Id) return Boolean is
+      Op_Name : constant Name_Id   := Chars (Op);
+      T       : constant Entity_Id := Etype (New_S);
+      New_F   : Entity_Id;
+      Old_F   : Entity_Id;
+      Num     : Int;
+      T1      : Entity_Id;
+      T2      : Entity_Id;
+
+   begin
+      --  To verify that a predefined operator matches a given signature,
+      --  do a case analysis of the operator classes. Function can have one
+      --  or two formals and must have the proper result type.
+
+      New_F := First_Formal (New_S);
+      Old_F := First_Formal (Op);
+      Num := 0;
+
+      while Present (New_F) and then Present (Old_F) loop
+         Num := Num + 1;
+         Next_Formal (New_F);
+         Next_Formal (Old_F);
+      end loop;
+
+      --  Definite mismatch if different number of parameters
+
+      if Present (Old_F) or else Present (New_F) then
+         return False;
+
+      --  Unary operators
+
+      elsif Num = 1 then
+         T1 := Etype (First_Formal (New_S));
+
+         if Op_Name = Name_Op_Subtract
+           or else Op_Name = Name_Op_Add
+           or else Op_Name = Name_Op_Abs
+         then
+            return Base_Type (T1) = Base_Type (T)
+              and then Is_Numeric_Type (T);
+
+         elsif Op_Name = Name_Op_Not then
+            return Base_Type (T1) = Base_Type (T)
+              and then Valid_Boolean_Arg (Base_Type (T));
+
+         else
+            return False;
+         end if;
+
+      --  Binary operators
+
+      else
+         T1 := Etype (First_Formal (New_S));
+         T2 := Etype (Next_Formal (First_Formal (New_S)));
+
+         if Op_Name =  Name_Op_And or else Op_Name = Name_Op_Or
+           or else Op_Name = Name_Op_Xor
+         then
+            return Base_Type (T1) = Base_Type (T2)
+              and then Base_Type (T1) = Base_Type (T)
+              and then Valid_Boolean_Arg (Base_Type (T));
+
+         elsif Op_Name = Name_Op_Eq or else Op_Name = Name_Op_Ne then
+            return Base_Type (T1) = Base_Type (T2)
+              and then not Is_Limited_Type (T1)
+              and then Is_Boolean_Type (T);
+
+         elsif Op_Name = Name_Op_Lt or else Op_Name = Name_Op_Le
+           or else Op_Name = Name_Op_Gt or else Op_Name = Name_Op_Ge
+         then
+            return Base_Type (T1) = Base_Type (T2)
+              and then Valid_Comparison_Arg (T1)
+              and then Is_Boolean_Type (T);
+
+         elsif Op_Name = Name_Op_Add or else Op_Name = Name_Op_Subtract then
+            return Base_Type (T1) = Base_Type (T2)
+              and then Base_Type (T1) = Base_Type (T)
+              and then Is_Numeric_Type (T);
+
+         --  for division and multiplication, a user-defined function does
+         --  not match the predefined universal_fixed operation, except in
+         --  Ada83 mode.
+
+         elsif Op_Name = Name_Op_Divide then
+            return (Base_Type (T1) = Base_Type (T2)
+              and then Base_Type (T1) = Base_Type (T)
+              and then Is_Numeric_Type (T)
+              and then (not Is_Fixed_Point_Type (T)
+                         or else Ada_83))
+
+            --  Mixed_Mode operations on fixed-point types.
+
+              or else (Base_Type (T1) = Base_Type (T)
+                        and then Base_Type (T2) = Base_Type (Standard_Integer)
+                        and then Is_Fixed_Point_Type (T))
+
+            --  A user defined operator can also match (and hide) a mixed
+            --  operation on universal literals.
+
+              or else (Is_Integer_Type (T2)
+                        and then Is_Floating_Point_Type (T1)
+                        and then Base_Type (T1) = Base_Type (T));
+
+         elsif Op_Name = Name_Op_Multiply then
+            return (Base_Type (T1) = Base_Type (T2)
+              and then Base_Type (T1) = Base_Type (T)
+              and then Is_Numeric_Type (T)
+              and then (not Is_Fixed_Point_Type (T)
+                         or else Ada_83))
+
+            --  Mixed_Mode operations on fixed-point types.
+
+              or else (Base_Type (T1) = Base_Type (T)
+                        and then Base_Type (T2) = Base_Type (Standard_Integer)
+                        and then Is_Fixed_Point_Type (T))
+
+              or else (Base_Type (T2) = Base_Type (T)
+                        and then Base_Type (T1) = Base_Type (Standard_Integer)
+                        and then Is_Fixed_Point_Type (T))
+
+              or else (Is_Integer_Type (T2)
+                        and then Is_Floating_Point_Type (T1)
+                        and then Base_Type (T1) = Base_Type (T))
+
+              or else (Is_Integer_Type (T1)
+                        and then Is_Floating_Point_Type (T2)
+                        and then Base_Type (T2) = Base_Type (T));
+
+         elsif Op_Name = Name_Op_Mod or else Op_Name = Name_Op_Rem then
+            return Base_Type (T1) = Base_Type (T2)
+              and then Base_Type (T1) = Base_Type (T)
+              and then Is_Integer_Type (T);
+
+         elsif Op_Name = Name_Op_Expon then
+            return Base_Type (T1) = Base_Type (T)
+              and then Is_Numeric_Type (T)
+              and then Base_Type (T2) = Base_Type (Standard_Integer);
+
+         elsif Op_Name = Name_Op_Concat then
+            return Is_Array_Type (T)
+              and then (Base_Type (T) = Base_Type (Etype (Op)))
+              and then (Base_Type (T1) = Base_Type (T)
+                         or else
+                        Base_Type (T1) = Base_Type (Component_Type (T)))
+              and then (Base_Type (T2) = Base_Type (T)
+                         or else
+                        Base_Type (T2) = Base_Type (Component_Type (T)));
+
+         else
+            return False;
+         end if;
+      end if;
+   end Operator_Matches_Spec;
+
+   -------------------
+   -- Remove_Interp --
+   -------------------
+
+   procedure Remove_Interp (I : in out Interp_Index) is
+      II : Interp_Index;
+
+   begin
+      --  Find end of Interp list and copy downward to erase the discarded one
+
+      II := I + 1;
+
+      while Present (All_Interp.Table (II).Typ) loop
+         II := II + 1;
+      end loop;
+
+      for J in I + 1 .. II loop
+         All_Interp.Table (J - 1) := All_Interp.Table (J);
+      end loop;
+
+      --  Back up interp. index to insure that iterator will pick up next
+      --  available interpretation.
+
+      I := I - 1;
+   end Remove_Interp;
+
+   ------------------
+   -- Save_Interps --
+   ------------------
+
+   procedure Save_Interps (Old_N : Node_Id; New_N : Node_Id) is
+   begin
+      if Is_Overloaded (Old_N) then
+         for Index in 0 .. Interp_Map.Last loop
+            if Interp_Map.Table (Index).Node = Old_N then
+               Interp_Map.Table (Index).Node := New_N;
+               exit;
+            end if;
+         end loop;
+      end if;
+   end Save_Interps;
+
+   -------------------
+   -- Specific_Type --
+   -------------------
+
+   function Specific_Type (T1, T2 : Entity_Id) return Entity_Id is
+      B1 : constant Entity_Id := Base_Type (T1);
+      B2 : constant Entity_Id := Base_Type (T2);
+
+      function Is_Remote_Access (T : Entity_Id) return Boolean;
+      --  Check whether T is the equivalent type of a remote access type.
+      --  If distribution is enabled, T is a legal context for Null.
+
+      ----------------------
+      -- Is_Remote_Access --
+      ----------------------
+
+      function Is_Remote_Access (T : Entity_Id) return Boolean is
+      begin
+         return Is_Record_Type (T)
+           and then (Is_Remote_Call_Interface (T)
+                      or else Is_Remote_Types (T))
+           and then Present (Corresponding_Remote_Type (T))
+           and then Is_Access_Type (Corresponding_Remote_Type (T));
+      end Is_Remote_Access;
+
+   --  Start of processing for Specific_Type
+
+   begin
+      if (T1 = Any_Type or else T2 = Any_Type) then
+         return Any_Type;
+      end if;
+
+      if B1 = B2 then
+         return B1;
+
+      elsif (T1 = Universal_Integer  and then Is_Integer_Type (T2))
+        or else (T1 = Universal_Real and then Is_Real_Type (T2))
+        or else (T1 = Any_Fixed      and then Is_Fixed_Point_Type (T2))
+      then
+         return B2;
+
+      elsif (T2 = Universal_Integer  and then Is_Integer_Type (T1))
+        or else (T2 = Universal_Real and then Is_Real_Type (T1))
+        or else (T2 = Any_Fixed      and then Is_Fixed_Point_Type (T1))
+      then
+         return B1;
+
+      elsif (T2 = Any_String and then Is_String_Type (T1)) then
+         return B1;
+
+      elsif (T1 = Any_String and then Is_String_Type (T2)) then
+         return B2;
+
+      elsif (T2 = Any_Character and then Is_Character_Type (T1)) then
+         return B1;
+
+      elsif (T1 = Any_Character and then Is_Character_Type (T2)) then
+         return B2;
+
+      elsif (T1 = Any_Access
+        and then (Is_Access_Type (T2) or else Is_Remote_Access (T2)))
+      then
+         return T2;
+
+      elsif (T2 = Any_Access
+        and then (Is_Access_Type (T1) or else Is_Remote_Access (T1)))
+      then
+         return T1;
+
+      elsif (T2 = Any_Composite
+         and then Ekind (T1) in E_Array_Type .. E_Record_Subtype)
+      then
+         return T1;
+
+      elsif (T1 = Any_Composite
+         and then Ekind (T2) in E_Array_Type .. E_Record_Subtype)
+      then
+         return T2;
+
+      elsif (T1 = Any_Modular and then Is_Modular_Integer_Type (T2)) then
+         return T2;
+
+      elsif (T2 = Any_Modular and then Is_Modular_Integer_Type (T1)) then
+         return T1;
+
+      --  Special cases for equality operators (all other predefined
+      --  operators can never apply to tagged types)
+
+      elsif Is_Class_Wide_Type (T1)
+        and then Is_Ancestor (Root_Type (T1), T2)
+      then
+         return T1;
+
+      elsif Is_Class_Wide_Type (T2)
+        and then Is_Ancestor (Root_Type (T2), T1)
+      then
+         return T2;
+
+      elsif (Ekind (B1) = E_Access_Subprogram_Type
+               or else
+             Ekind (B1) = E_Access_Protected_Subprogram_Type)
+        and then Ekind (Designated_Type (B1)) /= E_Subprogram_Type
+        and then Is_Access_Type (T2)
+      then
+         return T2;
+
+      elsif (Ekind (B2) = E_Access_Subprogram_Type
+               or else
+             Ekind (B2) = E_Access_Protected_Subprogram_Type)
+        and then Ekind (Designated_Type (B2)) /= E_Subprogram_Type
+        and then Is_Access_Type (T1)
+      then
+         return T1;
+
+      elsif (Ekind (T1) = E_Allocator_Type
+              or else Ekind (T1) = E_Access_Attribute_Type
+              or else Ekind (T1) = E_Anonymous_Access_Type)
+        and then Is_Access_Type (T2)
+      then
+         return T2;
+
+      elsif (Ekind (T2) = E_Allocator_Type
+              or else Ekind (T2) = E_Access_Attribute_Type
+              or else Ekind (T2) = E_Anonymous_Access_Type)
+        and then Is_Access_Type (T1)
+      then
+         return T1;
+
+      --  If none of the above cases applies, types are not compatible.
+
+      else
+         return Any_Type;
+      end if;
+   end Specific_Type;
+
+   ------------------------------
+   -- Universal_Interpretation --
+   ------------------------------
+
+   function Universal_Interpretation (Opnd : Node_Id) return Entity_Id is
+      Index : Interp_Index;
+      It    : Interp;
+
+   begin
+      --  The argument may be a formal parameter of an operator or subprogram
+      --  with multiple interpretations, or else an expression for an actual.
+
+      if Nkind (Opnd) = N_Defining_Identifier
+        or else not Is_Overloaded (Opnd)
+      then
+         if Etype (Opnd) = Universal_Integer
+           or else Etype (Opnd) = Universal_Real
+         then
+            return Etype (Opnd);
+         else
+            return Empty;
+         end if;
+
+      else
+         Get_First_Interp (Opnd, Index, It);
+
+         while Present (It.Typ) loop
+
+            if It.Typ = Universal_Integer
+              or else It.Typ = Universal_Real
+            then
+               return It.Typ;
+            end if;
+
+            Get_Next_Interp (Index, It);
+         end loop;
+
+         return Empty;
+      end if;
+   end Universal_Interpretation;
+
+   -----------------------
+   -- Valid_Boolean_Arg --
+   -----------------------
+
+   --  In addition to booleans and arrays of booleans, we must include
+   --  aggregates as valid boolean arguments, because in the first pass
+   --  of resolution their components are not examined. If it turns out not
+   --  to be an aggregate of booleans, this will be diagnosed in Resolve.
+   --  Any_Composite must be checked for prior to the array type checks
+   --  because Any_Composite does not have any associated indexes.
+
+   function Valid_Boolean_Arg (T : Entity_Id) return Boolean is
+   begin
+      return Is_Boolean_Type (T)
+        or else T = Any_Composite
+        or else (Is_Array_Type (T)
+                  and then T /= Any_String
+                  and then Number_Dimensions (T) = 1
+                  and then Is_Boolean_Type (Component_Type (T))
+                  and then (not Is_Private_Composite (T)
+                             or else In_Instance)
+                  and then (not Is_Limited_Composite (T)
+                             or else In_Instance))
+        or else Is_Modular_Integer_Type (T)
+        or else T = Universal_Integer;
+   end Valid_Boolean_Arg;
+
+   --------------------------
+   -- Valid_Comparison_Arg --
+   --------------------------
+
+   function Valid_Comparison_Arg (T : Entity_Id) return Boolean is
+   begin
+      return Is_Discrete_Type (T)
+        or else Is_Real_Type (T)
+        or else (Is_Array_Type (T) and then Number_Dimensions (T) = 1
+                  and then Is_Discrete_Type (Component_Type (T))
+                  and then (not Is_Private_Composite (T)
+                             or else In_Instance)
+                  and then (not Is_Limited_Composite (T)
+                             or else In_Instance))
+        or else Is_String_Type (T);
+   end Valid_Comparison_Arg;
+
+   ---------------------
+   -- Write_Overloads --
+   ---------------------
+
+   procedure Write_Overloads (N : Node_Id) is
+      I   : Interp_Index;
+      It  : Interp;
+      Nam : Entity_Id;
+
+   begin
+      if not Is_Overloaded (N) then
+         Write_Str ("Non-overloaded entity ");
+         Write_Eol;
+         Write_Entity_Info (Entity (N), " ");
+
+      else
+         Get_First_Interp (N, I, It);
+         Write_Str ("Overloaded entity ");
+         Write_Eol;
+         Nam := It.Nam;
+
+         while Present (Nam) loop
+            Write_Entity_Info (Nam,  "      ");
+            Write_Str ("=================");
+            Write_Eol;
+            Get_Next_Interp (I, It);
+            Nam := It.Nam;
+         end loop;
+      end if;
+   end Write_Overloads;
+
+end Sem_Type;
diff --git a/gcc/ada/sem_type.ads b/gcc/ada/sem_type.ads
new file mode 100644 (file)
index 0000000..5498e38
--- /dev/null
@@ -0,0 +1,262 @@
+------------------------------------------------------------------------------
+--                                                                          --
+--                         GNAT COMPILER COMPONENTS                         --
+--                                                                          --
+--                             S E M _ T Y P E                              --
+--                                                                          --
+--                                 S p e c                                  --
+--                                                                          --
+--                            $Revision: 1.26 $
+--                                                                          --
+--          Copyright (C) 1992-2001 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- --
+-- ware  Foundation;  either version 2,  or (at your option) any later ver- --
+-- sion.  GNAT is distributed in the hope that it will be useful, but WITH- --
+-- OUT ANY WARRANTY;  without even the  implied warranty of MERCHANTABILITY --
+-- or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License --
+-- for  more details.  You should have  received  a copy of the GNU General --
+-- Public License  distributed with GNAT;  see file COPYING.  If not, write --
+-- to  the Free Software Foundation,  59 Temple Place - Suite 330,  Boston, --
+-- MA 02111-1307, USA.                                                      --
+--                                                                          --
+-- GNAT was originally developed  by the GNAT team at  New York University. --
+-- It is now maintained by Ada Core Technologies Inc (http://www.gnat.com). --
+--                                                                          --
+------------------------------------------------------------------------------
+
+--  This unit contains the routines used to handle type determination,
+--  including the routine used to support overload resolution.
+
+with Alloc;
+with Table;
+with Types; use Types;
+
+package Sem_Type is
+
+   ---------------------------------------------
+   -- Data Structures for Overload Resolution --
+   ---------------------------------------------
+
+   --  To determine the unique meaning of an identifier, overload resolution
+   --  may have to be performed if the visibility rules alone identify more
+   --  than one possible entity as the denotation of a given identifier. When
+   --  the visibility rules find such a potential ambiguity, the set of
+   --  possible interpretations must be attached to the identifier, and
+   --  overload resolution must be performed over the innermost enclosing
+   --  complete context. At the end of the resolution,  either a single
+   --  interpretation is found for all identifiers in the context, or else a
+   --  type error (invalid type or ambiguous reference) must be signalled.
+
+   --  The set of interpretations of a given name is stored in a data structure
+   --  that is separate from the syntax tree, because it corresponds to
+   --  transient information.  The interpretations themselves are stored in
+   --  table All_Interp. A mapping from tree nodes to sets of interpretations
+   --  called Interp_Map, is maintained by the overload resolution routines.
+   --  Both these structures are initialized at the beginning of every complete
+   --  context.
+
+   --  Corresponding to the set of interpretation for a given overloadable
+   --  identifier, there is a set of possible types corresponding to the types
+   --  that the overloaded call may return. We keep a 1-to-1 correspondence
+   --  between interpretations and types: for user-defined subprograms the
+   --  type is the declared return type. For operators, the type is determined
+   --  by the type of the arguments. If the arguments themselves are
+   --  overloaded, we enter the operator name in the names table for each
+   --  possible result type. In most cases, arguments are not overloaded and
+   --  only one interpretation is present anyway.
+
+   type Interp is record
+      Nam : Entity_Id;
+      Typ : Entity_Id;
+   end record;
+
+   No_Interp : constant Interp := (Empty, Empty);
+
+   package All_Interp is new Table.Table (
+     Table_Component_Type => Interp,
+     Table_Index_Type     => Int,
+     Table_Low_Bound      => 0,
+     Table_Initial        => Alloc.All_Interp_Initial,
+     Table_Increment      => Alloc.All_Interp_Increment,
+     Table_Name           => "All_Interp");
+
+   --  The following data structures establish a mapping between nodes and
+   --  their interpretations. Eventually the Interp_Index corresponding to
+   --  the first interpretation of a node may be stored directly in the
+   --  corresponding node.
+
+   subtype Interp_Index is Int;
+
+   type Interp_Ref is record
+      Node  : Node_Id;
+      Index : Interp_Index;
+   end record;
+
+   package Interp_Map is new Table.Table (
+     Table_Component_Type => Interp_Ref,
+     Table_Index_Type     => Int,
+     Table_Low_Bound      => 0,
+     Table_Initial        => Alloc.Interp_Map_Initial,
+     Table_Increment      => Alloc.Interp_Map_Increment,
+     Table_Name           => "Interp_Map");
+
+   --  For now Interp_Map is searched sequentially
+
+   ----------------------
+   --  Error Reporting --
+   ----------------------
+
+   --  A common error is the use of an operator in infix notation on arguments
+   --  of a type that is not directly visible. Rather than diagnosing a type
+   --  mismatch, it is better to indicate that the type can be made use-visible
+   --  with the appropriate use clause. The global variable Candidate_Type is
+   --  set in Add_One_Interp whenever an interpretation might be legal for an
+   --  operator if the type were directly visible. This variable is used in
+   --  sem_ch4 when no legal interpretation is found.
+
+   Candidate_Type : Entity_Id;
+
+   -----------------
+   -- Subprograms --
+   -----------------
+
+   procedure Init_Interp_Tables;
+   --  Invoked by gnatf when processing multiple files.
+
+   procedure Collect_Interps (N : Node_Id);
+   --  Invoked when the name N has more than one visible interpretation.
+   --  This is the high level routine which accumulates the possible
+   --  interpretations of the node. The first meaning and type of N have
+   --  already been stored in N. If the name is an expanded name, the homonyms
+   --  are only those that belong to the same scope.
+
+   procedure New_Interps (N : Node_Id);
+   --  Initialize collection of interpretations for the given node, which is
+   --  either an overloaded entity, or an operation whose arguments have
+   --  multiple intepretations. Interpretations can be added to only one
+   --  node at a time.
+
+   procedure Add_One_Interp
+     (N         : Node_Id;
+      E         : Entity_Id;
+      T         : Entity_Id;
+      Opnd_Type : Entity_Id := Empty);
+   --  Add (E, T) to the list of interpretations of the node being resolved.
+   --  For calls and operators, i.e. for nodes that have a name field,
+   --  E is an overloadable entity, and T is its type. For constructs such
+   --  as indexed expressions, the caller sets E equal to T, because the
+   --  overloading comes from other fields, and the node itself has no name
+   --  to resolve. Add_One_Interp includes the semantic processing to deal
+   --  with adding entries that hide one another etc.
+
+   --  For operators, the legality of the operation depends on the visibility
+   --  of T and its scope. If the operator is an equality or comparison, T is
+   --  always Boolean, and we use Opnd_Type, which is a candidate type for one
+   --  of the operands of N, to check visibility.
+
+   procedure End_Interp_List;
+   --  End the list of interpretations of current node.
+
+   procedure Get_First_Interp
+     (N  : Node_Id;
+      I  : out Interp_Index;
+      It : out Interp);
+   --  Initialize iteration over set of interpretations for Node N. The first
+   --  interpretation is placed in It, and I is initialized for subsequent
+   --  calls to Get_Next_Interp.
+
+   procedure Get_Next_Interp (I : in out Interp_Index; It : out Interp);
+   --  Iteration step over set of interpretations. Using the value in I, which
+   --  was set by a previous call to Get_First_Interp or Get_Next_Interp, the
+   --  next interpretation is placed in It, and I is updated for the next call.
+   --  The end of the list of interpretations is signalled by It.Nam = Empty.
+
+   procedure Remove_Interp (I : in out Interp_Index);
+   --  Remove an interpretation that his hidden by another, or that does not
+   --  match the context. The value of I on input was set by a call to either
+   --  Get_First_Interp or Get_Next_Interp and references the interpretation
+   --  to be removed. The only allowed use of the exit value of I is as input
+   --  to a subsequent call to Get_Next_Interp, which yields the interpretation
+   --  following the removed one.
+
+   procedure Save_Interps (Old_N : Node_Id; New_N : Node_Id);
+   --  If an overloaded node is rewritten during semantic analysis, its
+   --  possible interpretations must be linked to the copy. This procedure
+   --  transfers the overload information from Old_N, the old node, to
+   --  New_N, its new copy. It has no effect in the non-overloaded case.
+
+   function Covers (T1, T2 : Entity_Id) return Boolean;
+   --  This is the basic type compatibility routine. T1 is the expexted
+   --  type, imposed by context, and T2 is the actual type. The processing
+   --  reflects both the definition of type coverage and the rules
+   --  for operand matching.
+
+   function Disambiguate
+     (N      : Node_Id;
+      I1, I2 : Interp_Index;
+      Typ    : Entity_Id)
+      return   Interp;
+   --  If more than one interpretation  of a name in a call is legal, apply
+   --  preference rules (universal types first) and operator visibility in
+   --  order to remove ambiguity. I1 and I2 are the first two interpretations
+   --  that are compatible with the context, but there may be others.
+
+   function Entity_Matches_Spec (Old_S,  New_S : Entity_Id) return Boolean;
+   --  To resolve subprogram renaming and default formal subprograms in generic
+   --  definitions. Old_S is a possible interpretation of the entity being
+   --  renamed, New_S has an explicit signature. If Old_S is a subprogram, as
+   --  opposed to an operator, type and mode conformance are required.
+
+   function Find_Unique_Type (L : Node_Id; R : Node_Id) return Entity_Id;
+   --  Used in second pass of resolution,  for equality and comparison nodes.
+   --  L is the left operand, whose type is known to be correct, and R is
+   --  the right operand,  which has one interpretation compatible with that
+   --  of L. Return the type intersection of the two.
+
+   function Has_Compatible_Type
+     (N    : Node_Id;
+      Typ  : Entity_Id)
+      return Boolean;
+   --  Verify that some interpretation of the node N has a type compatible
+   --  with Typ. If N is not overloaded, then its unique type must be
+   --  compatible with Typ. Otherwise iterate through the interpretations
+   --  of N looking for a compatible one.
+
+   function Hides_Op (F : Entity_Id; Op : Entity_Id) return Boolean;
+   --  A user-defined function hides a predefined operator if it is
+   --  matches the signature of the operator, and is declared in an
+   --  open scope, or in the scope of the result type.
+
+   function Intersect_Types (L, R : Node_Id) return Entity_Id;
+   --  Find the common interpretation to two analyzed nodes. If one of the
+   --  interpretations is universal, choose the non-universal one. If either
+   --  node is overloaded, find single common interpretation.
+
+   function Is_Subtype_Of (T1 : Entity_Id; T2 : Entity_Id) return Boolean;
+   --  Checks whether T1 is any subtype of T2 directly or indirectly. Applies
+   --  only to scalar subtypes ???
+
+   function Is_Ancestor (T1, T2 : Entity_Id) return Boolean;
+   --  T1 is a tagged type (not class-wide). Verify that it is one of the
+   --  ancestors of type T2 (which may or not be class-wide)
+
+   function Operator_Matches_Spec (Op,  New_S : Entity_Id) return Boolean;
+   --  Used to resolve subprograms renaming operators, and calls to user
+   --  defined operators. Determines whether a given operator Op, matches
+   --  a specification, New_S.
+
+   function Valid_Comparison_Arg (T : Entity_Id) return Boolean;
+   --  A valid argument to an ordering operator must be a discrete type, a
+   --  real type, or a one dimensional array with a discrete component type.
+
+   function Valid_Boolean_Arg (T : Entity_Id) return Boolean;
+   --  A valid argument of a boolean operator is either some boolean type,
+   --  or a one-dimensional array of boolean type.
+
+   procedure Write_Overloads (N : Node_Id);
+   --  Debugging procedure to output info on possibly overloaded entities
+   --  for specified node.
+
+end Sem_Type;
diff --git a/gcc/ada/sem_util.adb b/gcc/ada/sem_util.adb
new file mode 100644 (file)
index 0000000..c247472
--- /dev/null
@@ -0,0 +1,5205 @@
+-----------------------------------------------------------------------------
+--                                                                          --
+--                         GNAT COMPILER COMPONENTS                         --
+--                                                                          --
+--                             S E M _ U T I L                              --
+--                                                                          --
+--                                 B o d y                                  --
+--                                                                          --
+--                            $Revision: 1.541 $
+--                                                                          --
+--          Copyright (C) 1992-2001, 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- --
+-- ware  Foundation;  either version 2,  or (at your option) any later ver- --
+-- sion.  GNAT is distributed in the hope that it will be useful, but WITH- --
+-- OUT ANY WARRANTY;  without even the  implied warranty of MERCHANTABILITY --
+-- or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License --
+-- for  more details.  You should have  received  a copy of the GNU General --
+-- Public License  distributed with GNAT;  see file COPYING.  If not, write --
+-- to  the Free Software Foundation,  59 Temple Place - Suite 330,  Boston, --
+-- MA 02111-1307, USA.                                                      --
+--                                                                          --
+-- GNAT was originally developed  by the GNAT team at  New York University. --
+-- It is now maintained by Ada Core Technologies Inc (http://www.gnat.com). --
+--                                                                          --
+------------------------------------------------------------------------------
+
+with Atree;    use Atree;
+with Casing;   use Casing;
+with Debug;    use Debug;
+with Errout;   use Errout;
+with Elists;   use Elists;
+with Exp_Util; use Exp_Util;
+with Freeze;   use Freeze;
+with Lib;      use Lib;
+with Lib.Xref; use Lib.Xref;
+with Namet;    use Namet;
+with Nlists;   use Nlists;
+with Nmake;    use Nmake;
+with Output;   use Output;
+with Opt;      use Opt;
+with Restrict; use Restrict;
+with Scans;    use Scans;
+with Scn;      use Scn;
+with Sem;      use Sem;
+with Sem_Ch8;  use Sem_Ch8;
+with Sem_Eval; use Sem_Eval;
+with Sem_Res;  use Sem_Res;
+with Sem_Type; use Sem_Type;
+with Sinfo;    use Sinfo;
+with Sinput;   use Sinput;
+with Snames;   use Snames;
+with Stand;    use Stand;
+with Style;
+with Stringt;  use Stringt;
+with Targparm; use Targparm;
+with Tbuild;   use Tbuild;
+with Ttypes;   use Ttypes;
+
+package body Sem_Util is
+
+   -----------------------
+   -- Local Subprograms --
+   -----------------------
+
+   function Build_Component_Subtype
+     (C    : List_Id;
+      Loc  : Source_Ptr;
+      T    : Entity_Id)
+      return Node_Id;
+   --  This function builds the subtype for Build_Actual_Subtype_Of_Component
+   --  and Build_Discriminal_Subtype_Of_Component. C is a list of constraints,
+   --  Loc is the source location, T is the original subtype.
+
+   --------------------------------
+   -- Add_Access_Type_To_Process --
+   --------------------------------
+
+   procedure Add_Access_Type_To_Process (E : Entity_Id; A : Entity_Id)
+   is
+      L : Elist_Id;
+   begin
+      Ensure_Freeze_Node (E);
+      L := Access_Types_To_Process (Freeze_Node (E));
+
+      if No (L) then
+         L := New_Elmt_List;
+         Set_Access_Types_To_Process (Freeze_Node (E), L);
+      end if;
+
+      Append_Elmt (A, L);
+   end Add_Access_Type_To_Process;
+
+   -----------------------
+   -- Alignment_In_Bits --
+   -----------------------
+
+   function Alignment_In_Bits (E : Entity_Id) return Uint is
+   begin
+      return Alignment (E) * System_Storage_Unit;
+   end Alignment_In_Bits;
+
+   -----------------------------------------
+   -- Apply_Compile_Time_Constraint_Error --
+   -----------------------------------------
+
+   procedure Apply_Compile_Time_Constraint_Error
+     (N   : Node_Id;
+      Msg : String;
+      Ent : Entity_Id  := Empty;
+      Typ : Entity_Id  := Empty;
+      Loc : Source_Ptr := No_Location;
+      Rep : Boolean    := True)
+   is
+      Stat : constant Boolean := Is_Static_Expression (N);
+      Rtyp : Entity_Id;
+
+   begin
+      if No (Typ) then
+         Rtyp := Etype (N);
+      else
+         Rtyp := Typ;
+      end if;
+
+      if No (Compile_Time_Constraint_Error (N, Msg, Ent, Loc))
+        or else not Rep
+      then
+         return;
+      end if;
+
+      --  Now we replace the node by an N_Raise_Constraint_Error node
+      --  This does not need reanalyzing, so set it as analyzed now.
+
+      Rewrite (N, Make_Raise_Constraint_Error (Sloc (N)));
+      Set_Analyzed (N, True);
+      Set_Etype (N, Rtyp);
+      Set_Raises_Constraint_Error (N);
+
+      --  If the original expression was marked as static, the result is
+      --  still marked as static, but the Raises_Constraint_Error flag is
+      --  always set so that further static evaluation is not attempted.
+
+      if Stat then
+         Set_Is_Static_Expression (N);
+      end if;
+   end Apply_Compile_Time_Constraint_Error;
+
+   --------------------------
+   -- Build_Actual_Subtype --
+   --------------------------
+
+   function Build_Actual_Subtype
+     (T    : Entity_Id;
+      N    : Node_Or_Entity_Id)
+      return Node_Id
+   is
+      Obj : Node_Id;
+
+      Loc         : constant Source_Ptr := Sloc (N);
+      Constraints : List_Id;
+      Decl        : Node_Id;
+      Discr       : Entity_Id;
+      Hi          : Node_Id;
+      Lo          : Node_Id;
+      Subt        : Entity_Id;
+      Disc_Type   : Entity_Id;
+
+   begin
+      if Nkind (N) = N_Defining_Identifier then
+         Obj := New_Reference_To (N, Loc);
+      else
+         Obj := N;
+      end if;
+
+      if Is_Array_Type (T) then
+         Constraints := New_List;
+
+         for J in 1 .. Number_Dimensions (T) loop
+
+            --  Build an array subtype declaration with the nominal
+            --  subtype and the bounds of the actual. Add the declaration
+            --  in front of the local declarations for the subprogram,for
+            --  analysis before any reference to the formal in the body.
+
+            Lo :=
+              Make_Attribute_Reference (Loc,
+                Prefix         => Duplicate_Subexpr (Obj, Name_Req => True),
+                Attribute_Name => Name_First,
+                Expressions    => New_List (
+                  Make_Integer_Literal (Loc, J)));
+
+            Hi :=
+              Make_Attribute_Reference (Loc,
+                Prefix         => Duplicate_Subexpr (Obj, Name_Req => True),
+                Attribute_Name => Name_Last,
+                Expressions    => New_List (
+                  Make_Integer_Literal (Loc, J)));
+
+            Append (Make_Range (Loc, Lo, Hi), Constraints);
+         end loop;
+
+      --  If the type has unknown discriminants there is no constrained
+      --  subtype to build.
+
+      elsif Has_Unknown_Discriminants (T) then
+         return T;
+
+      else
+         Constraints := New_List;
+
+         if Is_Private_Type (T) and then No (Full_View (T)) then
+
+            --  Type is a generic derived type. Inherit discriminants from
+            --  Parent type.
+
+            Disc_Type := Etype (Base_Type (T));
+         else
+            Disc_Type := T;
+         end if;
+
+         Discr := First_Discriminant (Disc_Type);
+
+         while Present (Discr) loop
+            Append_To (Constraints,
+              Make_Selected_Component (Loc,
+                Prefix => Duplicate_Subexpr (Obj),
+                Selector_Name => New_Occurrence_Of (Discr, Loc)));
+            Next_Discriminant (Discr);
+         end loop;
+      end if;
+
+      Subt :=
+        Make_Defining_Identifier (Loc,
+          Chars => New_Internal_Name ('S'));
+      Set_Is_Internal (Subt);
+
+      Decl :=
+        Make_Subtype_Declaration (Loc,
+          Defining_Identifier => Subt,
+          Subtype_Indication =>
+            Make_Subtype_Indication (Loc,
+              Subtype_Mark => New_Reference_To (T,  Loc),
+              Constraint  =>
+                Make_Index_Or_Discriminant_Constraint (Loc,
+                  Constraints => Constraints)));
+
+      Mark_Rewrite_Insertion (Decl);
+      return Decl;
+   end Build_Actual_Subtype;
+
+   ---------------------------------------
+   -- Build_Actual_Subtype_Of_Component --
+   ---------------------------------------
+
+   function Build_Actual_Subtype_Of_Component
+     (T    : Entity_Id;
+      N    : Node_Id)
+      return Node_Id
+   is
+      Loc       : constant Source_Ptr := Sloc (N);
+      P         : constant Node_Id    := Prefix (N);
+      D         : Elmt_Id;
+      Id        : Node_Id;
+      Indx_Type : Entity_Id;
+
+      Deaccessed_T : Entity_Id;
+      --  This is either a copy of T, or if T is an access type, then it is
+      --  the directly designated type of this access type.
+
+      function Build_Actual_Array_Constraint return List_Id;
+      --  If one or more of the bounds of the component depends on
+      --  discriminants, build  actual constraint using the discriminants
+      --  of the prefix.
+
+      function Build_Actual_Record_Constraint return List_Id;
+      --  Similar to previous one, for discriminated components constrained
+      --  by the discriminant of the enclosing object.
+
+      -----------------------------------
+      -- Build_Actual_Array_Constraint --
+      -----------------------------------
+
+      function Build_Actual_Array_Constraint return List_Id is
+         Constraints : List_Id := New_List;
+         Indx        : Node_Id;
+         Hi          : Node_Id;
+         Lo          : Node_Id;
+         Old_Hi      : Node_Id;
+         Old_Lo      : Node_Id;
+
+      begin
+         Indx := First_Index (Deaccessed_T);
+         while Present (Indx) loop
+            Old_Lo := Type_Low_Bound  (Etype (Indx));
+            Old_Hi := Type_High_Bound (Etype (Indx));
+
+            if Denotes_Discriminant (Old_Lo) then
+               Lo :=
+                 Make_Selected_Component (Loc,
+                   Prefix => New_Copy_Tree (P),
+                   Selector_Name => New_Occurrence_Of (Entity (Old_Lo), Loc));
+
+            else
+               Lo := New_Copy_Tree (Old_Lo);
+
+               --  The new bound will be reanalyzed in the enclosing
+               --  declaration. For literal bounds that come from a type
+               --  declaration, the type of the context must be imposed, so
+               --  insure that analysis will take place. For non-universal
+               --  types this is not strictly necessary.
+
+               Set_Analyzed (Lo, False);
+            end if;
+
+            if Denotes_Discriminant (Old_Hi) then
+               Hi :=
+                 Make_Selected_Component (Loc,
+                   Prefix => New_Copy_Tree (P),
+                   Selector_Name => New_Occurrence_Of (Entity (Old_Hi), Loc));
+
+            else
+               Hi := New_Copy_Tree (Old_Hi);
+               Set_Analyzed (Hi, False);
+            end if;
+
+            Append (Make_Range (Loc, Lo, Hi), Constraints);
+            Next_Index (Indx);
+         end loop;
+
+         return Constraints;
+      end Build_Actual_Array_Constraint;
+
+      ------------------------------------
+      -- Build_Actual_Record_Constraint --
+      ------------------------------------
+
+      function Build_Actual_Record_Constraint return List_Id is
+         Constraints : List_Id := New_List;
+         D           : Elmt_Id;
+         D_Val       : Node_Id;
+
+      begin
+         D := First_Elmt (Discriminant_Constraint (Deaccessed_T));
+         while Present (D) loop
+
+            if Denotes_Discriminant (Node (D)) then
+               D_Val :=  Make_Selected_Component (Loc,
+                 Prefix => New_Copy_Tree (P),
+                Selector_Name => New_Occurrence_Of (Entity (Node (D)), Loc));
+
+            else
+               D_Val := New_Copy_Tree (Node (D));
+            end if;
+
+            Append (D_Val, Constraints);
+            Next_Elmt (D);
+         end loop;
+
+         return Constraints;
+      end Build_Actual_Record_Constraint;
+
+   --  Start of processing for Build_Actual_Subtype_Of_Component
+
+   begin
+      if Nkind (N) = N_Explicit_Dereference then
+         if Is_Composite_Type (T)
+           and then not Is_Constrained (T)
+           and then not (Is_Class_Wide_Type (T)
+                          and then Is_Constrained (Root_Type (T)))
+           and then not Has_Unknown_Discriminants (T)
+         then
+            --  If the type of the dereference is already constrained, it
+            --  is an actual subtype.
+
+            if Is_Array_Type (Etype (N))
+              and then Is_Constrained (Etype (N))
+            then
+               return Empty;
+            else
+               Remove_Side_Effects (P);
+               return Build_Actual_Subtype (T, N);
+            end if;
+         else
+            return Empty;
+         end if;
+      end if;
+
+      if Ekind (T) = E_Access_Subtype then
+         Deaccessed_T := Designated_Type (T);
+      else
+         Deaccessed_T := T;
+      end if;
+
+      if Ekind (Deaccessed_T) = E_Array_Subtype then
+
+         Id := First_Index (Deaccessed_T);
+         Indx_Type := Underlying_Type (Etype (Id));
+
+         while Present (Id) loop
+
+            if Denotes_Discriminant (Type_Low_Bound  (Indx_Type)) or else
+               Denotes_Discriminant (Type_High_Bound (Indx_Type))
+            then
+               Remove_Side_Effects (P);
+               return
+                 Build_Component_Subtype (
+                   Build_Actual_Array_Constraint, Loc, Base_Type (T));
+            end if;
+
+            Next_Index (Id);
+         end loop;
+
+      elsif Is_Composite_Type (Deaccessed_T)
+        and then Has_Discriminants (Deaccessed_T)
+        and then not Has_Unknown_Discriminants (Deaccessed_T)
+      then
+         D := First_Elmt (Discriminant_Constraint (Deaccessed_T));
+         while Present (D) loop
+
+            if Denotes_Discriminant (Node (D)) then
+               Remove_Side_Effects (P);
+               return
+                 Build_Component_Subtype (
+                   Build_Actual_Record_Constraint, Loc, Base_Type (T));
+            end if;
+
+            Next_Elmt (D);
+         end loop;
+      end if;
+
+      --  If none of the above, the actual and nominal subtypes are the same.
+
+      return Empty;
+
+   end Build_Actual_Subtype_Of_Component;
+
+   -----------------------------
+   -- Build_Component_Subtype --
+   -----------------------------
+
+   function Build_Component_Subtype
+     (C    : List_Id;
+      Loc  : Source_Ptr;
+      T    : Entity_Id)
+      return Node_Id
+   is
+      Subt : Entity_Id;
+      Decl : Node_Id;
+
+   begin
+      Subt :=
+        Make_Defining_Identifier (Loc,
+          Chars => New_Internal_Name ('S'));
+      Set_Is_Internal (Subt);
+
+      Decl :=
+        Make_Subtype_Declaration (Loc,
+          Defining_Identifier => Subt,
+          Subtype_Indication =>
+            Make_Subtype_Indication (Loc,
+              Subtype_Mark => New_Reference_To (Base_Type (T),  Loc),
+              Constraint  =>
+                Make_Index_Or_Discriminant_Constraint (Loc,
+                  Constraints => C)));
+
+      Mark_Rewrite_Insertion (Decl);
+      return Decl;
+   end Build_Component_Subtype;
+
+   --------------------------------------------
+   -- Build_Discriminal_Subtype_Of_Component --
+   --------------------------------------------
+
+   function Build_Discriminal_Subtype_Of_Component
+     (T    : Entity_Id)
+      return Node_Id
+   is
+      Loc : constant Source_Ptr := Sloc (T);
+      D   : Elmt_Id;
+      Id  : Node_Id;
+
+      function Build_Discriminal_Array_Constraint return List_Id;
+      --  If one or more of the bounds of the component depends on
+      --  discriminants, build  actual constraint using the discriminants
+      --  of the prefix.
+
+      function Build_Discriminal_Record_Constraint return List_Id;
+      --  Similar to previous one, for discriminated components constrained
+      --  by the discriminant of the enclosing object.
+
+      ----------------------------------------
+      -- Build_Discriminal_Array_Constraint --
+      ----------------------------------------
+
+      function Build_Discriminal_Array_Constraint return List_Id is
+         Constraints : List_Id := New_List;
+         Indx        : Node_Id;
+         Hi          : Node_Id;
+         Lo          : Node_Id;
+         Old_Hi      : Node_Id;
+         Old_Lo      : Node_Id;
+
+      begin
+         Indx := First_Index (T);
+         while Present (Indx) loop
+            Old_Lo := Type_Low_Bound  (Etype (Indx));
+            Old_Hi := Type_High_Bound (Etype (Indx));
+
+            if Denotes_Discriminant (Old_Lo) then
+               Lo := New_Occurrence_Of (Discriminal (Entity (Old_Lo)), Loc);
+
+            else
+               Lo := New_Copy_Tree (Old_Lo);
+            end if;
+
+            if Denotes_Discriminant (Old_Hi) then
+               Hi := New_Occurrence_Of (Discriminal (Entity (Old_Hi)), Loc);
+
+            else
+               Hi := New_Copy_Tree (Old_Hi);
+            end if;
+
+            Append (Make_Range (Loc, Lo, Hi), Constraints);
+            Next_Index (Indx);
+         end loop;
+
+         return Constraints;
+      end Build_Discriminal_Array_Constraint;
+
+      -----------------------------------------
+      -- Build_Discriminal_Record_Constraint --
+      -----------------------------------------
+
+      function Build_Discriminal_Record_Constraint return List_Id is
+         Constraints     : List_Id := New_List;
+         D     : Elmt_Id;
+         D_Val : Node_Id;
+
+      begin
+         D := First_Elmt (Discriminant_Constraint (T));
+         while Present (D) loop
+
+            if Denotes_Discriminant (Node (D)) then
+               D_Val :=
+                 New_Occurrence_Of (Discriminal (Entity (Node (D))), Loc);
+
+            else
+               D_Val := New_Copy_Tree (Node (D));
+            end if;
+
+            Append (D_Val, Constraints);
+            Next_Elmt (D);
+         end loop;
+
+         return Constraints;
+      end Build_Discriminal_Record_Constraint;
+
+   --  Start of processing for Build_Discriminal_Subtype_Of_Component
+
+   begin
+      if Ekind (T) = E_Array_Subtype then
+
+         Id := First_Index (T);
+
+         while Present (Id) loop
+
+            if Denotes_Discriminant (Type_Low_Bound  (Etype (Id))) or else
+               Denotes_Discriminant (Type_High_Bound (Etype (Id)))
+            then
+               return Build_Component_Subtype
+                 (Build_Discriminal_Array_Constraint, Loc, T);
+            end if;
+
+            Next_Index (Id);
+         end loop;
+
+      elsif Ekind (T) = E_Record_Subtype
+        and then Has_Discriminants (T)
+        and then not Has_Unknown_Discriminants (T)
+      then
+         D := First_Elmt (Discriminant_Constraint (T));
+         while Present (D) loop
+
+            if Denotes_Discriminant (Node (D)) then
+               return Build_Component_Subtype
+                 (Build_Discriminal_Record_Constraint, Loc, T);
+            end if;
+
+            Next_Elmt (D);
+         end loop;
+      end if;
+
+      --  If none of the above, the actual and nominal subtypes are the same.
+
+      return Empty;
+
+   end Build_Discriminal_Subtype_Of_Component;
+
+   ------------------------------
+   -- Build_Elaboration_Entity --
+   ------------------------------
+
+   procedure Build_Elaboration_Entity (N : Node_Id; Spec_Id : Entity_Id) is
+      Loc       : constant Source_Ptr       := Sloc (N);
+      Unum      : constant Unit_Number_Type := Get_Source_Unit (Loc);
+      Decl      : Node_Id;
+      P         : Natural;
+      Elab_Ent  : Entity_Id;
+
+   begin
+      --  Ignore if already constructed
+
+      if Present (Elaboration_Entity (Spec_Id)) then
+         return;
+      end if;
+
+      --  Construct name of elaboration entity as xxx_E, where xxx
+      --  is the unit name with dots replaced by double underscore.
+      --  We have to manually construct this name, since it will
+      --  be elaborated in the outer scope, and thus will not have
+      --  the unit name automatically prepended.
+
+      Get_Name_String (Unit_Name (Unum));
+
+      --  Replace the %s by _E
+
+      Name_Buffer (Name_Len - 1 .. Name_Len) := "_E";
+
+      --  Replace dots by double underscore
+
+      P := 2;
+      while P < Name_Len - 2 loop
+         if Name_Buffer (P) = '.' then
+            Name_Buffer (P + 2 .. Name_Len + 1) :=
+              Name_Buffer (P + 1 .. Name_Len);
+            Name_Len := Name_Len + 1;
+            Name_Buffer (P) := '_';
+            Name_Buffer (P + 1) := '_';
+            P := P + 3;
+         else
+            P := P + 1;
+         end if;
+      end loop;
+
+      --  Create elaboration flag
+
+      Elab_Ent :=
+        Make_Defining_Identifier (Loc, Chars => Name_Find);
+      Set_Elaboration_Entity (Spec_Id, Elab_Ent);
+
+      if No (Declarations (Aux_Decls_Node (N))) then
+         Set_Declarations (Aux_Decls_Node (N), New_List);
+      end if;
+
+      Decl :=
+         Make_Object_Declaration (Loc,
+           Defining_Identifier => Elab_Ent,
+           Object_Definition   =>
+             New_Occurrence_Of (Standard_Boolean, Loc),
+           Expression          =>
+             New_Occurrence_Of (Standard_False, Loc));
+
+      Append_To (Declarations (Aux_Decls_Node (N)), Decl);
+      Analyze (Decl);
+
+      --  Reset True_Constant indication, since we will indeed
+      --  assign a value to the variable in the binder main.
+
+      Set_Is_True_Constant (Elab_Ent, False);
+
+      --  We do not want any further qualification of the name (if we did
+      --  not do this, we would pick up the name of the generic package
+      --  in the case of a library level generic instantiation).
+
+      Set_Has_Qualified_Name       (Elab_Ent);
+      Set_Has_Fully_Qualified_Name (Elab_Ent);
+   end Build_Elaboration_Entity;
+
+   --------------------------
+   -- Check_Fully_Declared --
+   --------------------------
+
+   procedure Check_Fully_Declared (T : Entity_Id; N : Node_Id) is
+   begin
+      if Ekind (T) = E_Incomplete_Type then
+         Error_Msg_NE
+           ("premature usage of incomplete}", N, First_Subtype (T));
+
+      elsif Has_Private_Component (T)
+        and then not Is_Generic_Type (Root_Type (T))
+        and then not In_Default_Expression
+      then
+         Error_Msg_NE
+           ("premature usage of incomplete}", N, First_Subtype (T));
+      end if;
+   end Check_Fully_Declared;
+
+   ------------------------------------------
+   -- Check_Potentially_Blocking_Operation --
+   ------------------------------------------
+
+   procedure Check_Potentially_Blocking_Operation (N : Node_Id) is
+      S   : Entity_Id;
+      Loc : constant Source_Ptr := Sloc (N);
+
+   begin
+      --  N is one of the potentially blocking operations listed in
+      --  9.5.1 (8). When using the Ravenscar profile, raise Program_Error
+      --  before N if the context is a protected action. Otherwise, only issue
+      --  a warning, since some users are relying on blocking operations
+      --  inside protected objects.
+      --  Indirect blocking through a subprogram call
+      --  cannot be diagnosed statically without interprocedural analysis,
+      --  so we do not attempt to do it here.
+
+      S := Scope (Current_Scope);
+
+      while Present (S) and then S /= Standard_Standard loop
+         if Is_Protected_Type (S) then
+            if Restricted_Profile then
+               Insert_Before (N,
+                  Make_Raise_Statement (Loc,
+                   Name => New_Occurrence_Of (Standard_Program_Error, Loc)));
+               Error_Msg_N ("potentially blocking operation, " &
+                 " Program Error will be raised at run time?", N);
+
+            else
+               Error_Msg_N
+                 ("potentially blocking operation in protected operation?", N);
+            end if;
+
+            return;
+         end if;
+
+         S := Scope (S);
+      end loop;
+   end Check_Potentially_Blocking_Operation;
+
+   ---------------
+   -- Check_VMS --
+   ---------------
+
+   procedure Check_VMS (Construct : Node_Id) is
+   begin
+      if not OpenVMS_On_Target then
+         Error_Msg_N
+           ("this construct is allowed only in Open'V'M'S", Construct);
+      end if;
+   end Check_VMS;
+
+   ----------------------------------
+   -- Collect_Primitive_Operations --
+   ----------------------------------
+
+   function Collect_Primitive_Operations (T : Entity_Id) return Elist_Id is
+      B_Type         : constant Entity_Id := Base_Type (T);
+      B_Decl         : constant Node_Id   := Original_Node (Parent (B_Type));
+      B_Scope        : Entity_Id          := Scope (B_Type);
+      Op_List        : Elist_Id;
+      Formal         : Entity_Id;
+      Is_Prim        : Boolean;
+      Formal_Derived : Boolean := False;
+      Id             : Entity_Id;
+
+   begin
+      --  For tagged types, the primitive operations are collected as they
+      --  are declared, and held in an explicit list which is simply returned.
+
+      if Is_Tagged_Type (B_Type) then
+         return Primitive_Operations (B_Type);
+
+      --  An untagged generic type that is a derived type inherits the
+      --  primitive operations of its parent type. Other formal types only
+      --  have predefined operators, which are not explicitly represented.
+
+      elsif Is_Generic_Type (B_Type) then
+         if Nkind (B_Decl) = N_Formal_Type_Declaration
+           and then Nkind (Formal_Type_Definition (B_Decl))
+             = N_Formal_Derived_Type_Definition
+         then
+            Formal_Derived := True;
+         else
+            return New_Elmt_List;
+         end if;
+      end if;
+
+      Op_List := New_Elmt_List;
+
+      if B_Scope = Standard_Standard then
+         if B_Type = Standard_String then
+            Append_Elmt (Standard_Op_Concat, Op_List);
+
+         elsif B_Type = Standard_Wide_String then
+            Append_Elmt (Standard_Op_Concatw, Op_List);
+
+         else
+            null;
+         end if;
+
+      elsif (Is_Package (B_Scope)
+               and then Nkind (
+                 Parent (Declaration_Node (First_Subtype (T))))
+                   /=  N_Package_Body)
+
+        or else Is_Derived_Type (B_Type)
+      then
+         --  The primitive operations appear after the base type, except
+         --  if the derivation happens within the private part of B_Scope
+         --  and the type is a private type, in which case both the type
+         --  and some primitive operations may appear before the base
+         --  type, and the list of candidates starts after the type.
+
+         if In_Open_Scopes (B_Scope)
+           and then Scope (T) = B_Scope
+           and then In_Private_Part (B_Scope)
+         then
+            Id := Next_Entity (T);
+         else
+            Id := Next_Entity (B_Type);
+         end if;
+
+         while Present (Id) loop
+
+            --  Note that generic formal subprograms are not
+            --  considered to be primitive operations and thus
+            --  are never inherited.
+
+            if Is_Overloadable (Id)
+              and then Nkind (Parent (Parent (Id)))
+                         /= N_Formal_Subprogram_Declaration
+            then
+               Is_Prim := False;
+
+               if Base_Type (Etype (Id)) = B_Type then
+                  Is_Prim := True;
+               else
+                  Formal := First_Formal (Id);
+                  while Present (Formal) loop
+                     if Base_Type (Etype (Formal)) = B_Type then
+                        Is_Prim := True;
+                        exit;
+
+                     elsif Ekind (Etype (Formal)) = E_Anonymous_Access_Type
+                       and then Base_Type
+                         (Designated_Type (Etype (Formal))) = B_Type
+                     then
+                        Is_Prim := True;
+                        exit;
+                     end if;
+
+                     Next_Formal (Formal);
+                  end loop;
+               end if;
+
+               --  For a formal derived type, the only primitives are the
+               --  ones inherited from the parent type. Operations appearing
+               --  in the package declaration are not primitive for it.
+
+               if Is_Prim
+                 and then (not Formal_Derived
+                            or else Present (Alias (Id)))
+               then
+                  Append_Elmt (Id, Op_List);
+               end if;
+            end if;
+
+            Next_Entity (Id);
+
+            --  For a type declared in System, some of its operations
+            --  may appear in  the target-specific extension to System.
+
+            if No (Id)
+              and then Chars (B_Scope) = Name_System
+              and then Scope (B_Scope) = Standard_Standard
+              and then Present_System_Aux
+            then
+               B_Scope := System_Aux_Id;
+               Id := First_Entity (System_Aux_Id);
+            end if;
+
+         end loop;
+
+      end if;
+
+      return Op_List;
+   end Collect_Primitive_Operations;
+
+   -----------------------------------
+   -- Compile_Time_Constraint_Error --
+   -----------------------------------
+
+   function Compile_Time_Constraint_Error
+     (N    : Node_Id;
+      Msg  : String;
+      Ent  : Entity_Id  := Empty;
+      Loc  : Source_Ptr := No_Location)
+      return Node_Id
+   is
+      Msgc : String (1 .. Msg'Length + 2);
+      Msgl : Natural;
+      Warn : Boolean;
+      P    : Node_Id;
+      Msgs : Boolean;
+
+   begin
+      --  A static constraint error in an instance body is not a fatal error.
+      --  we choose to inhibit the message altogether, because there is no
+      --  obvious node (for now) on which to post it. On the other hand the
+      --  offending node must be replaced with a constraint_error in any case.
+
+      --  No messages are generated if we already posted an error on this node
+
+      if not Error_Posted (N) then
+
+         --  Make all such messages unconditional
+
+         Msgc (1 .. Msg'Length) := Msg;
+         Msgc (Msg'Length + 1) := '!';
+         Msgl := Msg'Length + 1;
+
+         --  Message is a warning, even in Ada 95 case
+
+         if Msg (Msg'Length) = '?' then
+            Warn := True;
+
+         --  In Ada 83, all messages are warnings. In the private part and
+         --  the body of an instance, constraint_checks are only warnings.
+
+         elsif Ada_83 and then Comes_From_Source (N) then
+
+            Msgl := Msgl + 1;
+            Msgc (Msgl) := '?';
+            Warn := True;
+
+         elsif In_Instance_Not_Visible then
+
+            Msgl := Msgl + 1;
+            Msgc (Msgl) := '?';
+            Warn := True;
+            Warn_On_Instance := True;
+
+         --  Otherwise we have a real error message (Ada 95 static case)
+
+         else
+            Warn := False;
+         end if;
+
+         --  Should we generate a warning? The answer is not quite yes. The
+         --  very annoying exception occurs in the case of a short circuit
+         --  operator where the left operand is static and decisive. Climb
+         --  parents to see if that is the case we have here.
+
+         Msgs := True;
+         P := N;
+
+         loop
+            P := Parent (P);
+
+            if (Nkind (P) = N_And_Then
+                and then Compile_Time_Known_Value (Left_Opnd (P))
+                and then Is_False (Expr_Value (Left_Opnd (P))))
+              or else (Nkind (P) = N_Or_Else
+                and then Compile_Time_Known_Value (Left_Opnd (P))
+                and then Is_True (Expr_Value (Left_Opnd (P))))
+            then
+               Msgs := False;
+               exit;
+
+            elsif Nkind (P) = N_Component_Association
+              and then Nkind (Parent (P)) = N_Aggregate
+            then
+               null;  --   Keep going.
+
+            else
+               exit when Nkind (P) not in N_Subexpr;
+            end if;
+         end loop;
+
+         if Msgs then
+            if Present (Ent) then
+               Error_Msg_NE (Msgc (1 .. Msgl), N, Ent);
+            else
+               Error_Msg_NE (Msgc (1 .. Msgl), N, Etype (N));
+            end if;
+
+            if Warn then
+               if Inside_Init_Proc then
+                  Error_Msg_NE
+                    ("\& will be raised for objects of this type!?",
+                     N, Standard_Constraint_Error);
+               else
+                  Error_Msg_NE
+                    ("\& will be raised at run time!?",
+                     N, Standard_Constraint_Error);
+               end if;
+            else
+               Error_Msg_NE
+                 ("\static expression raises&!",
+                  N, Standard_Constraint_Error);
+            end if;
+         end if;
+      end if;
+
+      return N;
+   end Compile_Time_Constraint_Error;
+
+   -----------------------
+   -- Conditional_Delay --
+   -----------------------
+
+   procedure Conditional_Delay (New_Ent, Old_Ent : Entity_Id) is
+   begin
+      if Has_Delayed_Freeze (Old_Ent) and then not Is_Frozen (Old_Ent) then
+         Set_Has_Delayed_Freeze (New_Ent);
+      end if;
+   end Conditional_Delay;
+
+   --------------------
+   -- Current_Entity --
+   --------------------
+
+   --  The currently visible definition for a given identifier is the
+   --  one most chained at the start of the visibility chain, i.e. the
+   --  one that is referenced by the Node_Id value of the name of the
+   --  given identifier.
+
+   function Current_Entity (N : Node_Id) return Entity_Id is
+   begin
+      return Get_Name_Entity_Id (Chars (N));
+   end Current_Entity;
+
+   -----------------------------
+   -- Current_Entity_In_Scope --
+   -----------------------------
+
+   function Current_Entity_In_Scope (N : Node_Id) return Entity_Id is
+      E  : Entity_Id;
+      CS : constant Entity_Id := Current_Scope;
+
+      Transient_Case : constant Boolean := Scope_Is_Transient;
+
+   begin
+      E := Get_Name_Entity_Id (Chars (N));
+
+      while Present (E)
+        and then Scope (E) /= CS
+        and then (not Transient_Case or else Scope (E) /= Scope (CS))
+      loop
+         E := Homonym (E);
+      end loop;
+
+      return E;
+   end Current_Entity_In_Scope;
+
+   -------------------
+   -- Current_Scope --
+   -------------------
+
+   function Current_Scope return Entity_Id is
+   begin
+      if Scope_Stack.Last = -1 then
+         return Standard_Standard;
+      else
+         declare
+            C : constant Entity_Id :=
+                  Scope_Stack.Table (Scope_Stack.Last).Entity;
+         begin
+            if Present (C) then
+               return C;
+            else
+               return Standard_Standard;
+            end if;
+         end;
+      end if;
+   end Current_Scope;
+
+   ------------------------
+   -- Current_Subprogram --
+   ------------------------
+
+   function Current_Subprogram return Entity_Id is
+      Scop : constant Entity_Id := Current_Scope;
+
+   begin
+      if Ekind (Scop) = E_Function
+           or else
+         Ekind (Scop) = E_Procedure
+           or else
+         Ekind (Scop) = E_Generic_Function
+           or else
+         Ekind (Scop) = E_Generic_Procedure
+      then
+         return Scop;
+
+      else
+         return Enclosing_Subprogram (Scop);
+      end if;
+   end Current_Subprogram;
+
+   ---------------------
+   -- Defining_Entity --
+   ---------------------
+
+   function Defining_Entity (N : Node_Id) return Entity_Id is
+      K : constant Node_Kind := Nkind (N);
+
+   begin
+      case K is
+         when
+           N_Subprogram_Declaration                 |
+           N_Abstract_Subprogram_Declaration        |
+           N_Subprogram_Body                        |
+           N_Package_Declaration                    |
+           N_Subprogram_Renaming_Declaration        |
+           N_Subprogram_Body_Stub                   |
+           N_Generic_Subprogram_Declaration         |
+           N_Generic_Package_Declaration            |
+           N_Formal_Subprogram_Declaration
+         =>
+            return Defining_Entity (Specification (N));
+
+         when
+           N_Component_Declaration                  |
+           N_Defining_Program_Unit_Name             |
+           N_Discriminant_Specification             |
+           N_Entry_Body                             |
+           N_Entry_Declaration                      |
+           N_Entry_Index_Specification              |
+           N_Exception_Declaration                  |
+           N_Exception_Renaming_Declaration         |
+           N_Formal_Object_Declaration              |
+           N_Formal_Package_Declaration             |
+           N_Formal_Type_Declaration                |
+           N_Full_Type_Declaration                  |
+           N_Implicit_Label_Declaration             |
+           N_Incomplete_Type_Declaration            |
+           N_Loop_Parameter_Specification           |
+           N_Number_Declaration                     |
+           N_Object_Declaration                     |
+           N_Object_Renaming_Declaration            |
+           N_Package_Body_Stub                      |
+           N_Parameter_Specification                |
+           N_Private_Extension_Declaration          |
+           N_Private_Type_Declaration               |
+           N_Protected_Body                         |
+           N_Protected_Body_Stub                    |
+           N_Protected_Type_Declaration             |
+           N_Single_Protected_Declaration           |
+           N_Single_Task_Declaration                |
+           N_Subtype_Declaration                    |
+           N_Task_Body                              |
+           N_Task_Body_Stub                         |
+           N_Task_Type_Declaration
+         =>
+            return Defining_Identifier (N);
+
+         when N_Subunit =>
+            return Defining_Entity (Proper_Body (N));
+
+         when
+           N_Function_Instantiation                 |
+           N_Function_Specification                 |
+           N_Generic_Function_Renaming_Declaration  |
+           N_Generic_Package_Renaming_Declaration   |
+           N_Generic_Procedure_Renaming_Declaration |
+           N_Package_Body                           |
+           N_Package_Instantiation                  |
+           N_Package_Renaming_Declaration           |
+           N_Package_Specification                  |
+           N_Procedure_Instantiation                |
+           N_Procedure_Specification
+         =>
+            declare
+               Nam : constant Node_Id := Defining_Unit_Name (N);
+
+            begin
+               if Nkind (Nam) in N_Entity then
+                  return Nam;
+               else
+                  return Defining_Identifier (Nam);
+               end if;
+            end;
+
+         when N_Block_Statement =>
+            return Entity (Identifier (N));
+
+         when others =>
+            raise Program_Error;
+
+      end case;
+   end Defining_Entity;
+
+   --------------------------
+   -- Denotes_Discriminant --
+   --------------------------
+
+   function Denotes_Discriminant (N : Node_Id) return Boolean is
+   begin
+      return Is_Entity_Name (N)
+        and then Present (Entity (N))
+        and then Ekind (Entity (N)) = E_Discriminant;
+   end Denotes_Discriminant;
+
+   -----------------------------
+   -- Depends_On_Discriminant --
+   -----------------------------
+
+   function Depends_On_Discriminant (N : Node_Id) return Boolean is
+      L : Node_Id;
+      H : Node_Id;
+
+   begin
+      Get_Index_Bounds (N, L, H);
+      return Denotes_Discriminant (L) or else Denotes_Discriminant (H);
+   end Depends_On_Discriminant;
+
+   -------------------------
+   -- Designate_Same_Unit --
+   -------------------------
+
+   function Designate_Same_Unit
+     (Name1 : Node_Id;
+      Name2 : Node_Id)
+      return  Boolean
+   is
+      K1 : Node_Kind := Nkind (Name1);
+      K2 : Node_Kind := Nkind (Name2);
+
+      function Prefix_Node (N : Node_Id) return Node_Id;
+      --  Returns the parent unit name node of a defining program unit name
+      --  or the prefix if N is a selected component or an expanded name.
+
+      function Select_Node (N : Node_Id) return Node_Id;
+      --  Returns the defining identifier node of a defining program unit
+      --  name or  the selector node if N is a selected component or an
+      --  expanded name.
+
+      function Prefix_Node (N : Node_Id) return Node_Id is
+      begin
+         if Nkind (N) = N_Defining_Program_Unit_Name then
+            return Name (N);
+
+         else
+            return Prefix (N);
+         end if;
+      end Prefix_Node;
+
+      function Select_Node (N : Node_Id) return Node_Id is
+      begin
+         if Nkind (N) = N_Defining_Program_Unit_Name then
+            return Defining_Identifier (N);
+
+         else
+            return Selector_Name (N);
+         end if;
+      end Select_Node;
+
+   --  Start of processing for Designate_Next_Unit
+
+   begin
+      if (K1 = N_Identifier or else
+          K1 = N_Defining_Identifier)
+        and then
+         (K2 = N_Identifier or else
+          K2 = N_Defining_Identifier)
+      then
+         return Chars (Name1) = Chars (Name2);
+
+      elsif
+         (K1 = N_Expanded_Name      or else
+          K1 = N_Selected_Component or else
+          K1 = N_Defining_Program_Unit_Name)
+        and then
+         (K2 = N_Expanded_Name      or else
+          K2 = N_Selected_Component or else
+          K2 = N_Defining_Program_Unit_Name)
+      then
+         return
+           (Chars (Select_Node (Name1)) = Chars (Select_Node (Name2)))
+             and then
+               Designate_Same_Unit (Prefix_Node (Name1), Prefix_Node (Name2));
+
+      else
+         return False;
+      end if;
+   end Designate_Same_Unit;
+
+   ----------------------------
+   -- Enclosing_Generic_Body --
+   ----------------------------
+
+   function Enclosing_Generic_Body
+     (E    : Entity_Id)
+      return Node_Id
+   is
+      P    : Node_Id;
+      Decl : Node_Id;
+      Spec : Node_Id;
+
+   begin
+      P := Parent (E);
+
+      while Present (P) loop
+         if Nkind (P) = N_Package_Body
+           or else Nkind (P) = N_Subprogram_Body
+         then
+            Spec := Corresponding_Spec (P);
+
+            if Present (Spec) then
+               Decl := Unit_Declaration_Node (Spec);
+
+               if Nkind (Decl) = N_Generic_Package_Declaration
+                 or else Nkind (Decl) = N_Generic_Subprogram_Declaration
+               then
+                  return P;
+               end if;
+            end if;
+         end if;
+
+         P := Parent (P);
+      end loop;
+
+      return Empty;
+   end Enclosing_Generic_Body;
+
+   -------------------------------
+   -- Enclosing_Lib_Unit_Entity --
+   -------------------------------
+
+   function Enclosing_Lib_Unit_Entity return Entity_Id is
+      Unit_Entity : Entity_Id := Current_Scope;
+
+   begin
+      --  Look for enclosing library unit entity by following scope links.
+      --  Equivalent to, but faster than indexing through the scope stack.
+
+      while (Present (Scope (Unit_Entity))
+        and then Scope (Unit_Entity) /= Standard_Standard)
+        and not Is_Child_Unit (Unit_Entity)
+      loop
+         Unit_Entity := Scope (Unit_Entity);
+      end loop;
+
+      return Unit_Entity;
+   end Enclosing_Lib_Unit_Entity;
+
+   -----------------------------
+   -- Enclosing_Lib_Unit_Node --
+   -----------------------------
+
+   function Enclosing_Lib_Unit_Node (N : Node_Id) return Node_Id is
+      Current_Node : Node_Id := N;
+
+   begin
+      while Present (Current_Node)
+        and then Nkind (Current_Node) /= N_Compilation_Unit
+      loop
+         Current_Node := Parent (Current_Node);
+      end loop;
+
+      if Nkind (Current_Node) /= N_Compilation_Unit then
+         return Empty;
+      end if;
+
+      return Current_Node;
+   end Enclosing_Lib_Unit_Node;
+
+   --------------------------
+   -- Enclosing_Subprogram --
+   --------------------------
+
+   function Enclosing_Subprogram (E : Entity_Id) return Entity_Id is
+      Dynamic_Scope : constant Entity_Id := Enclosing_Dynamic_Scope (E);
+
+   begin
+      if Dynamic_Scope = Standard_Standard then
+         return Empty;
+
+      elsif Ekind (Dynamic_Scope) = E_Subprogram_Body then
+         return Corresponding_Spec (Parent (Parent (Dynamic_Scope)));
+
+      elsif Ekind (Dynamic_Scope) = E_Block then
+         return Enclosing_Subprogram (Dynamic_Scope);
+
+      elsif Ekind (Dynamic_Scope) = E_Task_Type then
+         return Get_Task_Body_Procedure (Dynamic_Scope);
+
+      elsif Convention (Dynamic_Scope) = Convention_Protected then
+         return Protected_Body_Subprogram (Dynamic_Scope);
+
+      else
+         return Dynamic_Scope;
+      end if;
+   end Enclosing_Subprogram;
+
+   ------------------------
+   -- Ensure_Freeze_Node --
+   ------------------------
+
+   procedure Ensure_Freeze_Node (E : Entity_Id) is
+      FN : Node_Id;
+
+   begin
+      if No (Freeze_Node (E)) then
+         FN := Make_Freeze_Entity (Sloc (E));
+         Set_Has_Delayed_Freeze (E);
+         Set_Freeze_Node (E, FN);
+         Set_Access_Types_To_Process (FN, No_Elist);
+         Set_TSS_Elist (FN, No_Elist);
+         Set_Entity (FN, E);
+      end if;
+   end Ensure_Freeze_Node;
+
+   ----------------
+   -- Enter_Name --
+   ----------------
+
+   procedure Enter_Name (Def_Id : Node_Id) is
+      C : constant Entity_Id := Current_Entity (Def_Id);
+      E : constant Entity_Id := Current_Entity_In_Scope (Def_Id);
+      S : constant Entity_Id := Current_Scope;
+
+   begin
+      Generate_Definition (Def_Id);
+
+      --  Add new name to current scope declarations. Check for duplicate
+      --  declaration, which may or may not be a genuine error.
+
+      if Present (E) then
+
+         --  Case of previous entity entered because of a missing declaration
+         --  or else a bad subtype indication. Best is to use the new entity,
+         --  and make the previous one invisible.
+
+         if Etype (E) = Any_Type then
+            Set_Is_Immediately_Visible (E, False);
+
+         --  Case of renaming declaration constructed for package instances.
+         --  if there is an explicit declaration with the same identifier,
+         --  the renaming is not immediately visible any longer, but remains
+         --  visible through selected component notation.
+
+         elsif Nkind (Parent (E)) = N_Package_Renaming_Declaration
+           and then not Comes_From_Source (E)
+         then
+            Set_Is_Immediately_Visible (E, False);
+
+         --  The new entity may be the package renaming, which has the same
+         --  same name as a generic formal which has been seen already.
+
+         elsif Nkind (Parent (Def_Id)) = N_Package_Renaming_Declaration
+            and then not Comes_From_Source (Def_Id)
+         then
+            Set_Is_Immediately_Visible (E, False);
+
+         --  For a fat pointer corresponding to a remote access to subprogram,
+         --  we use the same identifier as the RAS type, so that the proper
+         --  name appears in the stub. This type is only retrieved through
+         --  the RAS type and never by visibility, and is not added to the
+         --  visibility list (see below).
+
+         elsif Nkind (Parent (Def_Id)) = N_Full_Type_Declaration
+           and then Present (Corresponding_Remote_Type (Def_Id))
+         then
+            null;
+
+         --  A controller component for a type extension overrides the
+         --  inherited component.
+
+         elsif Chars (E) = Name_uController then
+            null;
+
+         --  Case of an implicit operation or derived literal. The new entity
+         --  hides the implicit one,  which is removed from all visibility,
+         --  i.e. the entity list of its scope, and homonym chain of its name.
+
+         elsif (Is_Overloadable (E) and then Present (Alias (E)))
+           or else Is_Internal (E)
+           or else (Ekind (E) = E_Enumeration_Literal
+                     and then Is_Derived_Type (Etype (E)))
+         then
+            declare
+               Prev     : Entity_Id;
+               Prev_Vis : Entity_Id;
+
+            begin
+               --  If E is an implicit declaration, it cannot be the first
+               --  entity in the scope.
+
+               Prev := First_Entity (Current_Scope);
+
+               while Next_Entity (Prev) /= E loop
+                  Next_Entity (Prev);
+               end loop;
+
+               Set_Next_Entity (Prev, Next_Entity (E));
+
+               if No (Next_Entity (Prev)) then
+                  Set_Last_Entity (Current_Scope, Prev);
+               end if;
+
+               if E = Current_Entity (E) then
+                     Prev_Vis := Empty;
+               else
+                  Prev_Vis := Current_Entity (E);
+                  while Homonym (Prev_Vis) /= E loop
+                     Prev_Vis := Homonym (Prev_Vis);
+                  end loop;
+               end if;
+
+               if Present (Prev_Vis)  then
+
+                  --  Skip E in the visibility chain
+
+                  Set_Homonym (Prev_Vis, Homonym (E));
+
+               else
+                  Set_Name_Entity_Id (Chars (E), Homonym (E));
+               end if;
+            end;
+
+         --  This section of code could use a comment ???
+
+         elsif Present (Etype (E))
+           and then Is_Concurrent_Type (Etype (E))
+           and then E = Def_Id
+         then
+            return;
+
+         --  In the body or private part of an instance, a type extension
+         --  may introduce a component with the same name as that of an
+         --  actual. The legality rule is not enforced, but the semantics
+         --  of the full type with two components of the same name are not
+         --  clear at this point ???
+
+         elsif In_Instance_Not_Visible  then
+            null;
+
+         --  When compiling a package body, some child units may have become
+         --  visible. They cannot conflict with local entities that hide them.
+
+         elsif Is_Child_Unit (E)
+           and then In_Open_Scopes (Scope (E))
+           and then not Is_Immediately_Visible (E)
+         then
+            null;
+
+         --  Conversely, with front-end inlining we may compile the parent
+         --  body first, and a child unit subsequently. The context is now
+         --  the parent spec, and body entities are not visible.
+
+         elsif Is_Child_Unit (Def_Id)
+           and then Is_Package_Body_Entity (E)
+           and then not In_Package_Body (Current_Scope)
+         then
+            null;
+
+         --  Case of genuine duplicate declaration
+
+         else
+            Error_Msg_Sloc := Sloc (E);
+
+            --  If the previous declaration is an incomplete type declaration
+            --  this may be an attempt to complete it with a private type.
+            --  The following avoids confusing cascaded errors.
+
+            if Nkind (Parent (E)) = N_Incomplete_Type_Declaration
+              and then Nkind (Parent (Def_Id)) = N_Private_Type_Declaration
+            then
+               Error_Msg_N
+                 ("incomplete type cannot be completed" &
+                        " with a private declaration",
+                    Parent (Def_Id));
+               Set_Is_Immediately_Visible (E, False);
+               Set_Full_View (E, Def_Id);
+
+            elsif Ekind (E) = E_Discriminant
+              and then Present (Scope (Def_Id))
+              and then Scope (Def_Id) /= Current_Scope
+            then
+               --  An inherited component of a record conflicts with
+               --  a new discriminant. The discriminant is inserted first
+               --  in the scope, but the error should be posted on it, not
+               --  on the component.
+
+               Error_Msg_Sloc := Sloc (Def_Id);
+               Error_Msg_N ("& conflicts with declaration#", E);
+               return;
+
+            else
+               Error_Msg_N ("& conflicts with declaration#", Def_Id);
+
+               --  Avoid cascaded messages with duplicate components in
+               --  derived types.
+
+               if Ekind (E) = E_Component
+                 or else Ekind (E) = E_Discriminant
+               then
+                  return;
+               end if;
+            end if;
+
+            if Nkind (Parent (Parent (Def_Id)))
+                 = N_Generic_Subprogram_Declaration
+              and then Def_Id =
+                Defining_Entity (Specification (Parent (Parent (Def_Id))))
+            then
+               Error_Msg_N ("\generic units cannot be overloaded", Def_Id);
+            end if;
+
+            --  If entity is in standard, then we are in trouble, because
+            --  it means that we have a library package with a duplicated
+            --  name. That's hard to recover from, so abort!
+
+            if S = Standard_Standard then
+               raise Unrecoverable_Error;
+
+            --  Otherwise we continue with the declaration. Having two
+            --  identical declarations should not cause us too much trouble!
+
+            else
+               null;
+            end if;
+         end if;
+      end if;
+
+      --  If we fall through, declaration is OK , or OK enough to continue
+
+      --  If Def_Id is a discriminant or a record component we are in the
+      --  midst of inheriting components in a derived record definition.
+      --  Preserve their Ekind and Etype.
+
+      if Ekind (Def_Id) = E_Discriminant
+        or else Ekind (Def_Id) = E_Component
+      then
+         null;
+
+      --  If a type is already set, leave it alone (happens whey a type
+      --  declaration is reanalyzed following a call to the optimizer)
+
+      elsif Present (Etype (Def_Id)) then
+         null;
+
+      --  Otherwise, the kind E_Void insures that premature uses of the entity
+      --  will be detected. Any_Type insures that no cascaded errors will occur
+
+      else
+         Set_Ekind (Def_Id, E_Void);
+         Set_Etype (Def_Id, Any_Type);
+      end if;
+
+      --  Inherited discriminants and components in derived record types are
+      --  immediately visible. Itypes are not.
+
+      if Ekind (Def_Id) = E_Discriminant
+        or else Ekind (Def_Id) = E_Component
+        or else (No (Corresponding_Remote_Type (Def_Id))
+                 and then not Is_Itype (Def_Id))
+      then
+         Set_Is_Immediately_Visible (Def_Id);
+         Set_Current_Entity         (Def_Id);
+      end if;
+
+      Set_Homonym       (Def_Id, C);
+      Append_Entity     (Def_Id, S);
+      Set_Public_Status (Def_Id);
+
+      --  Warn if new entity hides an old one
+
+      if Warn_On_Hiding
+        and then Length_Of_Name (Chars (C)) /= 1
+        and then Present (C)
+        and then Comes_From_Source (C)
+        and then Comes_From_Source (Def_Id)
+        and then In_Extended_Main_Source_Unit (Def_Id)
+      then
+         Error_Msg_Sloc := Sloc (C);
+         Error_Msg_N ("declaration hides &#?", Def_Id);
+      end if;
+
+   end Enter_Name;
+
+   -------------------------------------
+   -- Find_Corresponding_Discriminant --
+   -------------------------------------
+
+   function Find_Corresponding_Discriminant
+     (Id   : Node_Id;
+      Typ  : Entity_Id)
+      return Entity_Id
+   is
+      Par_Disc : Entity_Id;
+      Old_Disc : Entity_Id;
+      New_Disc : Entity_Id;
+
+   begin
+      Par_Disc := Original_Record_Component (Original_Discriminant (Id));
+      Old_Disc := First_Discriminant (Scope (Par_Disc));
+
+      if Is_Class_Wide_Type (Typ) then
+         New_Disc := First_Discriminant (Root_Type (Typ));
+      else
+         New_Disc := First_Discriminant (Typ);
+      end if;
+
+      while Present (Old_Disc) and then Present (New_Disc) loop
+         if Old_Disc = Par_Disc  then
+            return New_Disc;
+         else
+            Next_Discriminant (Old_Disc);
+            Next_Discriminant (New_Disc);
+         end if;
+      end loop;
+
+      --  Should always find it
+
+      raise Program_Error;
+   end Find_Corresponding_Discriminant;
+
+   ------------------
+   -- First_Actual --
+   ------------------
+
+   function First_Actual (Node : Node_Id) return Node_Id is
+      N : Node_Id;
+
+   begin
+      if No (Parameter_Associations (Node)) then
+         return Empty;
+      end if;
+
+      N := First (Parameter_Associations (Node));
+
+      if Nkind (N) = N_Parameter_Association then
+         return First_Named_Actual (Node);
+      else
+         return N;
+      end if;
+   end First_Actual;
+
+   -------------------------
+   -- Full_Qualified_Name --
+   -------------------------
+
+   function Full_Qualified_Name (E : Entity_Id) return String_Id is
+
+      Res : String_Id;
+
+      function Internal_Full_Qualified_Name (E : Entity_Id) return String_Id;
+      --  Compute recursively the qualified name without NUL at the end.
+
+      function Internal_Full_Qualified_Name (E : Entity_Id) return String_Id is
+         Ent         : Entity_Id := E;
+         Parent_Name : String_Id := No_String;
+
+      begin
+         --  Deals properly with child units
+
+         if Nkind (Ent) = N_Defining_Program_Unit_Name then
+            Ent := Defining_Identifier (Ent);
+         end if;
+
+         --  Compute recursively the qualification. Only "Standard" has no
+         --  scope.
+
+         if Present (Scope (Scope (Ent))) then
+            Parent_Name := Internal_Full_Qualified_Name (Scope (Ent));
+         end if;
+
+         --  Every entity should have a name except some expanded blocks
+         --  don't bother about those.
+
+         if Chars (Ent) = No_Name then
+            return Parent_Name;
+         end if;
+
+         --  Add a period between Name and qualification
+
+         if Parent_Name /= No_String then
+            Start_String (Parent_Name);
+            Store_String_Char (Get_Char_Code ('.'));
+
+         else
+            Start_String;
+         end if;
+
+         --  Generates the entity name in upper case
+
+         Get_Name_String (Chars (Ent));
+         Set_All_Upper_Case;
+         Store_String_Chars (Name_Buffer (1 .. Name_Len));
+         return End_String;
+      end Internal_Full_Qualified_Name;
+
+   begin
+      Res := Internal_Full_Qualified_Name (E);
+      Store_String_Char (Get_Char_Code (ASCII.nul));
+      return End_String;
+   end Full_Qualified_Name;
+
+   -----------------------
+   -- Gather_Components --
+   -----------------------
+
+   procedure Gather_Components
+     (Typ           : Entity_Id;
+      Comp_List     : Node_Id;
+      Governed_By   : List_Id;
+      Into          : Elist_Id;
+      Report_Errors : out Boolean)
+   is
+      Assoc           : Node_Id;
+      Variant         : Node_Id;
+      Discrete_Choice : Node_Id;
+      Comp_Item       : Node_Id;
+
+      Discrim       : Entity_Id;
+      Discrim_Name  : Node_Id;
+      Discrim_Value : Node_Id;
+
+   begin
+      Report_Errors := False;
+
+      if No (Comp_List) or else Null_Present (Comp_List) then
+         return;
+
+      elsif Present (Component_Items (Comp_List)) then
+         Comp_Item := First (Component_Items (Comp_List));
+
+      else
+         Comp_Item := Empty;
+      end if;
+
+      while Present (Comp_Item) loop
+
+         --  Skip the tag of a tagged record, as well as all items
+         --  that are not user components (anonymous types, rep clauses,
+         --  Parent field, controller field).
+
+         if Nkind (Comp_Item) = N_Component_Declaration
+           and then Chars (Defining_Identifier (Comp_Item)) /= Name_uTag
+           and then Chars (Defining_Identifier (Comp_Item)) /= Name_uParent
+           and then Chars (Defining_Identifier (Comp_Item)) /= Name_uController
+         then
+            Append_Elmt (Defining_Identifier (Comp_Item), Into);
+         end if;
+
+         Next (Comp_Item);
+      end loop;
+
+      if No (Variant_Part (Comp_List)) then
+         return;
+      else
+         Discrim_Name := Name (Variant_Part (Comp_List));
+         Variant := First_Non_Pragma (Variants (Variant_Part (Comp_List)));
+      end if;
+
+      --  Look for the discriminant that governs this variant part.
+      --  The discriminant *must* be in the Governed_By List
+
+      Assoc := First (Governed_By);
+      Find_Constraint : loop
+         Discrim := First (Choices (Assoc));
+         exit Find_Constraint when Chars (Discrim_Name) = Chars (Discrim)
+           or else (Present (Corresponding_Discriminant (Entity (Discrim)))
+                      and then
+                    Chars (Corresponding_Discriminant (Entity (Discrim)))
+                         = Chars  (Discrim_Name))
+           or else Chars (Original_Record_Component (Entity (Discrim)))
+                         = Chars (Discrim_Name);
+
+         if No (Next (Assoc)) then
+            if not Is_Constrained (Typ)
+              and then Is_Derived_Type (Typ)
+              and then Present (Girder_Constraint (Typ))
+            then
+
+               --  If the type is a tagged type with inherited discriminants,
+               --  use the girder constraint on the parent in order to find
+               --  the values of discriminants that are otherwise hidden by an
+               --  explicit constraint. Renamed discriminants are handled in
+               --  the code above.
+
+               declare
+                  D : Entity_Id;
+                  C : Elmt_Id;
+
+               begin
+                  D := First_Discriminant (Etype (Typ));
+                  C := First_Elmt (Girder_Constraint (Typ));
+
+                  while Present (D)
+                    and then Present (C)
+                  loop
+                     if Chars (Discrim_Name) = Chars (D) then
+                        Assoc :=
+                          Make_Component_Association (Sloc (Typ),
+                            New_List
+                              (New_Occurrence_Of (D, Sloc (Typ))),
+                            Duplicate_Subexpr (Node (C)));
+                        exit Find_Constraint;
+                     end if;
+
+                     D := Next_Discriminant (D);
+                     Next_Elmt (C);
+                  end loop;
+               end;
+            end if;
+         end if;
+
+         if No (Next (Assoc)) then
+            Error_Msg_NE (" missing value for discriminant&",
+              First (Governed_By), Discrim_Name);
+            Report_Errors := True;
+            return;
+         end if;
+
+         Next (Assoc);
+      end loop Find_Constraint;
+
+      Discrim_Value := Expression (Assoc);
+
+      if not Is_OK_Static_Expression (Discrim_Value) then
+         Error_Msg_NE
+           ("value for discriminant & must be static", Discrim_Value, Discrim);
+         Report_Errors := True;
+         return;
+      end if;
+
+      Search_For_Discriminant_Value : declare
+         Low  : Node_Id;
+         High : Node_Id;
+
+         UI_High          : Uint;
+         UI_Low           : Uint;
+         UI_Discrim_Value : constant Uint := Expr_Value (Discrim_Value);
+
+      begin
+         Find_Discrete_Value : while Present (Variant) loop
+            Discrete_Choice := First (Discrete_Choices (Variant));
+            while Present (Discrete_Choice) loop
+
+               exit Find_Discrete_Value when
+                 Nkind (Discrete_Choice) = N_Others_Choice;
+
+               Get_Index_Bounds (Discrete_Choice, Low, High);
+
+               UI_Low  := Expr_Value (Low);
+               UI_High := Expr_Value (High);
+
+               exit Find_Discrete_Value when
+                 UI_Low <= UI_Discrim_Value
+                   and then
+                 UI_High >= UI_Discrim_Value;
+
+               Next (Discrete_Choice);
+            end loop;
+
+            Next_Non_Pragma (Variant);
+         end loop Find_Discrete_Value;
+      end Search_For_Discriminant_Value;
+
+      if No (Variant) then
+         Error_Msg_NE
+           ("value of discriminant & is out of range", Discrim_Value, Discrim);
+         Report_Errors := True;
+         return;
+      end  if;
+
+      --  If we have found the corresponding choice, recursively add its
+      --  components to the Into list.
+
+      Gather_Components (Empty,
+        Component_List (Variant), Governed_By, Into, Report_Errors);
+   end Gather_Components;
+
+   ------------------------
+   -- Get_Actual_Subtype --
+   ------------------------
+
+   function Get_Actual_Subtype (N : Node_Id) return Entity_Id is
+      Typ  : constant Entity_Id := Etype (N);
+      Utyp : Entity_Id := Underlying_Type (Typ);
+      Decl : Node_Id;
+      Atyp : Entity_Id;
+
+   begin
+      if not Present (Utyp) then
+         Utyp := Typ;
+      end if;
+
+      --  If what we have is an identifier that references a subprogram
+      --  formal, or a variable or constant object, then we get the actual
+      --  subtype from the referenced entity if one has been built.
+
+      if Nkind (N) = N_Identifier
+        and then
+          (Is_Formal (Entity (N))
+            or else Ekind (Entity (N)) = E_Constant
+            or else Ekind (Entity (N)) = E_Variable)
+        and then Present (Actual_Subtype (Entity (N)))
+      then
+         return Actual_Subtype (Entity (N));
+
+      --  Actual subtype of unchecked union is always itself. We never need
+      --  the "real" actual subtype. If we did, we couldn't get it anyway
+      --  because the discriminant is not available. The restrictions on
+      --  Unchecked_Union are designed to make sure that this is OK.
+
+      elsif Is_Unchecked_Union (Utyp) then
+         return Typ;
+
+      --  Here for the unconstrained case, we must find actual subtype
+      --  No actual subtype is available, so we must build it on the fly.
+
+      --  Checking the type, not the underlying type, for constrainedness
+      --  seems to be necessary. Maybe all the tests should be on the type???
+
+      elsif (not Is_Constrained (Typ))
+           and then (Is_Array_Type (Utyp)
+                      or else (Is_Record_Type (Utyp)
+                                and then Has_Discriminants (Utyp)))
+           and then not Has_Unknown_Discriminants (Utyp)
+           and then not (Ekind (Utyp) = E_String_Literal_Subtype)
+      then
+         --  Nothing to do if in default expression
+
+         if In_Default_Expression then
+            return Typ;
+
+         --  Else build the actual subtype
+
+         else
+            Decl := Build_Actual_Subtype (Typ, N);
+            Atyp := Defining_Identifier (Decl);
+
+            --  If Build_Actual_Subtype generated a new declaration then use it
+
+            if Atyp /= Typ then
+
+               --  The actual subtype is an Itype, so analyze the declaration,
+               --  but do not attach it to the tree, to get the type defined.
+
+               Set_Parent (Decl, N);
+               Set_Is_Itype (Atyp);
+               Analyze (Decl, Suppress => All_Checks);
+               Set_Associated_Node_For_Itype (Atyp, N);
+               Set_Has_Delayed_Freeze (Atyp, False);
+
+               --  We need to freeze the actual subtype immediately. This is
+               --  needed, because otherwise this Itype will not get frozen
+               --  at all, and it is always safe to freeze on creation because
+               --  any associated types must be frozen at this point.
+
+               Freeze_Itype (Atyp, N);
+               return Atyp;
+
+            --  Otherwise we did not build a declaration, so return original
+
+            else
+               return Typ;
+            end if;
+         end if;
+
+      --  For all remaining cases, the actual subtype is the same as
+      --  the nominal type.
+
+      else
+         return Typ;
+      end if;
+   end Get_Actual_Subtype;
+
+   -------------------------------------
+   -- Get_Actual_Subtype_If_Available --
+   -------------------------------------
+
+   function Get_Actual_Subtype_If_Available (N : Node_Id) return Entity_Id is
+      Typ  : constant Entity_Id := Etype (N);
+
+   begin
+      --  If what we have is an identifier that references a subprogram
+      --  formal, or a variable or constant object, then we get the actual
+      --  subtype from the referenced entity if one has been built.
+
+      if Nkind (N) = N_Identifier
+        and then
+          (Is_Formal (Entity (N))
+            or else Ekind (Entity (N)) = E_Constant
+            or else Ekind (Entity (N)) = E_Variable)
+        and then Present (Actual_Subtype (Entity (N)))
+      then
+         return Actual_Subtype (Entity (N));
+
+      --  Otherwise the Etype of N is returned unchanged
+
+      else
+         return Typ;
+      end if;
+   end Get_Actual_Subtype_If_Available;
+
+   -------------------------------
+   -- Get_Default_External_Name --
+   -------------------------------
+
+   function Get_Default_External_Name (E : Node_Or_Entity_Id) return Node_Id is
+   begin
+      Get_Decoded_Name_String (Chars (E));
+
+      if Opt.External_Name_Imp_Casing = Uppercase then
+         Set_Casing (All_Upper_Case);
+      else
+         Set_Casing (All_Lower_Case);
+      end if;
+
+      return
+        Make_String_Literal (Sloc (E),
+          Strval => String_From_Name_Buffer);
+
+   end Get_Default_External_Name;
+
+   ---------------------------
+   -- Get_Enum_Lit_From_Pos --
+   ---------------------------
+
+   function Get_Enum_Lit_From_Pos
+     (T    : Entity_Id;
+      Pos  : Uint;
+      Loc  : Source_Ptr)
+      return Node_Id
+   is
+      Lit : Node_Id;
+      P   : constant Nat := UI_To_Int (Pos);
+
+   begin
+      --  In the case where the literal is either of type Wide_Character
+      --  or Character or of a type derived from them, there needs to be
+      --  some special handling since there is no explicit chain of
+      --  literals to search. Instead, an N_Character_Literal node is
+      --  created with the appropriate Char_Code and Chars fields.
+
+      if Root_Type (T) = Standard_Character
+        or else Root_Type (T) = Standard_Wide_Character
+      then
+         Set_Character_Literal_Name (Char_Code (P));
+         return
+           Make_Character_Literal (Loc,
+             Chars => Name_Find,
+             Char_Literal_Value => Char_Code (P));
+
+      --  For all other cases, we have a complete table of literals, and
+      --  we simply iterate through the chain of literal until the one
+      --  with the desired position value is found.
+      --
+
+      else
+         Lit := First_Literal (Base_Type (T));
+         for J in 1 .. P loop
+            Next_Literal (Lit);
+         end loop;
+
+         return New_Occurrence_Of (Lit, Loc);
+      end if;
+   end Get_Enum_Lit_From_Pos;
+
+   ----------------------
+   -- Get_Index_Bounds --
+   ----------------------
+
+   procedure Get_Index_Bounds (N : Node_Id; L, H : out Node_Id) is
+      Kind : constant Node_Kind := Nkind (N);
+
+   begin
+      if Kind = N_Range then
+         L := Low_Bound (N);
+         H := High_Bound (N);
+
+      elsif Kind = N_Subtype_Indication then
+         L := Low_Bound  (Range_Expression (Constraint (N)));
+         H := High_Bound (Range_Expression (Constraint (N)));
+
+      elsif Is_Entity_Name (N) and then Is_Type (Entity (N)) then
+         if Error_Posted (Scalar_Range (Entity (N))) then
+            L := Error;
+            H := Error;
+
+         elsif Nkind (Scalar_Range (Entity (N))) = N_Subtype_Indication then
+            Get_Index_Bounds (Scalar_Range (Entity (N)), L, H);
+
+         else
+            L := Low_Bound  (Scalar_Range (Entity (N)));
+            H := High_Bound (Scalar_Range (Entity (N)));
+         end if;
+
+      else
+         --  N is an expression, indicating a range with one value.
+
+         L := N;
+         H := N;
+      end if;
+
+   end Get_Index_Bounds;
+
+   ------------------------
+   -- Get_Name_Entity_Id --
+   ------------------------
+
+   function Get_Name_Entity_Id (Id : Name_Id) return Entity_Id is
+   begin
+      return Entity_Id (Get_Name_Table_Info (Id));
+   end Get_Name_Entity_Id;
+
+   ---------------------------
+   -- Get_Referenced_Object --
+   ---------------------------
+
+   function Get_Referenced_Object (N : Node_Id) return Node_Id is
+      R   : Node_Id := N;
+
+   begin
+      while Is_Entity_Name (R)
+        and then Present (Renamed_Object (Entity (R)))
+      loop
+         R := Renamed_Object (Entity (R));
+      end loop;
+
+      return R;
+   end Get_Referenced_Object;
+
+   -------------------------
+   -- Get_Subprogram_Body --
+   -------------------------
+
+   function Get_Subprogram_Body (E : Entity_Id) return Node_Id is
+      Decl : Node_Id;
+
+   begin
+      Decl := Unit_Declaration_Node (E);
+
+      if Nkind (Decl) = N_Subprogram_Body then
+         return Decl;
+
+      else           --  Nkind (Decl) = N_Subprogram_Declaration
+
+         if Present (Corresponding_Body (Decl)) then
+            return Unit_Declaration_Node (Corresponding_Body (Decl));
+
+         else        --  imported subprogram.
+            return Empty;
+         end if;
+      end if;
+   end Get_Subprogram_Body;
+
+   -----------------------------
+   -- Get_Task_Body_Procedure --
+   -----------------------------
+
+   function Get_Task_Body_Procedure (E : Entity_Id) return Node_Id is
+   begin
+      return Task_Body_Procedure (Declaration_Node (Root_Type (E)));
+   end Get_Task_Body_Procedure;
+
+   --------------------
+   -- Has_Infinities --
+   --------------------
+
+   function Has_Infinities (E : Entity_Id) return Boolean is
+   begin
+      return
+        Is_Floating_Point_Type (E)
+          and then Nkind (Scalar_Range (E)) = N_Range
+          and then Includes_Infinities (Scalar_Range (E));
+   end Has_Infinities;
+
+   ---------------------------
+   -- Has_Private_Component --
+   ---------------------------
+
+   function Has_Private_Component (Type_Id : Entity_Id) return Boolean is
+      Btype     : Entity_Id := Base_Type (Type_Id);
+      Component : Entity_Id;
+
+   begin
+      if Error_Posted (Type_Id)
+        or else Error_Posted (Btype)
+      then
+         return False;
+      end if;
+
+      if Is_Class_Wide_Type (Btype) then
+         Btype := Root_Type (Btype);
+      end if;
+
+      if Is_Private_Type (Btype) then
+         declare
+            UT : constant Entity_Id := Underlying_Type (Btype);
+         begin
+            if No (UT) then
+
+               if No (Full_View (Btype)) then
+                  return not Is_Generic_Type (Btype)
+                    and then not Is_Generic_Type (Root_Type (Btype));
+
+               else
+                  return not Is_Generic_Type (Root_Type (Full_View (Btype)));
+               end if;
+
+            else
+               return not Is_Frozen (UT) and then Has_Private_Component (UT);
+            end if;
+         end;
+      elsif Is_Array_Type (Btype) then
+         return Has_Private_Component (Component_Type (Btype));
+
+      elsif Is_Record_Type (Btype) then
+
+         Component := First_Component (Btype);
+         while Present (Component) loop
+
+            if Has_Private_Component (Etype (Component)) then
+               return True;
+            end if;
+
+            Next_Component (Component);
+         end loop;
+
+         return False;
+
+      elsif Is_Protected_Type (Btype)
+        and then Present (Corresponding_Record_Type (Btype))
+      then
+         return Has_Private_Component (Corresponding_Record_Type (Btype));
+
+      else
+         return False;
+      end if;
+   end Has_Private_Component;
+
+   --------------------------
+   -- Has_Tagged_Component --
+   --------------------------
+
+   function Has_Tagged_Component (Typ : Entity_Id) return Boolean is
+      Comp : Entity_Id;
+
+   begin
+      if Is_Private_Type (Typ)
+        and then Present (Underlying_Type (Typ))
+      then
+         return Has_Tagged_Component (Underlying_Type (Typ));
+
+      elsif Is_Array_Type (Typ) then
+         return Has_Tagged_Component (Component_Type (Typ));
+
+      elsif Is_Tagged_Type (Typ) then
+         return True;
+
+      elsif Is_Record_Type (Typ) then
+         Comp := First_Component (Typ);
+
+         while Present (Comp) loop
+            if Has_Tagged_Component (Etype (Comp)) then
+               return True;
+            end if;
+
+            Comp := Next_Component (Typ);
+         end loop;
+
+         return False;
+
+      else
+         return False;
+      end if;
+   end Has_Tagged_Component;
+
+   -----------------
+   -- In_Instance --
+   -----------------
+
+   function In_Instance return Boolean is
+      S : Entity_Id := Current_Scope;
+
+   begin
+      while Present (S)
+        and then S /= Standard_Standard
+      loop
+         if (Ekind (S) = E_Function
+              or else Ekind (S) = E_Package
+              or else Ekind (S) = E_Procedure)
+           and then Is_Generic_Instance (S)
+         then
+            return True;
+         end if;
+
+         S := Scope (S);
+      end loop;
+
+      return False;
+   end In_Instance;
+
+   ----------------------
+   -- In_Instance_Body --
+   ----------------------
+
+   function In_Instance_Body return Boolean is
+      S : Entity_Id := Current_Scope;
+
+   begin
+      while Present (S)
+        and then S /= Standard_Standard
+      loop
+         if (Ekind (S) = E_Function
+              or else Ekind (S) = E_Procedure)
+           and then Is_Generic_Instance (S)
+         then
+            return True;
+
+         elsif Ekind (S) = E_Package
+           and then In_Package_Body (S)
+           and then Is_Generic_Instance (S)
+         then
+            return True;
+         end if;
+
+         S := Scope (S);
+      end loop;
+
+      return False;
+   end In_Instance_Body;
+
+   -----------------------------
+   -- In_Instance_Not_Visible --
+   -----------------------------
+
+   function In_Instance_Not_Visible return Boolean is
+      S : Entity_Id := Current_Scope;
+
+   begin
+      while Present (S)
+        and then S /= Standard_Standard
+      loop
+         if (Ekind (S) = E_Function
+              or else Ekind (S) = E_Procedure)
+           and then Is_Generic_Instance (S)
+         then
+            return True;
+
+         elsif Ekind (S) = E_Package
+           and then (In_Package_Body (S) or else In_Private_Part (S))
+           and then Is_Generic_Instance (S)
+         then
+            return True;
+         end if;
+
+         S := Scope (S);
+      end loop;
+
+      return False;
+   end In_Instance_Not_Visible;
+
+   ------------------------------
+   -- In_Instance_Visible_Part --
+   ------------------------------
+
+   function In_Instance_Visible_Part return Boolean is
+      S : Entity_Id := Current_Scope;
+
+   begin
+      while Present (S)
+        and then S /= Standard_Standard
+      loop
+         if Ekind (S) = E_Package
+           and then Is_Generic_Instance (S)
+           and then not In_Package_Body (S)
+           and then not In_Private_Part (S)
+         then
+            return True;
+         end if;
+
+         S := Scope (S);
+      end loop;
+
+      return False;
+   end In_Instance_Visible_Part;
+
+   --------------------------------------
+   -- In_Subprogram_Or_Concurrent_Unit --
+   --------------------------------------
+
+   function In_Subprogram_Or_Concurrent_Unit return Boolean is
+      E : Entity_Id;
+      K : Entity_Kind;
+
+   begin
+      --  Use scope chain to check successively outer scopes
+
+      E := Current_Scope;
+      loop
+         K := Ekind (E);
+
+         if K in Subprogram_Kind
+           or else K in Concurrent_Kind
+           or else K = E_Generic_Procedure
+           or else K = E_Generic_Function
+         then
+            return True;
+
+         elsif E = Standard_Standard then
+            return False;
+         end if;
+
+         E := Scope (E);
+      end loop;
+
+   end In_Subprogram_Or_Concurrent_Unit;
+
+   ---------------------
+   -- In_Visible_Part --
+   ---------------------
+
+   function In_Visible_Part (Scope_Id : Entity_Id) return Boolean is
+   begin
+      return
+        Is_Package (Scope_Id)
+          and then In_Open_Scopes (Scope_Id)
+          and then not In_Package_Body (Scope_Id)
+          and then not In_Private_Part (Scope_Id);
+   end In_Visible_Part;
+
+   -------------------
+   -- Is_AAMP_Float --
+   -------------------
+
+   function Is_AAMP_Float (E : Entity_Id) return Boolean is
+   begin
+      pragma Assert (Is_Type (E));
+
+      return AAMP_On_Target
+         and then Is_Floating_Point_Type (E)
+         and then E = Base_Type (E);
+   end Is_AAMP_Float;
+
+   -------------------------
+   -- Is_Actual_Parameter --
+   -------------------------
+
+   function Is_Actual_Parameter (N : Node_Id) return Boolean is
+      PK : constant Node_Kind := Nkind (Parent (N));
+
+   begin
+      case PK is
+         when N_Parameter_Association =>
+            return N = Explicit_Actual_Parameter (Parent (N));
+
+         when N_Function_Call | N_Procedure_Call_Statement =>
+            return Is_List_Member (N)
+              and then
+                List_Containing (N) = Parameter_Associations (Parent (N));
+
+         when others =>
+            return False;
+      end case;
+   end Is_Actual_Parameter;
+
+   ---------------------
+   -- Is_Aliased_View --
+   ---------------------
+
+   function Is_Aliased_View (Obj : Node_Id) return Boolean is
+      E : Entity_Id;
+
+   begin
+      if Is_Entity_Name (Obj) then
+
+         --  Shouldn't we check that we really have an object here?
+         --  If we do, then a-caldel.adb blows up mysteriously ???
+
+         E := Entity (Obj);
+
+         return Is_Aliased (E)
+           or else (Present (Renamed_Object (E))
+                     and then Is_Aliased_View (Renamed_Object (E)))
+
+           or else ((Is_Formal (E)
+                      or else Ekind (E) = E_Generic_In_Out_Parameter
+                      or else Ekind (E) = E_Generic_In_Parameter)
+                    and then Is_Tagged_Type (Etype (E)))
+
+           or else ((Ekind (E) = E_Task_Type or else
+                     Ekind (E) = E_Protected_Type)
+                    and then In_Open_Scopes (E))
+
+            --  Current instance of type
+
+           or else (Is_Type (E) and then E = Current_Scope)
+           or else (Is_Incomplete_Or_Private_Type (E)
+                     and then Full_View (E) = Current_Scope);
+
+      elsif Nkind (Obj) = N_Selected_Component then
+         return Is_Aliased (Entity (Selector_Name (Obj)));
+
+      elsif Nkind (Obj) = N_Indexed_Component then
+         return Has_Aliased_Components (Etype (Prefix (Obj)))
+           or else
+             (Is_Access_Type (Etype (Prefix (Obj)))
+               and then
+              Has_Aliased_Components
+                (Designated_Type (Etype (Prefix (Obj)))));
+
+      elsif Nkind (Obj) = N_Unchecked_Type_Conversion
+        or else Nkind (Obj) = N_Type_Conversion
+      then
+         return Is_Tagged_Type (Etype (Obj))
+           or else Is_Aliased_View (Expression (Obj));
+
+      elsif Nkind (Obj) = N_Explicit_Dereference then
+         return Nkind (Original_Node (Obj)) /= N_Function_Call;
+
+      else
+         return False;
+      end if;
+   end Is_Aliased_View;
+
+   ----------------------
+   -- Is_Atomic_Object --
+   ----------------------
+
+   function Is_Atomic_Object (N : Node_Id) return Boolean is
+
+      function Object_Has_Atomic_Components (N : Node_Id) return Boolean;
+      --  Determines if given object has atomic components
+
+      function Is_Atomic_Prefix (N : Node_Id) return Boolean;
+      --  If prefix is an implicit dereference, examine designated type.
+
+      function Is_Atomic_Prefix (N : Node_Id) return Boolean is
+      begin
+         if Is_Access_Type (Etype (N)) then
+            return
+              Has_Atomic_Components (Designated_Type (Etype (N)));
+         else
+            return Object_Has_Atomic_Components (N);
+         end if;
+      end Is_Atomic_Prefix;
+
+      function Object_Has_Atomic_Components (N : Node_Id) return Boolean is
+      begin
+         if Has_Atomic_Components (Etype (N))
+           or else Is_Atomic (Etype (N))
+         then
+            return True;
+
+         elsif Is_Entity_Name (N)
+           and then (Has_Atomic_Components (Entity (N))
+                      or else Is_Atomic (Entity (N)))
+         then
+            return True;
+
+         elsif Nkind (N) = N_Indexed_Component
+           or else Nkind (N) = N_Selected_Component
+         then
+            return Is_Atomic_Prefix (Prefix (N));
+
+         else
+            return False;
+         end if;
+      end Object_Has_Atomic_Components;
+
+   --  Start of processing for Is_Atomic_Object
+
+   begin
+      if Is_Atomic (Etype (N))
+        or else (Is_Entity_Name (N) and then Is_Atomic (Entity (N)))
+      then
+         return True;
+
+      elsif Nkind (N) = N_Indexed_Component
+        or else Nkind (N) = N_Selected_Component
+      then
+         return Is_Atomic_Prefix (Prefix (N));
+
+      else
+         return False;
+      end if;
+   end Is_Atomic_Object;
+
+   ----------------------------------------------
+   -- Is_Dependent_Component_Of_Mutable_Object --
+   ----------------------------------------------
+
+   function Is_Dependent_Component_Of_Mutable_Object
+     (Object : Node_Id)
+      return   Boolean
+   is
+      P           : Node_Id;
+      Prefix_Type : Entity_Id;
+      P_Aliased   : Boolean := False;
+      Comp        : Entity_Id;
+
+      function Has_Dependent_Constraint (Comp : Entity_Id) return Boolean;
+      --  Returns True if and only if Comp has a constrained subtype
+      --  that depends on a discriminant.
+
+      function Is_Declared_Within_Variant (Comp : Entity_Id) return Boolean;
+      --  Returns True if and only if Comp is declared within a variant part.
+
+      ------------------------------
+      -- Has_Dependent_Constraint --
+      ------------------------------
+
+      function Has_Dependent_Constraint (Comp : Entity_Id) return Boolean is
+         Comp_Decl  : constant Node_Id   := Parent (Comp);
+         Subt_Indic : constant Node_Id   := Subtype_Indication (Comp_Decl);
+         Constr     : Node_Id;
+         Assn       : Node_Id;
+
+      begin
+         if Nkind (Subt_Indic) = N_Subtype_Indication then
+            Constr := Constraint (Subt_Indic);
+
+            if Nkind (Constr) = N_Index_Or_Discriminant_Constraint then
+               Assn := First (Constraints (Constr));
+               while Present (Assn) loop
+                  case Nkind (Assn) is
+                     when N_Subtype_Indication |
+                          N_Range              |
+                          N_Identifier
+                     =>
+                        if Depends_On_Discriminant (Assn) then
+                           return True;
+                        end if;
+
+                     when N_Discriminant_Association =>
+                        if Depends_On_Discriminant (Expression (Assn)) then
+                           return True;
+                        end if;
+
+                     when others =>
+                        null;
+
+                  end case;
+
+                  Next (Assn);
+               end loop;
+            end if;
+         end if;
+
+         return False;
+      end Has_Dependent_Constraint;
+
+      --------------------------------
+      -- Is_Declared_Within_Variant --
+      --------------------------------
+
+      function Is_Declared_Within_Variant (Comp : Entity_Id) return Boolean is
+         Comp_Decl : constant Node_Id   := Parent (Comp);
+         Comp_List : constant Node_Id   := Parent (Comp_Decl);
+
+      begin
+         return Nkind (Parent (Comp_List)) = N_Variant;
+      end Is_Declared_Within_Variant;
+
+   --  Start of processing for Is_Dependent_Component_Of_Mutable_Object
+
+   begin
+      if Is_Variable (Object) then
+
+         if Nkind (Object) = N_Selected_Component then
+            P := Prefix (Object);
+            Prefix_Type := Etype (P);
+
+            if Is_Entity_Name (P) then
+
+               if Ekind (Entity (P)) = E_Generic_In_Out_Parameter then
+                  Prefix_Type := Base_Type (Prefix_Type);
+               end if;
+
+               if Is_Aliased (Entity (P)) then
+                  P_Aliased := True;
+               end if;
+
+            else
+               --  Check for prefix being an aliased component ???
+               null;
+            end if;
+
+            if Is_Access_Type (Prefix_Type)
+              or else Nkind (P) = N_Explicit_Dereference
+            then
+               return False;
+            end if;
+
+            Comp :=
+              Original_Record_Component (Entity (Selector_Name (Object)));
+
+            if not Is_Constrained (Prefix_Type)
+              and then not Is_Indefinite_Subtype (Prefix_Type)
+              and then (Is_Declared_Within_Variant (Comp)
+                          or else Has_Dependent_Constraint (Comp))
+              and then not P_Aliased
+            then
+               return True;
+
+            else
+               return
+                 Is_Dependent_Component_Of_Mutable_Object (Prefix (Object));
+
+            end if;
+
+         elsif Nkind (Object) = N_Indexed_Component
+           or else Nkind (Object) = N_Slice
+         then
+            return Is_Dependent_Component_Of_Mutable_Object (Prefix (Object));
+         end if;
+      end if;
+
+      return False;
+   end Is_Dependent_Component_Of_Mutable_Object;
+
+   --------------
+   -- Is_False --
+   --------------
+
+   function Is_False (U : Uint) return Boolean is
+   begin
+      return (U = 0);
+   end Is_False;
+
+   ---------------------------
+   -- Is_Fixed_Model_Number --
+   ---------------------------
+
+   function Is_Fixed_Model_Number (U : Ureal; T : Entity_Id) return Boolean is
+      S : constant Ureal := Small_Value (T);
+      M : Urealp.Save_Mark;
+      R : Boolean;
+
+   begin
+      M := Urealp.Mark;
+      R := (U = UR_Trunc (U / S) * S);
+      Urealp.Release (M);
+      return R;
+   end Is_Fixed_Model_Number;
+
+   -------------------------------
+   -- Is_Fully_Initialized_Type --
+   -------------------------------
+
+   function Is_Fully_Initialized_Type (Typ : Entity_Id) return Boolean is
+   begin
+      if Is_Scalar_Type (Typ) then
+         return False;
+
+      elsif Is_Access_Type (Typ) then
+         return True;
+
+      elsif Is_Array_Type (Typ) then
+         if Is_Fully_Initialized_Type (Component_Type (Typ)) then
+            return True;
+         end if;
+
+         --  An interesting case, if we have a constrained type one of whose
+         --  bounds is known to be null, then there are no elements to be
+         --  initialized, so all the elements are initialized!
+
+         if Is_Constrained (Typ) then
+            declare
+               Indx     : Node_Id;
+               Indx_Typ : Entity_Id;
+               Lbd, Hbd : Node_Id;
+
+            begin
+               Indx := First_Index (Typ);
+               while Present (Indx) loop
+
+                  if Etype (Indx) = Any_Type then
+                     return False;
+
+                  --  If index is a range, use directly.
+
+                  elsif Nkind (Indx) = N_Range then
+                     Lbd := Low_Bound  (Indx);
+                     Hbd := High_Bound (Indx);
+
+                  else
+                     Indx_Typ := Etype (Indx);
+
+                     if Is_Private_Type (Indx_Typ)  then
+                        Indx_Typ := Full_View (Indx_Typ);
+                     end if;
+
+                     if No (Indx_Typ) then
+                        return False;
+                     else
+                        Lbd := Type_Low_Bound  (Indx_Typ);
+                        Hbd := Type_High_Bound (Indx_Typ);
+                     end if;
+                  end if;
+
+                  if Compile_Time_Known_Value (Lbd)
+                    and then Compile_Time_Known_Value (Hbd)
+                  then
+                     if Expr_Value (Hbd) < Expr_Value (Lbd) then
+                        return True;
+                     end if;
+                  end if;
+
+                  Next_Index (Indx);
+               end loop;
+            end;
+         end if;
+
+         return False;
+
+      elsif Is_Record_Type (Typ) then
+         declare
+            Ent : Entity_Id;
+
+         begin
+            Ent := First_Entity (Typ);
+
+            while Present (Ent) loop
+               if Ekind (Ent) = E_Component
+                 and then (No (Parent (Ent))
+                             or else No (Expression (Parent (Ent))))
+                 and then not Is_Fully_Initialized_Type (Etype (Ent))
+               then
+                  return False;
+               end if;
+
+               Next_Entity (Ent);
+            end loop;
+         end;
+
+         return True;
+
+      elsif Is_Concurrent_Type (Typ) then
+         return True;
+
+      elsif Is_Private_Type (Typ) then
+         declare
+            U : constant Entity_Id := Underlying_Type (Typ);
+
+         begin
+            if No (U) then
+               return False;
+            else
+               return Is_Fully_Initialized_Type (U);
+            end if;
+         end;
+
+      else
+         return False;
+      end if;
+   end Is_Fully_Initialized_Type;
+
+   ----------------------------
+   -- Is_Inherited_Operation --
+   ----------------------------
+
+   function Is_Inherited_Operation (E : Entity_Id) return Boolean is
+      Kind : constant Node_Kind := Nkind (Parent (E));
+
+   begin
+      pragma Assert (Is_Overloadable (E));
+      return Kind = N_Full_Type_Declaration
+        or else Kind = N_Private_Extension_Declaration
+        or else Kind = N_Subtype_Declaration
+        or else (Ekind (E) = E_Enumeration_Literal
+                  and then Is_Derived_Type (Etype (E)));
+   end Is_Inherited_Operation;
+
+   -----------------------------
+   -- Is_Library_Level_Entity --
+   -----------------------------
+
+   function Is_Library_Level_Entity (E : Entity_Id) return Boolean is
+   begin
+      return Enclosing_Dynamic_Scope (E) = Standard_Standard;
+   end Is_Library_Level_Entity;
+
+   ---------------------------------
+   -- Is_Local_Variable_Reference --
+   ---------------------------------
+
+   function Is_Local_Variable_Reference (Expr : Node_Id) return Boolean is
+   begin
+      if not Is_Entity_Name (Expr) then
+         return False;
+
+      else
+         declare
+            Ent : constant Entity_Id := Entity (Expr);
+            Sub : constant Entity_Id := Enclosing_Subprogram (Ent);
+
+         begin
+            if Ekind (Ent) /= E_Variable
+                 and then
+               Ekind (Ent) /= E_In_Out_Parameter
+            then
+               return False;
+
+            else
+               return Present (Sub) and then Sub = Current_Subprogram;
+            end if;
+         end;
+      end if;
+   end Is_Local_Variable_Reference;
+
+   -------------------------
+   -- Is_Object_Reference --
+   -------------------------
+
+   function Is_Object_Reference (N : Node_Id) return Boolean is
+   begin
+      if Is_Entity_Name (N) then
+         return Is_Object (Entity (N));
+
+      else
+         case Nkind (N) is
+            when N_Indexed_Component | N_Slice =>
+               return True;
+
+            --  In Ada95, a function call is a constant object.
+
+            when N_Function_Call =>
+               return True;
+
+            when N_Selected_Component =>
+               return Is_Object_Reference (Selector_Name (N));
+
+            when N_Explicit_Dereference =>
+               return True;
+
+            --  An unchecked type conversion is considered to be an object if
+            --  the operand is an object (this construction arises only as a
+            --  result of expansion activities).
+
+            when N_Unchecked_Type_Conversion =>
+               return True;
+
+            when others =>
+               return False;
+         end case;
+      end if;
+   end Is_Object_Reference;
+
+   -----------------------------------
+   -- Is_OK_Variable_For_Out_Formal --
+   -----------------------------------
+
+   function Is_OK_Variable_For_Out_Formal (AV : Node_Id) return Boolean is
+   begin
+      Note_Possible_Modification (AV);
+
+      --  We must reject parenthesized variable names. The check for
+      --  Comes_From_Source is present because there are currently
+      --  cases where the compiler violates this rule (e.g. passing
+      --  a task object to its controlled Initialize routine).
+
+      if Paren_Count (AV) > 0 and then Comes_From_Source (AV) then
+         return False;
+
+      --  A variable is always allowed
+
+      elsif Is_Variable (AV) then
+         return True;
+
+      --  Unchecked conversions are allowed only if they come from the
+      --  generated code, which sometimes uses unchecked conversions for
+      --  out parameters in cases where code generation is unaffected.
+      --  We tell source unchecked conversions by seeing if they are
+      --  rewrites of an original UC function call, or of an explicit
+      --  conversion of a function call.
+
+      elsif Nkind (AV) = N_Unchecked_Type_Conversion then
+         if Nkind (Original_Node (AV)) = N_Function_Call then
+            return False;
+
+         elsif Comes_From_Source (AV)
+           and then Nkind (Original_Node (Expression (AV))) = N_Function_Call
+         then
+            return False;
+
+         else
+            return True;
+         end if;
+
+      --  Normal type conversions are allowed if argument is a variable
+
+      elsif Nkind (AV) = N_Type_Conversion then
+         if Is_Variable (Expression (AV))
+           and then Paren_Count (Expression (AV)) = 0
+         then
+            Note_Possible_Modification (Expression (AV));
+            return True;
+
+         --  We also allow a non-parenthesized expression that raises
+         --  constraint error if it rewrites what used to be a variable
+
+         elsif Raises_Constraint_Error (Expression (AV))
+            and then Paren_Count (Expression (AV)) = 0
+            and then Is_Variable (Original_Node (Expression (AV)))
+         then
+            return True;
+
+         --  Type conversion of something other than a variable
+
+         else
+            return False;
+         end if;
+
+      --  If this node is rewritten, then test the original form, if that is
+      --  OK, then we consider the rewritten node OK (for example, if the
+      --  original node is a conversion, then Is_Variable will not be true
+      --  but we still want to allow the conversion if it converts a variable.
+
+      elsif Original_Node (AV) /= AV then
+         return Is_OK_Variable_For_Out_Formal (Original_Node (AV));
+
+      --  All other non-variables are rejected
+
+      else
+         return False;
+      end if;
+   end Is_OK_Variable_For_Out_Formal;
+
+   -----------------------------
+   -- Is_RCI_Pkg_Spec_Or_Body --
+   -----------------------------
+
+   function Is_RCI_Pkg_Spec_Or_Body (Cunit : Node_Id) return Boolean is
+
+      function Is_RCI_Pkg_Decl_Cunit (Cunit : Node_Id) return Boolean;
+      --  Return True if the unit of Cunit is an RCI package declaration
+
+      ---------------------------
+      -- Is_RCI_Pkg_Decl_Cunit --
+      ---------------------------
+
+      function Is_RCI_Pkg_Decl_Cunit (Cunit : Node_Id) return Boolean is
+         The_Unit : constant Node_Id := Unit (Cunit);
+
+      begin
+         if Nkind (The_Unit) /= N_Package_Declaration then
+            return False;
+         end if;
+         return Is_Remote_Call_Interface (Defining_Entity (The_Unit));
+      end Is_RCI_Pkg_Decl_Cunit;
+
+   --  Start of processing for Is_RCI_Pkg_Spec_Or_Body
+
+   begin
+      return Is_RCI_Pkg_Decl_Cunit (Cunit)
+        or else
+         (Nkind (Unit (Cunit)) = N_Package_Body
+           and then Is_RCI_Pkg_Decl_Cunit (Library_Unit (Cunit)));
+   end Is_RCI_Pkg_Spec_Or_Body;
+
+   -----------------------------------------
+   -- Is_Remote_Access_To_Class_Wide_Type --
+   -----------------------------------------
+
+   function Is_Remote_Access_To_Class_Wide_Type
+     (E    : Entity_Id)
+      return Boolean
+   is
+      D : Entity_Id;
+
+      function Comes_From_Limited_Private_Type_Declaration
+        (E    : Entity_Id)
+         return Boolean;
+      --  Check if the original declaration is a limited private one and
+      --  if all the derivations have been using private extensions.
+
+      -------------------------------------------------
+      -- Comes_From_Limited_Private_Type_Declaration --
+      -------------------------------------------------
+
+      function Comes_From_Limited_Private_Type_Declaration (E : in Entity_Id)
+        return Boolean
+      is
+         N : constant Node_Id := Declaration_Node (E);
+      begin
+         if Nkind (N) = N_Private_Type_Declaration
+           and then Limited_Present (N)
+         then
+            return True;
+         end if;
+
+         if Nkind (N) = N_Private_Extension_Declaration then
+            return Comes_From_Limited_Private_Type_Declaration (Etype (E));
+         end if;
+
+         return False;
+      end Comes_From_Limited_Private_Type_Declaration;
+
+   --  Start of processing for Is_Remote_Access_To_Class_Wide_Type
+
+   begin
+      if not (Is_Remote_Call_Interface (E)
+               or else Is_Remote_Types (E))
+        or else Ekind (E) /= E_General_Access_Type
+      then
+         return False;
+      end if;
+
+      D := Designated_Type (E);
+
+      if Ekind (D) /= E_Class_Wide_Type then
+         return False;
+      end if;
+
+      return Comes_From_Limited_Private_Type_Declaration
+               (Defining_Identifier (Parent (D)));
+   end Is_Remote_Access_To_Class_Wide_Type;
+
+   -----------------------------------------
+   -- Is_Remote_Access_To_Subprogram_Type --
+   -----------------------------------------
+
+   function Is_Remote_Access_To_Subprogram_Type
+     (E    : Entity_Id)
+      return Boolean
+   is
+   begin
+      return (Ekind (E) = E_Access_Subprogram_Type
+                or else (Ekind (E) = E_Record_Type
+                           and then Present (Corresponding_Remote_Type (E))))
+        and then (Is_Remote_Call_Interface (E)
+                   or else Is_Remote_Types (E));
+   end Is_Remote_Access_To_Subprogram_Type;
+
+   --------------------
+   -- Is_Remote_Call --
+   --------------------
+
+   function Is_Remote_Call (N : Node_Id) return Boolean is
+   begin
+      if Nkind (N) /= N_Procedure_Call_Statement
+        and then Nkind (N) /= N_Function_Call
+      then
+         --  An entry call cannot be remote
+
+         return False;
+
+      elsif Nkind (Name (N)) in N_Has_Entity
+        and then Is_Remote_Call_Interface (Entity (Name (N)))
+      then
+         --  A subprogram declared in the spec of a RCI package is remote
+
+         return True;
+
+      elsif Nkind (Name (N)) = N_Explicit_Dereference
+        and then Is_Remote_Access_To_Subprogram_Type
+          (Etype (Prefix (Name (N))))
+      then
+         --  The dereference of a RAS is a remote call
+
+         return True;
+
+      elsif Present (Controlling_Argument (N))
+        and then Is_Remote_Access_To_Class_Wide_Type
+          (Etype (Controlling_Argument (N)))
+      then
+         --  Any primitive operation call with a controlling argument of
+         --  a RACW type is a remote call.
+
+         return True;
+      end if;
+
+      --  All other calls are local calls
+
+      return False;
+   end Is_Remote_Call;
+
+   ----------------------
+   -- Is_Selector_Name --
+   ----------------------
+
+   function Is_Selector_Name (N : Node_Id) return Boolean is
+
+   begin
+      if not Is_List_Member (N) then
+         declare
+            P : constant Node_Id   := Parent (N);
+            K : constant Node_Kind := Nkind (P);
+
+         begin
+            return
+              (K = N_Expanded_Name          or else
+               K = N_Generic_Association    or else
+               K = N_Parameter_Association  or else
+               K = N_Selected_Component)
+              and then Selector_Name (P) = N;
+         end;
+
+      else
+         declare
+            L : constant List_Id := List_Containing (N);
+            P : constant Node_Id := Parent (L);
+
+         begin
+            return (Nkind (P) = N_Discriminant_Association
+                     and then Selector_Names (P) = L)
+              or else
+                   (Nkind (P) = N_Component_Association
+                     and then Choices (P) = L);
+         end;
+      end if;
+   end Is_Selector_Name;
+
+   ------------------
+   -- Is_Statement --
+   ------------------
+
+   function Is_Statement (N : Node_Id) return Boolean is
+   begin
+      return
+        Nkind (N) in N_Statement_Other_Than_Procedure_Call
+          or else Nkind (N) = N_Procedure_Call_Statement;
+   end Is_Statement;
+
+   -----------------
+   -- Is_Transfer --
+   -----------------
+
+   function Is_Transfer (N : Node_Id) return Boolean is
+      Kind : constant Node_Kind := Nkind (N);
+
+   begin
+      if Kind = N_Return_Statement
+           or else
+         Kind = N_Goto_Statement
+           or else
+         Kind = N_Raise_Statement
+           or else
+         Kind = N_Requeue_Statement
+      then
+         return True;
+
+      elsif (Kind = N_Exit_Statement or else Kind in N_Raise_xxx_Error)
+        and then No (Condition (N))
+      then
+         return True;
+
+      elsif Kind = N_Procedure_Call_Statement
+        and then Is_Entity_Name (Name (N))
+        and then Present (Entity (Name (N)))
+        and then No_Return (Entity (Name (N)))
+      then
+         return True;
+
+      elsif Nkind (Original_Node (N)) = N_Raise_Statement then
+         return True;
+
+      else
+         return False;
+      end if;
+   end Is_Transfer;
+
+   -------------
+   -- Is_True --
+   -------------
+
+   function Is_True (U : Uint) return Boolean is
+   begin
+      return (U /= 0);
+   end Is_True;
+
+   -----------------
+   -- Is_Variable --
+   -----------------
+
+   function Is_Variable (N : Node_Id) return Boolean is
+
+      Orig_Node : constant Node_Id := Original_Node (N);
+      --  We do the test on the original node, since this is basically a
+      --  test of syntactic categories, so it must not be disturbed by
+      --  whatever rewriting might have occurred. For example, an aggregate,
+      --  which is certainly NOT a variable, could be turned into a variable
+      --  by expansion.
+
+      function In_Protected_Function (E : Entity_Id) return Boolean;
+      --  Within a protected function, the private components of the
+      --  enclosing protected type are constants. A function nested within
+      --  a (protected) procedure is not itself protected.
+
+      function Is_Variable_Prefix (P : Node_Id) return Boolean;
+      --  Prefixes can involve implicit dereferences, in which case we
+      --  must test for the case of a reference of a constant access
+      --  type, which can never be a variable.
+
+      function In_Protected_Function (E : Entity_Id) return Boolean is
+         Prot : constant Entity_Id := Scope (E);
+         S    : Entity_Id;
+
+      begin
+         if not Is_Protected_Type (Prot) then
+            return False;
+         else
+            S := Current_Scope;
+
+            while Present (S) and then S /= Prot loop
+
+               if Ekind (S) = E_Function
+                 and then Scope (S) = Prot
+               then
+                  return True;
+               end if;
+
+               S := Scope (S);
+            end loop;
+
+            return False;
+         end if;
+      end In_Protected_Function;
+
+      function Is_Variable_Prefix (P : Node_Id) return Boolean is
+      begin
+         if Is_Access_Type (Etype (P)) then
+            return not Is_Access_Constant (Root_Type (Etype (P)));
+         else
+            return Is_Variable (P);
+         end if;
+      end Is_Variable_Prefix;
+
+   --  Start of processing for Is_Variable
+
+   begin
+      --  Definitely OK if Assignment_OK is set. Since this is something that
+      --  only gets set for expanded nodes, the test is on N, not Orig_Node.
+
+      if Nkind (N) in N_Subexpr and then Assignment_OK (N) then
+         return True;
+
+      --  Normally we go to the original node, but there is one exception
+      --  where we use the rewritten node, namely when it is an explicit
+      --  dereference. The generated code may rewrite a prefix which is an
+      --  access type with an explicit dereference. The dereference is a
+      --  variable, even though the original node may not be (since it could
+      --  be a constant of the access type).
+
+      elsif Nkind (N) = N_Explicit_Dereference
+        and then Nkind (Orig_Node) /= N_Explicit_Dereference
+        and then Is_Access_Type (Etype (Orig_Node))
+      then
+         return Is_Variable_Prefix (Original_Node (Prefix (N)));
+
+      --  All remaining checks use the original node
+
+      elsif Is_Entity_Name (Orig_Node) then
+         declare
+            E : constant Entity_Id := Entity (Orig_Node);
+            K : constant Entity_Kind := Ekind (E);
+
+         begin
+            return (K = E_Variable
+                      and then Nkind (Parent (E)) /= N_Exception_Handler)
+              or else  (K = E_Component
+                          and then not In_Protected_Function (E))
+              or else  K = E_Out_Parameter
+              or else  K = E_In_Out_Parameter
+              or else  K = E_Generic_In_Out_Parameter
+
+               --  Current instance of type:
+
+              or else (Is_Type (E) and then In_Open_Scopes (E))
+              or else (Is_Incomplete_Or_Private_Type (E)
+                        and then In_Open_Scopes (Full_View (E)));
+         end;
+
+      else
+         case Nkind (Orig_Node) is
+            when N_Indexed_Component | N_Slice =>
+               return Is_Variable_Prefix (Prefix (Orig_Node));
+
+            when N_Selected_Component =>
+               return Is_Variable_Prefix (Prefix (Orig_Node))
+                 and then Is_Variable (Selector_Name (Orig_Node));
+
+            --  For an explicit dereference, we must check whether the type
+            --  is ACCESS CONSTANT, since if it is, then it is not a variable.
+
+            when N_Explicit_Dereference =>
+               return Is_Access_Type (Etype (Prefix (Orig_Node)))
+                 and then not
+                   Is_Access_Constant (Root_Type (Etype (Prefix (Orig_Node))));
+
+            --  The type conversion is the case where we do not deal with the
+            --  context dependent special case of an actual parameter. Thus
+            --  the type conversion is only considered a variable for the
+            --  purposes of this routine if the target type is tagged. However,
+            --  a type conversion is considered to be a variable if it does not
+            --  come from source (this deals for example with the conversions
+            --  of expressions to their actual subtypes).
+
+            when N_Type_Conversion =>
+               return Is_Variable (Expression (Orig_Node))
+                 and then
+                   (not Comes_From_Source (Orig_Node)
+                      or else
+                        (Is_Tagged_Type (Etype (Subtype_Mark (Orig_Node)))
+                          and then
+                         Is_Tagged_Type (Etype (Expression (Orig_Node)))));
+
+            --  GNAT allows an unchecked type conversion as a variable. This
+            --  only affects the generation of internal expanded code, since
+            --  calls to instantiations of Unchecked_Conversion are never
+            --  considered variables (since they are function calls).
+            --  This is also true for expression actions.
+
+            when N_Unchecked_Type_Conversion =>
+               return Is_Variable (Expression (Orig_Node));
+
+            when others =>
+               return False;
+         end case;
+      end if;
+   end Is_Variable;
+
+   ------------------------
+   -- Is_Volatile_Object --
+   ------------------------
+
+   function Is_Volatile_Object (N : Node_Id) return Boolean is
+
+      function Object_Has_Volatile_Components (N : Node_Id) return Boolean;
+      --  Determines if given object has volatile components
+
+      function Is_Volatile_Prefix (N : Node_Id) return Boolean;
+      --  If prefix is an implicit dereference, examine designated type.
+
+      function Is_Volatile_Prefix (N : Node_Id) return Boolean is
+      begin
+         if Is_Access_Type (Etype (N)) then
+            return Has_Volatile_Components (Designated_Type (Etype (N)));
+         else
+            return Object_Has_Volatile_Components (N);
+         end if;
+      end Is_Volatile_Prefix;
+
+      function Object_Has_Volatile_Components (N : Node_Id) return Boolean is
+      begin
+         if Is_Volatile (Etype (N))
+           or else Has_Volatile_Components (Etype (N))
+         then
+            return True;
+
+         elsif Is_Entity_Name (N)
+           and then (Has_Volatile_Components (Entity (N))
+                      or else Is_Volatile (Entity (N)))
+         then
+            return True;
+
+         elsif Nkind (N) = N_Indexed_Component
+           or else Nkind (N) = N_Selected_Component
+         then
+            return Is_Volatile_Prefix (Prefix (N));
+
+         else
+            return False;
+         end if;
+      end Object_Has_Volatile_Components;
+
+   --  Start of processing for Is_Volatile_Object
+
+   begin
+      if Is_Volatile (Etype (N))
+        or else (Is_Entity_Name (N) and then Is_Volatile (Entity (N)))
+      then
+         return True;
+
+      elsif Nkind (N) = N_Indexed_Component
+        or else Nkind (N) = N_Selected_Component
+      then
+         return Is_Volatile_Prefix (Prefix (N));
+
+      else
+         return False;
+      end if;
+   end Is_Volatile_Object;
+
+   --------------------------
+   -- Kill_Size_Check_Code --
+   --------------------------
+
+   procedure Kill_Size_Check_Code (E : Entity_Id) is
+   begin
+      if (Ekind (E) = E_Constant or else Ekind (E) = E_Variable)
+        and then Present (Size_Check_Code (E))
+      then
+         Remove (Size_Check_Code (E));
+         Set_Size_Check_Code (E, Empty);
+      end if;
+   end Kill_Size_Check_Code;
+
+   -------------------------
+   -- New_External_Entity --
+   -------------------------
+
+   function New_External_Entity
+     (Kind         : Entity_Kind;
+      Scope_Id     : Entity_Id;
+      Sloc_Value   : Source_Ptr;
+      Related_Id   : Entity_Id;
+      Suffix       : Character;
+      Suffix_Index : Nat := 0;
+      Prefix       : Character := ' ')
+      return         Entity_Id
+   is
+      N : constant Entity_Id :=
+            Make_Defining_Identifier (Sloc_Value,
+              New_External_Name
+                (Chars (Related_Id), Suffix, Suffix_Index, Prefix));
+
+   begin
+      Set_Ekind          (N, Kind);
+      Set_Is_Internal    (N, True);
+      Append_Entity      (N, Scope_Id);
+      Set_Public_Status  (N);
+
+      if Kind in Type_Kind then
+         Init_Size_Align (N);
+      end if;
+
+      return N;
+   end New_External_Entity;
+
+   -------------------------
+   -- New_Internal_Entity --
+   -------------------------
+
+   function New_Internal_Entity
+     (Kind       : Entity_Kind;
+      Scope_Id   : Entity_Id;
+      Sloc_Value : Source_Ptr;
+      Id_Char    : Character)
+      return       Entity_Id
+   is
+      N : constant Entity_Id :=
+            Make_Defining_Identifier (Sloc_Value, New_Internal_Name (Id_Char));
+
+   begin
+      Set_Ekind          (N, Kind);
+      Set_Is_Internal    (N, True);
+      Append_Entity      (N, Scope_Id);
+
+      if Kind in Type_Kind then
+         Init_Size_Align (N);
+      end if;
+
+      return N;
+   end New_Internal_Entity;
+
+   -----------------
+   -- Next_Actual --
+   -----------------
+
+   function Next_Actual (Actual_Id : Node_Id) return Node_Id is
+      N  : Node_Id;
+
+   begin
+      --  If we are pointing at a positional parameter, it is a member of
+      --  a node list (the list of parameters), and the next parameter
+      --  is the next node on the list, unless we hit a parameter
+      --  association, in which case we shift to using the chain whose
+      --  head is the First_Named_Actual in the parent, and then is
+      --  threaded using the Next_Named_Actual of the Parameter_Association.
+      --  All this fiddling is because the original node list is in the
+      --  textual call order, and what we need is the declaration order.
+
+      if Is_List_Member (Actual_Id) then
+         N := Next (Actual_Id);
+
+         if Nkind (N) = N_Parameter_Association then
+            return First_Named_Actual (Parent (Actual_Id));
+         else
+            return N;
+         end if;
+
+      else
+         return Next_Named_Actual (Parent (Actual_Id));
+      end if;
+   end Next_Actual;
+
+   procedure Next_Actual (Actual_Id : in out Node_Id) is
+   begin
+      Actual_Id := Next_Actual (Actual_Id);
+   end Next_Actual;
+
+   -----------------------
+   -- Normalize_Actuals --
+   -----------------------
+
+   --  Chain actuals according to formals of subprogram. If there are
+   --  no named associations, the chain is simply the list of Parameter
+   --  Associations, since the order is the same as the declaration order.
+   --  If there are named associations, then the First_Named_Actual field
+   --  in the N_Procedure_Call_Statement node or N_Function_Call node
+   --  points to the Parameter_Association node for the parameter that
+   --  comes first in declaration order. The remaining named parameters
+   --  are then chained in declaration order using Next_Named_Actual.
+
+   --  This routine also verifies that the number of actuals is compatible
+   --  with the number and default values of formals, but performs no type
+   --  checking (type checking is done by the caller).
+
+   --  If the matching succeeds, Success is set to True, and the caller
+   --  proceeds with type-checking. If the match is unsuccessful, then
+   --  Success is set to False, and the caller attempts a different
+   --  interpretation, if there is one.
+
+   --  If the flag Report is on, the call is not overloaded, and a failure
+   --  to match can be reported here, rather than in the caller.
+
+   procedure Normalize_Actuals
+     (N       : Node_Id;
+      S       : Entity_Id;
+      Report  : Boolean;
+      Success : out Boolean)
+   is
+      Actuals     : constant List_Id := Parameter_Associations (N);
+      Actual      : Node_Id   := Empty;
+      Formal      : Entity_Id;
+      Last        : Node_Id := Empty;
+      First_Named : Node_Id := Empty;
+      Found       : Boolean;
+
+      Formals_To_Match : Integer := 0;
+      Actuals_To_Match : Integer := 0;
+
+      procedure Chain (A : Node_Id);
+      --  Add named actual at the proper place in the list, using the
+      --  Next_Named_Actual link.
+
+      function Reporting return Boolean;
+      --  Determines if an error is to be reported. To report an error, we
+      --  need Report to be True, and also we do not report errors caused
+      --  by calls to Init_Proc's that occur within other Init_Proc's. Such
+      --  errors must always be cascaded errors, since if all the types are
+      --  declared correctly, the compiler will certainly build decent calls!
+
+      procedure Chain (A : Node_Id) is
+      begin
+         if No (Last) then
+
+            --  Call node points to first actual in list.
+
+            Set_First_Named_Actual (N, Explicit_Actual_Parameter (A));
+
+         else
+            Set_Next_Named_Actual (Last, Explicit_Actual_Parameter (A));
+         end if;
+
+         Last := A;
+         Set_Next_Named_Actual (Last, Empty);
+      end Chain;
+
+      function Reporting return Boolean is
+      begin
+         if not Report then
+            return False;
+
+         elsif not Within_Init_Proc then
+            return True;
+
+         elsif Chars (Entity (Name (N))) = Name_uInit_Proc then
+            return False;
+
+         else
+            return True;
+         end if;
+      end Reporting;
+
+   --  Start of processing for Normalize_Actuals
+
+   begin
+      if Is_Access_Type (S) then
+
+         --  The name in the call is a function call that returns an access
+         --  to subprogram. The designated type has the list of formals.
+
+         Formal := First_Formal (Designated_Type (S));
+      else
+         Formal := First_Formal (S);
+      end if;
+
+      while Present (Formal) loop
+         Formals_To_Match := Formals_To_Match + 1;
+         Next_Formal (Formal);
+      end loop;
+
+      --  Find if there is a named association, and verify that no positional
+      --  associations appear after named ones.
+
+      if Present (Actuals) then
+         Actual := First (Actuals);
+      end if;
+
+      while Present (Actual)
+        and then Nkind (Actual) /= N_Parameter_Association
+      loop
+         Actuals_To_Match := Actuals_To_Match + 1;
+         Next (Actual);
+      end loop;
+
+      if No (Actual) and Actuals_To_Match = Formals_To_Match then
+
+         --  Most common case: positional notation, no defaults
+
+         Success := True;
+         return;
+
+      elsif Actuals_To_Match > Formals_To_Match then
+
+         --  Too many actuals: will not work.
+
+         if Reporting then
+            Error_Msg_N ("too many arguments in call", N);
+         end if;
+
+         Success := False;
+         return;
+      end if;
+
+      First_Named := Actual;
+
+      while Present (Actual) loop
+         if Nkind (Actual) /= N_Parameter_Association then
+            Error_Msg_N
+              ("positional parameters not allowed after named ones", Actual);
+            Success := False;
+            return;
+
+         else
+            Actuals_To_Match := Actuals_To_Match + 1;
+         end if;
+
+         Next (Actual);
+      end loop;
+
+      if Present (Actuals) then
+         Actual := First (Actuals);
+      end if;
+
+      Formal := First_Formal (S);
+
+      while Present (Formal) loop
+
+         --  Match the formals in order. If the corresponding actual
+         --  is positional,  nothing to do. Else scan the list of named
+         --  actuals to find the one with the right name.
+
+         if Present (Actual)
+           and then Nkind (Actual) /= N_Parameter_Association
+         then
+            Next (Actual);
+            Actuals_To_Match := Actuals_To_Match - 1;
+            Formals_To_Match := Formals_To_Match - 1;
+
+         else
+            --  For named parameters, search the list of actuals to find
+            --  one that matches the next formal name.
+
+            Actual := First_Named;
+            Found  := False;
+
+            while Present (Actual) loop
+               if Chars (Selector_Name (Actual)) = Chars (Formal) then
+                  Found := True;
+                  Chain (Actual);
+                  Actuals_To_Match := Actuals_To_Match - 1;
+                  Formals_To_Match := Formals_To_Match - 1;
+                  exit;
+               end if;
+
+               Next (Actual);
+            end loop;
+
+            if not Found then
+               if Ekind (Formal) /= E_In_Parameter
+                 or else No (Default_Value (Formal))
+               then
+                  if Reporting then
+                     if Comes_From_Source (S)
+                       and then Is_Overloadable (S)
+                     then
+                        Error_Msg_Name_1 := Chars (S);
+                        Error_Msg_Sloc := Sloc (S);
+                        Error_Msg_NE
+                          ("missing argument for parameter & " &
+                             "in call to % declared #", N, Formal);
+                     else
+                        Error_Msg_NE
+                          ("missing argument for parameter &", N, Formal);
+                     end if;
+                  end if;
+
+                  Success := False;
+                  return;
+
+               else
+                  Formals_To_Match := Formals_To_Match - 1;
+               end if;
+            end if;
+         end if;
+
+         Next_Formal (Formal);
+      end loop;
+
+      if  Formals_To_Match = 0 and then Actuals_To_Match = 0 then
+         Success := True;
+         return;
+
+      else
+         if Reporting then
+
+            --  Find some superfluous named actual that did not get
+            --  attached to the list of associations.
+
+            Actual := First (Actuals);
+
+            while Present (Actual) loop
+
+               if Nkind (Actual) = N_Parameter_Association
+                 and then Actual /= Last
+                 and then No (Next_Named_Actual (Actual))
+               then
+                  Error_Msg_N ("Unmatched actual in call",  Actual);
+                  exit;
+               end if;
+
+               Next (Actual);
+            end loop;
+         end if;
+
+         Success := False;
+         return;
+      end if;
+   end Normalize_Actuals;
+
+   --------------------------------
+   -- Note_Possible_Modification --
+   --------------------------------
+
+   procedure Note_Possible_Modification (N : Node_Id) is
+      Ent : Entity_Id;
+      Exp : Node_Id;
+
+      procedure Set_Ref (E : Entity_Id; N : Node_Id);
+      --  Internal routine to note modification on entity E by node N
+
+      procedure Set_Ref (E : Entity_Id; N : Node_Id) is
+      begin
+         Set_Not_Source_Assigned (E, False);
+         Set_Is_True_Constant (E, False);
+         Generate_Reference (E, N, 'm');
+      end Set_Ref;
+
+   --  Start of processing for Note_Possible_Modification
+
+   begin
+      --  Loop to find referenced entity, if there is one
+
+      Exp := N;
+      loop
+         --  Test for node rewritten as dereference (e.g. accept parameter)
+
+         if Nkind (Exp) = N_Explicit_Dereference
+           and then Is_Entity_Name (Original_Node (Exp))
+         then
+            Set_Ref (Entity (Original_Node (Exp)), Original_Node (Exp));
+            return;
+
+         elsif Is_Entity_Name (Exp) then
+            Ent := Entity (Exp);
+
+            if (Ekind (Ent) = E_Variable or else Ekind (Ent) = E_Constant)
+              and then Present (Renamed_Object (Ent))
+            then
+               Exp := Renamed_Object (Ent);
+
+            else
+               Set_Ref (Ent, Exp);
+               return;
+            end if;
+
+         elsif     Nkind (Exp) = N_Type_Conversion
+           or else Nkind (Exp) = N_Unchecked_Type_Conversion
+         then
+            Exp := Expression (Exp);
+
+         elsif     Nkind (Exp) = N_Slice
+           or else Nkind (Exp) = N_Indexed_Component
+           or else Nkind (Exp) = N_Selected_Component
+         then
+            Exp := Prefix (Exp);
+
+         else
+            return;
+         end if;
+      end loop;
+   end Note_Possible_Modification;
+
+   -------------------------
+   -- Object_Access_Level --
+   -------------------------
+
+   function Object_Access_Level (Obj : Node_Id) return Uint is
+      E : Entity_Id;
+
+   --  Returns the static accessibility level of the view denoted
+   --  by Obj.  Note that the value returned is the result of a
+   --  call to Scope_Depth.  Only scope depths associated with
+   --  dynamic scopes can actually be returned.  Since only
+   --  relative levels matter for accessibility checking, the fact
+   --  that the distance between successive levels of accessibility
+   --  is not always one is immaterial (invariant: if level(E2) is
+   --  deeper than level(E1), then Scope_Depth(E1) < Scope_Depth(E2)).
+
+   begin
+      if Is_Entity_Name (Obj) then
+         E := Entity (Obj);
+
+         --  If E is a type then it denotes a current instance.
+         --  For this case we add one to the normal accessibility
+         --  level of the type to ensure that current instances
+         --  are treated as always being deeper than than the level
+         --  of any visible named access type (see 3.10.2(21)).
+
+         if Is_Type (E) then
+            return Type_Access_Level (E) +  1;
+
+         elsif Present (Renamed_Object (E)) then
+            return Object_Access_Level (Renamed_Object (E));
+
+         --  Similarly, if E is a component of the current instance of a
+         --  protected type, any instance of it is assumed to be at a deeper
+         --  level than the type. For a protected object (whose type is an
+         --  anonymous protected type) its components are at the same level
+         --  as the type itself.
+
+         elsif not Is_Overloadable (E)
+           and then Ekind (Scope (E)) = E_Protected_Type
+           and then Comes_From_Source (Scope (E))
+         then
+            return Type_Access_Level (Scope (E)) + 1;
+
+         else
+            return Scope_Depth (Enclosing_Dynamic_Scope (E));
+         end if;
+
+      elsif Nkind (Obj) = N_Selected_Component then
+         if Is_Access_Type (Etype (Prefix (Obj))) then
+            return Type_Access_Level (Etype (Prefix (Obj)));
+         else
+            return Object_Access_Level (Prefix (Obj));
+         end if;
+
+      elsif Nkind (Obj) = N_Indexed_Component then
+         if Is_Access_Type (Etype (Prefix (Obj))) then
+            return Type_Access_Level (Etype (Prefix (Obj)));
+         else
+            return Object_Access_Level (Prefix (Obj));
+         end if;
+
+      elsif Nkind (Obj) = N_Explicit_Dereference then
+
+         --  If the prefix is a selected access discriminant then
+         --  we make a recursive call on the prefix, which will
+         --  in turn check the level of the prefix object of
+         --  the selected discriminant.
+
+         if Nkind (Prefix (Obj)) = N_Selected_Component
+           and then Ekind (Etype (Prefix (Obj))) = E_Anonymous_Access_Type
+           and then
+             Ekind (Entity (Selector_Name (Prefix (Obj)))) = E_Discriminant
+         then
+            return Object_Access_Level (Prefix (Obj));
+         else
+            return Type_Access_Level (Etype (Prefix (Obj)));
+         end if;
+
+      elsif Nkind (Obj) = N_Type_Conversion then
+         return Object_Access_Level (Expression (Obj));
+
+      --  Function results are objects, so we get either the access level
+      --  of the function or, in the case of an indirect call, the level of
+      --  of the access-to-subprogram type.
+
+      elsif Nkind (Obj) = N_Function_Call then
+         if Is_Entity_Name (Name (Obj)) then
+            return Subprogram_Access_Level (Entity (Name (Obj)));
+         else
+            return Type_Access_Level (Etype (Prefix (Name (Obj))));
+         end if;
+
+      --  For convenience we handle qualified expressions, even though
+      --  they aren't technically object names.
+
+      elsif Nkind (Obj) = N_Qualified_Expression then
+         return Object_Access_Level (Expression (Obj));
+
+      --  Otherwise return the scope level of Standard.
+      --  (If there are cases that fall through
+      --  to this point they will be treated as
+      --  having global accessibility for now. ???)
+
+      else
+         return Scope_Depth (Standard_Standard);
+      end if;
+   end Object_Access_Level;
+
+   -----------------------
+   -- Private_Component --
+   -----------------------
+
+   function Private_Component (Type_Id : Entity_Id) return Entity_Id is
+      Ancestor  : constant Entity_Id := Base_Type (Type_Id);
+
+      function Trace_Components
+        (T     : Entity_Id;
+         Check : Boolean)
+         return  Entity_Id;
+      --  Recursive function that does the work, and checks against circular
+      --  definition for each subcomponent type.
+
+      ----------------------
+      -- Trace_Components --
+      ----------------------
+
+      function Trace_Components
+         (T     : Entity_Id;
+          Check : Boolean) return Entity_Id
+       is
+         Btype     : constant Entity_Id := Base_Type (T);
+         Component : Entity_Id;
+         P         : Entity_Id;
+         Candidate : Entity_Id := Empty;
+
+      begin
+         if Check and then Btype = Ancestor then
+            Error_Msg_N ("circular type definition", Type_Id);
+            return Any_Type;
+         end if;
+
+         if Is_Private_Type (Btype)
+           and then not Is_Generic_Type (Btype)
+         then
+            return Btype;
+
+         elsif Is_Array_Type (Btype) then
+            return Trace_Components (Component_Type (Btype), True);
+
+         elsif Is_Record_Type (Btype) then
+            Component := First_Entity (Btype);
+            while Present (Component) loop
+
+               --  skip anonymous types generated by constrained components.
+
+               if not Is_Type (Component) then
+                  P := Trace_Components (Etype (Component), True);
+
+                  if Present (P) then
+                     if P = Any_Type then
+                        return P;
+                     else
+                        Candidate := P;
+                     end if;
+                  end if;
+               end if;
+
+               Next_Entity (Component);
+            end loop;
+
+            return Candidate;
+
+         else
+            return Empty;
+         end if;
+      end Trace_Components;
+
+   --  Start of processing for Private_Component
+
+   begin
+      return Trace_Components (Type_Id, False);
+   end Private_Component;
+
+   -----------------------
+   -- Process_End_Label --
+   -----------------------
+
+   procedure Process_End_Label (N : Node_Id; Typ  : Character) is
+      Loc  : Source_Ptr;
+      Nam  : Node_Id;
+      Ctyp : Entity_Id;
+
+      Label_Ref : Boolean;
+      --  Set True if reference to end label itself is required
+
+      Endl : Node_Id;
+      --  Gets set to the operator symbol or identifier that references
+      --  the entity Ent. For the child unit case, this is the identifier
+      --  from the designator. For other cases, this is simply Endl.
+
+      Ent : Entity_Id;
+      --  This is the entity for the construct to which the End_Label applies
+
+      procedure Generate_Parent_Ref (N : Node_Id);
+      --  N is an identifier node that appears as a parent unit reference
+      --  in the case where Ent is a child unit. This procedure generates
+      --  an appropriate cross-reference entry.
+
+      procedure Generate_Parent_Ref (N : Node_Id) is
+         Parent_Ent : Entity_Id;
+
+      begin
+         --  Search up scope stack. The reason we do this is that normal
+         --  visibility analysis would not work for two reasons. First in
+         --  some subunit cases, the entry for the parent unit may not be
+         --  visible, and in any case there can be a local entity that
+         --  hides the scope entity.
+
+         Parent_Ent := Current_Scope;
+         while Present (Parent_Ent) loop
+            if Chars (Parent_Ent) = Chars (N) then
+
+               --  Generate the reference. We do NOT consider this as a
+               --  reference for unreferenced symbol purposes, but we do
+               --  force a cross-reference even if the end line does not
+               --  come from source (the caller already generated the
+               --  appropriate Typ for this situation).
+
+               Generate_Reference
+                 (Parent_Ent, N, 'r', Set_Ref => False, Force => True);
+               Style.Check_Identifier (N, Parent_Ent);
+               return;
+            end if;
+
+            Parent_Ent := Scope (Parent_Ent);
+         end loop;
+
+         --  Fall through means entity was not found -- that's odd, but
+         --  the appropriate thing is simply to ignore and not generate
+         --  any cross-reference for this entry.
+
+         return;
+      end Generate_Parent_Ref;
+
+   --  Start of processing for Process_End_Label
+
+   begin
+      --  If no node, ignore. This happens in some error situations,
+      --  and also for some internally generated structures where no
+      --  end label references are required in any case.
+
+      if No (N) then
+         return;
+      end if;
+
+      --  Nothing to do if no End_Label, happens for internally generated
+      --  constructs where we don't want an end label reference anyway.
+
+      Endl := End_Label (N);
+
+      if No (Endl) then
+         return;
+      end if;
+
+      --  Reference node is not in extended main source unit
+
+      if not In_Extended_Main_Source_Unit (N) then
+
+         --  Generally we do not collect references except for the
+         --  extended main source unit. The one exception is the 'e'
+         --  entry for a package spec, where it is useful for a client
+         --  to have the ending information to define scopes.
+
+         if Typ /= 'e' then
+            return;
+
+         else
+            Label_Ref := False;
+
+            --  For this case, we can ignore any parent references,
+            --  but we need the package name itself for the 'e' entry.
+
+            if Nkind (Endl) = N_Designator then
+               Endl := Identifier (Endl);
+            end if;
+         end if;
+
+      --  Reference is in extended main source unit
+
+      else
+         Label_Ref := True;
+
+         --  For designator, generate references for the parent entries
+
+         if Nkind (Endl) = N_Designator then
+
+            --  Generate references for the prefix if the END line comes
+            --  from source (otherwise we do not need these references)
+
+            if Comes_From_Source (Endl) then
+               Nam := Name (Endl);
+               while Nkind (Nam) = N_Selected_Component loop
+                  Generate_Parent_Ref (Selector_Name (Nam));
+                  Nam := Prefix (Nam);
+               end loop;
+
+               Generate_Parent_Ref (Nam);
+            end if;
+
+            Endl := Identifier (Endl);
+         end if;
+      end if;
+
+      --  Locate the entity to which the end label applies. Most of the
+      --  time this is simply the current scope containing the construct.
+
+      Ent := Current_Scope;
+
+      if Chars (Ent) = Chars (Endl) then
+         null;
+
+      --  But in the case of single tasks and single protected objects,
+      --  the current scope is the anonymous task or protected type and
+      --  what we want is the object. There is no direct link so what we
+      --  do is search ahead in the entity chain for the object with the
+      --  matching type and name. In practice it is almost certain to be
+      --  the very next entity on the chain, so this is not inefficient.
+
+      else
+         Ctyp := Etype (Ent);
+         loop
+            Next_Entity (Ent);
+
+            --  If we don't find the entry we are looking for, that's
+            --  odd, perhaps results from some error condition? Anyway
+            --  the appropriate thing is just to abandon the attempt.
+
+            if No (Ent) then
+               return;
+
+            --  Exit if we find the entity we are looking for
+
+            elsif Etype (Ent) = Ctyp
+              and then Chars (Ent) = Chars (Endl)
+            then
+               exit;
+            end if;
+         end loop;
+      end if;
+
+      --  If label was really there, then generate a normal reference
+      --  and then adjust the location in the end label to point past
+      --  the name (which should almost always be the semicolon).
+
+      Loc := Sloc (Endl);
+
+      if Comes_From_Source (Endl) then
+
+         --  If a label reference is required, then do the style check
+         --  and generate a normal cross-reference entry for the label
+
+         if Label_Ref then
+            Style.Check_Identifier (Endl, Ent);
+            Generate_Reference (Ent, Endl, 'r', Set_Ref => False);
+         end if;
+
+         --  Set the location to point past the label (normally this will
+         --  mean the semicolon immediately following the label). This is
+         --  done for the sake of the 'e' or 't' entry generated below.
+
+         Get_Decoded_Name_String (Chars (Endl));
+         Set_Sloc (Endl, Sloc (Endl) + Source_Ptr (Name_Len));
+      end if;
+
+      --  Now generate the e/t reference
+
+      Generate_Reference (Ent, Endl, Typ, Set_Ref => False, Force => True);
+
+      --  Restore Sloc, in case modified above, since we have an identifier
+      --  and the normal Sloc should be left set in the tree.
+
+      Set_Sloc (Endl, Loc);
+   end Process_End_Label;
+
+   ------------------
+   -- Real_Convert --
+   ------------------
+
+   --  We do the conversion to get the value of the real string by using
+   --  the scanner, see Sinput for details on use of the internal source
+   --  buffer for scanning internal strings.
+
+   function Real_Convert (S : String) return Node_Id is
+      Save_Src : constant Source_Buffer_Ptr := Source;
+      Negative : Boolean;
+
+   begin
+      Source := Internal_Source_Ptr;
+      Scan_Ptr := 1;
+
+      for J in S'Range loop
+         Source (Source_Ptr (J)) := S (J);
+      end loop;
+
+      Source (S'Length + 1) := EOF;
+
+      if Source (Scan_Ptr) = '-' then
+         Negative := True;
+         Scan_Ptr := Scan_Ptr + 1;
+      else
+         Negative := False;
+      end if;
+
+      Scan;
+
+      if Negative then
+         Set_Realval (Token_Node, UR_Negate (Realval (Token_Node)));
+      end if;
+
+      Source := Save_Src;
+      return Token_Node;
+   end Real_Convert;
+
+   ------------------------------
+   -- Requires_Transient_Scope --
+   ------------------------------
+
+   --  A transient scope is required when variable-sized temporaries are
+   --  allocated in the primary or secondary stack, or when finalization
+   --  actions must be generated before the next instruction
+
+   function Requires_Transient_Scope (Id : Entity_Id) return Boolean is
+      Typ : constant Entity_Id := Underlying_Type (Id);
+
+   begin
+      --  This is a private type which is not completed yet. This can only
+      --  happen in a default expression (of a formal parameter or of a
+      --  record component). Do not expand transient scope in this case
+
+      if No (Typ) then
+         return False;
+
+      elsif Typ = Standard_Void_Type then
+         return False;
+
+      --  The back-end has trouble allocating variable-size temporaries so
+      --  we generate them in the front-end and need a transient scope to
+      --  reclaim them properly
+
+      elsif not Size_Known_At_Compile_Time (Typ) then
+         return True;
+
+      --  Unconstrained discriminated records always require a variable
+      --  length temporary, since the length may depend on the variant.
+
+      elsif Is_Record_Type (Typ)
+        and then Has_Discriminants (Typ)
+        and then not Is_Constrained (Typ)
+      then
+         return True;
+
+      --  Functions returning tagged types may dispatch on result so their
+      --  returned value is allocated on the secondary stack. Controlled
+      --  type temporaries need finalization.
+
+      elsif Is_Tagged_Type (Typ)
+        or else Has_Controlled_Component (Typ)
+      then
+         return True;
+
+      --  Unconstrained array types are returned on the secondary stack
+
+      elsif Is_Array_Type (Typ) then
+         return not Is_Constrained (Typ);
+      end if;
+
+      return False;
+   end Requires_Transient_Scope;
+
+   --------------------------
+   -- Reset_Analyzed_Flags --
+   --------------------------
+
+   procedure Reset_Analyzed_Flags (N : Node_Id) is
+
+      function Clear_Analyzed
+        (N    : Node_Id)
+         return Traverse_Result;
+      --  Function used to reset Analyzed flags in tree. Note that we do
+      --  not reset Analyzed flags in entities, since there is no need to
+      --  renalalyze entities, and indeed, it is wrong to do so, since it
+      --  can result in generating auxiliary stuff more than once.
+
+      function Clear_Analyzed
+        (N    : Node_Id)
+         return Traverse_Result
+      is
+      begin
+         if not Has_Extension (N) then
+            Set_Analyzed (N, False);
+         end if;
+
+         return OK;
+      end Clear_Analyzed;
+
+      function Reset_Analyzed is
+        new Traverse_Func (Clear_Analyzed);
+
+      Discard : Traverse_Result;
+
+   --  Start of processing for Reset_Analyzed_Flags
+
+   begin
+      Discard := Reset_Analyzed (N);
+   end Reset_Analyzed_Flags;
+
+   ---------------
+   -- Same_Name --
+   ---------------
+
+   function Same_Name (N1, N2 : Node_Id) return Boolean is
+      K1 : constant Node_Kind := Nkind (N1);
+      K2 : constant Node_Kind := Nkind (N2);
+
+   begin
+      if (K1 = N_Identifier or else K1 = N_Defining_Identifier)
+        and then (K2 = N_Identifier or else K2 = N_Defining_Identifier)
+      then
+         return Chars (N1) = Chars (N2);
+
+      elsif (K1 = N_Selected_Component or else K1 = N_Expanded_Name)
+        and then (K2 = N_Selected_Component or else K2 = N_Expanded_Name)
+      then
+         return Same_Name (Selector_Name (N1), Selector_Name (N2))
+           and then Same_Name (Prefix (N1), Prefix (N2));
+
+      else
+         return False;
+      end if;
+   end Same_Name;
+
+   ---------------
+   -- Same_Type --
+   ---------------
+
+   function Same_Type (T1, T2 : Entity_Id) return Boolean is
+   begin
+      if T1 = T2 then
+         return True;
+
+      elsif not Is_Constrained (T1)
+        and then not Is_Constrained (T2)
+        and then Base_Type (T1) = Base_Type (T2)
+      then
+         return True;
+
+      --  For now don't bother with case of identical constraints, to be
+      --  fiddled with later on perhaps (this is only used for optimization
+      --  purposes, so it is not critical to do a best possible job)
+
+      else
+         return False;
+      end if;
+   end Same_Type;
+
+   ------------------------
+   -- Scope_Is_Transient --
+   ------------------------
+
+   function Scope_Is_Transient  return Boolean is
+   begin
+      return Scope_Stack.Table (Scope_Stack.Last).Is_Transient;
+   end Scope_Is_Transient;
+
+   ------------------
+   -- Scope_Within --
+   ------------------
+
+   function Scope_Within (Scope1, Scope2 : Entity_Id) return Boolean is
+      Scop : Entity_Id;
+
+   begin
+      Scop := Scope1;
+      while Scop /= Standard_Standard loop
+         Scop := Scope (Scop);
+
+         if Scop = Scope2 then
+            return True;
+         end if;
+      end loop;
+
+      return False;
+   end Scope_Within;
+
+   --------------------------
+   -- Scope_Within_Or_Same --
+   --------------------------
+
+   function Scope_Within_Or_Same (Scope1, Scope2 : Entity_Id) return Boolean is
+      Scop : Entity_Id;
+
+   begin
+      Scop := Scope1;
+      while Scop /= Standard_Standard loop
+         if Scop = Scope2 then
+            return True;
+         else
+            Scop := Scope (Scop);
+         end if;
+      end loop;
+
+      return False;
+   end Scope_Within_Or_Same;
+
+   ------------------------
+   -- Set_Current_Entity --
+   ------------------------
+
+   --  The given entity is to be set as the currently visible definition
+   --  of its associated name (i.e. the Node_Id associated with its name).
+   --  All we have to do is to get the name from the identifier, and
+   --  then set the associated Node_Id to point to the given entity.
+
+   procedure Set_Current_Entity (E : Entity_Id) is
+   begin
+      Set_Name_Entity_Id (Chars (E), E);
+   end Set_Current_Entity;
+
+   ---------------------------------
+   -- Set_Entity_With_Style_Check --
+   ---------------------------------
+
+   procedure Set_Entity_With_Style_Check (N : Node_Id; Val : Entity_Id) is
+      Val_Actual : Entity_Id;
+      Nod        : Node_Id;
+
+   begin
+      Set_Entity (N, Val);
+
+      if Style_Check
+        and then not Suppress_Style_Checks (Val)
+        and then not In_Instance
+      then
+         if Nkind (N) = N_Identifier then
+            Nod := N;
+
+         elsif Nkind (N) = N_Expanded_Name then
+            Nod := Selector_Name (N);
+
+         else
+            return;
+         end if;
+
+         Val_Actual := Val;
+
+         --  A special situation arises for derived operations, where we want
+         --  to do the check against the parent (since the Sloc of the derived
+         --  operation points to the derived type declaration itself).
+
+         while not Comes_From_Source (Val_Actual)
+           and then Nkind (Val_Actual) in N_Entity
+           and then (Ekind (Val_Actual) = E_Enumeration_Literal
+                      or else Ekind (Val_Actual) = E_Function
+                      or else Ekind (Val_Actual) = E_Generic_Function
+                      or else Ekind (Val_Actual) = E_Procedure
+                      or else Ekind (Val_Actual) = E_Generic_Procedure)
+           and then Present (Alias (Val_Actual))
+         loop
+            Val_Actual := Alias (Val_Actual);
+         end loop;
+
+         --  Renaming declarations for generic actuals do not come from source,
+         --  and have a different name from that of the entity they rename, so
+         --  there is no style check to perform here.
+
+         if Chars (Nod) = Chars (Val_Actual) then
+            Style.Check_Identifier (Nod, Val_Actual);
+         end if;
+
+      end if;
+
+      Set_Entity (N, Val);
+   end Set_Entity_With_Style_Check;
+
+   ------------------------
+   -- Set_Name_Entity_Id --
+   ------------------------
+
+   procedure Set_Name_Entity_Id (Id : Name_Id; Val : Entity_Id) is
+   begin
+      Set_Name_Table_Info (Id, Int (Val));
+   end Set_Name_Entity_Id;
+
+   ---------------------
+   -- Set_Next_Actual --
+   ---------------------
+
+   procedure Set_Next_Actual (Ass1_Id : Node_Id; Ass2_Id : Node_Id) is
+   begin
+      if Nkind (Parent (Ass1_Id)) = N_Parameter_Association then
+         Set_First_Named_Actual (Parent (Ass1_Id), Ass2_Id);
+      end if;
+   end Set_Next_Actual;
+
+   -----------------------
+   -- Set_Public_Status --
+   -----------------------
+
+   procedure Set_Public_Status (Id : Entity_Id) is
+      S : constant Entity_Id := Current_Scope;
+
+   begin
+      if S = Standard_Standard
+        or else (Is_Public (S)
+                  and then (Ekind (S) = E_Package
+                             or else Is_Record_Type (S)
+                             or else Ekind (S) = E_Void))
+      then
+         Set_Is_Public (Id);
+
+      --  The bounds of an entry family declaration can generate object
+      --  declarations that are visible to the back-end, e.g. in the
+      --  the declaration of a composite type that contains tasks.
+
+      elsif Is_Public (S)
+        and then Is_Concurrent_Type (S)
+        and then not Has_Completion (S)
+        and then Nkind (Parent (Id)) = N_Object_Declaration
+      then
+         Set_Is_Public (Id);
+      end if;
+   end Set_Public_Status;
+
+   ----------------------------
+   -- Set_Scope_Is_Transient --
+   ----------------------------
+
+   procedure Set_Scope_Is_Transient (V : Boolean := True) is
+   begin
+      Scope_Stack.Table (Scope_Stack.Last).Is_Transient := V;
+   end Set_Scope_Is_Transient;
+
+   -------------------
+   -- Set_Size_Info --
+   -------------------
+
+   procedure Set_Size_Info (T1, T2 : Entity_Id) is
+   begin
+      --  We copy Esize, but not RM_Size, since in general RM_Size is
+      --  subtype specific and does not get inherited by all subtypes.
+
+      Set_Esize                     (T1, Esize                     (T2));
+      Set_Has_Biased_Representation (T1, Has_Biased_Representation (T2));
+
+      if Is_Discrete_Or_Fixed_Point_Type (T1)
+           and then
+         Is_Discrete_Or_Fixed_Point_Type (T2)
+      then
+         Set_Is_Unsigned_Type       (T1, Is_Unsigned_Type          (T2));
+      end if;
+
+      Set_Alignment                 (T1, Alignment                 (T2));
+   end Set_Size_Info;
+
+   --------------------
+   -- Static_Integer --
+   --------------------
+
+   function Static_Integer (N : Node_Id) return Uint is
+   begin
+      Analyze_And_Resolve (N, Any_Integer);
+
+      if N = Error
+        or else Error_Posted (N)
+        or else Etype (N) = Any_Type
+      then
+         return No_Uint;
+      end if;
+
+      if Is_Static_Expression (N) then
+         if not Raises_Constraint_Error (N) then
+            return Expr_Value (N);
+         else
+            return No_Uint;
+         end if;
+
+      elsif Etype (N) = Any_Type then
+         return No_Uint;
+
+      else
+         Error_Msg_N ("static integer expression required here", N);
+         return No_Uint;
+      end if;
+   end Static_Integer;
+
+   --------------------------
+   -- Statically_Different --
+   --------------------------
+
+   function Statically_Different (E1, E2 : Node_Id) return Boolean is
+      R1 : constant Node_Id := Get_Referenced_Object (E1);
+      R2 : constant Node_Id := Get_Referenced_Object (E2);
+
+   begin
+      return     Is_Entity_Name (R1)
+        and then Is_Entity_Name (R2)
+        and then Entity (R1) /= Entity (R2)
+        and then not Is_Formal (Entity (R1))
+        and then not Is_Formal (Entity (R2));
+   end Statically_Different;
+
+   -----------------------------
+   -- Subprogram_Access_Level --
+   -----------------------------
+
+   function Subprogram_Access_Level (Subp : Entity_Id) return Uint is
+   begin
+      if Present (Alias (Subp)) then
+         return Subprogram_Access_Level (Alias (Subp));
+      else
+         return Scope_Depth (Enclosing_Dynamic_Scope (Subp));
+      end if;
+   end Subprogram_Access_Level;
+
+   -----------------
+   -- Trace_Scope --
+   -----------------
+
+   procedure Trace_Scope (N : Node_Id; E : Entity_Id; Msg : String) is
+   begin
+      if Debug_Flag_W then
+         for J in 0 .. Scope_Stack.Last loop
+            Write_Str ("  ");
+         end loop;
+
+         Write_Str (Msg);
+         Write_Name (Chars (E));
+         Write_Str ("   line ");
+         Write_Int (Int (Get_Logical_Line_Number (Sloc (N))));
+         Write_Eol;
+      end if;
+   end Trace_Scope;
+
+   -----------------------
+   -- Transfer_Entities --
+   -----------------------
+
+   procedure Transfer_Entities (From : Entity_Id; To : Entity_Id) is
+      Ent      : Entity_Id := First_Entity (From);
+
+   begin
+      if No (Ent) then
+         return;
+      end if;
+
+      if (Last_Entity (To)) = Empty then
+         Set_First_Entity (To, Ent);
+      else
+         Set_Next_Entity (Last_Entity (To), Ent);
+      end if;
+
+      Set_Last_Entity (To, Last_Entity (From));
+
+      while Present (Ent) loop
+         Set_Scope (Ent, To);
+
+         if not Is_Public (Ent) then
+            Set_Public_Status (Ent);
+
+            if Is_Public (Ent)
+              and then Ekind (Ent) = E_Record_Subtype
+
+            then
+               --  The components of the propagated Itype must be public
+               --  as well.
+
+               declare
+                  Comp : Entity_Id;
+
+               begin
+                  Comp := First_Entity (Ent);
+
+                  while Present (Comp) loop
+                     Set_Is_Public (Comp);
+                     Next_Entity (Comp);
+                  end loop;
+               end;
+            end if;
+         end if;
+
+         Next_Entity (Ent);
+      end loop;
+
+      Set_First_Entity (From, Empty);
+      Set_Last_Entity (From, Empty);
+   end Transfer_Entities;
+
+   -----------------------
+   -- Type_Access_Level --
+   -----------------------
+
+   function Type_Access_Level (Typ : Entity_Id) return Uint is
+      Btyp : Entity_Id := Base_Type (Typ);
+
+   begin
+      --  If the type is an anonymous access type we treat it as being
+      --  declared at the library level to ensure that names such as
+      --  X.all'access don't fail static accessibility checks.
+
+      if Ekind (Btyp) in Access_Kind then
+         if Ekind (Btyp) = E_Anonymous_Access_Type then
+            return Scope_Depth (Standard_Standard);
+         end if;
+
+         Btyp := Root_Type (Btyp);
+      end if;
+
+      return Scope_Depth (Enclosing_Dynamic_Scope (Btyp));
+   end Type_Access_Level;
+
+   --------------------------
+   -- Unit_Declaration_Node --
+   --------------------------
+
+   function Unit_Declaration_Node (Unit_Id : Entity_Id) return Node_Id is
+      N : Node_Id := Parent (Unit_Id);
+
+   begin
+      --  Predefined operators do not have a full function declaration.
+
+      if Ekind (Unit_Id) = E_Operator then
+         return N;
+      end if;
+
+      while Nkind (N) /= N_Abstract_Subprogram_Declaration
+        and then Nkind (N) /= N_Formal_Package_Declaration
+        and then Nkind (N) /= N_Formal_Subprogram_Declaration
+        and then Nkind (N) /= N_Function_Instantiation
+        and then Nkind (N) /= N_Generic_Package_Declaration
+        and then Nkind (N) /= N_Generic_Subprogram_Declaration
+        and then Nkind (N) /= N_Package_Declaration
+        and then Nkind (N) /= N_Package_Body
+        and then Nkind (N) /= N_Package_Instantiation
+        and then Nkind (N) /= N_Package_Renaming_Declaration
+        and then Nkind (N) /= N_Procedure_Instantiation
+        and then Nkind (N) /= N_Subprogram_Declaration
+        and then Nkind (N) /= N_Subprogram_Body
+        and then Nkind (N) /= N_Subprogram_Body_Stub
+        and then Nkind (N) /= N_Subprogram_Renaming_Declaration
+        and then Nkind (N) /= N_Task_Body
+        and then Nkind (N) /= N_Task_Type_Declaration
+        and then Nkind (N) not in N_Generic_Renaming_Declaration
+      loop
+         N := Parent (N);
+         pragma Assert (Present (N));
+      end loop;
+
+      return N;
+   end Unit_Declaration_Node;
+
+   ----------------------
+   -- Within_Init_Proc --
+   ----------------------
+
+   function Within_Init_Proc return Boolean is
+      S : Entity_Id;
+
+   begin
+      S := Current_Scope;
+      while not Is_Overloadable (S) loop
+         if S = Standard_Standard then
+            return False;
+         else
+            S := Scope (S);
+         end if;
+      end loop;
+
+      return Chars (S) = Name_uInit_Proc;
+   end Within_Init_Proc;
+
+   ----------------
+   -- Wrong_Type --
+   ----------------
+
+   procedure Wrong_Type (Expr : Node_Id; Expected_Type : Entity_Id) is
+      Found_Type : constant Entity_Id := First_Subtype (Etype (Expr));
+      Expec_Type : constant Entity_Id := First_Subtype (Expected_Type);
+
+      function Has_One_Matching_Field return Boolean;
+      --  Determines whether Expec_Type is a record type with a single
+      --  component or discriminant whose type matches the found type or
+      --  is a one dimensional array whose component type matches the
+      --  found type.
+
+      function Has_One_Matching_Field return Boolean is
+         E : Entity_Id;
+
+      begin
+         if Is_Array_Type (Expec_Type)
+           and then Number_Dimensions (Expec_Type) = 1
+           and then
+             Covers (Etype (Component_Type (Expec_Type)), Found_Type)
+         then
+            return True;
+
+         elsif not Is_Record_Type (Expec_Type) then
+            return False;
+
+         else
+            E := First_Entity (Expec_Type);
+
+            loop
+               if No (E) then
+                  return False;
+
+               elsif (Ekind (E) /= E_Discriminant
+                       and then Ekind (E) /= E_Component)
+                 or else (Chars (E) = Name_uTag
+                           or else Chars (E) = Name_uParent)
+               then
+                  Next_Entity (E);
+
+               else
+                  exit;
+               end if;
+            end loop;
+
+            if not Covers (Etype (E), Found_Type) then
+               return False;
+
+            elsif Present (Next_Entity (E)) then
+               return False;
+
+            else
+               return True;
+            end if;
+         end if;
+      end Has_One_Matching_Field;
+
+   --  Start of processing for Wrong_Type
+
+   begin
+      --  Don't output message if either type is Any_Type, or if a message
+      --  has already been posted for this node. We need to do the latter
+      --  check explicitly (it is ordinarily done in Errout), because we
+      --  are using ! to force the output of the error messages.
+
+      if Expec_Type = Any_Type
+        or else Found_Type = Any_Type
+        or else Error_Posted (Expr)
+      then
+         return;
+
+      --  In  an instance, there is an ongoing problem with completion of
+      --  type derived from private types. Their structure is what Gigi
+      --  expects, but the  Etype is the parent type rather than the
+      --  derived private type itself. Do not flag error in this case. The
+      --  private completion is an entity without a parent, like an Itype.
+      --  Similarly, full and partial views may be incorrect in the instance.
+      --  There is no simple way to insure that it is consistent ???
+
+      elsif In_Instance then
+
+         if Etype (Etype (Expr)) = Etype (Expected_Type)
+           and then No (Parent (Expected_Type))
+         then
+            return;
+         end if;
+      end if;
+
+      --  An interesting special check. If the expression is parenthesized
+      --  and its type corresponds to the type of the sole component of the
+      --  expected record type, or to the component type of the expected one
+      --  dimensional array type, then assume we have a bad aggregate attempt.
+
+      if Nkind (Expr) in N_Subexpr
+        and then Paren_Count (Expr) /= 0
+        and then Has_One_Matching_Field
+      then
+         Error_Msg_N ("positional aggregate cannot have one component", Expr);
+
+      --  Another special check, if we are looking for a pool-specific access
+      --  type and we found an E_Access_Attribute_Type, then we have the case
+      --  of an Access attribute being used in a context which needs a pool-
+      --  specific type, which is never allowed. The one extra check we make
+      --  is that the expected designated type covers the Found_Type.
+
+      elsif Is_Access_Type (Expec_Type)
+        and then Ekind (Found_Type) = E_Access_Attribute_Type
+        and then Ekind (Base_Type (Expec_Type)) /= E_General_Access_Type
+        and then Ekind (Base_Type (Expec_Type)) /= E_Anonymous_Access_Type
+        and then Covers
+          (Designated_Type (Expec_Type), Designated_Type (Found_Type))
+      then
+         Error_Msg_N ("result must be general access type!", Expr);
+         Error_Msg_NE ("add ALL to }!", Expr, Expec_Type);
+
+      --  If the expected type is an anonymous access type, as for access
+      --  parameters and discriminants, the error is on the designated types.
+
+      elsif Ekind (Expec_Type) = E_Anonymous_Access_Type then
+         if Comes_From_Source (Expec_Type) then
+            Error_Msg_NE ("expected}!", Expr, Expec_Type);
+         else
+            Error_Msg_NE
+              ("expected an access type with designated}",
+                 Expr, Designated_Type (Expec_Type));
+         end if;
+
+         if Is_Access_Type (Found_Type)
+           and then not Comes_From_Source (Found_Type)
+         then
+            Error_Msg_NE
+              ("found an access type with designated}!",
+                Expr, Designated_Type (Found_Type));
+         else
+            if From_With_Type (Found_Type) then
+               Error_Msg_NE ("found incomplete}!", Expr, Found_Type);
+               Error_Msg_NE
+                 ("\possibly missing with_clause on&", Expr,
+                   Scope (Found_Type));
+            else
+               Error_Msg_NE ("found}!", Expr, Found_Type);
+            end if;
+         end if;
+
+      --  Normal case of one type found, some other type expected
+
+      else
+         --  If the names of the two types are the same, see if some
+         --  number of levels of qualification will help. Don't try
+         --  more than three levels, and if we get to standard, it's
+         --  no use (and probably represents an error in the compiler)
+         --  Also do not bother with internal scope names.
+
+         declare
+            Expec_Scope : Entity_Id;
+            Found_Scope : Entity_Id;
+
+         begin
+            Expec_Scope := Expec_Type;
+            Found_Scope := Found_Type;
+
+            for Levels in Int range 0 .. 3 loop
+               if Chars (Expec_Scope) /= Chars (Found_Scope) then
+                  Error_Msg_Qual_Level := Levels;
+                  exit;
+               end if;
+
+               Expec_Scope := Scope (Expec_Scope);
+               Found_Scope := Scope (Found_Scope);
+
+               exit when Expec_Scope = Standard_Standard
+                           or else
+                         Found_Scope = Standard_Standard
+                           or else
+                         not Comes_From_Source (Expec_Scope)
+                           or else
+                         not Comes_From_Source (Found_Scope);
+            end loop;
+         end;
+
+         Error_Msg_NE ("expected}!", Expr, Expec_Type);
+
+         if Is_Entity_Name (Expr)
+           and then Is_Package (Entity (Expr))
+         then
+            Error_Msg_N ("found package name!", Expr);
+
+         elsif Is_Entity_Name (Expr)
+           and then
+             (Ekind (Entity (Expr)) = E_Procedure
+                or else
+              Ekind (Entity (Expr)) = E_Generic_Procedure)
+         then
+            Error_Msg_N ("found procedure name instead of function!", Expr);
+
+         --  catch common error: a prefix or infix operator which is not
+         --  directly visible because the type isn't.
+
+         elsif Nkind (Expr) in N_Op
+            and then Is_Overloaded (Expr)
+            and then not Is_Immediately_Visible (Expec_Type)
+            and then not Is_Potentially_Use_Visible (Expec_Type)
+            and then not In_Use (Expec_Type)
+            and then Has_Compatible_Type (Right_Opnd (Expr), Expec_Type)
+         then
+            Error_Msg_N (
+              "operator of the type is not directly visible!", Expr);
+
+         else
+            Error_Msg_NE ("found}!", Expr, Found_Type);
+         end if;
+
+         Error_Msg_Qual_Level := 0;
+      end if;
+   end Wrong_Type;
+
+end Sem_Util;
diff --git a/gcc/ada/sem_util.ads b/gcc/ada/sem_util.ads
new file mode 100644 (file)
index 0000000..2d49394
--- /dev/null
@@ -0,0 +1,698 @@
+------------------------------------------------------------------------------
+--                                                                          --
+--                         GNAT COMPILER COMPONENTS                         --
+--                                                                          --
+--                             S E M _ U T I L                              --
+--                                                                          --
+--                                 S p e c                                  --
+--                                                                          --
+--                            $Revision: 1.225 $
+--                                                                          --
+--          Copyright (C) 1992-2001, 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- --
+-- ware  Foundation;  either version 2,  or (at your option) any later ver- --
+-- sion.  GNAT is distributed in the hope that it will be useful, but WITH- --
+-- OUT ANY WARRANTY;  without even the  implied warranty of MERCHANTABILITY --
+-- or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License --
+-- for  more details.  You should have  received  a copy of the GNU General --
+-- Public License  distributed with GNAT;  see file COPYING.  If not, write --
+-- to  the Free Software Foundation,  59 Temple Place - Suite 330,  Boston, --
+-- MA 02111-1307, USA.                                                      --
+--                                                                          --
+-- GNAT was originally developed  by the GNAT team at  New York University. --
+-- It is now maintained by Ada Core Technologies Inc (http://www.gnat.com). --
+--                                                                          --
+------------------------------------------------------------------------------
+
+--  Package containing utility procedures used throughout the semantics
+
+with Einfo;  use Einfo;
+with Types;  use Types;
+with Uintp;  use Uintp;
+with Urealp; use Urealp;
+
+package Sem_Util is
+
+   procedure Add_Access_Type_To_Process (E : Entity_Id; A : Entity_Id);
+   --  Add A to the list of access types to process when expanding the
+   --  freeze node of E.
+
+   function Alignment_In_Bits (E : Entity_Id) return Uint;
+   --  If the alignment of the type or object E is currently known to the
+   --  compiler, then this function returns the alignment value in bits.
+   --  Otherwise Uint_0 is returned, indicating that the alignment of the
+   --  entity is not yet known to the compiler.
+
+   procedure Apply_Compile_Time_Constraint_Error
+     (N   : Node_Id;
+      Msg : String;
+      Ent : Entity_Id  := Empty;
+      Typ : Entity_Id  := Empty;
+      Loc : Source_Ptr := No_Location;
+      Rep : Boolean    := True);
+   --  N is a subexpression which will raise constraint error when evaluated
+   --  at runtime. Msg is a message that explains the reason for raising the
+   --  exception. The last character is ? if the message is always a
+   --  warning, even in Ada 95, and is not a ? if the message represents an
+   --  illegality (because of violation of static expression rules) in Ada 95
+   --  (but not in Ada 83). Typically this routine posts all messages at
+   --  the Sloc of node N. However, if Loc /= No_Location, Loc is the Sloc
+   --  used to output the message. After posting the appropriate message,
+   --  and if the flag Rep is set, this routine replaces the expression
+   --  with an N_Raise_Constraint_Error node. This node is then marked as
+   --  being static if the original node is static, but sets the flag
+   --  Raises_Constraint_Error, preventing further evaluation.
+   --  The error message may contain a } or & insertion character.
+   --  This normally references Etype (N), unless the Ent argument is given
+   --  explicitly, in which case it is used instead. The type of the raise
+   --  node that is built is normally Etype (N), but if the Typ parameter
+   --  is present, this is used instead.
+
+   function Build_Actual_Subtype
+     (T    : Entity_Id;
+      N    : Node_Or_Entity_Id)
+      return Node_Id;
+   --  Build an anonymous subtype for an entity or expression, using the
+   --  bounds of the entity or the discriminants of the enclosing record.
+   --  T is the type for which the actual subtype is required, and N is either
+   --  a defining identifier, or any subexpression.
+
+   function Build_Actual_Subtype_Of_Component
+     (T    : Entity_Id;
+      N    : Node_Id)
+      return Node_Id;
+   --  Determine whether a selected component has a type that depends on
+   --  discriminants, and build actual subtype for it if so.
+
+   function Build_Discriminal_Subtype_Of_Component
+     (T    : Entity_Id)
+      return Node_Id;
+   --  Determine whether a record component has a type that depends on
+   --  discriminants, and build actual subtype for it if so.
+
+   procedure Build_Elaboration_Entity (N : Node_Id; Spec_Id : Entity_Id);
+   --  Given a compilation unit node N, allocate an elaboration boolean for
+   --  the compilation unit, and install it in the Elaboration_Entity field
+   --  of Spec_Id, the entity for the compilation unit.
+
+   procedure Check_Fully_Declared (T : Entity_Id; N : Node_Id);
+   --  Verify that the full declaration of type T has been seen. If not,
+   --  place error message on node N. Used in  object declarations, type
+   --  conversions, qualified expressions.
+
+   procedure Check_Potentially_Blocking_Operation (N : Node_Id);
+   --  N is one of the statement forms that is a potentially blocking
+   --  operation. If it appears within a protected action, emit warning
+   --  and raise Program_Error.
+
+   procedure Check_VMS (Construct : Node_Id);
+   --  Check that this the target is OpenVMS, and if so, return with
+   --  no effect, otherwise post an error noting this can only be used
+   --  with OpenVMS ports. The argument is the construct in question
+   --  and is used to post the error message.
+
+   function Collect_Primitive_Operations (T : Entity_Id) return Elist_Id;
+   --  Called upon type derivation and extension. We scan the declarative
+   --  part in  which the type appears, and collect subprograms that have
+   --  one subsidiary subtype of the type. These subprograms can only
+   --  appear after the type itself.
+
+   function Compile_Time_Constraint_Error
+     (N    : Node_Id;
+      Msg  : String;
+      Ent  : Entity_Id  := Empty;
+      Loc  : Source_Ptr := No_Location)
+      return Node_Id;
+   --  Subsidiary to Apply_Compile_Time_Constraint_Error and Checks routines.
+   --  Does not modify any nodes, but generates a warning (or error) message.
+   --  For convenience, the function always returns its first argument.
+
+   procedure Conditional_Delay (New_Ent, Old_Ent : Entity_Id);
+   --  Sets the Has_Delayed_Freeze flag of New if the Delayed_Freeze flag
+   --  of Old is set and Old has no yet been Frozen (i.e. Is_Frozen is false);
+
+   function Current_Entity (N : Node_Id) return Entity_Id;
+   --  Find the currently visible definition for a given identifier, that is to
+   --  say the first entry in the visibility chain for the Chars of N.
+
+   function Current_Entity_In_Scope (N : Node_Id) return Entity_Id;
+   --  Find whether there is a previous definition for identifier N in the
+   --  current scope. Because declarations for a scope are not necessarily
+   --  contiguous (e.g. for packages) the first entry on the visibility chain
+   --  for N is not necessarily in the current scope.
+
+   function Current_Scope return Entity_Id;
+   --  Get entity representing current scope
+
+   function Current_Subprogram return Entity_Id;
+   --  Returns current enclosing subprogram. If Current_Scope is a subprogram,
+   --  then that is what is returned, otherwise the Enclosing_Subprogram of
+   --  the Current_Scope is returned. The returned value is Empty if this
+   --  is called from a library package which is not within any subprogram.
+
+   function Defining_Entity (N : Node_Id) return Entity_Id;
+   --  Given a declaration N, returns the associated defining entity. If
+   --  the declaration has a specification, the entity is obtained from
+   --  the specification. If the declaration has a defining unit name,
+   --  then the defining entity is obtained from the defining unit name
+   --  ignoring any child unit prefixes.
+
+   function Denotes_Discriminant (N : Node_Id) return Boolean;
+   --  Returns True if node N is an N_Identifier node for a discriminant.
+   --  Returns False for any other kind of node, or for an N_Identifier
+   --  node that does not denote a discriminant.
+
+   function Depends_On_Discriminant (N : Node_Id) return Boolean;
+   --  Returns True if N denotes a discriminant or if N is a range, a subtype
+   --  indication or a scalar subtype where one of the bounds is a
+   --  discriminant.
+
+   function Designate_Same_Unit
+     (Name1 : Node_Id;
+      Name2 : Node_Id)
+      return  Boolean;
+   --  Return true if Name1 and Name2 designate the same unit name;
+   --  each of these names is supposed to be a selected component name,
+   --  an expanded name, a defining program unit name or an identifier
+
+   function Enclosing_Generic_Body
+     (E    : Entity_Id)
+      return Node_Id;
+   --  Returns the Node_Id associated with the innermost enclosing
+   --  generic body, if any. If none, then returns Empty.
+
+   function Enclosing_Lib_Unit_Entity return Entity_Id;
+   --  Returns the entity of enclosing N_Compilation_Unit Node which is the
+   --  root of the current scope (which must not be Standard_Standard, and
+   --  the caller is responsible for ensuring this condition).
+
+   function Enclosing_Lib_Unit_Node (N : Node_Id) return Node_Id;
+   --  Returns the enclosing N_Compilation_Unit Node that is the root
+   --  of a subtree containing N.
+
+   function Enclosing_Subprogram (E : Entity_Id) return Entity_Id;
+   --  Utility function to return the Ada entity of the subprogram enclosing
+   --  the entity E, if any. Returns Empty if no enclosing subprogram.
+
+   procedure Ensure_Freeze_Node (E : Entity_Id);
+   --  Make sure a freeze node is allocated for entity E. If necessary,
+   --  build and initialize a new freeze node and set Has_Delayed_Freeze
+   --  true for entity E.
+
+   procedure Enter_Name (Def_Id : Node_Id);
+   --  Insert new name in symbol table of current scope with check for
+   --  duplications (error message is issued if a conflict is found)
+   --  Note: Enter_Name is not used for overloadable entities, instead
+   --  these are entered using Sem_Ch6.Enter_Overloadable_Entity.
+
+   function Find_Corresponding_Discriminant
+     (Id   : Node_Id;
+      Typ  : Entity_Id)
+      return Entity_Id;
+   --  Because discriminants may have different names in a generic unit
+   --  and in an instance, they are resolved positionally when possible.
+   --  A reference to a discriminant carries the discriminant that it
+   --  denotes when analyzed. Subsequent uses of this id on a different
+   --  type denote the discriminant at the same position in this new type.
+
+   function First_Actual (Node : Node_Id) return Node_Id;
+   --  Node is an N_Function_Call or N_Procedure_Call_Statement node. The
+   --  result returned is the first actual parameter in declaration order
+   --  (not the order of parameters as they appeared in the source, which
+   --  can be quite different as a result of the use of named parameters).
+   --  Empty is returned for a call with no parameters. The procedure for
+   --  iterating through the actuals in declaration order is to use this
+   --  function to find the first actual, and then use Next_Actual to obtain
+   --  the next actual in declaration order. Note that the value returned
+   --  is always the expression (not the N_Parameter_Association nodes
+   --  even if named association is used).
+
+   function Full_Qualified_Name (E : Entity_Id) return String_Id;
+   --  Generates the string literal corresponding to the E's full qualified
+   --  name in upper case. An ASCII.NUL is appended as the last character
+
+   procedure Gather_Components
+     (Typ           : Entity_Id;
+      Comp_List     : Node_Id;
+      Governed_By   : List_Id;
+      Into          : Elist_Id;
+      Report_Errors : out Boolean);
+   --  The purpose of this procedure is to gather the valid components
+   --  in a record type according to the values of its discriminants, in order
+   --  to validate the components of a record aggregate.
+   --
+   --    Typ is the type of the aggregate when its constrained discriminants
+   --      need to be collected, otherwise it is Empty.
+   --
+   --    Comp_List is an N_Component_List node.
+   --
+   --    Governed_By is a list of N_Component_Association nodes,
+   --     where each choice list contains the name of a discriminant and
+   --     the expression field gives its value. The values of the
+   --     discriminants governing the (possibly nested) variant parts in
+   --     Comp_List are found in this Component_Association List.
+   --
+   --    Into is the list where the valid components are appended.
+   --     Note that Into need not be an Empty list. If it's not, components
+   --     are attached to its tail.
+   --
+   --    Report_Errors is set to True if the values of the discriminants
+   --     are non-static.
+
+   --  This procedure is also used when building a record subtype. If the
+   --  discriminant constraint of the subtype is static, the components of the
+   --  subtype are only those of the variants selected by the values of the
+   --  discriminants. Otherwise all components of the parent must be included
+   --  in the subtype for semantic analysis.
+
+   function Get_Actual_Subtype (N : Node_Id) return Entity_Id;
+   --  Given a node for an expression, obtain the actual subtype of the
+   --  expression. In the case of a parameter where the formal is an
+   --  unconstrained array or discriminated type, this will be the
+   --  previously constructed subtype of the actual. Note that this is
+   --  not quite the "Actual Subtype" of the RM, since it is always
+   --  a constrained type, i.e. it is the subtype of the value of the
+   --  actual. The actual subtype is also returned in other cases where
+   --  it has already been constructed for an object. Otherwise the
+   --  expression type is returned unchanged, except for the case of an
+   --  unconstrained array type, where an actual subtype is created, using
+   --  Insert_Actions if necessary to insert any associated actions.
+
+   function Get_Actual_Subtype_If_Available (N : Node_Id) return Entity_Id;
+   --  This is like Get_Actual_Subtype, except that it never constructs an
+   --  actual subtype. If an actual subtype is already available, i.e. the
+   --  Actual_Subtype field of the corresponding entity is set, then it is
+   --  returned. Otherwise the Etype of the node is returned.
+
+   function Get_Default_External_Name (E : Node_Or_Entity_Id) return Node_Id;
+   --  This is used to construct the string literal node representing a
+   --  default external name, i.e. one that is constructed from the name
+   --  of an entity, or (in the case of extended DEC import/export pragmas,
+   --  an identifier provided as the external name. Letters in the name are
+   --  according to the setting of Opt.External_Name_Default_Casing.
+
+   procedure Get_Index_Bounds (N : Node_Id; L, H : out Node_Id);
+   --  This procedure assigns to L and H respectively the values of the
+   --  low and high bounds of node N, which must be a range, subtype
+   --  indication, or the name of a scalar subtype. The result in L, H
+   --  may be set to Error if there was an earlier error in the range.
+
+   function Get_Enum_Lit_From_Pos
+     (T    : Entity_Id;
+      Pos  : Uint;
+      Loc  : Source_Ptr)
+      return Entity_Id;
+   --  This function obtains the E_Enumeration_Literal entity for the
+   --  specified value from the enumneration type or subtype T. The
+   --  second argument is the Pos value, which is assumed to be in range.
+   --  The third argument supplies a source location for constructed
+   --  nodes returned by this function.
+
+   function Get_Name_Entity_Id (Id : Name_Id) return Entity_Id;
+   --  An entity value is associated with each name in the name table. The
+   --  Get_Name_Entity_Id function fetches the Entity_Id of this entity,
+   --  which is the innermost visible entity with the given name. See the
+   --  body of Sem_Ch8 for further details on handling of entity visibility.
+
+   function Get_Referenced_Object (N : Node_Id) return Node_Id;
+   --  Given a node, return the renamed object if the node represents
+   --  a renamed object, otherwise return the node unchanged. The node
+   --  may represent an arbitrary expression.
+
+   function Get_Subprogram_Body (E : Entity_Id) return Node_Id;
+   --  Given the entity for a subprogram (E_Function or E_Procedure),
+   --  return the corresponding N_Subprogram_Body node. If the corresponding
+   --  body of the declaration is missing (as for an imported subprogram)
+   --  return Empty.
+
+   function Get_Task_Body_Procedure (E : Entity_Id) return Node_Id;
+   pragma Inline (Get_Task_Body_Procedure);
+   --  Given an entity for a task type or subtype, retrieves the
+   --  Task_Body_Procedure field from the corresponding task type
+   --  declaration.
+
+   function Has_Infinities (E : Entity_Id) return Boolean;
+   --  Determines if the range of the floating-point type E includes
+   --  infinities. Returns False if E is not a floating-point type.
+
+   function Has_Private_Component (Type_Id : Entity_Id) return Boolean;
+   --  Check if a type has a (sub)component of a private type that has not
+   --  yet received a full declaration.
+
+   function Has_Tagged_Component (Typ : Entity_Id) return Boolean;
+   --  Typ must be a composite type (array or record). This function is used
+   --  to check if '=' has to be expanded into a bunch component comparaisons.
+
+   function In_Instance return Boolean;
+   --  Returns True if the current scope is within a generic instance.
+
+   function In_Instance_Body return Boolean;
+   --  Returns True if current scope is within the body of an instance, where
+   --  several semantic checks (e.g. accessibility checks) are relaxed.
+
+   function In_Instance_Not_Visible return Boolean;
+   --  Returns True if current scope is with the private part or the body of
+   --  an instance. Other semantic checks are suppressed in this context.
+
+   function In_Instance_Visible_Part return Boolean;
+   --  Returns True if current scope is within the visible part of a package
+   --  instance, where several additional semantic checks apply.
+
+   function In_Subprogram_Or_Concurrent_Unit return Boolean;
+   --  Determines if the current scope is within a subprogram compilation
+   --  unit (inside a subprogram declaration, subprogram body, or generic
+   --  subprogram declaration) or within a task or protected body. The test
+   --  is for appearing anywhere within such a construct (that is it does not
+   --  need to be directly within).
+
+   function In_Visible_Part (Scope_Id : Entity_Id) return Boolean;
+   --  Determine whether a declaration occurs within the visible part of a
+   --  package specification. The package must be on the scope stack, and the
+   --  corresponding private part must not.
+
+   function Is_AAMP_Float (E : Entity_Id) return Boolean;
+   --  Defined for all type entities. Returns True only for the base type
+   --  of float types with AAMP format. The particular format is determined
+   --  by the Digits_Value value which is 6 for the 32-bit floating point type,
+   --  or 9 for the 48-bit type. This is not an attribute function (like
+   --  VAX_Float) in order to not use up an extra flag and to prevent
+   --  the dependency of Einfo on Targparm which would be required for a
+   --  synthesized attribute.
+
+   function Is_Dependent_Component_Of_Mutable_Object
+     (Object : Node_Id)
+      return   Boolean;
+   --  Returns True if Object is the name of a subcomponent that
+   --  depends on discriminants of a variable whose nominal subtype
+   --  is unconstrained and not indefinite, and the variable is
+   --  not aliased.  Otherwise returns False.  The nodes passed
+   --  to this function are assumed to denote objects.
+
+   function Is_Actual_Parameter (N : Node_Id) return Boolean;
+   --  Determines if N is an actual parameter in a subprogram call.
+
+   function Is_Aliased_View (Obj : Node_Id) return Boolean;
+   --  Determine if Obj is an aliased view, i.e. the name of an
+   --  object to which 'Access or 'Unchecked_Access can apply.
+
+   function Is_Atomic_Object (N : Node_Id) return Boolean;
+   --  Determines if the given node denotes an atomic object in the sense
+   --  of the legality checks described in RM C.6(12).
+
+   function Is_False (U : Uint) return Boolean;
+   --  The argument is a Uint value which is the Boolean'Pos value of a
+   --  Boolean operand (i.e. is either 0 for False, or 1 for True). This
+   --  function simply tests if it is False (i.e. zero)
+
+   function Is_Fixed_Model_Number (U : Ureal; T : Entity_Id) return Boolean;
+   --  Returns True iff the number U is a model number of the fixed-
+   --  point type T, i.e. if it is an exact multiple of Small.
+
+   function Is_Fully_Initialized_Type (Typ : Entity_Id) return Boolean;
+   --  Typ is a type entity. This function returns true if this type is
+   --  fully initialized, meaning that an object of the type is fully
+   --  initialized. Note that initialization resulting from the use of
+   --  pragma Normalized_Scalars does not count.
+
+   function Is_Inherited_Operation (E : Entity_Id) return Boolean;
+   --  E is a subprogram. Return True is E is an implicit operation inherited
+   --  by a derived type declarations.
+
+   function Is_Library_Level_Entity (E : Entity_Id) return Boolean;
+   --  A library-level declaration is one that is accessible from Standard,
+   --  i.e. a library unit or an entity declared in a library package.
+
+   function Is_Local_Variable_Reference (Expr : Node_Id) return Boolean;
+   --  Determines whether Expr is a refeference to a variable or IN OUT
+   --  mode parameter of the current enclosing subprogram.
+
+   function Is_Object_Reference (N : Node_Id) return Boolean;
+   --  Determines if the tree referenced by N represents an object. Both
+   --  variable and constant objects return True (compare Is_Variable).
+
+   function Is_OK_Variable_For_Out_Formal (AV : Node_Id) return Boolean;
+   --  Used to test if AV is an acceptable formal for an OUT or IN OUT
+   --  formal. Note that the Is_Variable function is not quite the right
+   --  test because this is a case in which conversions whose expression
+   --  is a variable (in the Is_Variable sense) with a non-tagged type
+   --  target are considered view conversions and hence variables.
+
+   function Is_RCI_Pkg_Spec_Or_Body (Cunit : Node_Id) return Boolean;
+   --  Return True if a compilation unit is the specification or the
+   --  body of a remote call interface package.
+
+   function Is_Remote_Access_To_Class_Wide_Type (E : Entity_Id) return Boolean;
+   --  Return True if E is a remote access-to-class-wide-limited_private type
+
+   function Is_Remote_Access_To_Subprogram_Type (E : Entity_Id) return Boolean;
+   --  Return True if E is a remote access to subprogram type.
+
+   function Is_Remote_Call (N : Node_Id) return Boolean;
+   --  Return True if N denotes a potentially remote call
+
+   function Is_Selector_Name (N : Node_Id) return Boolean;
+   --  Given an N_Identifier node N, determines if it is a Selector_Name.
+   --  As described in Sinfo, Selector_Names are special because they
+   --  represent use of the N_Identifier node for a true identifer, when
+   --  normally such nodes represent a direct name.
+
+   function Is_Statement (N : Node_Id) return Boolean;
+   --  Check if the node N is a statement node. Note that this includes
+   --  the case of procedure call statements (unlike the direct use of
+   --  the N_Statement_Other_Than_Procedure_Call subtype from Sinfo)
+
+   function Is_Transfer (N : Node_Id) return Boolean;
+   --  Returns True if the node N is a statement which is known to cause
+   --  an unconditional transfer of control at runtime, i.e. the following
+   --  statement definitely will not be executed.
+
+   function Is_True (U : Uint) return Boolean;
+   --  The argument is a Uint value which is the Boolean'Pos value of a
+   --  Boolean operand (i.e. is either 0 for False, or 1 for True). This
+   --  function simply tests if it is True (i.e. non-zero)
+
+   function Is_Variable (N : Node_Id) return Boolean;
+   --  Determines if the tree referenced by N represents a variable, i.e.
+   --  can appear on the left side of an assignment. There is one situation,
+   --  namely formal parameters, in which non-tagged type conversions are
+   --  also considered variables, but Is_Variable returns False for such
+   --  cases, since it has no knowledge of the context. Note that this is
+   --  the point at which Assignment_OK is checked, and True is returned
+   --  for any tree thus marked.
+
+   function Is_Volatile_Object (N : Node_Id) return Boolean;
+   --  Determines if the given node denotes an volatile object in the sense
+   --  of the legality checks described in RM C.6(12).
+
+   procedure Kill_Size_Check_Code (E : Entity_Id);
+   --  Called when an address clause or pragma Import is applied to an
+   --  entity. If the entity is a variable or a constant, and size check
+   --  code is present, this size check code is killed, since the object
+   --  will not be allocated by the program.
+
+   function New_External_Entity
+     (Kind         : Entity_Kind;
+      Scope_Id     : Entity_Id;
+      Sloc_Value   : Source_Ptr;
+      Related_Id   : Entity_Id;
+      Suffix       : Character;
+      Suffix_Index : Nat := 0;
+      Prefix       : Character := ' ')
+      return         Entity_Id;
+   --  This function creates an N_Defining_Identifier node for an internal
+   --  created entity, such as an implicit type or subtype, or a record
+   --  initialization procedure. The entity name is constructed with a call
+   --  to New_External_Name (Related_Id, Suffix, Suffix_Index, Prefix), so
+   --  that the generated name may be referenced as a public entry, and the
+   --  Is_Public flag is set if needed (using Set_Public_Status). If the
+   --  entity is for a type or subtype, the size/align fields are initialized
+   --  to unknown (Uint_0).
+
+   function New_Internal_Entity
+     (Kind       : Entity_Kind;
+      Scope_Id   : Entity_Id;
+      Sloc_Value : Source_Ptr;
+      Id_Char    : Character)
+      return       Entity_Id;
+   --  This function is similar to New_External_Entity, except that the
+   --  name is constructed by New_Internal_Name (Id_Char). This is used
+   --  when the resulting entity does not have to be referenced as a
+   --  public entity (and in this case Is_Public is not set).
+
+   procedure Next_Actual (Actual_Id : in out Node_Id);
+   pragma Inline (Next_Actual);
+   --  Next_Actual (N) is equivalent to N := Next_Actual (N)
+
+   function Next_Actual (Actual_Id : Node_Id) return Node_Id;
+   --  Find next actual parameter in declaration order. As described for
+   --  First_Actual, this is the next actual in the declaration order, not
+   --  the call order, so this does not correspond to simply taking the
+   --  next entry of the Parameter_Associations list. The argument is an
+   --  actual previously returned by a call to First_Actual or Next_Actual.
+   --  Note tha the result produced is always an expression, not a parameter
+   --  assciation node, even if named notation was used.
+
+   procedure Normalize_Actuals
+     (N       : Node_Id;
+      S       : Entity_Id;
+      Report  : Boolean;
+      Success : out Boolean);
+   --  Reorders lists of actuals according to names of formals, value returned
+   --  in Success indicates sucess of reordering. For more details, see body.
+   --  Errors are reported only if Report is set to True.
+
+   procedure Note_Possible_Modification (N : Node_Id);
+   --  This routine is called if the sub-expression N maybe the target of
+   --  an assignment (e.g. it is the left side of an assignment, used as
+   --  an out parameters, or used as prefixes of access attributes). It
+   --  sets May_Be_Modified in the associated entity if there is one,
+   --  taking into account the rule that in the case of renamed objects,
+   --  it is the flag in the renamed object that must be set.
+
+   function Object_Access_Level (Obj : Node_Id) return Uint;
+   --  Return the accessibility level of the view of the object Obj.
+   --  For convenience, qualified expressions applied to object names
+   --  are also allowed as actuals for this function.
+
+   function Private_Component (Type_Id : Entity_Id) return Entity_Id;
+   --  Returns some private component (if any) of the given Type_Id.
+   --  Used to enforce the rules on visibility of operations on composite
+   --  types, that depend on the full view of the component type. For a
+   --  record type there may be several such components, we just return
+   --  the first one.
+
+   procedure Process_End_Label (N : Node_Id; Typ : Character);
+   --  N is a node whose End_Label is to be processed, generating all
+   --  appropriate cross-reference entries, and performing style checks
+   --  for any identifier references in the end label. Typ is either
+   --  'e' or 't indicating the type of the cross-reference entity
+   --  (e for spec, t for body, see Lib.Xref spec for details).
+
+   function Real_Convert (S : String) return Node_Id;
+   --  S is a possibly signed syntactically valid real literal. The result
+   --  returned is an N_Real_Literal node representing the literal value.
+
+   function Requires_Transient_Scope (Id : Entity_Id) return Boolean;
+   --  E is a type entity. The result is True when temporaries of this
+   --  type need to be wrapped in a transient scope to be reclaimed
+   --  properly when a secondary stack is in use. Examples of types
+   --  requiring such wrapping are controlled types and variable-sized
+   --  types including unconstrained arrays
+
+   procedure Reset_Analyzed_Flags (N : Node_Id);
+   --  Reset the Analyzed flags in all nodes of the tree whose root is N
+
+   function Same_Name (N1, N2 : Node_Id) return Boolean;
+   --  Determine if two (possibly expanded) names are the same name
+
+   function Same_Type (T1, T2 : Entity_Id) return Boolean;
+   --  Determines if T1 and T2 represent exactly the same type. Two types
+   --  are the same if they are identical, or if one is an unconstrained
+   --  subtype of the other, or they are both common subtypes of the same
+   --  type with identical contraints. The result returned is conservative.
+   --  It is True if the types are known to be the same, but a result of
+   --  False is indecisive (e.g. the compiler may not be able to tell that
+   --  two constraints are identical).
+
+   function Scope_Within_Or_Same (Scope1, Scope2 : Entity_Id) return Boolean;
+   --  Determines if the entity Scope1 is the same as Scope2, or if it is
+   --  inside it, where both entities represent scopes. Note that scopes
+   --  are only partially ordered, so Scope_Within_Or_Same (A,B) and
+   --  Scope_Within_Or_Same (B,A) can both be False for a given pair A,B.
+
+   function Scope_Within (Scope1, Scope2 : Entity_Id) return Boolean;
+   --  Like Scope_Within_Or_Same, except that this function returns
+   --  False in the case where Scope1 and Scope2 are the same scope.
+
+   procedure Set_Current_Entity (E : Entity_Id);
+   --  Establish the entity E as the currently visible definition of its
+   --  associated name (i.e. the Node_Id associated with its name)
+
+   procedure Set_Entity_With_Style_Check (N : Node_Id; Val : Entity_Id);
+   --  This procedure has the same calling sequence as Set_Entity, but
+   --  if Style_Check is set, then it calls a style checking routine which
+   --  can check identifier spelling style.
+
+   procedure Set_Name_Entity_Id (Id : Name_Id; Val : Entity_Id);
+   --  Sets the Entity_Id value associated with the given name, which is the
+   --  Id of the innermost visible entity with the given name. See the body
+   --  of package Sem_Ch8 for further details on the handling of visibility.
+
+   procedure Set_Next_Actual (Ass1_Id : Node_Id; Ass2_Id : Node_Id);
+   --  The arguments may be parameter associations, whose descendants
+   --  are the optional formal name and the actual parameter. Positional
+   --  parameters are already members of a list, and do not need to be
+   --  chained separately. See also First_Actual and Next_Actual.
+
+   procedure Set_Public_Status (Id : Entity_Id);
+   --  If an entity (visible or otherwise) is defined in a library
+   --  package, or a package that is itself public, then this subprogram
+   --  labels the entity public as well.
+
+   procedure Set_Scope_Is_Transient (V : Boolean := True);
+   --  Set the flag Is_Transient of the current scope
+
+   procedure Set_Size_Info (T1, T2 : Entity_Id);
+   --  Copies the Esize field and Has_Biased_Representation flag from
+   --  (sub)type entity T2 to (sub)type entity T1. Also copies the
+   --  Is_Unsigned_Type flag in the fixed-point and discrete cases,
+   --  and also copies the alignment value from T2 to T1. It does NOT
+   --  copy the RM_Size field, which must be separately set if this
+   --  is required to be copied also.
+
+   function Scope_Is_Transient  return Boolean;
+   --  True if the current scope is transient.
+
+   function Static_Integer (N : Node_Id) return Uint;
+   --  This function analyzes the given expression node and then resolves it
+   --  as any integer type. If the result is static, then the value of the
+   --  universal expression is returned, otherwise an error message is output
+   --  and a value of No_Uint is returned.
+
+   function Statically_Different (E1, E2 : Node_Id) return Boolean;
+   --  Return True if it can be statically determined that the Expressions
+   --  E1 and E2 refer to different objects
+
+   function Subprogram_Access_Level (Subp : Entity_Id) return Uint;
+   --  Return the accessibility level of the view denoted by Subp.
+
+   procedure Trace_Scope (N : Node_Id; E : Entity_Id; Msg : String);
+   --  Print debugging information on entry to each unit being analyzed.
+
+   procedure Transfer_Entities (From : Entity_Id; To : Entity_Id);
+   --  Move a list of entities from one scope to another, and recompute
+   --  Is_Public based upon the new scope.
+
+   function Type_Access_Level (Typ : Entity_Id) return Uint;
+   --  Return the accessibility level of Typ.
+
+   function Unit_Declaration_Node (Unit_Id : Entity_Id) return Node_Id;
+   --  Unit_Id is the simple name of a program unit, this function returns
+   --  the corresponding xxx_Declaration node for the entity. Also applies
+   --  to the body entities for subprograms in tasks, in which case it
+   --  returns the subprogram or task body node for it. The unit may be
+   --  a child unit with any number of ancestors.
+
+   function Within_Init_Proc return Boolean;
+   --  Determines if Current_Scope is within an Init_Proc
+
+   procedure Wrong_Type (Expr : Node_Id; Expected_Type : Entity_Id);
+   --  Output error message for incorrectly typed expression. Expr is the
+   --  node for the incorrectly typed construct (Etype (Expr) is the type
+   --  found), and Expected_Type is the entity for the expected type. Note
+   --  that Expr does not have to be a subexpression, anything with an
+   --  Etype field may be used.
+
+private
+   pragma Inline (Current_Entity);
+   pragma Inline (Get_Name_Entity_Id);
+   pragma Inline (Is_False);
+   pragma Inline (Is_Statement);
+   pragma Inline (Is_True);
+   pragma Inline (Set_Current_Entity);
+   pragma Inline (Set_Name_Entity_Id);
+   pragma Inline (Set_Size_Info);
+
+end Sem_Util;
diff --git a/gcc/ada/sem_vfpt.adb b/gcc/ada/sem_vfpt.adb
new file mode 100644 (file)
index 0000000..d4b76d4
--- /dev/null
@@ -0,0 +1,168 @@
+------------------------------------------------------------------------------
+--                                                                          --
+--                         GNAT COMPILER COMPONENTS                         --
+--                                                                          --
+--                             S E M _ V F P T                              --
+--                                                                          --
+--                                 B o d y                                  --
+--                                                                          --
+--                            $Revision: 1.10 $
+--                                                                          --
+--          Copyright (C) 1997-2000, 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- --
+-- ware  Foundation;  either version 2,  or (at your option) any later ver- --
+-- sion.  GNAT is distributed in the hope that it will be useful, but WITH- --
+-- OUT ANY WARRANTY;  without even the  implied warranty of MERCHANTABILITY --
+-- or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License --
+-- for  more details.  You should have  received  a copy of the GNU General --
+-- Public License  distributed with GNAT;  see file COPYING.  If not, write --
+-- to  the Free Software Foundation,  59 Temple Place - Suite 330,  Boston, --
+-- MA 02111-1307, USA.                                                      --
+--                                                                          --
+-- GNAT was originally developed  by the GNAT team at  New York University. --
+-- It is now maintained by Ada Core Technologies Inc (http://www.gnat.com). --
+--                                                                          --
+------------------------------------------------------------------------------
+
+with CStand;   use CStand;
+with Einfo;    use Einfo;
+with Opt;      use Opt;
+with Stand;    use Stand;
+with Targparm; use Targparm;
+with Ttypef;   use Ttypef;
+with Uintp;    use Uintp;
+
+pragma Elaborate_All (Uintp);
+
+package body Sem_VFpt is
+
+   T_Digits : constant Uint := UI_From_Int (IEEEL_Digits);
+   --  Digits for IEEE formats
+
+   -----------------
+   -- Set_D_Float --
+   -----------------
+
+   procedure Set_D_Float (E : Entity_Id) is
+   begin
+      Init_Size         (Base_Type (E), 64);
+      Init_Alignment    (Base_Type (E));
+      Init_Digits_Value (Base_Type (E), VAXDF_Digits);
+      Set_Vax_Float     (Base_Type (E), True);
+      Set_Float_Bounds  (Base_Type (E));
+
+      Init_Size         (E, 64);
+      Init_Alignment    (E);
+      Init_Digits_Value (E, VAXDF_Digits);
+      Set_Scalar_Range  (E, Scalar_Range (Base_Type (E)));
+   end Set_D_Float;
+
+   -----------------
+   -- Set_F_Float --
+   -----------------
+
+   procedure Set_F_Float (E : Entity_Id) is
+   begin
+      Init_Size         (Base_Type (E), 32);
+      Init_Alignment    (Base_Type (E));
+      Init_Digits_Value (Base_Type (E), VAXFF_Digits);
+      Set_Vax_Float     (Base_Type (E), True);
+      Set_Float_Bounds  (Base_Type (E));
+
+      Init_Size         (E, 32);
+      Init_Alignment    (E);
+      Init_Digits_Value (E, VAXFF_Digits);
+      Set_Scalar_Range  (E, Scalar_Range (Base_Type (E)));
+   end Set_F_Float;
+
+   -----------------
+   -- Set_G_Float --
+   -----------------
+
+   procedure Set_G_Float (E : Entity_Id) is
+   begin
+      Init_Size         (Base_Type (E), 64);
+      Init_Alignment    (Base_Type (E));
+      Init_Digits_Value (Base_Type (E), VAXGF_Digits);
+      Set_Vax_Float     (Base_Type (E), True);
+      Set_Float_Bounds  (Base_Type (E));
+
+      Init_Size         (E, 64);
+      Init_Alignment    (E);
+      Init_Digits_Value (E, VAXGF_Digits);
+      Set_Scalar_Range  (E, Scalar_Range (Base_Type (E)));
+   end Set_G_Float;
+
+   -------------------
+   -- Set_IEEE_Long --
+   -------------------
+
+   procedure Set_IEEE_Long (E : Entity_Id) is
+   begin
+      Init_Size         (Base_Type (E), 64);
+      Init_Alignment    (Base_Type (E));
+      Init_Digits_Value (Base_Type (E), IEEEL_Digits);
+      Set_Vax_Float     (Base_Type (E), False);
+      Set_Float_Bounds  (Base_Type (E));
+
+      Init_Size         (E, 64);
+      Init_Alignment    (E);
+      Init_Digits_Value (E, IEEEL_Digits);
+      Set_Scalar_Range  (E, Scalar_Range (Base_Type (E)));
+   end Set_IEEE_Long;
+
+   --------------------
+   -- Set_IEEE_Short --
+   --------------------
+
+   procedure Set_IEEE_Short (E : Entity_Id) is
+   begin
+      Init_Size         (Base_Type (E), 32);
+      Init_Alignment    (Base_Type (E));
+      Init_Digits_Value (Base_Type (E), IEEES_Digits);
+      Set_Vax_Float     (Base_Type (E), False);
+      Set_Float_Bounds  (Base_Type (E));
+
+      Init_Size         (E, 32);
+      Init_Alignment    (E);
+      Init_Digits_Value (E, IEEES_Digits);
+      Set_Scalar_Range  (E, Scalar_Range (Base_Type (E)));
+   end Set_IEEE_Short;
+
+   ------------------------------
+   -- Set_Standard_Fpt_Formats --
+   ------------------------------
+
+   procedure Set_Standard_Fpt_Formats is
+   begin
+      --  IEEE case
+
+      if Opt.Float_Format = 'I' then
+         Set_IEEE_Short (Standard_Float);
+         Set_IEEE_Long  (Standard_Long_Float);
+         Set_IEEE_Long  (Standard_Long_Long_Float);
+
+      --  Vax float case
+
+      else
+         Set_F_Float (Standard_Float);
+
+         if Opt.Float_Format_Long = 'D' then
+            Set_D_Float (Standard_Long_Float);
+         else
+            Set_G_Float (Standard_Long_Float);
+         end if;
+
+         --  Note: Long_Long_Float gets set only in the real VMS case,
+         --  because this gives better results for testing out the use
+         --  of VAX float on non-VMS environments with the -gnatdm switch.
+
+         if OpenVMS_On_Target then
+            Set_G_Float (Standard_Long_Long_Float);
+         end if;
+      end if;
+   end Set_Standard_Fpt_Formats;
+
+end Sem_VFpt;
diff --git a/gcc/ada/sem_vfpt.ads b/gcc/ada/sem_vfpt.ads
new file mode 100644 (file)
index 0000000..ed27175
--- /dev/null
@@ -0,0 +1,58 @@
+------------------------------------------------------------------------------
+--                                                                          --
+--                         GNAT COMPILER COMPONENTS                         --
+--                                                                          --
+--                             S E M _ V F P T                              --
+--                                                                          --
+--                                 S p e c                                  --
+--                                                                          --
+--                            $Revision: 1.1 $                              --
+--                                                                          --
+--             Copyright (C) 1997 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- --
+-- ware  Foundation;  either version 2,  or (at your option) any later ver- --
+-- sion.  GNAT is distributed in the hope that it will be useful, but WITH- --
+-- OUT ANY WARRANTY;  without even the  implied warranty of MERCHANTABILITY --
+-- or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License --
+-- for  more details.  You should have  received  a copy of the GNU General --
+-- Public License  distributed with GNAT;  see file COPYING.  If not, write --
+-- to  the Free Software Foundation,  59 Temple Place - Suite 330,  Boston, --
+-- MA 02111-1307, USA.                                                      --
+--                                                                          --
+-- GNAT was originally developed  by the GNAT team at  New York University. --
+-- It is now maintained by Ada Core Technologies Inc (http://www.gnat.com). --
+--                                                                          --
+------------------------------------------------------------------------------
+
+--  This package contains specialized routines for handling the Alpha
+--  floating point formats. It is used only in Alpha implementations.
+--  Note that this means that the caller can assume that we are on an
+--  Alpha implementation, and that Vax floating-point formats are valid.
+
+with Types; use Types;
+
+package Sem_VFpt is
+
+   procedure Set_D_Float (E : Entity_Id);
+   --  Sets the given floating-point entity to have Vax D_Float format
+
+   procedure Set_F_Float (E : Entity_Id);
+   --  Sets the given floating-point entity to have Vax F_Float format
+
+   procedure Set_G_Float (E : Entity_Id);
+   --  Sets the given floating-point entity to have Vax G_Float format
+
+   procedure Set_IEEE_Short (E : Entity_Id);
+   --  Sets the given floating-point entity to have IEEE Short format
+
+   procedure Set_IEEE_Long (E : Entity_Id);
+   --  Sets the given floating-point entity to have IEEE Long format
+
+   procedure Set_Standard_Fpt_Formats;
+   --  This procedure sets the appropriate formats for the standard
+   --  floating-point types in Standard, based on the setting of
+   --  the flags Opt.Float_Format and Opt.Float_Format_Long
+
+end Sem_VFpt;
diff --git a/gcc/ada/sem_warn.adb b/gcc/ada/sem_warn.adb
new file mode 100644 (file)
index 0000000..f3133d2
--- /dev/null
@@ -0,0 +1,1062 @@
+------------------------------------------------------------------------------
+--                                                                          --
+--                         GNAT COMPILER COMPONENTS                         --
+--                                                                          --
+--                             S E M _ W A R N                              --
+--                                                                          --
+--                                 B o d y                                  --
+--                                                                          --
+--                            $Revision: 1.24 $
+--                                                                          --
+--          Copyright (C) 1999-2001 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- --
+-- ware  Foundation;  either version 2,  or (at your option) any later ver- --
+-- sion.  GNAT is distributed in the hope that it will be useful, but WITH- --
+-- OUT ANY WARRANTY;  without even the  implied warranty of MERCHANTABILITY --
+-- or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License --
+-- for  more details.  You should have  received  a copy of the GNU General --
+-- Public License  distributed with GNAT;  see file COPYING.  If not, write --
+-- to  the Free Software Foundation,  59 Temple Place - Suite 330,  Boston, --
+-- MA 02111-1307, USA.                                                      --
+--                                                                          --
+-- GNAT was originally developed  by the GNAT team at  New York University. --
+-- It is now maintained by Ada Core Technologies Inc (http://www.gnat.com). --
+--                                                                          --
+------------------------------------------------------------------------------
+
+with Alloc;
+with Atree;    use Atree;
+with Einfo;    use Einfo;
+with Errout;   use Errout;
+with Fname;    use Fname;
+with Lib;      use Lib;
+with Nlists;   use Nlists;
+with Opt;      use Opt;
+with Sem;      use Sem;
+with Sem_Util; use Sem_Util;
+with Sinfo;    use Sinfo;
+with Sinput;   use Sinput;
+with Snames;   use Snames;
+with Stand;    use Stand;
+with Table;
+
+package body Sem_Warn is
+
+   --  The following table collects Id's of entities that are potentially
+   --  unreferenced. See Check_Unset_Reference for further details.
+
+   package Unreferenced_Entities is new Table.Table (
+     Table_Component_Type => Entity_Id,
+     Table_Index_Type     => Nat,
+     Table_Low_Bound      => 1,
+     Table_Initial        => Alloc.Unreferenced_Entities_Initial,
+     Table_Increment      => Alloc.Unreferenced_Entities_Increment,
+     Table_Name           => "Unreferenced_Entities");
+
+   --  One entry is made in the following table for each branch of
+   --  a conditional, e.g. an if-then-elsif-else-endif structure
+   --  creates three entries in this table.
+
+   type Branch_Entry is record
+      Sloc : Source_Ptr;
+      --  Location for warnings associated with this branch
+
+      Defs : Elist_Id;
+      --  List of entities defined for the first time in this branch. On
+      --  exit from a conditional structure, any entity that is in the
+      --  list of all branches is removed (and the entity flagged as
+      --  defined by the conditional as a whole). Thus after processing
+      --  a conditional, Defs contains a list of entities defined in this
+      --  branch for the first time, but not defined at all in some other
+      --  branch of the same conditional. A value of No_Elist is used to
+      --  represent the initial empty list.
+
+      Next : Nat;
+      --  Index of next branch for this conditional, zero = last branch
+   end record;
+
+   package Branch_Table is new Table.Table (
+     Table_Component_Type => Branch_Entry,
+     Table_Index_Type     => Nat,
+     Table_Low_Bound      => 1,
+     Table_Initial        => Alloc.Branches_Initial,
+     Table_Increment      => Alloc.Branches_Increment,
+     Table_Name           => "Branches");
+
+   --  The following table is used to represent conditionals, there is
+   --  one entry in this table for each conditional structure.
+
+   type Conditional_Entry is record
+      If_Stmt : Boolean;
+      --  True for IF statement, False for CASE statement
+
+      First_Branch : Nat;
+      --  Index in Branch table of first branch, zero = none yet
+
+      Current_Branch : Nat;
+      --  Index in Branch table of current branch, zero = none yet
+   end record;
+
+   package Conditional_Table is new Table.Table (
+     Table_Component_Type => Conditional_Entry,
+     Table_Index_Type     => Nat,
+     Table_Low_Bound      => 1,
+     Table_Initial        => Alloc.Conditionals_Initial,
+     Table_Increment      => Alloc.Conditionals_Increment,
+     Table_Name           => "Conditionals");
+
+   --  The following table is a stack that keeps track of the current
+   --  conditional. The Last entry is the top of the stack. An Empty
+   --  entry represents the start of a compilation unit. Non-zero
+   --  entries in the stack are indexes into the conditional table.
+
+   package Conditional_Stack is new Table.Table (
+     Table_Component_Type => Nat,
+     Table_Index_Type     => Nat,
+     Table_Low_Bound      => 1,
+     Table_Initial        => Alloc.Conditional_Stack_Initial,
+     Table_Increment      => Alloc.Conditional_Stack_Increment,
+     Table_Name           => "Conditional_Stack");
+
+   Current_Entity_List : Elist_Id := No_Elist;
+   --  This is a copy of the Defs list of the current branch of the current
+   --  conditional. It could be accessed by taking the top element of the
+   --  Conditional_Stack, and going to te Current_Branch entry of this
+   --  conditional, but we keep it precomputed for rapid access.
+
+   ----------------------
+   -- Check_References --
+   ----------------------
+
+   procedure Check_References (E : Entity_Id; Anod : Node_Id := Empty) is
+      E1 : Entity_Id;
+      UR : Node_Id;
+      PU : Node_Id;
+
+      procedure Output_Reference_Error (M : String);
+      --  Used to output an error message. Deals with posting the error on
+      --  the body formal in the accept case.
+
+      function Publicly_Referenceable (Ent : Entity_Id) return Boolean;
+      --  This is true if the entity in question is potentially referenceable
+      --  from another unit. This is true for entities in packages that are
+      --  at the library level, or for entities in tasks or protected objects
+      --  that are themselves publicly visible.
+
+      ----------------------------
+      -- Output_Reference_Error --
+      ----------------------------
+
+      procedure Output_Reference_Error (M : String) is
+      begin
+         --  Other than accept case, post error on defining identifier
+
+         if No (Anod) then
+            Error_Msg_N (M, E1);
+
+         --  Accept case, find body formal to post the message
+
+         else
+            declare
+               Parm  : Node_Id;
+               Enod  : Node_Id;
+               Defid : Entity_Id;
+
+            begin
+               Enod := Anod;
+
+               if Present (Parameter_Specifications (Anod)) then
+                  Parm := First (Parameter_Specifications (Anod));
+
+                  while Present (Parm) loop
+                     Defid := Defining_Identifier (Parm);
+
+                     if Chars (E1) = Chars (Defid) then
+                        Enod := Defid;
+                        exit;
+                     end if;
+
+                     Next (Parm);
+                  end loop;
+               end if;
+
+               Error_Msg_NE (M, Enod, E1);
+            end;
+         end if;
+      end Output_Reference_Error;
+
+      ----------------------------
+      -- Publicly_Referenceable --
+      ----------------------------
+
+      function Publicly_Referenceable (Ent : Entity_Id) return Boolean is
+         S : Entity_Id;
+
+      begin
+         --  Any entity in a generic package is considered to be publicly
+         --  referenceable, since it could be referenced in an instantiation
+
+         if Ekind (E) = E_Generic_Package then
+            return True;
+         end if;
+
+         --  Otherwise look up the scope stack
+
+         S := Scope (Ent);
+         loop
+            if Is_Package (S) then
+               return Is_Library_Level_Entity (S);
+
+            elsif Ekind (S) = E_Task_Type
+              or else Ekind (S) = E_Protected_Type
+              or else Ekind (S) = E_Entry
+            then
+               S := Scope (S);
+
+            else
+               return False;
+            end if;
+         end loop;
+      end Publicly_Referenceable;
+
+   --  Start of processing for Check_References
+
+   begin
+      --  No messages if warnings are suppressed, or if we have detected
+      --  any real errors so far (this last check avoids junk messages
+      --  resulting from errors, e.g. a subunit that is not loaded).
+
+      --  We also skip the messages if any subunits were not loaded (see
+      --  comment in Sem_Ch10 to understand how this is set, and why it is
+      --  necessary to suppress the warnings in this case).
+
+      if Warning_Mode = Suppress
+        or else Errors_Detected /= 0
+        or else Unloaded_Subunits
+      then
+         return;
+      end if;
+
+      --  Otherwise loop through entities, looking for suspicious stuff
+
+      E1 := First_Entity (E);
+      while Present (E1) loop
+
+         --  We only look at source entities with warning flag off
+
+         if Comes_From_Source (E1) and then not Warnings_Off (E1) then
+
+            --  We are interested in variables and out parameters, but we
+            --  exclude protected types, too complicated to worry about.
+
+            if Ekind (E1) = E_Variable
+                 or else
+               (Ekind (E1) = E_Out_Parameter
+                  and then not Is_Protected_Type (Current_Scope))
+            then
+               --  Post warning if this object not assigned. Note that we
+               --  do not consider the implicit initialization of an access
+               --  type to be the assignment of a value for this purpose.
+               --  If the entity is an out parameter of the current subprogram
+               --  body, check the warning status of the parameter in the spec.
+
+               if Ekind (E1) = E_Out_Parameter
+                 and then Present (Spec_Entity (E1))
+                 and then Warnings_Off (Spec_Entity (E1))
+               then
+                  null;
+
+               elsif Not_Source_Assigned (E1) then
+                  Output_Reference_Error ("& is never assigned a value?");
+
+                  --  Deal with special case where this variable is hidden
+                  --  by a loop variable
+
+                  if Ekind (E1) = E_Variable
+                    and then Present (Hiding_Loop_Variable (E1))
+                  then
+                     Error_Msg_Sloc := Sloc (E1);
+                     Error_Msg_N
+                       ("declaration hides &#?",
+                        Hiding_Loop_Variable (E1));
+                     Error_Msg_N
+                       ("for loop implicitly declares loop variable?",
+                        Hiding_Loop_Variable (E1));
+                  end if;
+
+                  goto Continue;
+               end if;
+
+               --  Check for unset reference, note that we exclude access
+               --  types from this check, since access types do always have
+               --  a null value, and that seems legitimate in this case.
+
+               UR := Unset_Reference (E1);
+               if Present (UR) then
+
+                  --  For access types, the only time we complain is when
+                  --  we have a dereference (of a null value)
+
+                  if Is_Access_Type (Etype (E1)) then
+                     PU := Parent (UR);
+
+                     if (Nkind (PU) = N_Selected_Component
+                           or else
+                         Nkind (PU) = N_Explicit_Dereference
+                           or else
+                         Nkind (PU) = N_Indexed_Component)
+                       and then
+                         Prefix (PU) = UR
+                     then
+                        Error_Msg_N ("& may be null?", UR);
+                        goto Continue;
+                     end if;
+
+                  --  For other than access type, go back to original node
+                  --  to deal with case where original unset reference
+                  --  has been rewritten during expansion.
+
+                  else
+                     UR := Original_Node (UR);
+
+                     --  In some cases, the original node may be a type
+                     --  conversion or qualification, and in this case
+                     --  we want the object entity inside.
+
+                     while Nkind (UR) = N_Type_Conversion
+                       or else Nkind (UR) = N_Qualified_Expression
+                     loop
+                        UR := Expression (UR);
+                     end loop;
+
+                     Error_Msg_N
+                       ("& may be referenced before it has a value?", UR);
+                     goto Continue;
+                  end if;
+               end if;
+            end if;
+
+            --  Then check for unreferenced variables
+
+            if Check_Unreferenced
+
+               --  Check entity is flagged as not referenced and that
+               --  warnings are not suppressed for this entity
+
+               and then not Referenced (E1)
+               and then not Warnings_Off (E1)
+
+               --  Warnings are placed on objects, types, subprograms,
+               --  labels, and enumeration literals.
+
+               and then (Is_Object (E1)
+                           or else
+                         Is_Type (E1)
+                           or else
+                         Ekind (E1) = E_Label
+                           or else
+                         Ekind (E1) = E_Named_Integer
+                           or else
+                         Ekind (E1) = E_Named_Real
+                           or else
+                         Is_Overloadable (E1))
+
+               --  We only place warnings for the main unit
+
+               and then In_Extended_Main_Source_Unit (E1)
+
+               --  Exclude instantiations, since there is no reason why
+               --  every entity in an instantiation should be referenced.
+
+               and then Instantiation_Location (Sloc (E1)) = No_Location
+
+               --  Exclude formal parameters from bodies (in the case
+               --  where there is a separate spec, it is the spec formals
+               --  that are of interest).
+
+               and then (not Is_Formal (E1)
+                           or else
+                         Ekind (Scope (E1)) /= E_Subprogram_Body)
+
+               --  Consider private type referenced if full view is
+               --  referenced.
+
+               and then not (Is_Private_Type (E1)
+                               and then
+                             Referenced (Full_View (E1)))
+
+               --  Don't worry about full view, only about private type
+
+               and then not Has_Private_Declaration (E1)
+
+               --  Eliminate dispatching operations from consideration, we
+               --  cannot tell if these are referenced or not in any easy
+               --  manner (note this also catches Adjust/Finalize/Initialize)
+
+               and then not Is_Dispatching_Operation (E1)
+
+               --  Check entity that can be publicly referenced (we do not
+               --  give messages for such entities, since there could be
+               --  other units, not involved in this compilation, that
+               --  contain relevant references.
+
+               and then not Publicly_Referenceable (E1)
+
+               --  Class wide types are marked as source entities, but
+               --  they are not really source entities, and are always
+               --  created, so we do not care if they are not referenced.
+
+               and then Ekind (E1) /= E_Class_Wide_Type
+
+               --  Objects other than parameters of task types are allowed
+               --  to be non-referenced, since they start up tasks!
+
+               and then ((Ekind (E1) /= E_Variable
+                             and then Ekind (E1) /= E_Constant
+                             and then Ekind (E1) /= E_Component)
+                           or else not Is_Task_Type (Etype (E1)))
+            then
+               --  Suppress warnings in internal units if not in -gnatg
+               --  mode (these would be junk warnings for an applications
+               --  program, since they refer to problems in internal units)
+
+               if GNAT_Mode
+                 or else not
+                   Is_Internal_File_Name
+                     (Unit_File_Name (Get_Source_Unit (E1)))
+               then
+                  --  We do not immediately flag the error. This is because
+                  --  we have not expanded generic bodies yet, and they may
+                  --  have the missing reference. So instead we park the
+                  --  entity on a list, for later processing. However, for
+                  --  the accept case, post the error right here, since we
+                  --  have the information now in this case.
+
+                  if Present (Anod) then
+                     Output_Reference_Error ("& is not referenced?");
+
+                  else
+                     Unreferenced_Entities.Increment_Last;
+                     Unreferenced_Entities.Table
+                       (Unreferenced_Entities.Last) := E1;
+                  end if;
+               end if;
+            end if;
+         end if;
+
+         --  Recurse into nested package or block
+
+         <<Continue>>
+            if (Ekind (E1) = E_Package
+                  and then Nkind (Parent (E1)) = N_Package_Specification)
+              or else Ekind (E1) = E_Block
+            then
+               Check_References (E1);
+            end if;
+
+            Next_Entity (E1);
+      end loop;
+   end Check_References;
+
+   ---------------------------
+   -- Check_Unset_Reference --
+   ---------------------------
+
+   procedure Check_Unset_Reference (N : Node_Id) is
+   begin
+      --  Nothing to do if warnings suppressed
+
+      if Warning_Mode = Suppress then
+         return;
+      end if;
+
+      --  Otherwise see what kind of node we have. If the entity already
+      --  has an unset reference, it is not necessarily the earliest in
+      --  the text, because resolution of the prefix of selected components
+      --  is completed before the resolution of the selected component itself.
+      --  as a result, given  (R /= null and then R.X > 0), the occurrences
+      --  of R are examined in right-to-left order. If there is already an
+      --  unset reference, we check whether N is earlier before proceeding.
+
+      case Nkind (N) is
+
+         when N_Identifier | N_Expanded_Name =>
+            declare
+               E  : constant Entity_Id := Entity (N);
+
+            begin
+               if (Ekind (E) = E_Variable
+                    or else Ekind (E) = E_Out_Parameter)
+                 and then Not_Source_Assigned (E)
+                 and then (No (Unset_Reference (E))
+                             or else Earlier_In_Extended_Unit
+                               (Sloc (N),  Sloc (Unset_Reference (E))))
+                 and then not Warnings_Off (E)
+               then
+                  --  Here we have a potential unset reference. But before we
+                  --  get worried about it, we have to make sure that the
+                  --  entity declaration is in the same procedure as the
+                  --  reference, since if they are in separate procedures,
+                  --  then we have no idea about sequential execution.
+
+                  --  The tests in the loop below catch all such cases, but
+                  --  do allow the reference to appear in a loop, block, or
+                  --  package spec that is nested within the declaring scope.
+                  --  As always, it is possible to construct cases where the
+                  --  warning is wrong, that is why it is a warning!
+
+                  --  If the entity is an out_parameter, it is ok to read its
+                  --  its discriminants (that was true in Ada83) so suppress
+                  --  the message in that case as well.
+
+                  if Ekind (E) = E_Out_Parameter
+                    and then Nkind (Parent (N)) = N_Selected_Component
+                    and then Ekind (Entity (Selector_Name (Parent (N))))
+                      = E_Discriminant
+                  then
+                     return;
+                  end if;
+
+                  declare
+                     SR : Entity_Id;
+                     SE : constant Entity_Id := Scope (E);
+
+                  begin
+                     SR := Current_Scope;
+                     while SR /= SE loop
+                        if SR = Standard_Standard
+                          or else Is_Subprogram (SR)
+                          or else Is_Concurrent_Body (SR)
+                          or else Is_Concurrent_Type (SR)
+                        then
+                           return;
+                        end if;
+
+                        SR := Scope (SR);
+                     end loop;
+
+                     if Nkind (N) = N_Identifier then
+                        Set_Unset_Reference (E, N);
+                     else
+                        Set_Unset_Reference (E, Selector_Name (N));
+                     end if;
+                  end;
+               end if;
+            end;
+
+         when N_Indexed_Component | N_Selected_Component | N_Slice =>
+            Check_Unset_Reference (Prefix (N));
+            return;
+
+         when N_Type_Conversion | N_Qualified_Expression =>
+            Check_Unset_Reference (Expression (N));
+
+         when others =>
+            null;
+
+      end case;
+   end Check_Unset_Reference;
+
+   ------------------------
+   -- Check_Unused_Withs --
+   ------------------------
+
+   procedure Check_Unused_Withs (Spec_Unit : Unit_Number_Type := No_Unit) is
+      Cnode : Node_Id;
+      Item  : Node_Id;
+      Lunit : Node_Id;
+      Ent   : Entity_Id;
+
+      Munite : constant Entity_Id := Cunit_Entity (Main_Unit);
+      --  This is needed for checking the special renaming case
+
+      procedure Check_One_Unit (Unit : Unit_Number_Type);
+      --  Subsidiary procedure, performs checks for specified unit
+
+      --------------------
+      -- Check_One_Unit --
+      --------------------
+
+      procedure Check_One_Unit (Unit : Unit_Number_Type) is
+         Is_Visible_Renaming : Boolean := False;
+         Pack                : Entity_Id;
+
+         function Find_Package_Renaming
+           (P : Entity_Id;
+            L : Entity_Id) return Entity_Id;
+         --  The only reference to a context unit may be in a renaming
+         --  declaration. If this renaming declares a visible entity, do
+         --  not warn that the context clause could be moved to the body,
+         --  because the renaming may be intented to re-export the unit.
+
+         ---------------------------
+         -- Find_Package_Renaming --
+         ---------------------------
+
+         function Find_Package_Renaming
+           (P : Entity_Id;
+            L : Entity_Id) return Entity_Id
+         is
+            E1 : Entity_Id;
+            R  : Entity_Id;
+
+         begin
+            Is_Visible_Renaming := False;
+            E1 := First_Entity (P);
+
+            while Present (E1) loop
+               if Ekind (E1) = E_Package
+                  and then Renamed_Object (E1) = L
+               then
+                  Is_Visible_Renaming := not Is_Hidden (E1);
+                  return E1;
+
+               elsif Ekind (E1) = E_Package
+                 and then No (Renamed_Object (E1))
+                 and then not Is_Generic_Instance (E1)
+               then
+                  R := Find_Package_Renaming (E1, L);
+
+                  if Present (R) then
+                     Is_Visible_Renaming := not Is_Hidden (R);
+                     return R;
+                  end if;
+               end if;
+
+               Next_Entity (E1);
+            end loop;
+
+            return Empty;
+         end Find_Package_Renaming;
+
+      --  Start of processing for Check_One_Unit
+
+      begin
+         Cnode := Cunit (Unit);
+
+         --  Only do check in units that are part of the extended main
+         --  unit. This is actually a necessary restriction, because in
+         --  the case of subprogram acting as its own specification,
+         --  there can be with's in subunits that we will not see.
+
+         if not In_Extended_Main_Source_Unit (Cnode) then
+            return;
+         end if;
+
+         --  Loop through context items in this unit
+
+         Item := First (Context_Items (Cnode));
+         while Present (Item) loop
+
+            if Nkind (Item) = N_With_Clause
+               and then not Implicit_With (Item)
+               and then In_Extended_Main_Source_Unit (Item)
+            then
+               Lunit := Entity (Name (Item));
+
+               --  Check if this unit is referenced
+
+               if not Referenced (Lunit) then
+
+                  --  Suppress warnings in internal units if not in -gnatg
+                  --  mode (these would be junk warnings for an applications
+                  --  program, since they refer to problems in internal units)
+
+                  if GNAT_Mode
+                    or else not Is_Internal_File_Name (Unit_File_Name (Unit))
+                  then
+                     --  Here we definitely have a non-referenced unit. If
+                     --  it is the special call for a spec unit, then just
+                     --  set the flag to be read later.
+
+                     if Unit = Spec_Unit then
+                        Set_Unreferenced_In_Spec (Item);
+
+                     --  Otherwise simple unreferenced message
+
+                     else
+                        Error_Msg_N
+                          ("unit& is not referenced?", Name (Item));
+                     end if;
+                  end if;
+
+               --  If main unit is a renaming of this unit, then we consider
+               --  the with to be OK (obviously it is needed in this case!)
+
+               elsif Present (Renamed_Entity (Munite))
+                  and then Renamed_Entity (Munite) = Lunit
+               then
+                  null;
+
+               --  If this unit is referenced, and it is a package, we
+               --  do another test, to see if any of the entities in the
+               --  package are referenced. If none of the entities are
+               --  referenced, we still post a warning. This occurs if
+               --  the only use of the package is in a use clause, or
+               --  in a package renaming declaration.
+
+               elsif Ekind (Lunit) = E_Package then
+
+                  --  If Is_Instantiated is set, it means that the package
+                  --  is implicitly instantiated (this is the case of a
+                  --  parent instance or an actual for a generic package
+                  --  formal), and this counts as a reference.
+
+                  if Is_Instantiated (Lunit) then
+                     null;
+
+                  --  If no entities in package, and there is a pragma
+                  --  Elaborate_Body present, then assume that this with
+                  --  is done for purposes of this elaboration.
+
+                  elsif No (First_Entity (Lunit))
+                    and then Has_Pragma_Elaborate_Body (Lunit)
+                  then
+                     null;
+
+                  --  Otherwise see if any entities have been referenced
+
+                  else
+                     Ent  := First_Entity (Lunit);
+
+                     loop
+                        --  No more entities, and we did not find one
+                        --  that was referenced. Means we have a definite
+                        --  case of a with none of whose entities was
+                        --  referenced.
+
+                        if No (Ent) then
+
+                           --  If in spec, just set the flag
+
+                           if Unit = Spec_Unit then
+                              Set_No_Entities_Ref_In_Spec (Item);
+
+                           --  Else give the warning
+
+                           else
+                              Error_Msg_N
+                                ("no entities of & are referenced?",
+                                 Name (Item));
+
+                              --  Look for renamings of this package, and
+                              --  flag them as well. If the original package
+                              --  has warnings off, we suppress the warning
+                              --  on the renaming as well.
+
+                              Pack := Find_Package_Renaming (Munite, Lunit);
+
+                              if Present (Pack)
+                                and then not Warnings_Off (Lunit)
+                              then
+                                 Error_Msg_NE
+                                   ("no entities of & are referenced?",
+                                     Unit_Declaration_Node (Pack),
+                                       Pack);
+                              end if;
+                           end if;
+
+                           exit;
+
+                        --  Case of next entity is referenced
+
+                        elsif Referenced (Ent) then
+
+                           --  This means that the with is indeed fine, in
+                           --  that it is definitely needed somewhere, and
+                           --  we can quite worrying about this one.
+
+                           --  Except for one little detail, if either of
+                           --  the flags was set during spec processing,
+                           --  this is where we complain that the with
+                           --  could be moved from the spec. If the spec
+                           --  contains a visible renaming of the package,
+                           --  inhibit warning to move with_clause to body.
+
+                           if Ekind (Munite) = E_Package_Body then
+                              Pack :=
+                                Find_Package_Renaming
+                                  (Spec_Entity (Munite), Lunit);
+                           end if;
+
+                           if Unreferenced_In_Spec (Item) then
+                              Error_Msg_N
+                                ("unit& is not referenced in spec?",
+                                 Name (Item));
+
+                           elsif No_Entities_Ref_In_Spec (Item) then
+                              Error_Msg_N
+                                ("no entities of & are referenced in spec?",
+                                 Name (Item));
+
+                           else
+                              exit;
+                           end if;
+
+                           if not Is_Visible_Renaming then
+                              Error_Msg_N
+                                ("\with clause might be moved to body?",
+                                 Name (Item));
+                           end if;
+
+                           exit;
+
+                        --  Move to next entity to continue search
+
+                        else
+                           Next_Entity (Ent);
+                        end if;
+                     end loop;
+                  end if;
+
+               --  For a generic package, the only interesting kind of
+               --  reference is an instantiation, since entities cannot
+               --  be referenced directly.
+
+               elsif Is_Generic_Unit (Lunit) then
+
+                  --  Unit was never instantiated, set flag for case of spec
+                  --  call, or give warning for normal call.
+
+                  if not Is_Instantiated (Lunit) then
+                     if Unit = Spec_Unit then
+                        Set_Unreferenced_In_Spec (Item);
+                     else
+                        Error_Msg_N
+                          ("unit& is never instantiated?", Name (Item));
+                     end if;
+
+                  --  If unit was indeed instantiated, make sure that
+                  --  flag is not set showing it was uninstantiated in
+                  --  the spec, and if so, give warning.
+
+                  elsif Unreferenced_In_Spec (Item) then
+                     Error_Msg_N
+                       ("unit& is not instantiated in spec?", Name (Item));
+                     Error_Msg_N
+                       ("\with clause can be moved to body?", Name (Item));
+                  end if;
+               end if;
+            end if;
+
+            Next (Item);
+         end loop;
+
+      end Check_One_Unit;
+
+   --  Start of processing for Check_Unused_Withs
+
+   begin
+      if not Opt.Check_Withs
+        or else Operating_Mode = Check_Syntax
+      then
+         return;
+      end if;
+
+      --  Flag any unused with clauses, but skip this step if we are
+      --  compiling a subunit on its own, since we do not have enough
+      --  information to determine whether with's are used. We will get
+      --  the relevant warnings when we compile the parent. This is the
+      --  normal style of GNAT compilation in any case.
+
+      if Nkind (Unit (Cunit (Main_Unit))) = N_Subunit then
+         return;
+      end if;
+
+      --  Process specified units
+
+      if Spec_Unit = No_Unit then
+
+         --  For main call, check all units
+
+         for Unit in Main_Unit .. Last_Unit loop
+            Check_One_Unit (Unit);
+         end loop;
+
+      else
+         --  For call for spec, check only the spec
+
+         Check_One_Unit (Spec_Unit);
+      end if;
+   end Check_Unused_Withs;
+
+   ---------------------
+   -- End_Conditional --
+   ---------------------
+
+   procedure End_Conditional is
+   begin
+      null;
+   end End_Conditional;
+
+   --------------
+   -- End_Unit --
+   --------------
+
+   procedure End_Unit is
+   begin
+      null;
+   end End_Unit;
+
+   ----------------------------------
+   -- Output_Unreferenced_Messages --
+   ----------------------------------
+
+   procedure Output_Unreferenced_Messages is
+      E : Entity_Id;
+
+   begin
+      for J in Unreferenced_Entities.First ..
+               Unreferenced_Entities.Last
+      loop
+         E := Unreferenced_Entities.Table (J);
+
+         if not Referenced (E) and then not Warnings_Off (E) then
+
+            case Ekind (E) is
+               when E_Variable =>
+                  if Present (Renamed_Object (E))
+                    and then Comes_From_Source (Renamed_Object (E))
+                  then
+                     Error_Msg_N ("renamed variable & is not referenced?", E);
+                  else
+                     Error_Msg_N ("variable & is not referenced?", E);
+                  end if;
+
+               when E_Constant =>
+                  if Present (Renamed_Object (E)) then
+                     Error_Msg_N ("renamed constant & is not referenced?", E);
+                  else
+                     Error_Msg_N ("constant & is not referenced?", E);
+                  end if;
+
+               when E_In_Parameter     |
+                    E_Out_Parameter    |
+                    E_In_Out_Parameter =>
+
+                  --  Do not emit message for formals of a renaming, because
+                  --  they are never referenced explicitly.
+
+                  if Nkind (Original_Node (Unit_Declaration_Node (Scope (E))))
+                    /= N_Subprogram_Renaming_Declaration
+                  then
+                     Error_Msg_N ("formal parameter & is not referenced?", E);
+                  end if;
+
+               when E_Named_Integer    |
+                    E_Named_Real       =>
+                  Error_Msg_N ("named number & is not referenced?", E);
+
+               when E_Enumeration_Literal =>
+                  Error_Msg_N ("literal & is not referenced?", E);
+
+               when E_Function         =>
+                  Error_Msg_N ("function & is not referenced?", E);
+
+               when E_Procedure         =>
+                  Error_Msg_N ("procedure & is not referenced?", E);
+
+               when Type_Kind          =>
+                  Error_Msg_N ("type & is not referenced?", E);
+
+               when others =>
+                  Error_Msg_N ("& is not referenced?", E);
+            end case;
+
+            Set_Warnings_Off (E);
+         end if;
+      end loop;
+   end Output_Unreferenced_Messages;
+
+   ------------------
+   -- Start_Branch --
+   ------------------
+
+   procedure Start_Branch (Loc : Source_Ptr) is
+   begin
+      null;
+   end Start_Branch;
+
+   -----------------------
+   -- Start_Conditional --
+   -----------------------
+
+   procedure Start_Conditional (If_Stmt : Boolean) is
+   begin
+      null;
+   end Start_Conditional;
+
+   ----------------
+   -- Start_Unit --
+   ----------------
+
+   procedure Start_Unit is
+   begin
+      null;
+   end Start_Unit;
+
+   -----------------------------
+   -- Warn_On_Known_Condition --
+   -----------------------------
+
+   procedure Warn_On_Known_Condition (C : Node_Id) is
+      P : Node_Id;
+
+   begin
+      if Constant_Condition_Warnings
+        and then Nkind (C) = N_Identifier
+        and then
+          (Entity (C) = Standard_False or else Entity (C) = Standard_True)
+        and then Comes_From_Source (Original_Node (C))
+        and then not In_Instance
+      then
+         --  See if this is in a statement or a declaration
+
+         P := Parent (C);
+         loop
+            --  If tree is not attached, do not issue warning (this is very
+            --  peculiar, and probably arises from some other error condition)
+
+            if No (P) then
+               return;
+
+            --  If we are in a declaration, then no warning, since in practice
+            --  conditionals in declarations are used for intended tests which
+            --  may be known at compile time, e.g. things like
+
+            --    x : constant Integer := 2 + (Word'Size = 32);
+
+            --  And a warning is annoying in such cases
+
+            elsif Nkind (P) in N_Declaration
+                    or else
+                  Nkind (P) in N_Later_Decl_Item
+            then
+               return;
+
+            --  Don't warn in assert pragma, since presumably tests in such
+            --  a context are very definitely intended, and might well be
+            --  known at compile time. Note that we have to test the original
+            --  node, since assert pragmas get rewritten at analysis time.
+
+            elsif Nkind (Original_Node (P)) = N_Pragma
+              and then Chars (Original_Node (P)) = Name_Assert
+            then
+               return;
+            end if;
+
+            exit when Is_Statement (P);
+            P := Parent (P);
+         end loop;
+
+         if Entity (C) = Standard_True then
+            Error_Msg_N ("condition is always True?", C);
+         else
+            Error_Msg_N ("condition is always False?", C);
+         end if;
+      end if;
+   end Warn_On_Known_Condition;
+
+end Sem_Warn;
diff --git a/gcc/ada/sem_warn.ads b/gcc/ada/sem_warn.ads
new file mode 100644 (file)
index 0000000..0c5d759
--- /dev/null
@@ -0,0 +1,161 @@
+------------------------------------------------------------------------------
+--                                                                          --
+--                         GNAT COMPILER COMPONENTS                         --
+--                                                                          --
+--                             S E M _ W A R N                              --
+--                                                                          --
+--                                 S p e c                                  --
+--                                                                          --
+--                            $Revision: 1.3 $
+--                                                                          --
+--          Copyright (C) 1999-2000 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- --
+-- ware  Foundation;  either version 2,  or (at your option) any later ver- --
+-- sion.  GNAT is distributed in the hope that it will be useful, but WITH- --
+-- OUT ANY WARRANTY;  without even the  implied warranty of MERCHANTABILITY --
+-- or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License --
+-- for  more details.  You should have  received  a copy of the GNU General --
+-- Public License  distributed with GNAT;  see file COPYING.  If not, write --
+-- to  the Free Software Foundation,  59 Temple Place - Suite 330,  Boston, --
+-- MA 02111-1307, USA.                                                      --
+--                                                                          --
+-- GNAT was originally developed  by the GNAT team at  New York University. --
+-- It is now maintained by Ada Core Technologies Inc (http://www.gnat.com). --
+--                                                                          --
+------------------------------------------------------------------------------
+
+--  This package contains the routines used to deal with issuing warnings
+--  about uses of uninitialized variables and unused with's. It also has
+--  some unrelated routines related to the generation of warnings.
+
+with Types; use Types;
+
+package Sem_Warn is
+
+   ------------------------------------------
+   -- Routines to Handle Unused References --
+   ------------------------------------------
+
+   procedure Check_References (E : Entity_Id; Anod : Node_Id := Empty);
+   --  Called at the end of processing a declarative region. The entity E
+   --  is the entity for the scope. All entities declared in the region,
+   --  as indicated by First_Entity and the entity chain, are checked to
+   --  see if they are variables for which warnings need to be posted for
+   --  either no assignments, or a use before an assignment or no references
+   --  at all. The Anod node is present for the case of an accept statement,
+   --  and references the accept statement. This is used to place the warning
+   --  messages in the right place.
+
+   procedure Check_Unset_Reference (N : Node_Id);
+   --  N is the node for an expression which occurs in a reference position,
+   --  e.g. as the right side of an assignment. This procedure checks to see
+   --  if the node is a reference to a variable entity where the entity has
+   --  Not_Assigned set. If so, the Unset_Reference field is set if it is not
+   --  the first occurrence. No warning is posted, instead warnings will be
+   --  posted later by Check_References. The reason we do things that
+   --  way is that if there are no assignments anywhere, we prefer to flag
+   --  the entity, rather than a reference to it. Note that for the purposes
+   --  of this routine, a type conversion or qualified expression whose
+   --  expression is an entity is also processed. The reason that we do not
+   --  process these at the point of occurrence is that both these constructs
+   --  can occur in non-reference positions (e.g. as out parameters).
+
+   procedure Check_Unused_Withs (Spec_Unit : Unit_Number_Type := No_Unit);
+   --  This routine performs two kinds of checks. It checks that all with'ed
+   --  units are referenced, and that at least one entity of each with'ed
+   --  unit is referenced (the latter check catches units that are only
+   --  referenced in a use or package renaming statement). Appropriate
+   --  warning messages are generated if either of these situations is
+   --  detected.
+   --
+   --  A special case arises when a package body or a subprogram body with
+   --  a separate spec is being compiled. In this case, a with may appear
+   --  on the spec, but be needed only by the body. This still generates
+   --  a warning, but the text is different (the with is not redundant,
+   --  it is misplaced).
+   --
+   --  This special case is implemented by making an initial call to this
+   --  procedure with Spec_Unit set to the unit number of the separate spec.
+   --  This call does not generate any warning messages, but instead may
+   --  result in flags being set in the N_With_Clause node that record that
+   --  there was no use in the spec.
+   --
+   --  The main call (made after all units have been analyzed, with Spec_Unit
+   --  set to the default value of No_Unit) generates the required warnings
+   --  using the flags set by the initial call where appropriate to specialize
+   --  the text of the warning messages.
+
+   ----------------------------------------
+   -- Routines to Deal with Conditionals --
+   ----------------------------------------
+
+   --  These routines provide the necessary interfacing information to
+   --  correctly handle references in conditional structures (if/then/end-if,
+   --  or case/when/end-case). The issue here is that if a variable is only
+   --  set in some but not all branches of a conditional, then it is not
+   --  considered as being set by the conditional as a whole.
+
+   procedure Start_Unit;
+   --  Mark start of new unit to be analyzed, deals with fact that a call to
+   --  Rtsfind may cause new unit to be analyzed in middle of conditional.
+
+   procedure End_Unit;
+   --  Mark end of unit corresponding to previous call to Start_Unit
+
+   procedure Start_Conditional (If_Stmt : Boolean);
+   --  Mark start of a new conditional structure (an if-elsif-else-endif
+   --  or a case-when-end-case structure). If_Stmt is True for the IF
+   --  statement case, and False for the CASE statement case.
+
+   procedure Start_Branch (Loc : Source_Ptr);
+   --  Start processing of one branch of conditional previously marked by
+   --  a call to Start_Conditional (i.e. start of then/elsif/else statements
+   --  or set of statements after a when condition). The Loc value is the
+   --  source pointer to be used in warning messages concerning variables
+   --  not properly initialized in this branch. A branch is terminated by
+   --  either another Start_Branch or End_Conditional call.
+
+   procedure End_Conditional;
+   --  Terminate conditional started by previous Start_Conditional statement.
+
+   ---------------------
+   -- Output Routines --
+   ---------------------
+
+   procedure Output_Unreferenced_Messages;
+   --  Warnings about unreferenced entities are collected till the end of
+   --  the compilation process (see Check_Unset_Reference for further
+   --  details). This procedure outputs waiting warnings, if any.
+
+   ----------------------------
+   -- Other Warning Routines --
+   ----------------------------
+
+   procedure Warn_On_Known_Condition (C : Node_Id);
+   --  C is a node for a boolean expression resluting from a relational
+   --  or membership operation. If the expression has a compile time known
+   --  value, then a warning is output if all the following conditions hold:
+   --
+   --    1. Original expression comes from source. We don't want to generate
+   --       warnings for internally generated conditionals.
+   --
+   --    2. As noted above, the expression is a relational or membership
+   --       test, we don't want to generate warnings for boolean variables
+   --       since this is typical of conditional compilation in Ada.
+   --
+   --    3. The expression appears in a statement, rather than a declaration.
+   --       In practice, most occurrences in declarations are legitimate
+   --       conditionalizations, but occurrences in statements are often
+   --       errors for which the warning is useful.
+   --
+   --    4. The expression does not occur within an instantiation. A non-
+   --       static expression in a generic may become constant because of
+   --       the attributes of the actuals, and we do not want to warn on
+   --       these legitimate constant foldings.
+   --
+   --  If all these conditions are met, the warning is issued noting that
+   --  the result of the test is always false or always true as appropriate.
+
+end Sem_Warn;
diff --git a/gcc/ada/sequenio.ads b/gcc/ada/sequenio.ads
new file mode 100644 (file)
index 0000000..e191a5a
--- /dev/null
@@ -0,0 +1,21 @@
+------------------------------------------------------------------------------
+--                                                                          --
+--                         GNAT RUNTIME COMPONENTS                          --
+--                                                                          --
+--                        S E Q U E N T I A L  _ I O                        --
+--                                                                          --
+--                                 S p e c                                  --
+--                                                                          --
+--                            $Revision: 1.8 $                              --
+--                                                                          --
+-- This specification is adapted from the Ada Reference Manual for use with --
+-- GNAT.  In accordance with the copyright of that document, you can freely --
+-- copy and modify this specification,  provided that if you redistribute a --
+-- modified version,  any changes that you have made are clearly indicated. --
+--                                                                          --
+------------------------------------------------------------------------------
+
+pragma Ada_95;
+with Ada.Sequential_IO;
+
+generic package Sequential_IO renames Ada.Sequential_IO;
diff --git a/gcc/ada/sfn_scan.adb b/gcc/ada/sfn_scan.adb
new file mode 100644 (file)
index 0000000..57bc534
--- /dev/null
@@ -0,0 +1,659 @@
+------------------------------------------------------------------------------
+--                                                                          --
+--                         GNAT COMPILER COMPONENTS                         --
+--                                                                          --
+--                             S F N _ S C A N                              --
+--                                                                          --
+--                                 B o d y                                  --
+--                                                                          --
+--                            $Revision: 1.6 $
+--                                                                          --
+--          Copyright (C) 2000-2001 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- --
+-- ware  Foundation;  either version 2,  or (at your option) any later ver- --
+-- sion.  GNAT is distributed in the hope that it will be useful, but WITH- --
+-- OUT ANY WARRANTY;  without even the  implied warranty of MERCHANTABILITY --
+-- or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License --
+-- for  more details.  You should have  received  a copy of the GNU General --
+-- Public License  distributed with GNAT;  see file COPYING.  If not, write --
+-- to  the Free Software Foundation,  59 Temple Place - Suite 330,  Boston, --
+-- MA 02111-1307, USA.                                                      --
+--                                                                          --
+-- As a special exception,  if other files  instantiate  generics from this --
+-- unit, or you link  this unit with other files  to produce an executable, --
+-- this  unit  does not  by itself cause  the resulting  executable  to  be --
+-- covered  by the  GNU  General  Public  License.  This exception does not --
+-- however invalidate  any other reasons why  the executable file  might be --
+-- covered by the  GNU Public License.                                      --
+--                                                                          --
+-- GNAT was originally developed  by the GNAT team at  New York University. --
+-- It is now maintained by Ada Core Technologies Inc (http://www.gnat.com). --
+--                                                                          --
+------------------------------------------------------------------------------
+
+with Ada.Exceptions; use Ada.Exceptions;
+
+package body SFN_Scan is
+
+   use ASCII;
+   --  Allow easy access to control character definitions
+
+   type String_Ptr is access String;
+
+   S : String_Ptr;
+   --  Points to the gnat.adc input file
+
+   P : Natural;
+   --  Subscript of next character to process in S
+
+   Line_Num : Natural;
+   --  Current line number
+
+   Start_Of_Line : Natural;
+   --  Subscript of first character at start of current line
+
+   ----------------------
+   -- Local Procedures --
+   ----------------------
+
+   function Acquire_String (B : Natural; E : Natural) return String;
+   --  This function takes a string scanned out by Scan_String, strips
+   --  the enclosing quote characters and any internal doubled quote
+   --  characters, and returns the result as a String. The arguments
+   --  B and E are as returned from a call to Scan_String. The lower
+   --  bound of the string returned is always 1.
+
+   function Acquire_Unit_Name return String;
+   --  Skips white space, and then scans and returns a unit name. The
+   --  unit name is cased exactly as it appears in the source file.
+   --  The terminating character must be white space, or a comma or
+   --  a right parenthesis or end of file.
+
+   function At_EOF return Boolean;
+   pragma Inline (At_EOF);
+   --  Returns True if at end of file, False if not. Note that this
+   --  function does NOT skip white space, so P is always unchanged.
+
+   procedure Check_Not_At_EOF;
+   pragma Inline (Check_Not_At_EOF);
+   --  Skips past white space if any, and then raises Error if at
+   --  end of file. Otherwise returns with P skipped past whitespace.
+
+   function Check_File_Type return Character;
+   --  Skips white space if any, and then looks for any of the tokens
+   --  Spec_File_Name, Body_File_Name, or Subunit_File_Name. If one
+   --  of these is found then the value returned is 's', 'b' or 'u'
+   --  respectively, and P is bumped past the token. If none of
+   --  these tokens is found, then P is unchanged (except for
+   --  possible skip of white space), and a space is returned.
+
+   function Check_Token (T : String) return Boolean;
+   --  Skips white space if any, and then checks if the string at the
+   --  current location matches the given string T, and the character
+   --  immediately following is non-alphabetic, non-numeric. If so,
+   --  P is stepped past the token, and True is returned. If not,
+   --  P is unchanged (except for possibly skipping past whitespace),
+   --  and False is returned. S may contain only lower-case letters
+   --  ('a' .. 'z').
+
+   procedure Error (Err : String);
+   --  Called if an error is detected. Raises Syntax_Error_In_GNAT_ADC
+   --  with a message of the form gnat.adc:line:col: xxx, where xxx is
+   --  the string Err passed as a parameter.
+
+   procedure Require_Token (T : String);
+   --  Skips white space if any, and then requires the given string
+   --  to be present. If it is, the P is stepped past it, otherwise
+   --  Error is raised, since this is a syntax error. Require_Token
+   --  is used only for sequences of special characters, so there
+   --  is no issue of terminators, or casing of letters.
+
+   procedure Scan_String (B : out Natural; E : out Natural);
+   --  Skips white space if any, then requires that a double quote
+   --  or percent be present (start of string). Raises error if
+   --  neither of these two characters is found. Otherwise scans
+   --  out the string, and returns with P pointing past the
+   --  closing quote and S (B .. E) contains the characters of the
+   --  string (including the enclosing quotes, with internal quotes
+   --  still doubled). Raises Error if the string is malformed.
+
+   procedure Skip_WS;
+   --  Skips P past any white space characters (end of line
+   --  characters, spaces, comments, horizontal tab characters).
+
+   --------------------
+   -- Acquire_String --
+   --------------------
+
+   function Acquire_String (B : Natural; E : Natural) return String is
+      Str : String (1 .. E - B - 1);
+      Q   : constant Character := S (B);
+      J   : Natural;
+      Ptr : Natural;
+
+   begin
+      Ptr := B + 1;
+      J := 0;
+      while Ptr < E loop
+         J := J + 1;
+         Str (J) := S (Ptr);
+
+         if S (Ptr) = Q and then S (Ptr + 1) = Q then
+            Ptr := Ptr + 2;
+         else
+            Ptr := Ptr + 1;
+         end if;
+      end loop;
+
+      return Str (1 .. J);
+   end Acquire_String;
+
+   -----------------------
+   -- Acquire_Unit_Name --
+   -----------------------
+
+   function Acquire_Unit_Name return String is
+      B : Natural;
+
+   begin
+      Check_Not_At_EOF;
+      B := P;
+
+      while not At_EOF loop
+         exit when S (P) not in '0' .. '9'
+           and then S (P) /= '.'
+           and then S (P) /= '_'
+           and then not (S (P) = '[' and then S (P + 1) = '"')
+           and then not (S (P) = '"' and then S (P - 1) = '[')
+           and then not (S (P) = '"' and then S (P + 1) = ']')
+           and then not (S (P) = ']' and then S (P - 1) = '"')
+           and then S (P) < 'A';
+         P := P + 1;
+      end loop;
+
+      if P = B then
+         Error ("null unit name");
+      end if;
+
+      return S (B .. P - 1);
+   end Acquire_Unit_Name;
+
+   ------------
+   -- At_EOF --
+   ------------
+
+   function At_EOF return Boolean is
+   begin
+      return P > S'Last;
+   end At_EOF;
+
+   ---------------------
+   -- Check_File_Type --
+   ---------------------
+
+   function Check_File_Type return Character is
+   begin
+      if Check_Token ("spec_file_name") then
+         return 's';
+      elsif Check_Token ("body_file_name") then
+         return 'b';
+      elsif Check_Token ("subunit_file_name") then
+         return 'u';
+      else
+         return ' ';
+      end if;
+   end Check_File_Type;
+
+   ----------------------
+   -- Check_Not_At_EOF --
+   ----------------------
+
+   procedure Check_Not_At_EOF is
+   begin
+      Skip_WS;
+
+      if At_EOF then
+         Error ("unexpected end of file");
+      end if;
+
+      return;
+   end Check_Not_At_EOF;
+
+   -----------------
+   -- Check_Token --
+   -----------------
+
+   function Check_Token (T : String) return Boolean is
+      Save_P : Natural;
+      C : Character;
+
+   begin
+      Skip_WS;
+      Save_P := P;
+
+      for K in T'Range loop
+         if At_EOF then
+            P := Save_P;
+            return False;
+         end if;
+
+         C := S (P);
+
+         if C in 'A' .. 'Z' then
+            C := Character'Val (Character'Pos (C) +
+                                 (Character'Pos ('a') - Character'Pos ('A')));
+         end if;
+
+         if C /= T (K) then
+            P := Save_P;
+            return False;
+         end if;
+
+         P := P + 1;
+      end loop;
+
+      if At_EOF then
+         return True;
+      end if;
+
+      C := S (P);
+
+      if C in '0' .. '9'
+        or else C in 'a' .. 'z'
+        or else C in 'A' .. 'Z'
+        or else C > Character'Val (127)
+      then
+         P := Save_P;
+         return False;
+
+      else
+         return True;
+      end if;
+   end Check_Token;
+
+   -----------
+   -- Error --
+   -----------
+
+   procedure Error (Err : String) is
+      C : Natural := 0;
+      --  Column number
+
+      M : String (1 .. 80);
+      --  Buffer used to build resulting error msg
+
+      LM : Natural := 0;
+      --  Pointer to last set location in M
+
+      procedure Add_Nat (N : Natural);
+      --  Add chars of integer to error msg buffer
+
+      procedure Add_Nat (N : Natural) is
+      begin
+         if N > 9 then
+            Add_Nat (N / 10);
+         end if;
+
+         LM := LM + 1;
+         M (LM) := Character'Val (N mod 10 + Character'Pos ('0'));
+      end Add_Nat;
+
+   --  Start of processing for Error
+
+   begin
+      M (1 .. 9) := "gnat.adc:";
+      LM := 9;
+      Add_Nat (Line_Num);
+      LM := LM + 1;
+      M (LM) := ':';
+
+      --  Determine column number
+
+      for X in Start_Of_Line .. P loop
+         C := C + 1;
+
+         if S (X) = HT then
+            C := (C + 7) / 8 * 8;
+         end if;
+      end loop;
+
+      Add_Nat (C);
+      M (LM + 1) := ':';
+      LM := LM + 1;
+      M (LM + 1) := ' ';
+      LM := LM + 1;
+
+      M (LM + 1 .. LM + Err'Length) := Err;
+      LM := LM + Err'Length;
+
+      Raise_Exception (Syntax_Error_In_GNAT_ADC'Identity, M (1 .. LM));
+   end Error;
+
+   -------------------
+   -- Require_Token --
+   -------------------
+
+   procedure Require_Token (T : String) is
+      SaveP : Natural;
+
+   begin
+      Skip_WS;
+      SaveP := P;
+
+      for J in T'Range loop
+
+         if At_EOF or else S (P) /= T (J) then
+            declare
+               S : String (1 .. T'Length + 10);
+
+            begin
+               S (1 .. 9) := "missing """;
+               S (10 .. T'Length + 9) := T;
+               S (T'Length + 10) := '"';
+               P := SaveP;
+               Error (S);
+            end;
+
+         else
+            P := P + 1;
+         end if;
+      end loop;
+   end Require_Token;
+
+   ----------------------
+   -- Scan_SFN_Pragmas --
+   ----------------------
+
+   procedure Scan_SFN_Pragmas
+     (Source   : String;
+      SFN_Ptr  : Set_File_Name_Ptr;
+      SFNP_Ptr : Set_File_Name_Pattern_Ptr)
+   is
+      B, E : Natural;
+      Typ  : Character;
+      Cas  : Character;
+
+   begin
+      Line_Num := 1;
+      S := Source'Unrestricted_Access;
+      P := Source'First;
+      Start_Of_Line := P;
+
+      --  Loop through pragmas in file
+
+      Main_Scan_Loop : loop
+         Skip_WS;
+         exit Main_Scan_Loop when At_EOF;
+
+         --  Error if something other than pragma
+
+         if not Check_Token ("pragma") then
+            Error ("non pragma encountered");
+         end if;
+
+         --  Source_File_Name pragma case
+
+         if Check_Token ("source_file_name") then
+            Require_Token ("(");
+
+            Typ := Check_File_Type;
+
+            --  First format, with unit name first
+
+            if Typ = ' ' then
+               if Check_Token ("unit_name") then
+                  Require_Token ("=>");
+               end if;
+
+               declare
+                  U : constant String := Acquire_Unit_Name;
+
+               begin
+                  Require_Token (",");
+                  Typ := Check_File_Type;
+
+                  if Typ /= 's' and then Typ /= 'b' then
+                     Error ("bad pragma");
+                  end if;
+
+                  Require_Token ("=>");
+                  Scan_String (B, E);
+
+                  declare
+                     F : constant String := Acquire_String (B, E);
+
+                  begin
+                     Require_Token (")");
+                     Require_Token (";");
+                     SFN_Ptr.all (Typ, U, F);
+                  end;
+               end;
+
+            --  Second format with pattern string
+
+            else
+               Require_Token ("=>");
+               Scan_String (B, E);
+
+               declare
+                  Pat : constant String := Acquire_String (B, E);
+                  Nas : Natural := 0;
+
+               begin
+                  --  Check exactly one asterisk
+
+                  for J in Pat'Range loop
+                     if Pat (J) = '*' then
+                        Nas := Nas + 1;
+                     end if;
+                  end loop;
+
+                  if Nas /= 1 then
+                     Error ("** not allowed");
+                  end if;
+
+                  B := 0;
+                  E := 0;
+                  Cas := ' ';
+
+                  --  Loop to scan out Casing or Dot_Replacement parameters
+
+                  loop
+                     Check_Not_At_EOF;
+                     exit when S (P) = ')';
+                     Require_Token (",");
+
+                     if Check_Token ("casing") then
+                        Require_Token ("=>");
+
+                        if Cas /= ' ' then
+                           Error ("duplicate casing argument");
+                        elsif Check_Token ("lowercase") then
+                           Cas := 'l';
+                        elsif Check_Token ("uppercase") then
+                           Cas := 'u';
+                        elsif Check_Token ("mixedcase") then
+                           Cas := 'm';
+                        else
+                           Error ("invalid casing argument");
+                        end if;
+
+                     elsif Check_Token ("dot_replacement") then
+                        Require_Token ("=>");
+
+                        if E /= 0 then
+                           Error ("duplicate dot_replacement");
+                        else
+                           Scan_String (B, E);
+                        end if;
+
+                     else
+                        Error ("invalid argument");
+                     end if;
+                  end loop;
+
+                  Require_Token (")");
+                  Require_Token (";");
+
+                  if Cas = ' ' then
+                     Cas := 'l';
+                  end if;
+
+                  if E = 0 then
+                     SFNP_Ptr.all (Pat, Typ, ".", Cas);
+
+                  else
+                     declare
+                        Dot : constant String := Acquire_String (B, E);
+
+                     begin
+                        SFNP_Ptr.all (Pat, Typ, Dot, Cas);
+                     end;
+                  end if;
+               end;
+            end if;
+
+         --  Some other pragma, scan to semicolon at end of pragma
+
+         else
+            Skip_Loop : loop
+               exit Main_Scan_Loop when At_EOF;
+               exit Skip_Loop when S (P) = ';';
+
+               if S (P) = '"' or else S (P) = '%' then
+                  Scan_String (B, E);
+               else
+                  P := P + 1;
+               end if;
+            end loop Skip_Loop;
+
+            --  We successfuly skipped to semicolon, so skip past it
+
+            P := P + 1;
+         end if;
+      end loop Main_Scan_Loop;
+
+   exception
+      when others =>
+         Cursor := P - S'First + 1;
+         raise;
+   end Scan_SFN_Pragmas;
+
+   -----------------
+   -- Scan_String --
+   -----------------
+
+   procedure Scan_String (B : out Natural; E : out Natural) is
+      Q : Character;
+
+   begin
+      Check_Not_At_EOF;
+
+      if S (P) = '"' then
+         Q := '"';
+      elsif S (P) = '%' then
+         Q := '%';
+      else
+         Error ("bad string");
+         Q := '"';
+      end if;
+
+      --  Scan out the string, B points to first char
+
+      B := P;
+      P := P + 1;
+
+      loop
+         if At_EOF or else S (P) = LF or else S (P) = CR then
+            Error ("missing string quote");
+
+         elsif S (P) = HT then
+            Error ("tab character in string");
+
+         elsif S (P) /= Q then
+            P := P + 1;
+
+         --  We have a quote
+
+         else
+            P := P + 1;
+
+            --  Check for doubled quote
+
+            if not At_EOF and then S (P) = Q then
+               P := P + 1;
+
+            --  Otherwise this is the terminating quote
+
+            else
+               E := P - 1;
+               return;
+            end if;
+         end if;
+      end loop;
+   end Scan_String;
+
+   -------------
+   -- Skip_WS --
+   -------------
+
+   procedure Skip_WS is
+   begin
+      WS_Scan : while not At_EOF loop
+         case S (P) is
+
+            --  End of physical line
+
+            when CR | LF =>
+               Line_Num := Line_Num + 1;
+               P := P + 1;
+
+               while not At_EOF
+                 and then (S (P) = CR or else S (P) = LF)
+               loop
+                  Line_Num := Line_Num + 1;
+                  P := P + 1;
+               end loop;
+
+               Start_Of_Line := P;
+
+            --  All other cases of white space characters
+
+            when ' ' | FF | VT | HT =>
+               P := P + 1;
+
+            --  Comment
+
+            when '-' =>
+               P := P + 1;
+
+               if At_EOF then
+                  Error ("bad comment");
+
+               elsif S (P) = '-' then
+                  P := P + 1;
+
+                  while not At_EOF loop
+                     case S (P) is
+                        when CR | LF | FF | VT =>
+                           exit;
+                        when others =>
+                           P := P + 1;
+                     end case;
+                  end loop;
+
+               else
+                  P := P - 1;
+                  exit WS_Scan;
+               end if;
+
+            when others =>
+               exit WS_Scan;
+
+         end case;
+      end loop WS_Scan;
+   end Skip_WS;
+
+end SFN_Scan;
diff --git a/gcc/ada/sfn_scan.ads b/gcc/ada/sfn_scan.ads
new file mode 100644 (file)
index 0000000..ed84fc6
--- /dev/null
@@ -0,0 +1,94 @@
+------------------------------------------------------------------------------
+--                                                                          --
+--                         GNAT COMPILER COMPONENTS                         --
+--                                                                          --
+--                             S F N _ S C A N                              --
+--                                                                          --
+--                                 S p e c                                  --
+--                                                                          --
+--                            $Revision: 1.2 $
+--                                                                          --
+--          Copyright (C) 2000-2001 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- --
+-- ware  Foundation;  either version 2,  or (at your option) any later ver- --
+-- sion.  GNAT is distributed in the hope that it will be useful, but WITH- --
+-- OUT ANY WARRANTY;  without even the  implied warranty of MERCHANTABILITY --
+-- or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License --
+-- for  more details.  You should have  received  a copy of the GNU General --
+-- Public License  distributed with GNAT;  see file COPYING.  If not, write --
+-- to  the Free Software Foundation,  59 Temple Place - Suite 330,  Boston, --
+-- MA 02111-1307, USA.                                                      --
+--                                                                          --
+-- GNAT was originally developed  by the GNAT team at  New York University. --
+-- It is now maintained by Ada Core Technologies Inc (http://www.gnat.com). --
+--                                                                          --
+------------------------------------------------------------------------------
+
+--  This package provides a stand alone capability for scanning a gnat.adc
+--  file for Source_File_Name pragmas. This is for use in tools other than
+--  the compiler, which want to scan source file name pragmas without the
+--  overhead of the full compiler scanner and parser.
+
+--  Note that neither the package spec, nor the package body, of this
+--  unit contains any with statements at all. This is a compeltely
+--  independent package, suitable for incorporation into tools that do
+--  not access any other units in the GNAT compiler or tools sources.
+
+--  This package is NOT task safe, so multiple tasks that may call the
+--  Scan_SFN_Pragmas procedure at the same time are responsibible for
+--  avoiding such multiple calls by appropriate synchronization.
+
+package SFN_Scan is
+
+   --  The call to SFN_Scan passes pointers to two procedures that are
+   --  used to store the results of scanning any Source_File_Name pragmas
+   --  that are encountered. The following access types define the form
+   --  of these procedures:
+
+   type Set_File_Name_Ptr is access
+     procedure (Typ : Character; U : String; F : String);
+   --  The procedure with this profile is called when a Source_File_Name
+   --  pragma of the form having a unit name parameter. Typ is 'b' for
+   --  a body file name, and 's' for a spec file name. U is a string that
+   --  contains the unit name, exactly as it appeared in the source file,
+   --  and F is the file taken from the second parameter.
+
+   type Set_File_Name_Pattern_Ptr is access
+     procedure (Pat : String; Typ : Character; Dot : String; Cas : Character);
+   --  This is called to process a Source_File_Name pragma whose first
+   --  argument is a file pattern. Pat is this pattern string, which
+   --  contains an asterisk to correspond to the unit. Typ is one of
+   --  ('b'/'s'/'u') for body/spec/subunit, Dot is the separator string
+   --  for child/subunit names (default is "."), and Cas is one of
+   --  ('l'/'u'/'m') indicating the required case for the file name.
+   --  The default setting for Cas is 'l' if no parameter is present.
+
+   Cursor : Natural;
+   --  Used to record the cursor value if a syntax error is found
+
+   Syntax_Error_In_GNAT_ADC : exception;
+   --  Exception raised if a syntax error is found
+
+   procedure Scan_SFN_Pragmas
+     (Source   : String;
+      SFN_Ptr  : Set_File_Name_Ptr;
+      SFNP_Ptr : Set_File_Name_Pattern_Ptr);
+   --  This is the procedure called to scan a gnat.adc file. The Source
+   --  parameter points to the full text of the file, with normal line end
+   --  characters, in the format normally read by the compiler. The two
+   --  parameters SFN_Ptr and SFNP_Ptr point to procedures that will be
+   --  called to register Source_File_Name pragmas as they are found.
+   --
+   --  If a syntax error is found, then Syntax_Error_In_GNAT_ADC is raised,
+   --  and the location SFN_Scan.Cursor contains the approximate index of
+   --  the error in the source string.
+   --
+   --  The scan assumes that it is dealing with a valid gnat.adc file,
+   --  that includes only pragmas and comments. It does not do a full
+   --  syntax correctness scan by any means, but if it does find anything
+   --  that it can tell is wrong it will immediately raise the exception
+   --  to indicate the aproximate location of the error
+
+end SFN_Scan;
diff --git a/gcc/ada/sinfo-cn.adb b/gcc/ada/sinfo-cn.adb
new file mode 100644 (file)
index 0000000..33e6da6
--- /dev/null
@@ -0,0 +1,114 @@
+------------------------------------------------------------------------------
+--                                                                          --
+--                         GNAT COMPILER COMPONENTS                         --
+--                                                                          --
+--                             S I N F O . C N                              --
+--                                                                          --
+--                                 B o d y                                  --
+--                                                                          --
+--                            $Revision: 1.7 $
+--                                                                          --
+--          Copyright (C) 1992-2001 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- --
+-- ware  Foundation;  either version 2,  or (at your option) any later ver- --
+-- sion.  GNAT is distributed in the hope that it will be useful, but WITH- --
+-- OUT ANY WARRANTY;  without even the  implied warranty of MERCHANTABILITY --
+-- or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License --
+-- for  more details.  You should have  received  a copy of the GNU General --
+-- Public License  distributed with GNAT;  see file COPYING.  If not, write --
+-- to  the Free Software Foundation,  59 Temple Place - Suite 330,  Boston, --
+-- MA 02111-1307, USA.                                                      --
+--                                                                          --
+-- GNAT was originally developed  by the GNAT team at  New York University. --
+-- It is now maintained by Ada Core Technologies Inc (http://www.gnat.com). --
+--                                                                          --
+------------------------------------------------------------------------------
+
+--  This child package of Sinfo contains some routines that permit in place
+--  alteration of existing tree nodes by changing the value in the Nkind
+--  field. Since Nkind functions logically in a manner similart to a variant
+--  record discriminant part, such alterations cannot be permitted in a
+--  general manner, but in some specific cases, the fields of related nodes
+--  have been deliberately layed out in a manner that permits such alteration.
+--  that determin
+
+with Atree; use Atree;
+
+package body Sinfo.CN is
+
+   use Atree.Unchecked_Access;
+   --  This package is one of the few packages which is allowed to make direct
+   --  references to tree nodes (since it is in the business of providing a
+   --  higher level of tree access which other clients are expected to use and
+   --  which implements checks).
+
+   ------------------------------------------------------------
+   -- Change_Character_Literal_To_Defining_Character_Literal --
+   ------------------------------------------------------------
+
+   procedure Change_Character_Literal_To_Defining_Character_Literal
+     (N : in out Node_Id)
+   is
+   begin
+      Set_Nkind (N, N_Defining_Character_Literal);
+      N := Extend_Node (N);
+   end Change_Character_Literal_To_Defining_Character_Literal;
+
+   ------------------------------------
+   -- Change_Conversion_To_Unchecked --
+   ------------------------------------
+
+   procedure Change_Conversion_To_Unchecked (N : Node_Id) is
+   begin
+      Set_Do_Overflow_Check (N, False);
+      Set_Do_Tag_Check (N, False);
+      Set_Do_Length_Check (N, False);
+      Set_Nkind (N, N_Unchecked_Type_Conversion);
+   end Change_Conversion_To_Unchecked;
+
+   ----------------------------------------------
+   -- Change_Identifier_To_Defining_Identifier --
+   ----------------------------------------------
+
+   procedure Change_Identifier_To_Defining_Identifier (N : in out Node_Id) is
+   begin
+      Set_Nkind (N, N_Defining_Identifier);
+      N := Extend_Node (N);
+   end Change_Identifier_To_Defining_Identifier;
+
+   --------------------------------------------------------
+   -- Change_Operator_Symbol_To_Defining_Operator_Symbol --
+   --------------------------------------------------------
+
+   procedure Change_Operator_Symbol_To_Defining_Operator_Symbol
+     (N : in out Node_Id)
+   is
+   begin
+      Set_Nkind (N, N_Defining_Operator_Symbol);
+      Set_Node2 (N, Empty); -- Clear unused Str2 field
+      N := Extend_Node (N);
+   end Change_Operator_Symbol_To_Defining_Operator_Symbol;
+
+   ----------------------------------------------
+   -- Change_Operator_Symbol_To_String_Literal --
+   ----------------------------------------------
+
+   procedure Change_Operator_Symbol_To_String_Literal (N : Node_Id) is
+   begin
+      Set_Nkind (N, N_String_Literal);
+      Set_Node1 (N, Empty); -- clear Name1 field
+   end Change_Operator_Symbol_To_String_Literal;
+
+   ------------------------------------------------
+   -- Change_Selected_Component_To_Expanded_Name --
+   ------------------------------------------------
+
+   procedure Change_Selected_Component_To_Expanded_Name (N : Node_Id) is
+   begin
+      Set_Nkind (N, N_Expanded_Name);
+      Set_Chars (N, Chars (Selector_Name (N)));
+   end Change_Selected_Component_To_Expanded_Name;
+
+end Sinfo.CN;
diff --git a/gcc/ada/sinfo-cn.ads b/gcc/ada/sinfo-cn.ads
new file mode 100644 (file)
index 0000000..03dcae3
--- /dev/null
@@ -0,0 +1,71 @@
+------------------------------------------------------------------------------
+--                                                                          --
+--                         GNAT COMPILER COMPONENTS                         --
+--                                                                          --
+--                             S I N F O . C N                              --
+--                                                                          --
+--                                 S p e c                                  --
+--                                                                          --
+--                            $Revision: 1.9 $
+--                                                                          --
+--          Copyright (C) 1992-2001, 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- --
+-- ware  Foundation;  either version 2,  or (at your option) any later ver- --
+-- sion.  GNAT is distributed in the hope that it will be useful, but WITH- --
+-- OUT ANY WARRANTY;  without even the  implied warranty of MERCHANTABILITY --
+-- or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License --
+-- for  more details.  You should have  received  a copy of the GNU General --
+-- Public License  distributed with GNAT;  see file COPYING.  If not, write --
+-- to  the Free Software Foundation,  59 Temple Place - Suite 330,  Boston, --
+-- MA 02111-1307, USA.                                                      --
+--                                                                          --
+-- GNAT was originally developed  by the GNAT team at  New York University. --
+-- It is now maintained by Ada Core Technologies Inc (http://www.gnat.com). --
+--                                                                          --
+------------------------------------------------------------------------------
+
+--  This child package of Sinfo contains some routines that permit in place
+--  alteration of existing tree nodes by changing the value in the Nkind
+--  field. Since Nkind functions logically in a manner similar to a variant
+--  record discriminant part, such alterations cannot be permitted in a
+--  general manner, but in some specific cases, the fields of related nodes
+--  have been deliberately laid out in a manner that permits such alteration.
+
+package Sinfo.CN is
+
+   procedure Change_Identifier_To_Defining_Identifier (N : in out Node_Id);
+   --  N must refer to a node of type N_Identifier. This node is modified to
+   --  be of type N_Defining_Identifier. The scanner always returns identifiers
+   --  as N_Identifier. The parser then uses this routine to change the node
+   --  to be a defining identifier where the context demands it. This routine
+   --  also allocates the necessary extension node. Note that this procedure
+   --  may (but is not required to) change the Id of the node in question.
+
+   procedure Change_Character_Literal_To_Defining_Character_Literal
+     (N : in out Node_Id);
+   --  Similar processing for a character literal
+
+   procedure Change_Operator_Symbol_To_Defining_Operator_Symbol
+     (N : in out Node_Id);
+   --  Similar processing for an operator symbol
+
+   procedure Change_Conversion_To_Unchecked (N : Node_Id);
+   --  Change checked conversion node to unchecked conversion node, clearing
+   --  irrelevant check flags (other fields in the two nodes are identical)
+
+   procedure Change_Operator_Symbol_To_String_Literal (N : Node_Id);
+   --  The scanner returns any string that looks like an operator symbol as
+   --  a N_Operator_Symbol node. The parser then uses this procedure to change
+   --  the node to a normal N_String_Literal node if the context is not one
+   --  in which an operator symbol is required. There are some cases where the
+   --  parser cannot tell, in which case this transformation happens later on.
+
+   procedure Change_Selected_Component_To_Expanded_Name (N : Node_Id);
+   --  The parser always generates Selected_Component nodes. The semantics
+   --  modifies these to Expanded_Name nodes where appropriate. Note that
+   --  on return the Chars field is set to a copy of the contents of the
+   --  Chars field of the Selector_Name field.
+
+end Sinfo.CN;
diff --git a/gcc/ada/sinfo.adb b/gcc/ada/sinfo.adb
new file mode 100644 (file)
index 0000000..fb96678
--- /dev/null
@@ -0,0 +1,4798 @@
+------------------------------------------------------------------------------
+--                                                                          --
+--                         GNAT COMPILER COMPONENTS                         --
+--                                                                          --
+--                                S I N F O                                 --
+--                                                                          --
+--                                 B o d y                                  --
+--                                                                          --
+--                            $Revision: 1.314 $
+--                                                                          --
+--          Copyright (C) 1992-2001, 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- --
+-- ware  Foundation;  either version 2,  or (at your option) any later ver- --
+-- sion.  GNAT is distributed in the hope that it will be useful, but WITH- --
+-- OUT ANY WARRANTY;  without even the  implied warranty of MERCHANTABILITY --
+-- or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License --
+-- for  more details.  You should have  received  a copy of the GNU General --
+-- Public License  distributed with GNAT;  see file COPYING.  If not, write --
+-- to  the Free Software Foundation,  59 Temple Place - Suite 330,  Boston, --
+-- MA 02111-1307, USA.                                                      --
+--                                                                          --
+-- As a special exception,  if other files  instantiate  generics from this --
+-- unit, or you link  this unit with other files  to produce an executable, --
+-- this  unit  does not  by itself cause  the resulting  executable  to  be --
+-- covered  by the  GNU  General  Public  License.  This exception does not --
+-- however invalidate  any other reasons why  the executable file  might be --
+-- covered by the  GNU Public License.                                      --
+--                                                                          --
+-- GNAT was originally developed  by the GNAT team at  New York University. --
+-- It is now maintained by Ada Core Technologies Inc (http://www.gnat.com). --
+--                                                                          --
+------------------------------------------------------------------------------
+
+pragma Style_Checks (All_Checks);
+--  No subprogram ordering check, due to logical grouping
+
+with Atree; use Atree;
+
+package body Sinfo is
+
+   use Atree.Unchecked_Access;
+   --  This package is one of the few packages which is allowed to make direct
+   --  references to tree nodes (since it is in the business of providing a
+   --  higher level of tree access which other clients are expected to use and
+   --  which implements checks).
+
+   use Atree_Private_Part;
+   --  The only reason that we ask for direct access to the private part of
+   --  the tree package is so that we can directly reference the Nkind field
+   --  of nodes table entries. We do this since it helps the efficiency of
+   --  the Sinfo debugging checks considerably (note that when we are checking
+   --  Nkind values, we don't need to check for a valid node reference, because
+   --  we will check that anyway when we reference the field).
+
+   NT : Nodes.Table_Ptr renames Nodes.Table;
+   --  A short hand abbreviation, useful for the debugging checks
+
+   ----------------------------
+   -- Field Access Functions --
+   ----------------------------
+
+   function ABE_Is_Certain
+      (N : Node_Id) return Boolean is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_Formal_Package_Declaration
+        or else NT (N).Nkind = N_Function_Call
+        or else NT (N).Nkind = N_Function_Instantiation
+        or else NT (N).Nkind = N_Package_Instantiation
+        or else NT (N).Nkind = N_Procedure_Call_Statement
+        or else NT (N).Nkind = N_Procedure_Instantiation);
+      return Flag18 (N);
+   end ABE_Is_Certain;
+
+   function Abort_Present
+      (N : Node_Id) return Boolean is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_Requeue_Statement);
+      return Flag15 (N);
+   end Abort_Present;
+
+   function Abortable_Part
+      (N : Node_Id) return Node_Id is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_Asynchronous_Select);
+      return Node2 (N);
+   end Abortable_Part;
+
+   function Abstract_Present
+      (N : Node_Id) return Boolean is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_Derived_Type_Definition
+        or else NT (N).Nkind = N_Formal_Derived_Type_Definition
+        or else NT (N).Nkind = N_Formal_Private_Type_Definition
+        or else NT (N).Nkind = N_Private_Extension_Declaration
+        or else NT (N).Nkind = N_Private_Type_Declaration
+        or else NT (N).Nkind = N_Record_Definition);
+      return Flag4 (N);
+   end Abstract_Present;
+
+   function Accept_Handler_Records
+      (N : Node_Id) return List_Id is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_Accept_Alternative);
+      return List5 (N);
+   end Accept_Handler_Records;
+
+   function Accept_Statement
+      (N : Node_Id) return Node_Id is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_Accept_Alternative);
+      return Node2 (N);
+   end Accept_Statement;
+
+   function Access_Types_To_Process
+      (N : Node_Id) return Elist_Id is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_Freeze_Entity);
+      return Elist2 (N);
+   end Access_Types_To_Process;
+
+   function Actions
+      (N : Node_Id) return List_Id is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_And_Then
+        or else NT (N).Nkind = N_Compilation_Unit_Aux
+        or else NT (N).Nkind = N_Freeze_Entity
+        or else NT (N).Nkind = N_Or_Else);
+      return List1 (N);
+   end Actions;
+
+   function Activation_Chain_Entity
+      (N : Node_Id) return Node_Id is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_Block_Statement
+        or else NT (N).Nkind = N_Entry_Body
+        or else NT (N).Nkind = N_Generic_Package_Declaration
+        or else NT (N).Nkind = N_Package_Declaration
+        or else NT (N).Nkind = N_Subprogram_Body
+        or else NT (N).Nkind = N_Task_Body);
+      return Node3 (N);
+   end Activation_Chain_Entity;
+
+   function Acts_As_Spec
+      (N : Node_Id) return Boolean is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_Compilation_Unit
+        or else NT (N).Nkind = N_Subprogram_Body);
+      return Flag4 (N);
+   end Acts_As_Spec;
+
+   function Aggregate_Bounds
+      (N : Node_Id) return Node_Id is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_Aggregate);
+      return Node3 (N);
+   end Aggregate_Bounds;
+
+   function Aliased_Present
+      (N : Node_Id) return Boolean is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_Component_Declaration
+        or else NT (N).Nkind = N_Constrained_Array_Definition
+        or else NT (N).Nkind = N_Object_Declaration
+        or else NT (N).Nkind = N_Unconstrained_Array_Definition);
+      return Flag4 (N);
+   end Aliased_Present;
+
+   function All_Others
+      (N : Node_Id) return Boolean is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_Others_Choice);
+      return Flag11 (N);
+   end All_Others;
+
+   function All_Present
+      (N : Node_Id) return Boolean is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_Access_To_Object_Definition);
+      return Flag15 (N);
+   end All_Present;
+
+   function Alternatives
+      (N : Node_Id) return List_Id is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_Case_Statement);
+      return List4 (N);
+   end Alternatives;
+
+   function Ancestor_Part
+      (N : Node_Id) return Node_Id is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_Extension_Aggregate);
+      return Node3 (N);
+   end Ancestor_Part;
+
+   function Array_Aggregate
+      (N : Node_Id) return Node_Id is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_Enumeration_Representation_Clause);
+      return Node3 (N);
+   end Array_Aggregate;
+
+   function Assignment_OK
+      (N : Node_Id) return Boolean is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_Object_Declaration
+          or else NT (N).Nkind in N_Subexpr);
+      return Flag15 (N);
+   end Assignment_OK;
+
+   function At_End_Proc
+      (N : Node_Id) return Node_Id is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_Handled_Sequence_Of_Statements);
+      return Node1 (N);
+   end At_End_Proc;
+
+   function Attribute_Name
+      (N : Node_Id) return Name_Id is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_Attribute_Reference);
+      return Name2 (N);
+   end Attribute_Name;
+
+   function Aux_Decls_Node
+      (N : Node_Id) return Node_Id is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_Compilation_Unit);
+      return Node5 (N);
+   end Aux_Decls_Node;
+
+   function Backwards_OK
+      (N : Node_Id) return Boolean is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_Assignment_Statement);
+      return Flag6 (N);
+   end Backwards_OK;
+
+   function Bad_Is_Detected
+      (N : Node_Id) return Boolean is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_Subprogram_Body);
+      return Flag15 (N);
+   end Bad_Is_Detected;
+
+   function Body_Required
+      (N : Node_Id) return Boolean is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_Compilation_Unit);
+      return Flag13 (N);
+   end Body_Required;
+
+   function Body_To_Inline
+      (N : Node_Id) return Node_Id is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_Subprogram_Declaration);
+      return Node3 (N);
+   end Body_To_Inline;
+
+   function Box_Present
+      (N : Node_Id) return Boolean is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_Formal_Package_Declaration
+        or else NT (N).Nkind = N_Formal_Subprogram_Declaration);
+      return Flag15 (N);
+   end Box_Present;
+
+   function By_Ref
+      (N : Node_Id) return Boolean is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_Return_Statement);
+      return Flag5 (N);
+   end By_Ref;
+
+   function Char_Literal_Value
+      (N : Node_Id) return Char_Code is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_Character_Literal);
+      return Char_Code2 (N);
+   end Char_Literal_Value;
+
+   function Chars
+      (N : Node_Id) return Name_Id is
+   begin
+      pragma Assert (False
+          or else NT (N).Nkind in N_Has_Chars);
+      return Name1 (N);
+   end Chars;
+
+   function Choice_Parameter
+      (N : Node_Id) return Node_Id is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_Exception_Handler);
+      return Node2 (N);
+   end Choice_Parameter;
+
+   function Choices
+      (N : Node_Id) return List_Id is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_Component_Association);
+      return List1 (N);
+   end Choices;
+
+   function Compile_Time_Known_Aggregate
+      (N : Node_Id) return Boolean is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_Aggregate);
+      return Flag18 (N);
+   end Compile_Time_Known_Aggregate;
+
+   function Component_Associations
+      (N : Node_Id) return List_Id is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_Aggregate
+        or else NT (N).Nkind = N_Extension_Aggregate);
+      return List2 (N);
+   end Component_Associations;
+
+   function Component_Clauses
+      (N : Node_Id) return List_Id is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_Record_Representation_Clause);
+      return List3 (N);
+   end Component_Clauses;
+
+   function Component_Items
+      (N : Node_Id) return List_Id is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_Component_List);
+      return List3 (N);
+   end Component_Items;
+
+   function Component_List
+      (N : Node_Id) return Node_Id is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_Record_Definition
+        or else NT (N).Nkind = N_Variant);
+      return Node1 (N);
+   end Component_List;
+
+   function Component_Name
+      (N : Node_Id) return Node_Id is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_Component_Clause);
+      return Node1 (N);
+   end Component_Name;
+
+   function Condition
+      (N : Node_Id) return Node_Id is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_Accept_Alternative
+        or else NT (N).Nkind = N_Delay_Alternative
+        or else NT (N).Nkind = N_Elsif_Part
+        or else NT (N).Nkind = N_Entry_Body_Formal_Part
+        or else NT (N).Nkind = N_Exit_Statement
+        or else NT (N).Nkind = N_If_Statement
+        or else NT (N).Nkind = N_Iteration_Scheme
+        or else NT (N).Nkind = N_Raise_Constraint_Error
+        or else NT (N).Nkind = N_Raise_Program_Error
+        or else NT (N).Nkind = N_Raise_Storage_Error
+        or else NT (N).Nkind = N_Terminate_Alternative);
+      return Node1 (N);
+   end Condition;
+
+   function Condition_Actions
+      (N : Node_Id) return List_Id is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_Elsif_Part
+        or else NT (N).Nkind = N_Iteration_Scheme);
+      return List3 (N);
+   end Condition_Actions;
+
+   function Constant_Present
+      (N : Node_Id) return Boolean is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_Access_To_Object_Definition
+        or else NT (N).Nkind = N_Object_Declaration);
+      return Flag17 (N);
+   end Constant_Present;
+
+   function Constraint
+      (N : Node_Id) return Node_Id is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_Subtype_Indication);
+      return Node3 (N);
+   end Constraint;
+
+   function Constraints
+      (N : Node_Id) return List_Id is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_Index_Or_Discriminant_Constraint);
+      return List1 (N);
+   end Constraints;
+
+   function Context_Installed
+      (N : Node_Id) return Boolean is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_With_Clause);
+      return Flag13 (N);
+   end Context_Installed;
+
+   function Context_Items
+      (N : Node_Id) return List_Id is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_Compilation_Unit);
+      return List1 (N);
+   end Context_Items;
+
+   function Controlling_Argument
+      (N : Node_Id) return Node_Id is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_Function_Call
+        or else NT (N).Nkind = N_Procedure_Call_Statement);
+      return Node1 (N);
+   end Controlling_Argument;
+
+   function Conversion_OK
+      (N : Node_Id) return Boolean is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_Type_Conversion);
+      return Flag14 (N);
+   end Conversion_OK;
+
+   function Corresponding_Body
+      (N : Node_Id) return Node_Id is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_Generic_Package_Declaration
+        or else NT (N).Nkind = N_Generic_Subprogram_Declaration
+        or else NT (N).Nkind = N_Package_Body_Stub
+        or else NT (N).Nkind = N_Package_Declaration
+        or else NT (N).Nkind = N_Protected_Body_Stub
+        or else NT (N).Nkind = N_Protected_Type_Declaration
+        or else NT (N).Nkind = N_Subprogram_Body_Stub
+        or else NT (N).Nkind = N_Subprogram_Declaration
+        or else NT (N).Nkind = N_Task_Body_Stub
+        or else NT (N).Nkind = N_Task_Type_Declaration);
+      return Node5 (N);
+   end Corresponding_Body;
+
+   function Corresponding_Generic_Association
+      (N : Node_Id) return Node_Id is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_Object_Declaration
+        or else NT (N).Nkind = N_Object_Renaming_Declaration);
+      return Node5 (N);
+   end Corresponding_Generic_Association;
+
+   function Corresponding_Integer_Value
+      (N : Node_Id) return Uint is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_Real_Literal);
+      return Uint4 (N);
+   end Corresponding_Integer_Value;
+
+   function Corresponding_Spec
+      (N : Node_Id) return Node_Id is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_Package_Body
+        or else NT (N).Nkind = N_Protected_Body
+        or else NT (N).Nkind = N_Subprogram_Body
+        or else NT (N).Nkind = N_Subprogram_Renaming_Declaration
+        or else NT (N).Nkind = N_Task_Body
+        or else NT (N).Nkind = N_With_Clause);
+      return Node5 (N);
+   end Corresponding_Spec;
+
+   function Corresponding_Stub
+      (N : Node_Id) return Node_Id is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_Subunit);
+      return Node3 (N);
+   end Corresponding_Stub;
+
+   function Dcheck_Function
+      (N : Node_Id) return Entity_Id is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_Variant);
+      return Node5 (N);
+   end Dcheck_Function;
+
+   function Debug_Statement
+      (N : Node_Id) return Node_Id is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_Pragma);
+      return Node3 (N);
+   end Debug_Statement;
+
+   function Declarations
+      (N : Node_Id) return List_Id is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_Accept_Statement
+        or else NT (N).Nkind = N_Block_Statement
+        or else NT (N).Nkind = N_Compilation_Unit_Aux
+        or else NT (N).Nkind = N_Entry_Body
+        or else NT (N).Nkind = N_Package_Body
+        or else NT (N).Nkind = N_Protected_Body
+        or else NT (N).Nkind = N_Subprogram_Body
+        or else NT (N).Nkind = N_Task_Body);
+      return List2 (N);
+   end Declarations;
+
+   function Default_Expression
+      (N : Node_Id) return Node_Id is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_Parameter_Specification);
+      return Node5 (N);
+   end Default_Expression;
+
+   function Default_Name
+      (N : Node_Id) return Node_Id is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_Formal_Subprogram_Declaration);
+      return Node2 (N);
+   end Default_Name;
+
+   function Defining_Identifier
+      (N : Node_Id) return Entity_Id is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_Component_Declaration
+        or else NT (N).Nkind = N_Defining_Program_Unit_Name
+        or else NT (N).Nkind = N_Discriminant_Specification
+        or else NT (N).Nkind = N_Entry_Body
+        or else NT (N).Nkind = N_Entry_Declaration
+        or else NT (N).Nkind = N_Entry_Index_Specification
+        or else NT (N).Nkind = N_Exception_Declaration
+        or else NT (N).Nkind = N_Exception_Renaming_Declaration
+        or else NT (N).Nkind = N_Formal_Object_Declaration
+        or else NT (N).Nkind = N_Formal_Package_Declaration
+        or else NT (N).Nkind = N_Formal_Type_Declaration
+        or else NT (N).Nkind = N_Full_Type_Declaration
+        or else NT (N).Nkind = N_Implicit_Label_Declaration
+        or else NT (N).Nkind = N_Incomplete_Type_Declaration
+        or else NT (N).Nkind = N_Loop_Parameter_Specification
+        or else NT (N).Nkind = N_Number_Declaration
+        or else NT (N).Nkind = N_Object_Declaration
+        or else NT (N).Nkind = N_Object_Renaming_Declaration
+        or else NT (N).Nkind = N_Package_Body_Stub
+        or else NT (N).Nkind = N_Parameter_Specification
+        or else NT (N).Nkind = N_Private_Extension_Declaration
+        or else NT (N).Nkind = N_Private_Type_Declaration
+        or else NT (N).Nkind = N_Protected_Body
+        or else NT (N).Nkind = N_Protected_Body_Stub
+        or else NT (N).Nkind = N_Protected_Type_Declaration
+        or else NT (N).Nkind = N_Single_Protected_Declaration
+        or else NT (N).Nkind = N_Single_Task_Declaration
+        or else NT (N).Nkind = N_Subtype_Declaration
+        or else NT (N).Nkind = N_Task_Body
+        or else NT (N).Nkind = N_Task_Body_Stub
+        or else NT (N).Nkind = N_Task_Type_Declaration);
+      return Node1 (N);
+   end Defining_Identifier;
+
+   function Defining_Unit_Name
+      (N : Node_Id) return Node_Id is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_Function_Instantiation
+        or else NT (N).Nkind = N_Function_Specification
+        or else NT (N).Nkind = N_Generic_Function_Renaming_Declaration
+        or else NT (N).Nkind = N_Generic_Package_Renaming_Declaration
+        or else NT (N).Nkind = N_Generic_Procedure_Renaming_Declaration
+        or else NT (N).Nkind = N_Package_Body
+        or else NT (N).Nkind = N_Package_Instantiation
+        or else NT (N).Nkind = N_Package_Renaming_Declaration
+        or else NT (N).Nkind = N_Package_Specification
+        or else NT (N).Nkind = N_Procedure_Instantiation
+        or else NT (N).Nkind = N_Procedure_Specification);
+      return Node1 (N);
+   end Defining_Unit_Name;
+
+   function Delay_Alternative
+      (N : Node_Id) return Node_Id is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_Timed_Entry_Call);
+      return Node4 (N);
+   end Delay_Alternative;
+
+   function Delay_Finalize_Attach
+      (N : Node_Id) return Boolean is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_Object_Declaration);
+      return Flag14 (N);
+   end Delay_Finalize_Attach;
+
+   function Delay_Statement
+      (N : Node_Id) return Node_Id is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_Delay_Alternative);
+      return Node2 (N);
+   end Delay_Statement;
+
+   function Delta_Expression
+      (N : Node_Id) return Node_Id is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_Decimal_Fixed_Point_Definition
+        or else NT (N).Nkind = N_Delta_Constraint
+        or else NT (N).Nkind = N_Ordinary_Fixed_Point_Definition);
+      return Node3 (N);
+   end Delta_Expression;
+
+   function Digits_Expression
+      (N : Node_Id) return Node_Id is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_Decimal_Fixed_Point_Definition
+        or else NT (N).Nkind = N_Digits_Constraint
+        or else NT (N).Nkind = N_Floating_Point_Definition);
+      return Node2 (N);
+   end Digits_Expression;
+
+   function Discr_Check_Funcs_Built
+      (N : Node_Id) return Boolean is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_Full_Type_Declaration);
+      return Flag11 (N);
+   end Discr_Check_Funcs_Built;
+
+   function Discrete_Choices
+      (N : Node_Id) return List_Id is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_Case_Statement_Alternative
+        or else NT (N).Nkind = N_Variant);
+      return List4 (N);
+   end Discrete_Choices;
+
+   function Discrete_Range
+      (N : Node_Id) return Node_Id is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_Slice);
+      return Node4 (N);
+   end Discrete_Range;
+
+   function Discrete_Subtype_Definition
+      (N : Node_Id) return Node_Id is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_Entry_Declaration
+        or else NT (N).Nkind = N_Entry_Index_Specification
+        or else NT (N).Nkind = N_Loop_Parameter_Specification);
+      return Node4 (N);
+   end Discrete_Subtype_Definition;
+
+   function Discrete_Subtype_Definitions
+      (N : Node_Id) return List_Id is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_Constrained_Array_Definition);
+      return List2 (N);
+   end Discrete_Subtype_Definitions;
+
+   function Discriminant_Specifications
+      (N : Node_Id) return List_Id is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_Formal_Type_Declaration
+        or else NT (N).Nkind = N_Full_Type_Declaration
+        or else NT (N).Nkind = N_Incomplete_Type_Declaration
+        or else NT (N).Nkind = N_Private_Extension_Declaration
+        or else NT (N).Nkind = N_Private_Type_Declaration
+        or else NT (N).Nkind = N_Protected_Type_Declaration
+        or else NT (N).Nkind = N_Task_Type_Declaration);
+      return List4 (N);
+   end Discriminant_Specifications;
+
+   function Discriminant_Type
+      (N : Node_Id) return Node_Id is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_Discriminant_Specification);
+      return Node5 (N);
+   end Discriminant_Type;
+
+   function Do_Access_Check
+      (N : Node_Id) return Boolean is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_Attribute_Reference
+        or else NT (N).Nkind = N_Explicit_Dereference
+        or else NT (N).Nkind = N_Indexed_Component
+        or else NT (N).Nkind = N_Selected_Component
+        or else NT (N).Nkind = N_Slice);
+      return Flag11 (N);
+   end Do_Access_Check;
+
+   function Do_Accessibility_Check
+      (N : Node_Id) return Boolean is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_Parameter_Specification);
+      return Flag13 (N);
+   end Do_Accessibility_Check;
+
+   function Do_Discriminant_Check
+      (N : Node_Id) return Boolean is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_Selected_Component);
+      return Flag13 (N);
+   end Do_Discriminant_Check;
+
+   function Do_Division_Check
+      (N : Node_Id) return Boolean is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_Op_Divide
+        or else NT (N).Nkind = N_Op_Mod
+        or else NT (N).Nkind = N_Op_Rem);
+      return Flag13 (N);
+   end Do_Division_Check;
+
+   function Do_Length_Check
+      (N : Node_Id) return Boolean is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_Assignment_Statement
+        or else NT (N).Nkind = N_Op_And
+        or else NT (N).Nkind = N_Op_Or
+        or else NT (N).Nkind = N_Op_Xor
+        or else NT (N).Nkind = N_Type_Conversion);
+      return Flag4 (N);
+   end Do_Length_Check;
+
+   function Do_Overflow_Check
+      (N : Node_Id) return Boolean is
+   begin
+      pragma Assert (False
+          or else NT (N).Nkind in N_Op
+        or else NT (N).Nkind = N_Attribute_Reference
+        or else NT (N).Nkind = N_Type_Conversion);
+      return Flag17 (N);
+   end Do_Overflow_Check;
+
+   function Do_Range_Check
+      (N : Node_Id) return Boolean is
+   begin
+      pragma Assert (False
+          or else NT (N).Nkind in N_Subexpr);
+      return Flag9 (N);
+   end Do_Range_Check;
+
+   function Do_Storage_Check
+      (N : Node_Id) return Boolean is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_Allocator
+        or else NT (N).Nkind = N_Subprogram_Body);
+      return Flag17 (N);
+   end Do_Storage_Check;
+
+   function Do_Tag_Check
+      (N : Node_Id) return Boolean is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_Assignment_Statement
+        or else NT (N).Nkind = N_Function_Call
+        or else NT (N).Nkind = N_Procedure_Call_Statement
+        or else NT (N).Nkind = N_Return_Statement
+        or else NT (N).Nkind = N_Type_Conversion);
+      return Flag13 (N);
+   end Do_Tag_Check;
+
+   function Elaborate_All_Present
+      (N : Node_Id) return Boolean is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_With_Clause);
+      return Flag15 (N);
+   end Elaborate_All_Present;
+
+   function Elaborate_Present
+      (N : Node_Id) return Boolean is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_With_Clause);
+      return Flag4 (N);
+   end Elaborate_Present;
+
+   function Elaboration_Boolean
+      (N : Node_Id) return Node_Id is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_Function_Specification
+        or else NT (N).Nkind = N_Procedure_Specification);
+      return Node2 (N);
+   end Elaboration_Boolean;
+
+   function Else_Actions
+      (N : Node_Id) return List_Id is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_Conditional_Expression);
+      return List3 (N);
+   end Else_Actions;
+
+   function Else_Statements
+      (N : Node_Id) return List_Id is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_Conditional_Entry_Call
+        or else NT (N).Nkind = N_If_Statement
+        or else NT (N).Nkind = N_Selective_Accept);
+      return List4 (N);
+   end Else_Statements;
+
+   function Elsif_Parts
+      (N : Node_Id) return List_Id is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_If_Statement);
+      return List3 (N);
+   end Elsif_Parts;
+
+   function Enclosing_Variant
+      (N : Node_Id) return Node_Id is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_Variant);
+      return Node2 (N);
+   end Enclosing_Variant;
+
+   function End_Label
+      (N : Node_Id) return Node_Id is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_Handled_Sequence_Of_Statements
+        or else NT (N).Nkind = N_Loop_Statement
+        or else NT (N).Nkind = N_Package_Specification
+        or else NT (N).Nkind = N_Protected_Body
+        or else NT (N).Nkind = N_Protected_Definition
+        or else NT (N).Nkind = N_Record_Definition
+        or else NT (N).Nkind = N_Task_Definition);
+      return Node4 (N);
+   end End_Label;
+
+   function End_Span
+      (N : Node_Id) return Uint is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_Case_Statement
+        or else NT (N).Nkind = N_If_Statement);
+      return Uint5 (N);
+   end End_Span;
+
+   function Entity
+      (N : Node_Id) return Node_Id is
+   begin
+      pragma Assert (False
+          or else NT (N).Nkind in N_Has_Entity
+        or else NT (N).Nkind = N_Freeze_Entity);
+      return Node4 (N);
+   end Entity;
+
+   function Entry_Body_Formal_Part
+      (N : Node_Id) return Node_Id is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_Entry_Body);
+      return Node5 (N);
+   end Entry_Body_Formal_Part;
+
+   function Entry_Call_Alternative
+      (N : Node_Id) return Node_Id is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_Conditional_Entry_Call
+        or else NT (N).Nkind = N_Timed_Entry_Call);
+      return Node1 (N);
+   end Entry_Call_Alternative;
+
+   function Entry_Call_Statement
+      (N : Node_Id) return Node_Id is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_Entry_Call_Alternative);
+      return Node1 (N);
+   end Entry_Call_Statement;
+
+   function Entry_Direct_Name
+      (N : Node_Id) return Node_Id is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_Accept_Statement);
+      return Node1 (N);
+   end Entry_Direct_Name;
+
+   function Entry_Index
+      (N : Node_Id) return Node_Id is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_Accept_Statement);
+      return Node5 (N);
+   end Entry_Index;
+
+   function Entry_Index_Specification
+      (N : Node_Id) return Node_Id is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_Entry_Body_Formal_Part);
+      return Node4 (N);
+   end Entry_Index_Specification;
+
+   function Etype
+      (N : Node_Id) return Node_Id is
+   begin
+      pragma Assert (False
+         or else NT (N).Nkind in N_Has_Etype);
+      return Node5 (N);
+   end Etype;
+
+   function Exception_Choices
+      (N : Node_Id) return List_Id is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_Exception_Handler);
+      return List4 (N);
+   end Exception_Choices;
+
+   function Exception_Handlers
+      (N : Node_Id) return List_Id is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_Handled_Sequence_Of_Statements);
+      return List5 (N);
+   end Exception_Handlers;
+
+   function Exception_Junk
+     (N : Node_Id) return Boolean is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_Goto_Statement
+        or else NT (N).Nkind = N_Label
+        or else NT (N).Nkind = N_Object_Declaration
+        or else NT (N).Nkind = N_Subtype_Declaration);
+      return Flag11 (N);
+   end Exception_Junk;
+
+   function Expansion_Delayed
+     (N : Node_Id) return Boolean is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_Aggregate
+        or else NT (N).Nkind = N_Extension_Aggregate);
+      return Flag11 (N);
+   end Expansion_Delayed;
+
+   function Explicit_Actual_Parameter
+      (N : Node_Id) return Node_Id is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_Parameter_Association);
+      return Node3 (N);
+   end Explicit_Actual_Parameter;
+
+   function Explicit_Generic_Actual_Parameter
+      (N : Node_Id) return Node_Id is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_Generic_Association);
+      return Node1 (N);
+   end Explicit_Generic_Actual_Parameter;
+
+   function Expression
+      (N : Node_Id) return Node_Id is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_Allocator
+        or else NT (N).Nkind = N_Assignment_Statement
+        or else NT (N).Nkind = N_At_Clause
+        or else NT (N).Nkind = N_Attribute_Definition_Clause
+        or else NT (N).Nkind = N_Case_Statement
+        or else NT (N).Nkind = N_Code_Statement
+        or else NT (N).Nkind = N_Component_Association
+        or else NT (N).Nkind = N_Component_Declaration
+        or else NT (N).Nkind = N_Delay_Relative_Statement
+        or else NT (N).Nkind = N_Delay_Until_Statement
+        or else NT (N).Nkind = N_Discriminant_Association
+        or else NT (N).Nkind = N_Discriminant_Specification
+        or else NT (N).Nkind = N_Exception_Declaration
+        or else NT (N).Nkind = N_Formal_Object_Declaration
+        or else NT (N).Nkind = N_Free_Statement
+        or else NT (N).Nkind = N_Mod_Clause
+        or else NT (N).Nkind = N_Modular_Type_Definition
+        or else NT (N).Nkind = N_Number_Declaration
+        or else NT (N).Nkind = N_Object_Declaration
+        or else NT (N).Nkind = N_Parameter_Specification
+        or else NT (N).Nkind = N_Pragma_Argument_Association
+        or else NT (N).Nkind = N_Qualified_Expression
+        or else NT (N).Nkind = N_Return_Statement
+        or else NT (N).Nkind = N_Type_Conversion
+        or else NT (N).Nkind = N_Unchecked_Expression
+        or else NT (N).Nkind = N_Unchecked_Type_Conversion);
+      return Node3 (N);
+   end Expression;
+
+   function Expressions
+      (N : Node_Id) return List_Id is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_Aggregate
+        or else NT (N).Nkind = N_Attribute_Reference
+        or else NT (N).Nkind = N_Conditional_Expression
+        or else NT (N).Nkind = N_Extension_Aggregate
+        or else NT (N).Nkind = N_Indexed_Component);
+      return List1 (N);
+   end Expressions;
+
+   function First_Bit
+      (N : Node_Id) return Node_Id is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_Component_Clause);
+      return Node3 (N);
+   end First_Bit;
+
+   function First_Inlined_Subprogram
+      (N : Node_Id) return Entity_Id is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_Compilation_Unit);
+      return Node3 (N);
+   end First_Inlined_Subprogram;
+
+   function First_Name
+      (N : Node_Id) return Boolean is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_With_Clause);
+      return Flag5 (N);
+   end First_Name;
+
+   function First_Named_Actual
+      (N : Node_Id) return Node_Id is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_Entry_Call_Statement
+        or else NT (N).Nkind = N_Function_Call
+        or else NT (N).Nkind = N_Procedure_Call_Statement);
+      return Node4 (N);
+   end First_Named_Actual;
+
+   function First_Real_Statement
+      (N : Node_Id) return Node_Id is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_Handled_Sequence_Of_Statements);
+      return Node2 (N);
+   end First_Real_Statement;
+
+   function First_Subtype_Link
+      (N : Node_Id) return Entity_Id is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_Freeze_Entity);
+      return Node5 (N);
+   end First_Subtype_Link;
+
+   function Float_Truncate
+      (N : Node_Id) return Boolean is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_Type_Conversion);
+      return Flag11 (N);
+   end Float_Truncate;
+
+   function Formal_Type_Definition
+      (N : Node_Id) return Node_Id is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_Formal_Type_Declaration);
+      return Node3 (N);
+   end Formal_Type_Definition;
+
+   function Forwards_OK
+      (N : Node_Id) return Boolean is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_Assignment_Statement);
+      return Flag5 (N);
+   end Forwards_OK;
+
+   function From_At_Mod
+      (N : Node_Id) return Boolean is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_Attribute_Definition_Clause);
+      return Flag4 (N);
+   end From_At_Mod;
+
+   function Generic_Associations
+      (N : Node_Id) return List_Id is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_Formal_Package_Declaration
+        or else NT (N).Nkind = N_Function_Instantiation
+        or else NT (N).Nkind = N_Package_Instantiation
+        or else NT (N).Nkind = N_Procedure_Instantiation);
+      return List3 (N);
+   end Generic_Associations;
+
+   function Generic_Formal_Declarations
+      (N : Node_Id) return List_Id is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_Generic_Package_Declaration
+        or else NT (N).Nkind = N_Generic_Subprogram_Declaration);
+      return List2 (N);
+   end Generic_Formal_Declarations;
+
+   function Generic_Parent
+      (N : Node_Id) return Node_Id is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_Function_Specification
+        or else NT (N).Nkind = N_Package_Specification
+        or else NT (N).Nkind = N_Procedure_Specification);
+      return Node5 (N);
+   end Generic_Parent;
+
+   function Generic_Parent_Type
+      (N : Node_Id) return Node_Id is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_Subtype_Declaration);
+      return Node4 (N);
+   end Generic_Parent_Type;
+
+   function Handled_Statement_Sequence
+      (N : Node_Id) return Node_Id is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_Accept_Statement
+        or else NT (N).Nkind = N_Block_Statement
+        or else NT (N).Nkind = N_Entry_Body
+        or else NT (N).Nkind = N_Package_Body
+        or else NT (N).Nkind = N_Subprogram_Body
+        or else NT (N).Nkind = N_Task_Body);
+      return Node4 (N);
+   end Handled_Statement_Sequence;
+
+   function Handler_List_Entry
+      (N : Node_Id) return Node_Id is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_Object_Declaration);
+      return Node2 (N);
+   end Handler_List_Entry;
+
+   function Has_Created_Identifier
+      (N : Node_Id) return Boolean is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_Block_Statement
+        or else NT (N).Nkind = N_Loop_Statement);
+      return Flag15 (N);
+   end Has_Created_Identifier;
+
+   function Has_Dynamic_Length_Check
+      (N : Node_Id) return Boolean is
+   begin
+      return Flag10 (N);
+   end Has_Dynamic_Length_Check;
+
+   function Has_Dynamic_Range_Check
+      (N : Node_Id) return Boolean is
+   begin
+      return Flag12 (N);
+   end Has_Dynamic_Range_Check;
+
+   function Has_No_Elaboration_Code
+      (N : Node_Id) return Boolean is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_Compilation_Unit);
+      return Flag17 (N);
+   end Has_No_Elaboration_Code;
+
+   function Has_Priority_Pragma
+      (N : Node_Id) return Boolean is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_Protected_Definition
+        or else NT (N).Nkind = N_Subprogram_Body
+        or else NT (N).Nkind = N_Task_Definition);
+      return Flag6 (N);
+   end Has_Priority_Pragma;
+
+   function Has_Private_View
+      (N : Node_Id) return Boolean is
+   begin
+      pragma Assert (False
+         or else NT (N).Nkind in N_Op
+       or else NT (N).Nkind = N_Character_Literal
+       or else NT (N).Nkind = N_Expanded_Name
+       or else NT (N).Nkind = N_Identifier
+       or else NT (N).Nkind = N_Operator_Symbol);
+      return Flag11 (N);
+   end Has_Private_View;
+
+   function Has_Storage_Size_Pragma
+      (N : Node_Id) return Boolean is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_Task_Definition);
+      return Flag5 (N);
+   end Has_Storage_Size_Pragma;
+
+   function Has_Task_Info_Pragma
+      (N : Node_Id) return Boolean is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_Task_Definition);
+      return Flag7 (N);
+   end Has_Task_Info_Pragma;
+
+   function Has_Task_Name_Pragma
+      (N : Node_Id) return Boolean is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_Task_Definition);
+      return Flag8 (N);
+   end Has_Task_Name_Pragma;
+
+   function Has_Wide_Character
+      (N : Node_Id) return Boolean is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_String_Literal);
+      return Flag11 (N);
+   end Has_Wide_Character;
+
+   function Hidden_By_Use_Clause
+     (N : Node_Id) return Elist_Id is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_Use_Package_Clause
+        or else NT (N).Nkind = N_Use_Type_Clause);
+      return Elist4 (N);
+   end Hidden_By_Use_Clause;
+
+   function High_Bound
+      (N : Node_Id) return Node_Id is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_Range
+        or else NT (N).Nkind = N_Real_Range_Specification
+        or else NT (N).Nkind = N_Signed_Integer_Type_Definition);
+      return Node2 (N);
+   end High_Bound;
+
+   function Identifier
+      (N : Node_Id) return Node_Id is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_At_Clause
+        or else NT (N).Nkind = N_Block_Statement
+        or else NT (N).Nkind = N_Designator
+        or else NT (N).Nkind = N_Enumeration_Representation_Clause
+        or else NT (N).Nkind = N_Label
+        or else NT (N).Nkind = N_Loop_Statement
+        or else NT (N).Nkind = N_Record_Representation_Clause
+        or else NT (N).Nkind = N_Subprogram_Info);
+      return Node1 (N);
+   end Identifier;
+
+   function Implicit_With
+      (N : Node_Id) return Boolean is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_With_Clause);
+      return Flag17 (N);
+   end Implicit_With;
+
+   function In_Present
+      (N : Node_Id) return Boolean is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_Formal_Object_Declaration
+        or else NT (N).Nkind = N_Parameter_Specification);
+      return Flag15 (N);
+   end In_Present;
+
+   function Includes_Infinities
+      (N : Node_Id) return Boolean is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_Range);
+      return Flag11 (N);
+   end Includes_Infinities;
+
+   function Instance_Spec
+      (N : Node_Id) return Node_Id is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_Formal_Package_Declaration
+        or else NT (N).Nkind = N_Function_Instantiation
+        or else NT (N).Nkind = N_Package_Instantiation
+        or else NT (N).Nkind = N_Procedure_Instantiation);
+      return Node5 (N);
+   end Instance_Spec;
+
+   function Intval
+      (N : Node_Id) return Uint is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_Integer_Literal);
+      return Uint3 (N);
+   end Intval;
+
+   function Is_Asynchronous_Call_Block
+      (N : Node_Id) return Boolean is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_Block_Statement);
+      return Flag7 (N);
+   end Is_Asynchronous_Call_Block;
+
+   function Is_Component_Left_Opnd
+      (N : Node_Id) return Boolean is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_Op_Concat);
+      return Flag13 (N);
+   end Is_Component_Left_Opnd;
+
+   function Is_Component_Right_Opnd
+      (N : Node_Id) return Boolean is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_Op_Concat);
+      return Flag14 (N);
+   end Is_Component_Right_Opnd;
+
+   function Is_Controlling_Actual
+      (N : Node_Id) return Boolean is
+   begin
+      pragma Assert (False
+          or else NT (N).Nkind in N_Subexpr);
+      return Flag16 (N);
+   end Is_Controlling_Actual;
+
+   function Is_Machine_Number
+      (N : Node_Id) return Boolean is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_Real_Literal);
+      return Flag11 (N);
+   end Is_Machine_Number;
+
+   function Is_Overloaded
+      (N : Node_Id) return Boolean is
+   begin
+      pragma Assert (False
+          or else NT (N).Nkind in N_Subexpr);
+      return Flag5 (N);
+   end Is_Overloaded;
+
+   function Is_Power_Of_2_For_Shift
+      (N : Node_Id) return Boolean is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_Op_Expon);
+      return Flag13 (N);
+   end Is_Power_Of_2_For_Shift;
+
+   function Is_Protected_Subprogram_Body
+      (N : Node_Id) return Boolean is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_Subprogram_Body);
+      return Flag7 (N);
+   end Is_Protected_Subprogram_Body;
+
+   function Is_Static_Expression
+      (N : Node_Id) return Boolean is
+   begin
+      pragma Assert (False
+          or else NT (N).Nkind in N_Subexpr);
+      return Flag6 (N);
+   end Is_Static_Expression;
+
+   function Is_Subprogram_Descriptor
+      (N : Node_Id) return Boolean is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_Object_Declaration);
+      return Flag16 (N);
+   end Is_Subprogram_Descriptor;
+
+   function Is_Task_Allocation_Block
+      (N : Node_Id) return Boolean is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_Block_Statement);
+      return Flag6 (N);
+   end Is_Task_Allocation_Block;
+
+   function Is_Task_Master
+      (N : Node_Id) return Boolean is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_Block_Statement
+        or else NT (N).Nkind = N_Subprogram_Body
+        or else NT (N).Nkind = N_Task_Body);
+      return Flag5 (N);
+   end Is_Task_Master;
+
+   function Iteration_Scheme
+      (N : Node_Id) return Node_Id is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_Loop_Statement);
+      return Node2 (N);
+   end Iteration_Scheme;
+
+   function Itype
+      (N : Node_Id) return Node_Id is
+   begin
+      pragma Assert (False
+      or else NT (N).Nkind = N_Itype_Reference);
+      return Node1 (N);
+   end Itype;
+
+   function Kill_Range_Check
+      (N : Node_Id) return Boolean is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_Unchecked_Type_Conversion);
+      return Flag11 (N);
+   end Kill_Range_Check;
+
+   function Label_Construct
+      (N : Node_Id) return Node_Id is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_Implicit_Label_Declaration);
+      return Node2 (N);
+   end Label_Construct;
+
+   function Last_Bit
+      (N : Node_Id) return Node_Id is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_Component_Clause);
+      return Node4 (N);
+   end Last_Bit;
+
+   function Last_Name
+      (N : Node_Id) return Boolean is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_With_Clause);
+      return Flag6 (N);
+   end Last_Name;
+
+   function Left_Opnd
+      (N : Node_Id) return Node_Id is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_And_Then
+        or else NT (N).Nkind = N_In
+        or else NT (N).Nkind = N_Not_In
+        or else NT (N).Nkind = N_Or_Else
+          or else NT (N).Nkind in N_Binary_Op);
+      return Node2 (N);
+   end Left_Opnd;
+
+   function Library_Unit
+      (N : Node_Id) return Node_Id is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_Compilation_Unit
+        or else NT (N).Nkind = N_Package_Body_Stub
+        or else NT (N).Nkind = N_Protected_Body_Stub
+        or else NT (N).Nkind = N_Subprogram_Body_Stub
+        or else NT (N).Nkind = N_Task_Body_Stub
+        or else NT (N).Nkind = N_With_Clause);
+      return Node4 (N);
+   end Library_Unit;
+
+   function Limited_Present
+      (N : Node_Id) return Boolean is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_Formal_Private_Type_Definition
+        or else NT (N).Nkind = N_Private_Type_Declaration
+        or else NT (N).Nkind = N_Record_Definition);
+      return Flag17 (N);
+   end Limited_Present;
+
+   function Literals
+      (N : Node_Id) return List_Id is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_Enumeration_Type_Definition);
+      return List1 (N);
+   end Literals;
+
+   function Loop_Actions
+      (N : Node_Id) return List_Id is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_Component_Association);
+      return List2 (N);
+   end Loop_Actions;
+
+   function Loop_Parameter_Specification
+      (N : Node_Id) return Node_Id is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_Iteration_Scheme);
+      return Node4 (N);
+   end Loop_Parameter_Specification;
+
+   function Low_Bound
+      (N : Node_Id) return Node_Id is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_Range
+        or else NT (N).Nkind = N_Real_Range_Specification
+        or else NT (N).Nkind = N_Signed_Integer_Type_Definition);
+      return Node1 (N);
+   end Low_Bound;
+
+   function Mod_Clause
+      (N : Node_Id) return Node_Id is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_Record_Representation_Clause);
+      return Node2 (N);
+   end Mod_Clause;
+
+   function More_Ids
+      (N : Node_Id) return Boolean is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_Component_Declaration
+        or else NT (N).Nkind = N_Discriminant_Specification
+        or else NT (N).Nkind = N_Exception_Declaration
+        or else NT (N).Nkind = N_Formal_Object_Declaration
+        or else NT (N).Nkind = N_Number_Declaration
+        or else NT (N).Nkind = N_Object_Declaration
+        or else NT (N).Nkind = N_Parameter_Specification);
+      return Flag5 (N);
+   end More_Ids;
+
+   function Must_Not_Freeze
+      (N : Node_Id) return Boolean is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_Subtype_Indication
+          or else NT (N).Nkind in N_Subexpr);
+      return Flag8 (N);
+   end Must_Not_Freeze;
+
+   function Name
+      (N : Node_Id) return Node_Id is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_Assignment_Statement
+        or else NT (N).Nkind = N_Attribute_Definition_Clause
+        or else NT (N).Nkind = N_Defining_Program_Unit_Name
+        or else NT (N).Nkind = N_Designator
+        or else NT (N).Nkind = N_Entry_Call_Statement
+        or else NT (N).Nkind = N_Exception_Renaming_Declaration
+        or else NT (N).Nkind = N_Exit_Statement
+        or else NT (N).Nkind = N_Formal_Package_Declaration
+        or else NT (N).Nkind = N_Function_Call
+        or else NT (N).Nkind = N_Function_Instantiation
+        or else NT (N).Nkind = N_Generic_Function_Renaming_Declaration
+        or else NT (N).Nkind = N_Generic_Package_Renaming_Declaration
+        or else NT (N).Nkind = N_Generic_Procedure_Renaming_Declaration
+        or else NT (N).Nkind = N_Goto_Statement
+        or else NT (N).Nkind = N_Object_Renaming_Declaration
+        or else NT (N).Nkind = N_Package_Instantiation
+        or else NT (N).Nkind = N_Package_Renaming_Declaration
+        or else NT (N).Nkind = N_Procedure_Call_Statement
+        or else NT (N).Nkind = N_Procedure_Instantiation
+        or else NT (N).Nkind = N_Raise_Statement
+        or else NT (N).Nkind = N_Requeue_Statement
+        or else NT (N).Nkind = N_Subprogram_Renaming_Declaration
+        or else NT (N).Nkind = N_Subunit
+        or else NT (N).Nkind = N_Variant_Part
+        or else NT (N).Nkind = N_With_Clause
+        or else NT (N).Nkind = N_With_Type_Clause);
+      return Node2 (N);
+   end Name;
+
+   function Names
+      (N : Node_Id) return List_Id is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_Abort_Statement
+        or else NT (N).Nkind = N_Use_Package_Clause);
+      return List2 (N);
+   end Names;
+
+   function Next_Entity
+      (N : Node_Id) return Node_Id is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_Defining_Character_Literal
+        or else NT (N).Nkind = N_Defining_Identifier
+        or else NT (N).Nkind = N_Defining_Operator_Symbol);
+      return Node2 (N);
+   end Next_Entity;
+
+   function Next_Named_Actual
+      (N : Node_Id) return Node_Id is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_Parameter_Association);
+      return Node4 (N);
+   end Next_Named_Actual;
+
+   function Next_Rep_Item
+      (N : Node_Id) return Node_Id is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_Attribute_Definition_Clause
+        or else NT (N).Nkind = N_Enumeration_Representation_Clause
+        or else NT (N).Nkind = N_Pragma
+        or else NT (N).Nkind = N_Record_Representation_Clause);
+      return Node4 (N);
+   end Next_Rep_Item;
+
+   function Next_Use_Clause
+      (N : Node_Id) return Node_Id is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_Use_Package_Clause
+        or else NT (N).Nkind = N_Use_Type_Clause);
+      return Node3 (N);
+   end Next_Use_Clause;
+
+   function No_Ctrl_Actions
+      (N : Node_Id) return Boolean is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_Assignment_Statement);
+      return Flag7 (N);
+   end No_Ctrl_Actions;
+
+   function No_Entities_Ref_In_Spec
+      (N : Node_Id) return Boolean is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_With_Clause);
+      return Flag8 (N);
+   end No_Entities_Ref_In_Spec;
+
+   function No_Initialization
+      (N : Node_Id) return Boolean is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_Allocator
+        or else NT (N).Nkind = N_Object_Declaration);
+      return Flag13 (N);
+   end No_Initialization;
+
+   function Null_Present
+      (N : Node_Id) return Boolean is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_Component_List
+        or else NT (N).Nkind = N_Record_Definition);
+      return Flag13 (N);
+   end Null_Present;
+
+   function Null_Record_Present
+      (N : Node_Id) return Boolean is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_Aggregate
+        or else NT (N).Nkind = N_Extension_Aggregate);
+      return Flag17 (N);
+   end Null_Record_Present;
+
+   function Object_Definition
+      (N : Node_Id) return Node_Id is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_Object_Declaration);
+      return Node4 (N);
+   end Object_Definition;
+
+   function OK_For_Stream
+      (N : Node_Id) return Boolean is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_Attribute_Reference);
+      return Flag4 (N);
+   end OK_For_Stream;
+
+   function Original_Discriminant
+      (N : Node_Id) return Node_Id is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_Identifier);
+      return Node2 (N);
+   end Original_Discriminant;
+
+   function Others_Discrete_Choices
+      (N : Node_Id) return List_Id is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_Others_Choice);
+      return List1 (N);
+   end Others_Discrete_Choices;
+
+   function Out_Present
+      (N : Node_Id) return Boolean is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_Formal_Object_Declaration
+        or else NT (N).Nkind = N_Parameter_Specification);
+      return Flag17 (N);
+   end Out_Present;
+
+   function Parameter_Associations
+      (N : Node_Id) return List_Id is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_Entry_Call_Statement
+        or else NT (N).Nkind = N_Function_Call
+        or else NT (N).Nkind = N_Procedure_Call_Statement);
+      return List3 (N);
+   end Parameter_Associations;
+
+   function Parameter_List_Truncated
+      (N : Node_Id) return Boolean is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_Function_Call
+        or else NT (N).Nkind = N_Procedure_Call_Statement);
+      return Flag17 (N);
+   end Parameter_List_Truncated;
+
+   function Parameter_Specifications
+      (N : Node_Id) return List_Id is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_Accept_Statement
+        or else NT (N).Nkind = N_Access_Function_Definition
+        or else NT (N).Nkind = N_Access_Procedure_Definition
+        or else NT (N).Nkind = N_Entry_Body_Formal_Part
+        or else NT (N).Nkind = N_Entry_Declaration
+        or else NT (N).Nkind = N_Function_Specification
+        or else NT (N).Nkind = N_Procedure_Specification);
+      return List3 (N);
+   end Parameter_Specifications;
+
+   function Parameter_Type
+      (N : Node_Id) return Node_Id is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_Parameter_Specification);
+      return Node2 (N);
+   end Parameter_Type;
+
+   function Parent_Spec
+      (N : Node_Id) return Node_Id is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_Function_Instantiation
+        or else NT (N).Nkind = N_Generic_Function_Renaming_Declaration
+        or else NT (N).Nkind = N_Generic_Package_Declaration
+        or else NT (N).Nkind = N_Generic_Package_Renaming_Declaration
+        or else NT (N).Nkind = N_Generic_Procedure_Renaming_Declaration
+        or else NT (N).Nkind = N_Generic_Subprogram_Declaration
+        or else NT (N).Nkind = N_Package_Declaration
+        or else NT (N).Nkind = N_Package_Instantiation
+        or else NT (N).Nkind = N_Package_Renaming_Declaration
+        or else NT (N).Nkind = N_Procedure_Instantiation
+        or else NT (N).Nkind = N_Subprogram_Declaration
+        or else NT (N).Nkind = N_Subprogram_Renaming_Declaration);
+      return Node4 (N);
+   end Parent_Spec;
+
+   function Position
+      (N : Node_Id) return Node_Id is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_Component_Clause);
+      return Node2 (N);
+   end Position;
+
+   function Pragma_Argument_Associations
+      (N : Node_Id) return List_Id is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_Pragma);
+      return List2 (N);
+   end Pragma_Argument_Associations;
+
+   function Pragmas_After
+      (N : Node_Id) return List_Id is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_Compilation_Unit_Aux
+        or else NT (N).Nkind = N_Terminate_Alternative);
+      return List5 (N);
+   end Pragmas_After;
+
+   function Pragmas_Before
+      (N : Node_Id) return List_Id is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_Accept_Alternative
+        or else NT (N).Nkind = N_Delay_Alternative
+        or else NT (N).Nkind = N_Entry_Call_Alternative
+        or else NT (N).Nkind = N_Mod_Clause
+        or else NT (N).Nkind = N_Terminate_Alternative
+        or else NT (N).Nkind = N_Triggering_Alternative);
+      return List4 (N);
+   end Pragmas_Before;
+
+   function Prefix
+      (N : Node_Id) return Node_Id is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_Attribute_Reference
+        or else NT (N).Nkind = N_Expanded_Name
+        or else NT (N).Nkind = N_Explicit_Dereference
+        or else NT (N).Nkind = N_Indexed_Component
+        or else NT (N).Nkind = N_Reference
+        or else NT (N).Nkind = N_Selected_Component
+        or else NT (N).Nkind = N_Slice);
+      return Node3 (N);
+   end Prefix;
+
+   function Present_Expr
+      (N : Node_Id) return Uint is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_Variant);
+      return Uint3 (N);
+   end Present_Expr;
+
+   function Prev_Ids
+      (N : Node_Id) return Boolean is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_Component_Declaration
+        or else NT (N).Nkind = N_Discriminant_Specification
+        or else NT (N).Nkind = N_Exception_Declaration
+        or else NT (N).Nkind = N_Formal_Object_Declaration
+        or else NT (N).Nkind = N_Number_Declaration
+        or else NT (N).Nkind = N_Object_Declaration
+        or else NT (N).Nkind = N_Parameter_Specification);
+      return Flag6 (N);
+   end Prev_Ids;
+
+   function Print_In_Hex
+      (N : Node_Id) return Boolean is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_Integer_Literal);
+      return Flag13 (N);
+   end Print_In_Hex;
+
+   function Private_Declarations
+      (N : Node_Id) return List_Id is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_Package_Specification
+        or else NT (N).Nkind = N_Protected_Definition
+        or else NT (N).Nkind = N_Task_Definition);
+      return List3 (N);
+   end Private_Declarations;
+
+   function Private_Present
+      (N : Node_Id) return Boolean is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_Compilation_Unit
+        or else NT (N).Nkind = N_Formal_Derived_Type_Definition);
+      return Flag15 (N);
+   end Private_Present;
+
+   function Procedure_To_Call
+      (N : Node_Id) return Node_Id is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_Allocator
+        or else NT (N).Nkind = N_Free_Statement
+        or else NT (N).Nkind = N_Return_Statement);
+      return Node4 (N);
+   end Procedure_To_Call;
+
+   function Proper_Body
+      (N : Node_Id) return Node_Id is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_Subunit);
+      return Node1 (N);
+   end Proper_Body;
+
+   function Protected_Definition
+      (N : Node_Id) return Node_Id is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_Protected_Type_Declaration
+        or else NT (N).Nkind = N_Single_Protected_Declaration);
+      return Node3 (N);
+   end Protected_Definition;
+
+   function Protected_Present
+      (N : Node_Id) return Boolean is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_Access_Function_Definition
+        or else NT (N).Nkind = N_Access_Procedure_Definition);
+      return Flag15 (N);
+   end Protected_Present;
+
+   function Raises_Constraint_Error
+      (N : Node_Id) return Boolean is
+   begin
+      pragma Assert (False
+          or else NT (N).Nkind in N_Subexpr);
+      return Flag7 (N);
+   end Raises_Constraint_Error;
+
+   function Range_Constraint
+      (N : Node_Id) return Node_Id is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_Delta_Constraint
+        or else NT (N).Nkind = N_Digits_Constraint);
+      return Node4 (N);
+   end Range_Constraint;
+
+   function Range_Expression
+      (N : Node_Id) return Node_Id is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_Range_Constraint);
+      return Node4 (N);
+   end Range_Expression;
+
+   function Real_Range_Specification
+      (N : Node_Id) return Node_Id is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_Decimal_Fixed_Point_Definition
+        or else NT (N).Nkind = N_Floating_Point_Definition
+        or else NT (N).Nkind = N_Ordinary_Fixed_Point_Definition);
+      return Node4 (N);
+   end Real_Range_Specification;
+
+   function Realval
+      (N : Node_Id) return Ureal is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_Real_Literal);
+      return Ureal3 (N);
+   end Realval;
+
+   function Record_Extension_Part
+      (N : Node_Id) return Node_Id is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_Derived_Type_Definition);
+      return Node3 (N);
+   end Record_Extension_Part;
+
+   function Redundant_Use
+      (N : Node_Id) return Boolean is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_Attribute_Reference
+        or else NT (N).Nkind = N_Expanded_Name
+        or else NT (N).Nkind = N_Identifier);
+      return Flag13 (N);
+   end Redundant_Use;
+
+   function Return_Type
+      (N : Node_Id) return Node_Id is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_Return_Statement);
+      return Node2 (N);
+   end Return_Type;
+
+   function Reverse_Present
+      (N : Node_Id) return Boolean is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_Loop_Parameter_Specification);
+      return Flag15 (N);
+   end Reverse_Present;
+
+   function Right_Opnd
+      (N : Node_Id) return Node_Id is
+   begin
+      pragma Assert (False
+          or else NT (N).Nkind in N_Op
+        or else NT (N).Nkind = N_And_Then
+        or else NT (N).Nkind = N_In
+        or else NT (N).Nkind = N_Not_In
+        or else NT (N).Nkind = N_Or_Else);
+      return Node3 (N);
+   end Right_Opnd;
+
+   function Rounded_Result
+      (N : Node_Id) return Boolean is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_Op_Divide
+        or else NT (N).Nkind = N_Op_Multiply
+        or else NT (N).Nkind = N_Type_Conversion);
+      return Flag18 (N);
+   end Rounded_Result;
+
+   function Scope
+      (N : Node_Id) return Node_Id is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_Defining_Character_Literal
+        or else NT (N).Nkind = N_Defining_Identifier
+        or else NT (N).Nkind = N_Defining_Operator_Symbol);
+      return Node3 (N);
+   end Scope;
+
+   function Select_Alternatives
+      (N : Node_Id) return List_Id is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_Selective_Accept);
+      return List1 (N);
+   end Select_Alternatives;
+
+   function Selector_Name
+      (N : Node_Id) return Node_Id is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_Expanded_Name
+        or else NT (N).Nkind = N_Generic_Association
+        or else NT (N).Nkind = N_Parameter_Association
+        or else NT (N).Nkind = N_Selected_Component);
+      return Node2 (N);
+   end Selector_Name;
+
+   function Selector_Names
+      (N : Node_Id) return List_Id is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_Discriminant_Association);
+      return List1 (N);
+   end Selector_Names;
+
+   function Shift_Count_OK
+      (N : Node_Id) return Boolean is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_Op_Rotate_Left
+        or else NT (N).Nkind = N_Op_Rotate_Right
+        or else NT (N).Nkind = N_Op_Shift_Left
+        or else NT (N).Nkind = N_Op_Shift_Right
+        or else NT (N).Nkind = N_Op_Shift_Right_Arithmetic);
+      return Flag4 (N);
+   end Shift_Count_OK;
+
+   function Source_Type
+      (N : Node_Id) return Entity_Id is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_Validate_Unchecked_Conversion);
+      return Node1 (N);
+   end Source_Type;
+
+   function Specification
+      (N : Node_Id) return Node_Id is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_Abstract_Subprogram_Declaration
+        or else NT (N).Nkind = N_Formal_Subprogram_Declaration
+        or else NT (N).Nkind = N_Generic_Package_Declaration
+        or else NT (N).Nkind = N_Generic_Subprogram_Declaration
+        or else NT (N).Nkind = N_Package_Declaration
+        or else NT (N).Nkind = N_Subprogram_Body
+        or else NT (N).Nkind = N_Subprogram_Body_Stub
+        or else NT (N).Nkind = N_Subprogram_Declaration
+        or else NT (N).Nkind = N_Subprogram_Renaming_Declaration);
+      return Node1 (N);
+   end Specification;
+
+   function Statements
+      (N : Node_Id) return List_Id is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_Abortable_Part
+        or else NT (N).Nkind = N_Accept_Alternative
+        or else NT (N).Nkind = N_Case_Statement_Alternative
+        or else NT (N).Nkind = N_Delay_Alternative
+        or else NT (N).Nkind = N_Entry_Call_Alternative
+        or else NT (N).Nkind = N_Exception_Handler
+        or else NT (N).Nkind = N_Handled_Sequence_Of_Statements
+        or else NT (N).Nkind = N_Loop_Statement
+        or else NT (N).Nkind = N_Triggering_Alternative);
+      return List3 (N);
+   end Statements;
+
+   function Static_Processing_OK
+      (N : Node_Id) return Boolean is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_Aggregate);
+      return Flag4 (N);
+   end Static_Processing_OK;
+
+   function Storage_Pool
+      (N : Node_Id) return Node_Id is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_Allocator
+        or else NT (N).Nkind = N_Free_Statement
+        or else NT (N).Nkind = N_Return_Statement);
+      return Node1 (N);
+   end Storage_Pool;
+
+   function Strval
+      (N : Node_Id) return String_Id is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_Operator_Symbol
+        or else NT (N).Nkind = N_String_Literal);
+      return Str3 (N);
+   end Strval;
+
+   function Subtype_Indication
+      (N : Node_Id) return Node_Id is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_Access_To_Object_Definition
+        or else NT (N).Nkind = N_Component_Declaration
+        or else NT (N).Nkind = N_Constrained_Array_Definition
+        or else NT (N).Nkind = N_Derived_Type_Definition
+        or else NT (N).Nkind = N_Private_Extension_Declaration
+        or else NT (N).Nkind = N_Subtype_Declaration
+        or else NT (N).Nkind = N_Unconstrained_Array_Definition);
+      return Node5 (N);
+   end Subtype_Indication;
+
+   function Subtype_Mark
+      (N : Node_Id) return Node_Id is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_Access_Definition
+        or else NT (N).Nkind = N_Access_Function_Definition
+        or else NT (N).Nkind = N_Formal_Derived_Type_Definition
+        or else NT (N).Nkind = N_Formal_Object_Declaration
+        or else NT (N).Nkind = N_Function_Specification
+        or else NT (N).Nkind = N_Object_Renaming_Declaration
+        or else NT (N).Nkind = N_Qualified_Expression
+        or else NT (N).Nkind = N_Subtype_Indication
+        or else NT (N).Nkind = N_Type_Conversion
+        or else NT (N).Nkind = N_Unchecked_Type_Conversion);
+      return Node4 (N);
+   end Subtype_Mark;
+
+   function Subtype_Marks
+      (N : Node_Id) return List_Id is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_Unconstrained_Array_Definition
+        or else NT (N).Nkind = N_Use_Type_Clause);
+      return List2 (N);
+   end Subtype_Marks;
+
+   function Tagged_Present
+      (N : Node_Id) return Boolean is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_Formal_Private_Type_Definition
+        or else NT (N).Nkind = N_Private_Type_Declaration
+        or else NT (N).Nkind = N_Record_Definition
+        or else NT (N).Nkind = N_With_Type_Clause);
+      return Flag15 (N);
+   end Tagged_Present;
+
+   function Target_Type
+      (N : Node_Id) return Entity_Id is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_Validate_Unchecked_Conversion);
+      return Node2 (N);
+   end Target_Type;
+
+   function Task_Body_Procedure
+      (N : Node_Id) return Entity_Id is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_Task_Type_Declaration);
+      return Node2 (N);
+   end Task_Body_Procedure;
+
+   function Task_Definition
+      (N : Node_Id) return Node_Id is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_Single_Task_Declaration
+        or else NT (N).Nkind = N_Task_Type_Declaration);
+      return Node3 (N);
+   end Task_Definition;
+
+   function Then_Actions
+      (N : Node_Id) return List_Id is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_Conditional_Expression);
+      return List2 (N);
+   end Then_Actions;
+
+   function Then_Statements
+      (N : Node_Id) return List_Id is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_Elsif_Part
+        or else NT (N).Nkind = N_If_Statement);
+      return List2 (N);
+   end Then_Statements;
+
+   function Treat_Fixed_As_Integer
+      (N : Node_Id) return Boolean is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_Op_Divide
+        or else NT (N).Nkind = N_Op_Mod
+        or else NT (N).Nkind = N_Op_Multiply
+        or else NT (N).Nkind = N_Op_Rem);
+      return Flag14 (N);
+   end Treat_Fixed_As_Integer;
+
+   function Triggering_Alternative
+      (N : Node_Id) return Node_Id is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_Asynchronous_Select);
+      return Node1 (N);
+   end Triggering_Alternative;
+
+   function Triggering_Statement
+      (N : Node_Id) return Node_Id is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_Triggering_Alternative);
+      return Node1 (N);
+   end Triggering_Statement;
+
+   function TSS_Elist
+      (N : Node_Id) return Elist_Id is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_Freeze_Entity);
+      return Elist3 (N);
+   end TSS_Elist;
+
+   function Type_Definition
+      (N : Node_Id) return Node_Id is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_Full_Type_Declaration);
+      return Node3 (N);
+   end Type_Definition;
+
+   function Unit
+      (N : Node_Id) return Node_Id is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_Compilation_Unit);
+      return Node2 (N);
+   end Unit;
+
+   function Unknown_Discriminants_Present
+      (N : Node_Id) return Boolean is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_Formal_Type_Declaration
+        or else NT (N).Nkind = N_Incomplete_Type_Declaration
+        or else NT (N).Nkind = N_Private_Extension_Declaration
+        or else NT (N).Nkind = N_Private_Type_Declaration);
+      return Flag13 (N);
+   end Unknown_Discriminants_Present;
+
+   function Unreferenced_In_Spec
+      (N : Node_Id) return Boolean is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_With_Clause);
+      return Flag7 (N);
+   end Unreferenced_In_Spec;
+
+   function Variant_Part
+      (N : Node_Id) return Node_Id is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_Component_List);
+      return Node4 (N);
+   end Variant_Part;
+
+   function Variants
+      (N : Node_Id) return List_Id is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_Variant_Part);
+      return List1 (N);
+   end Variants;
+
+   function Visible_Declarations
+      (N : Node_Id) return List_Id is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_Package_Specification
+        or else NT (N).Nkind = N_Protected_Definition
+        or else NT (N).Nkind = N_Task_Definition);
+      return List2 (N);
+   end Visible_Declarations;
+
+   function Was_Originally_Stub
+      (N : Node_Id) return Boolean is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_Package_Body
+        or else NT (N).Nkind = N_Protected_Body
+        or else NT (N).Nkind = N_Subprogram_Body
+        or else NT (N).Nkind = N_Task_Body);
+      return Flag13 (N);
+   end Was_Originally_Stub;
+
+   function Zero_Cost_Handling
+      (N : Node_Id) return Boolean is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_Exception_Handler
+        or else NT (N).Nkind = N_Handled_Sequence_Of_Statements);
+      return Flag5 (N);
+   end Zero_Cost_Handling;
+
+   --------------------------
+   -- Field Set Procedures --
+   --------------------------
+
+   procedure Set_ABE_Is_Certain
+      (N : Node_Id; Val : Boolean := True) is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_Formal_Package_Declaration
+        or else NT (N).Nkind = N_Function_Call
+        or else NT (N).Nkind = N_Function_Instantiation
+        or else NT (N).Nkind = N_Package_Instantiation
+        or else NT (N).Nkind = N_Procedure_Call_Statement
+        or else NT (N).Nkind = N_Procedure_Instantiation);
+      Set_Flag18 (N, Val);
+   end Set_ABE_Is_Certain;
+
+   procedure Set_Abort_Present
+      (N : Node_Id; Val : Boolean := True) is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_Requeue_Statement);
+      Set_Flag15 (N, Val);
+   end Set_Abort_Present;
+
+   procedure Set_Abortable_Part
+      (N : Node_Id; Val : Node_Id) is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_Asynchronous_Select);
+      Set_Node2_With_Parent (N, Val);
+   end Set_Abortable_Part;
+
+   procedure Set_Abstract_Present
+      (N : Node_Id; Val : Boolean := True) is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_Derived_Type_Definition
+        or else NT (N).Nkind = N_Formal_Derived_Type_Definition
+        or else NT (N).Nkind = N_Formal_Private_Type_Definition
+        or else NT (N).Nkind = N_Private_Extension_Declaration
+        or else NT (N).Nkind = N_Private_Type_Declaration
+        or else NT (N).Nkind = N_Record_Definition);
+      Set_Flag4 (N, Val);
+   end Set_Abstract_Present;
+
+   procedure Set_Accept_Handler_Records
+      (N : Node_Id; Val : List_Id) is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_Accept_Alternative);
+      Set_List5 (N, Val); -- semantic field, no parent set
+   end Set_Accept_Handler_Records;
+
+   procedure Set_Accept_Statement
+      (N : Node_Id; Val : Node_Id) is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_Accept_Alternative);
+      Set_Node2_With_Parent (N, Val);
+   end Set_Accept_Statement;
+
+   procedure Set_Access_Types_To_Process
+      (N : Node_Id; Val : Elist_Id) is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_Freeze_Entity);
+      Set_Elist2 (N, Val); -- semantic field, no parent set
+   end Set_Access_Types_To_Process;
+
+   procedure Set_Actions
+      (N : Node_Id; Val : List_Id) is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_And_Then
+        or else NT (N).Nkind = N_Compilation_Unit_Aux
+        or else NT (N).Nkind = N_Freeze_Entity
+        or else NT (N).Nkind = N_Or_Else);
+      Set_List1_With_Parent (N, Val);
+   end Set_Actions;
+
+   procedure Set_Activation_Chain_Entity
+      (N : Node_Id; Val : Node_Id) is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_Block_Statement
+        or else NT (N).Nkind = N_Entry_Body
+        or else NT (N).Nkind = N_Generic_Package_Declaration
+        or else NT (N).Nkind = N_Package_Declaration
+        or else NT (N).Nkind = N_Subprogram_Body
+        or else NT (N).Nkind = N_Task_Body);
+      Set_Node3 (N, Val); -- semantic field, no parent set
+   end Set_Activation_Chain_Entity;
+
+   procedure Set_Acts_As_Spec
+      (N : Node_Id; Val : Boolean := True) is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_Compilation_Unit
+        or else NT (N).Nkind = N_Subprogram_Body);
+      Set_Flag4 (N, Val);
+   end Set_Acts_As_Spec;
+
+   procedure Set_Aggregate_Bounds
+      (N : Node_Id; Val : Node_Id) is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_Aggregate);
+      Set_Node3 (N, Val); -- semantic field, no parent set
+   end Set_Aggregate_Bounds;
+
+   procedure Set_Aliased_Present
+      (N : Node_Id; Val : Boolean := True) is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_Component_Declaration
+        or else NT (N).Nkind = N_Constrained_Array_Definition
+        or else NT (N).Nkind = N_Object_Declaration
+        or else NT (N).Nkind = N_Unconstrained_Array_Definition);
+      Set_Flag4 (N, Val);
+   end Set_Aliased_Present;
+
+   procedure Set_All_Others
+      (N : Node_Id; Val : Boolean := True) is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_Others_Choice);
+      Set_Flag11 (N, Val);
+   end Set_All_Others;
+
+   procedure Set_All_Present
+      (N : Node_Id; Val : Boolean := True) is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_Access_To_Object_Definition);
+      Set_Flag15 (N, Val);
+   end Set_All_Present;
+
+   procedure Set_Alternatives
+      (N : Node_Id; Val : List_Id) is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_Case_Statement);
+      Set_List4_With_Parent (N, Val);
+   end Set_Alternatives;
+
+   procedure Set_Ancestor_Part
+      (N : Node_Id; Val : Node_Id) is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_Extension_Aggregate);
+      Set_Node3_With_Parent (N, Val);
+   end Set_Ancestor_Part;
+
+   procedure Set_Array_Aggregate
+      (N : Node_Id; Val : Node_Id) is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_Enumeration_Representation_Clause);
+      Set_Node3_With_Parent (N, Val);
+   end Set_Array_Aggregate;
+
+   procedure Set_Assignment_OK
+      (N : Node_Id; Val : Boolean := True) is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_Object_Declaration
+          or else NT (N).Nkind in N_Subexpr);
+      Set_Flag15 (N, Val);
+   end Set_Assignment_OK;
+
+   procedure Set_At_End_Proc
+      (N : Node_Id; Val : Node_Id) is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_Handled_Sequence_Of_Statements);
+      Set_Node1 (N, Val);
+   end Set_At_End_Proc;
+
+   procedure Set_Attribute_Name
+      (N : Node_Id; Val : Name_Id) is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_Attribute_Reference);
+      Set_Name2 (N, Val);
+   end Set_Attribute_Name;
+
+   procedure Set_Aux_Decls_Node
+      (N : Node_Id; Val : Node_Id) is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_Compilation_Unit);
+      Set_Node5_With_Parent (N, Val);
+   end Set_Aux_Decls_Node;
+
+   procedure Set_Backwards_OK
+      (N : Node_Id; Val : Boolean := True) is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_Assignment_Statement);
+      Set_Flag6 (N, Val);
+   end Set_Backwards_OK;
+
+   procedure Set_Bad_Is_Detected
+      (N : Node_Id; Val : Boolean := True) is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_Subprogram_Body);
+      Set_Flag15 (N, Val);
+   end Set_Bad_Is_Detected;
+
+   procedure Set_Body_Required
+      (N : Node_Id; Val : Boolean := True) is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_Compilation_Unit);
+      Set_Flag13 (N, Val);
+   end Set_Body_Required;
+
+   procedure Set_Body_To_Inline
+      (N : Node_Id; Val : Node_Id) is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_Subprogram_Declaration);
+      Set_Node3 (N, Val);
+   end Set_Body_To_Inline;
+
+   procedure Set_Box_Present
+      (N : Node_Id; Val : Boolean := True) is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_Formal_Package_Declaration
+        or else NT (N).Nkind = N_Formal_Subprogram_Declaration);
+      Set_Flag15 (N, Val);
+   end Set_Box_Present;
+
+   procedure Set_By_Ref
+      (N : Node_Id; Val : Boolean := True) is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_Return_Statement);
+      Set_Flag5 (N, Val);
+   end Set_By_Ref;
+
+   procedure Set_Char_Literal_Value
+      (N : Node_Id; Val : Char_Code) is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_Character_Literal);
+      Set_Char_Code2 (N, Val);
+   end Set_Char_Literal_Value;
+
+   procedure Set_Chars
+      (N : Node_Id; Val : Name_Id) is
+   begin
+      pragma Assert (False
+          or else NT (N).Nkind in N_Has_Chars);
+      Set_Name1 (N, Val);
+   end Set_Chars;
+
+   procedure Set_Choice_Parameter
+      (N : Node_Id; Val : Node_Id) is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_Exception_Handler);
+      Set_Node2_With_Parent (N, Val);
+   end Set_Choice_Parameter;
+
+   procedure Set_Choices
+      (N : Node_Id; Val : List_Id) is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_Component_Association);
+      Set_List1_With_Parent (N, Val);
+   end Set_Choices;
+
+   procedure Set_Compile_Time_Known_Aggregate
+      (N : Node_Id; Val : Boolean := True) is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_Aggregate);
+      Set_Flag18 (N, Val);
+   end Set_Compile_Time_Known_Aggregate;
+
+   procedure Set_Component_Associations
+      (N : Node_Id; Val : List_Id) is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_Aggregate
+        or else NT (N).Nkind = N_Extension_Aggregate);
+      Set_List2_With_Parent (N, Val);
+   end Set_Component_Associations;
+
+   procedure Set_Component_Clauses
+      (N : Node_Id; Val : List_Id) is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_Record_Representation_Clause);
+      Set_List3_With_Parent (N, Val);
+   end Set_Component_Clauses;
+
+   procedure Set_Component_Items
+      (N : Node_Id; Val : List_Id) is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_Component_List);
+      Set_List3_With_Parent (N, Val);
+   end Set_Component_Items;
+
+   procedure Set_Component_List
+      (N : Node_Id; Val : Node_Id) is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_Record_Definition
+        or else NT (N).Nkind = N_Variant);
+      Set_Node1_With_Parent (N, Val);
+   end Set_Component_List;
+
+   procedure Set_Component_Name
+      (N : Node_Id; Val : Node_Id) is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_Component_Clause);
+      Set_Node1_With_Parent (N, Val);
+   end Set_Component_Name;
+
+   procedure Set_Condition
+      (N : Node_Id; Val : Node_Id) is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_Accept_Alternative
+        or else NT (N).Nkind = N_Delay_Alternative
+        or else NT (N).Nkind = N_Elsif_Part
+        or else NT (N).Nkind = N_Entry_Body_Formal_Part
+        or else NT (N).Nkind = N_Exit_Statement
+        or else NT (N).Nkind = N_If_Statement
+        or else NT (N).Nkind = N_Iteration_Scheme
+        or else NT (N).Nkind = N_Raise_Constraint_Error
+        or else NT (N).Nkind = N_Raise_Program_Error
+        or else NT (N).Nkind = N_Raise_Storage_Error
+        or else NT (N).Nkind = N_Terminate_Alternative);
+      Set_Node1_With_Parent (N, Val);
+   end Set_Condition;
+
+   procedure Set_Condition_Actions
+      (N : Node_Id; Val : List_Id) is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_Elsif_Part
+        or else NT (N).Nkind = N_Iteration_Scheme);
+      Set_List3 (N, Val); -- semantic field, no parent set
+   end Set_Condition_Actions;
+
+   procedure Set_Constant_Present
+      (N : Node_Id; Val : Boolean := True) is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_Access_To_Object_Definition
+        or else NT (N).Nkind = N_Object_Declaration);
+      Set_Flag17 (N, Val);
+   end Set_Constant_Present;
+
+   procedure Set_Constraint
+      (N : Node_Id; Val : Node_Id) is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_Subtype_Indication);
+      Set_Node3_With_Parent (N, Val);
+   end Set_Constraint;
+
+   procedure Set_Constraints
+      (N : Node_Id; Val : List_Id) is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_Index_Or_Discriminant_Constraint);
+      Set_List1_With_Parent (N, Val);
+   end Set_Constraints;
+
+   procedure Set_Context_Installed
+      (N : Node_Id; Val : Boolean := True) is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_With_Clause);
+      Set_Flag13 (N, Val);
+   end Set_Context_Installed;
+
+   procedure Set_Context_Items
+      (N : Node_Id; Val : List_Id) is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_Compilation_Unit);
+      Set_List1_With_Parent (N, Val);
+   end Set_Context_Items;
+
+   procedure Set_Controlling_Argument
+      (N : Node_Id; Val : Node_Id) is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_Function_Call
+        or else NT (N).Nkind = N_Procedure_Call_Statement);
+      Set_Node1 (N, Val); -- semantic field, no parent set
+   end Set_Controlling_Argument;
+
+   procedure Set_Conversion_OK
+      (N : Node_Id; Val : Boolean := True) is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_Type_Conversion);
+      Set_Flag14 (N, Val);
+   end Set_Conversion_OK;
+
+   procedure Set_Corresponding_Body
+      (N : Node_Id; Val : Node_Id) is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_Generic_Package_Declaration
+        or else NT (N).Nkind = N_Generic_Subprogram_Declaration
+        or else NT (N).Nkind = N_Package_Body_Stub
+        or else NT (N).Nkind = N_Package_Declaration
+        or else NT (N).Nkind = N_Protected_Body_Stub
+        or else NT (N).Nkind = N_Protected_Type_Declaration
+        or else NT (N).Nkind = N_Subprogram_Body_Stub
+        or else NT (N).Nkind = N_Subprogram_Declaration
+        or else NT (N).Nkind = N_Task_Body_Stub
+        or else NT (N).Nkind = N_Task_Type_Declaration);
+      Set_Node5 (N, Val); -- semantic field, no parent set
+   end Set_Corresponding_Body;
+
+   procedure Set_Corresponding_Generic_Association
+      (N : Node_Id; Val : Node_Id) is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_Object_Declaration
+        or else NT (N).Nkind = N_Object_Renaming_Declaration);
+      Set_Node5 (N, Val); -- semantic field, no parent set
+   end Set_Corresponding_Generic_Association;
+   procedure Set_Corresponding_Integer_Value
+      (N : Node_Id; Val : Uint) is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_Real_Literal);
+      Set_Uint4 (N, Val); -- semantic field, no parent set
+   end Set_Corresponding_Integer_Value;
+
+   procedure Set_Corresponding_Spec
+      (N : Node_Id; Val : Node_Id) is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_Package_Body
+        or else NT (N).Nkind = N_Protected_Body
+        or else NT (N).Nkind = N_Subprogram_Body
+        or else NT (N).Nkind = N_Subprogram_Renaming_Declaration
+        or else NT (N).Nkind = N_Task_Body
+        or else NT (N).Nkind = N_With_Clause);
+      Set_Node5 (N, Val); -- semantic field, no parent set
+   end Set_Corresponding_Spec;
+
+   procedure Set_Corresponding_Stub
+      (N : Node_Id; Val : Node_Id) is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_Subunit);
+      Set_Node3 (N, Val);
+   end Set_Corresponding_Stub;
+
+   procedure Set_Dcheck_Function
+      (N : Node_Id; Val : Entity_Id) is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_Variant);
+      Set_Node5 (N, Val); -- semantic field, no parent set
+   end Set_Dcheck_Function;
+
+   procedure Set_Debug_Statement
+      (N : Node_Id; Val : Node_Id) is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_Pragma);
+      Set_Node3_With_Parent (N, Val);
+   end Set_Debug_Statement;
+
+   procedure Set_Declarations
+      (N : Node_Id; Val : List_Id) is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_Accept_Statement
+        or else NT (N).Nkind = N_Block_Statement
+        or else NT (N).Nkind = N_Compilation_Unit_Aux
+        or else NT (N).Nkind = N_Entry_Body
+        or else NT (N).Nkind = N_Package_Body
+        or else NT (N).Nkind = N_Protected_Body
+        or else NT (N).Nkind = N_Subprogram_Body
+        or else NT (N).Nkind = N_Task_Body);
+      Set_List2_With_Parent (N, Val);
+   end Set_Declarations;
+
+   procedure Set_Default_Expression
+      (N : Node_Id; Val : Node_Id) is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_Parameter_Specification);
+      Set_Node5 (N, Val); -- semantic field, no parent set
+   end Set_Default_Expression;
+
+   procedure Set_Default_Name
+      (N : Node_Id; Val : Node_Id) is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_Formal_Subprogram_Declaration);
+      Set_Node2_With_Parent (N, Val);
+   end Set_Default_Name;
+
+   procedure Set_Defining_Identifier
+      (N : Node_Id; Val : Entity_Id) is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_Component_Declaration
+        or else NT (N).Nkind = N_Defining_Program_Unit_Name
+        or else NT (N).Nkind = N_Discriminant_Specification
+        or else NT (N).Nkind = N_Entry_Body
+        or else NT (N).Nkind = N_Entry_Declaration
+        or else NT (N).Nkind = N_Entry_Index_Specification
+        or else NT (N).Nkind = N_Exception_Declaration
+        or else NT (N).Nkind = N_Exception_Renaming_Declaration
+        or else NT (N).Nkind = N_Formal_Object_Declaration
+        or else NT (N).Nkind = N_Formal_Package_Declaration
+        or else NT (N).Nkind = N_Formal_Type_Declaration
+        or else NT (N).Nkind = N_Full_Type_Declaration
+        or else NT (N).Nkind = N_Implicit_Label_Declaration
+        or else NT (N).Nkind = N_Incomplete_Type_Declaration
+        or else NT (N).Nkind = N_Loop_Parameter_Specification
+        or else NT (N).Nkind = N_Number_Declaration
+        or else NT (N).Nkind = N_Object_Declaration
+        or else NT (N).Nkind = N_Object_Renaming_Declaration
+        or else NT (N).Nkind = N_Package_Body_Stub
+        or else NT (N).Nkind = N_Parameter_Specification
+        or else NT (N).Nkind = N_Private_Extension_Declaration
+        or else NT (N).Nkind = N_Private_Type_Declaration
+        or else NT (N).Nkind = N_Protected_Body
+        or else NT (N).Nkind = N_Protected_Body_Stub
+        or else NT (N).Nkind = N_Protected_Type_Declaration
+        or else NT (N).Nkind = N_Single_Protected_Declaration
+        or else NT (N).Nkind = N_Single_Task_Declaration
+        or else NT (N).Nkind = N_Subtype_Declaration
+        or else NT (N).Nkind = N_Task_Body
+        or else NT (N).Nkind = N_Task_Body_Stub
+        or else NT (N).Nkind = N_Task_Type_Declaration);
+      Set_Node1_With_Parent (N, Val);
+   end Set_Defining_Identifier;
+
+   procedure Set_Defining_Unit_Name
+      (N : Node_Id; Val : Node_Id) is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_Function_Instantiation
+        or else NT (N).Nkind = N_Function_Specification
+        or else NT (N).Nkind = N_Generic_Function_Renaming_Declaration
+        or else NT (N).Nkind = N_Generic_Package_Renaming_Declaration
+        or else NT (N).Nkind = N_Generic_Procedure_Renaming_Declaration
+        or else NT (N).Nkind = N_Package_Body
+        or else NT (N).Nkind = N_Package_Instantiation
+        or else NT (N).Nkind = N_Package_Renaming_Declaration
+        or else NT (N).Nkind = N_Package_Specification
+        or else NT (N).Nkind = N_Procedure_Instantiation
+        or else NT (N).Nkind = N_Procedure_Specification);
+      Set_Node1_With_Parent (N, Val);
+   end Set_Defining_Unit_Name;
+
+   procedure Set_Delay_Alternative
+      (N : Node_Id; Val : Node_Id) is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_Timed_Entry_Call);
+      Set_Node4_With_Parent (N, Val);
+   end Set_Delay_Alternative;
+
+   procedure Set_Delay_Finalize_Attach
+      (N : Node_Id; Val : Boolean := True) is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_Object_Declaration);
+      Set_Flag14 (N, Val);
+   end Set_Delay_Finalize_Attach;
+
+   procedure Set_Delay_Statement
+      (N : Node_Id; Val : Node_Id) is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_Delay_Alternative);
+      Set_Node2_With_Parent (N, Val);
+   end Set_Delay_Statement;
+
+   procedure Set_Delta_Expression
+      (N : Node_Id; Val : Node_Id) is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_Decimal_Fixed_Point_Definition
+        or else NT (N).Nkind = N_Delta_Constraint
+        or else NT (N).Nkind = N_Ordinary_Fixed_Point_Definition);
+      Set_Node3_With_Parent (N, Val);
+   end Set_Delta_Expression;
+
+   procedure Set_Digits_Expression
+      (N : Node_Id; Val : Node_Id) is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_Decimal_Fixed_Point_Definition
+        or else NT (N).Nkind = N_Digits_Constraint
+        or else NT (N).Nkind = N_Floating_Point_Definition);
+      Set_Node2_With_Parent (N, Val);
+   end Set_Digits_Expression;
+
+   procedure Set_Discr_Check_Funcs_Built
+      (N : Node_Id; Val : Boolean := True) is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_Full_Type_Declaration);
+      Set_Flag11 (N, Val);
+   end Set_Discr_Check_Funcs_Built;
+
+   procedure Set_Discrete_Choices
+      (N : Node_Id; Val : List_Id) is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_Case_Statement_Alternative
+        or else NT (N).Nkind = N_Variant);
+      Set_List4_With_Parent (N, Val);
+   end Set_Discrete_Choices;
+
+   procedure Set_Discrete_Range
+      (N : Node_Id; Val : Node_Id) is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_Slice);
+      Set_Node4_With_Parent (N, Val);
+   end Set_Discrete_Range;
+
+   procedure Set_Discrete_Subtype_Definition
+      (N : Node_Id; Val : Node_Id) is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_Entry_Declaration
+        or else NT (N).Nkind = N_Entry_Index_Specification
+        or else NT (N).Nkind = N_Loop_Parameter_Specification);
+      Set_Node4_With_Parent (N, Val);
+   end Set_Discrete_Subtype_Definition;
+
+   procedure Set_Discrete_Subtype_Definitions
+      (N : Node_Id; Val : List_Id) is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_Constrained_Array_Definition);
+      Set_List2_With_Parent (N, Val);
+   end Set_Discrete_Subtype_Definitions;
+
+   procedure Set_Discriminant_Specifications
+      (N : Node_Id; Val : List_Id) is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_Formal_Type_Declaration
+        or else NT (N).Nkind = N_Full_Type_Declaration
+        or else NT (N).Nkind = N_Incomplete_Type_Declaration
+        or else NT (N).Nkind = N_Private_Extension_Declaration
+        or else NT (N).Nkind = N_Private_Type_Declaration
+        or else NT (N).Nkind = N_Protected_Type_Declaration
+        or else NT (N).Nkind = N_Task_Type_Declaration);
+      Set_List4_With_Parent (N, Val);
+   end Set_Discriminant_Specifications;
+
+   procedure Set_Discriminant_Type
+      (N : Node_Id; Val : Node_Id) is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_Discriminant_Specification);
+      Set_Node5_With_Parent (N, Val);
+   end Set_Discriminant_Type;
+
+   procedure Set_Do_Access_Check
+      (N : Node_Id; Val : Boolean := True) is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_Attribute_Reference
+        or else NT (N).Nkind = N_Explicit_Dereference
+        or else NT (N).Nkind = N_Indexed_Component
+        or else NT (N).Nkind = N_Selected_Component
+        or else NT (N).Nkind = N_Slice);
+      Set_Flag11 (N, Val);
+   end Set_Do_Access_Check;
+
+   procedure Set_Do_Accessibility_Check
+      (N : Node_Id; Val : Boolean := True) is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_Parameter_Specification);
+      Set_Flag13 (N, Val);
+   end Set_Do_Accessibility_Check;
+
+   procedure Set_Do_Discriminant_Check
+      (N : Node_Id; Val : Boolean := True) is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_Selected_Component);
+      Set_Flag13 (N, Val);
+   end Set_Do_Discriminant_Check;
+
+   procedure Set_Do_Division_Check
+      (N : Node_Id; Val : Boolean := True) is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_Op_Divide
+        or else NT (N).Nkind = N_Op_Mod
+        or else NT (N).Nkind = N_Op_Rem);
+      Set_Flag13 (N, Val);
+   end Set_Do_Division_Check;
+
+   procedure Set_Do_Length_Check
+      (N : Node_Id; Val : Boolean := True) is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_Assignment_Statement
+        or else NT (N).Nkind = N_Op_And
+        or else NT (N).Nkind = N_Op_Or
+        or else NT (N).Nkind = N_Op_Xor
+        or else NT (N).Nkind = N_Type_Conversion);
+      Set_Flag4 (N, Val);
+   end Set_Do_Length_Check;
+
+   procedure Set_Do_Overflow_Check
+      (N : Node_Id; Val : Boolean := True) is
+   begin
+      pragma Assert (False
+          or else NT (N).Nkind in N_Op
+        or else NT (N).Nkind = N_Attribute_Reference
+        or else NT (N).Nkind = N_Type_Conversion);
+      Set_Flag17 (N, Val);
+   end Set_Do_Overflow_Check;
+
+   procedure Set_Do_Range_Check
+      (N : Node_Id; Val : Boolean := True) is
+   begin
+      pragma Assert (False
+          or else NT (N).Nkind in N_Subexpr);
+      Set_Flag9 (N, Val);
+   end Set_Do_Range_Check;
+
+   procedure Set_Do_Storage_Check
+      (N : Node_Id; Val : Boolean := True) is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_Allocator
+        or else NT (N).Nkind = N_Subprogram_Body);
+      Set_Flag17 (N, Val);
+   end Set_Do_Storage_Check;
+
+   procedure Set_Do_Tag_Check
+      (N : Node_Id; Val : Boolean := True) is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_Assignment_Statement
+        or else NT (N).Nkind = N_Function_Call
+        or else NT (N).Nkind = N_Procedure_Call_Statement
+        or else NT (N).Nkind = N_Return_Statement
+        or else NT (N).Nkind = N_Type_Conversion);
+      Set_Flag13 (N, Val);
+   end Set_Do_Tag_Check;
+
+   procedure Set_Elaborate_All_Present
+      (N : Node_Id; Val : Boolean := True) is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_With_Clause);
+      Set_Flag15 (N, Val);
+   end Set_Elaborate_All_Present;
+
+   procedure Set_Elaborate_Present
+      (N : Node_Id; Val : Boolean := True) is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_With_Clause);
+      Set_Flag4 (N, Val);
+   end Set_Elaborate_Present;
+
+   procedure Set_Elaboration_Boolean
+      (N : Node_Id; Val : Node_Id) is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_Function_Specification
+        or else NT (N).Nkind = N_Procedure_Specification);
+      Set_Node2 (N, Val);
+   end Set_Elaboration_Boolean;
+
+   procedure Set_Else_Actions
+      (N : Node_Id; Val : List_Id) is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_Conditional_Expression);
+      Set_List3 (N, Val); -- semantic field, no parent set
+   end Set_Else_Actions;
+
+   procedure Set_Else_Statements
+      (N : Node_Id; Val : List_Id) is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_Conditional_Entry_Call
+        or else NT (N).Nkind = N_If_Statement
+        or else NT (N).Nkind = N_Selective_Accept);
+      Set_List4_With_Parent (N, Val);
+   end Set_Else_Statements;
+
+   procedure Set_Elsif_Parts
+      (N : Node_Id; Val : List_Id) is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_If_Statement);
+      Set_List3_With_Parent (N, Val);
+   end Set_Elsif_Parts;
+
+   procedure Set_Enclosing_Variant
+      (N : Node_Id; Val : Node_Id) is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_Variant);
+      Set_Node2 (N, Val); -- semantic field, no parent set
+   end Set_Enclosing_Variant;
+
+   procedure Set_End_Label
+      (N : Node_Id; Val : Node_Id) is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_Handled_Sequence_Of_Statements
+        or else NT (N).Nkind = N_Loop_Statement
+        or else NT (N).Nkind = N_Package_Specification
+        or else NT (N).Nkind = N_Protected_Body
+        or else NT (N).Nkind = N_Protected_Definition
+        or else NT (N).Nkind = N_Record_Definition
+        or else NT (N).Nkind = N_Task_Definition);
+      Set_Node4_With_Parent (N, Val);
+   end Set_End_Label;
+
+   procedure Set_End_Span
+      (N : Node_Id; Val : Uint) is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_Case_Statement
+        or else NT (N).Nkind = N_If_Statement);
+      Set_Uint5 (N, Val);
+   end Set_End_Span;
+
+   procedure Set_Entity
+      (N : Node_Id; Val : Node_Id) is
+   begin
+      pragma Assert (False
+          or else NT (N).Nkind in N_Has_Entity
+        or else NT (N).Nkind = N_Freeze_Entity);
+      Set_Node4 (N, Val); -- semantic field, no parent set
+   end Set_Entity;
+
+   procedure Set_Entry_Body_Formal_Part
+      (N : Node_Id; Val : Node_Id) is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_Entry_Body);
+      Set_Node5_With_Parent (N, Val);
+   end Set_Entry_Body_Formal_Part;
+
+   procedure Set_Entry_Call_Alternative
+      (N : Node_Id; Val : Node_Id) is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_Conditional_Entry_Call
+        or else NT (N).Nkind = N_Timed_Entry_Call);
+      Set_Node1_With_Parent (N, Val);
+   end Set_Entry_Call_Alternative;
+
+   procedure Set_Entry_Call_Statement
+      (N : Node_Id; Val : Node_Id) is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_Entry_Call_Alternative);
+      Set_Node1_With_Parent (N, Val);
+   end Set_Entry_Call_Statement;
+
+   procedure Set_Entry_Direct_Name
+      (N : Node_Id; Val : Node_Id) is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_Accept_Statement);
+      Set_Node1_With_Parent (N, Val);
+   end Set_Entry_Direct_Name;
+
+   procedure Set_Entry_Index
+      (N : Node_Id; Val : Node_Id) is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_Accept_Statement);
+      Set_Node5_With_Parent (N, Val);
+   end Set_Entry_Index;
+
+   procedure Set_Entry_Index_Specification
+      (N : Node_Id; Val : Node_Id) is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_Entry_Body_Formal_Part);
+      Set_Node4_With_Parent (N, Val);
+   end Set_Entry_Index_Specification;
+
+   procedure Set_Etype
+      (N : Node_Id; Val : Node_Id) is
+   begin
+      pragma Assert (False
+          or else NT (N).Nkind in N_Has_Etype);
+      Set_Node5 (N, Val); -- semantic field, no parent set
+   end Set_Etype;
+
+   procedure Set_Exception_Choices
+      (N : Node_Id; Val : List_Id) is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_Exception_Handler);
+      Set_List4_With_Parent (N, Val);
+   end Set_Exception_Choices;
+
+   procedure Set_Exception_Handlers
+      (N : Node_Id; Val : List_Id) is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_Handled_Sequence_Of_Statements);
+      Set_List5_With_Parent (N, Val);
+   end Set_Exception_Handlers;
+
+   procedure Set_Exception_Junk
+     (N : Node_Id; Val : Boolean := True) is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_Goto_Statement
+        or else NT (N).Nkind = N_Label
+        or else NT (N).Nkind = N_Object_Declaration
+        or else NT (N).Nkind = N_Subtype_Declaration);
+      Set_Flag11 (N, Val);
+   end Set_Exception_Junk;
+
+   procedure Set_Expansion_Delayed
+     (N : Node_Id; Val : Boolean := True) is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_Aggregate
+        or else NT (N).Nkind = N_Extension_Aggregate);
+      Set_Flag11 (N, Val);
+   end Set_Expansion_Delayed;
+
+   procedure Set_Explicit_Actual_Parameter
+      (N : Node_Id; Val : Node_Id) is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_Parameter_Association);
+      Set_Node3_With_Parent (N, Val);
+   end Set_Explicit_Actual_Parameter;
+
+   procedure Set_Explicit_Generic_Actual_Parameter
+      (N : Node_Id; Val : Node_Id) is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_Generic_Association);
+      Set_Node1_With_Parent (N, Val);
+   end Set_Explicit_Generic_Actual_Parameter;
+
+   procedure Set_Expression
+      (N : Node_Id; Val : Node_Id) is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_Allocator
+        or else NT (N).Nkind = N_Assignment_Statement
+        or else NT (N).Nkind = N_At_Clause
+        or else NT (N).Nkind = N_Attribute_Definition_Clause
+        or else NT (N).Nkind = N_Case_Statement
+        or else NT (N).Nkind = N_Code_Statement
+        or else NT (N).Nkind = N_Component_Association
+        or else NT (N).Nkind = N_Component_Declaration
+        or else NT (N).Nkind = N_Delay_Relative_Statement
+        or else NT (N).Nkind = N_Delay_Until_Statement
+        or else NT (N).Nkind = N_Discriminant_Association
+        or else NT (N).Nkind = N_Discriminant_Specification
+        or else NT (N).Nkind = N_Exception_Declaration
+        or else NT (N).Nkind = N_Formal_Object_Declaration
+        or else NT (N).Nkind = N_Free_Statement
+        or else NT (N).Nkind = N_Mod_Clause
+        or else NT (N).Nkind = N_Modular_Type_Definition
+        or else NT (N).Nkind = N_Number_Declaration
+        or else NT (N).Nkind = N_Object_Declaration
+        or else NT (N).Nkind = N_Parameter_Specification
+        or else NT (N).Nkind = N_Pragma_Argument_Association
+        or else NT (N).Nkind = N_Qualified_Expression
+        or else NT (N).Nkind = N_Return_Statement
+        or else NT (N).Nkind = N_Type_Conversion
+        or else NT (N).Nkind = N_Unchecked_Expression
+        or else NT (N).Nkind = N_Unchecked_Type_Conversion);
+      Set_Node3_With_Parent (N, Val);
+   end Set_Expression;
+
+   procedure Set_Expressions
+      (N : Node_Id; Val : List_Id) is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_Aggregate
+        or else NT (N).Nkind = N_Attribute_Reference
+        or else NT (N).Nkind = N_Conditional_Expression
+        or else NT (N).Nkind = N_Extension_Aggregate
+        or else NT (N).Nkind = N_Indexed_Component);
+      Set_List1_With_Parent (N, Val);
+   end Set_Expressions;
+
+   procedure Set_First_Bit
+      (N : Node_Id; Val : Node_Id) is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_Component_Clause);
+      Set_Node3_With_Parent (N, Val);
+   end Set_First_Bit;
+
+   procedure Set_First_Inlined_Subprogram
+      (N : Node_Id; Val : Entity_Id) is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_Compilation_Unit);
+      Set_Node3 (N, Val);  -- semantic field, no parent set
+   end Set_First_Inlined_Subprogram;
+
+   procedure Set_First_Name
+      (N : Node_Id; Val : Boolean := True) is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_With_Clause);
+      Set_Flag5 (N, Val);
+   end Set_First_Name;
+
+   procedure Set_First_Named_Actual
+      (N : Node_Id; Val : Node_Id) is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_Entry_Call_Statement
+        or else NT (N).Nkind = N_Function_Call
+        or else NT (N).Nkind = N_Procedure_Call_Statement);
+      Set_Node4 (N, Val); -- semantic field, no parent set
+   end Set_First_Named_Actual;
+
+   procedure Set_First_Real_Statement
+      (N : Node_Id; Val : Node_Id) is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_Handled_Sequence_Of_Statements);
+      Set_Node2 (N, Val); -- semantic field, no parent set
+   end Set_First_Real_Statement;
+
+   procedure Set_First_Subtype_Link
+      (N : Node_Id; Val : Entity_Id) is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_Freeze_Entity);
+      Set_Node5 (N, Val); -- semantic field, no parent set
+   end Set_First_Subtype_Link;
+
+   procedure Set_Float_Truncate
+      (N : Node_Id; Val : Boolean := True) is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_Type_Conversion);
+      Set_Flag11 (N, Val);
+   end Set_Float_Truncate;
+
+   procedure Set_Formal_Type_Definition
+      (N : Node_Id; Val : Node_Id) is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_Formal_Type_Declaration);
+      Set_Node3_With_Parent (N, Val);
+   end Set_Formal_Type_Definition;
+
+   procedure Set_Forwards_OK
+      (N : Node_Id; Val : Boolean := True) is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_Assignment_Statement);
+      Set_Flag5 (N, Val);
+   end Set_Forwards_OK;
+
+   procedure Set_From_At_Mod
+      (N : Node_Id; Val : Boolean := True) is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_Attribute_Definition_Clause);
+      Set_Flag4 (N, Val);
+   end Set_From_At_Mod;
+
+   procedure Set_Generic_Associations
+      (N : Node_Id; Val : List_Id) is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_Formal_Package_Declaration
+        or else NT (N).Nkind = N_Function_Instantiation
+        or else NT (N).Nkind = N_Package_Instantiation
+        or else NT (N).Nkind = N_Procedure_Instantiation);
+      Set_List3_With_Parent (N, Val);
+   end Set_Generic_Associations;
+
+   procedure Set_Generic_Formal_Declarations
+      (N : Node_Id; Val : List_Id) is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_Generic_Package_Declaration
+        or else NT (N).Nkind = N_Generic_Subprogram_Declaration);
+      Set_List2_With_Parent (N, Val);
+   end Set_Generic_Formal_Declarations;
+
+   procedure Set_Generic_Parent
+      (N : Node_Id; Val : Node_Id) is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_Function_Specification
+        or else NT (N).Nkind = N_Package_Specification
+        or else NT (N).Nkind = N_Procedure_Specification);
+      Set_Node5 (N, Val);
+   end Set_Generic_Parent;
+
+   procedure Set_Generic_Parent_Type
+      (N : Node_Id; Val : Node_Id) is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_Subtype_Declaration);
+      Set_Node4 (N, Val);
+   end Set_Generic_Parent_Type;
+
+   procedure Set_Handled_Statement_Sequence
+      (N : Node_Id; Val : Node_Id) is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_Accept_Statement
+        or else NT (N).Nkind = N_Block_Statement
+        or else NT (N).Nkind = N_Entry_Body
+        or else NT (N).Nkind = N_Package_Body
+        or else NT (N).Nkind = N_Subprogram_Body
+        or else NT (N).Nkind = N_Task_Body);
+      Set_Node4_With_Parent (N, Val);
+   end Set_Handled_Statement_Sequence;
+
+   procedure Set_Handler_List_Entry
+      (N : Node_Id; Val : Node_Id) is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_Object_Declaration);
+      Set_Node2 (N, Val);
+   end Set_Handler_List_Entry;
+
+   procedure Set_Has_Created_Identifier
+      (N : Node_Id; Val : Boolean := True) is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_Block_Statement
+        or else NT (N).Nkind = N_Loop_Statement);
+      Set_Flag15 (N, Val);
+   end Set_Has_Created_Identifier;
+
+   procedure Set_Has_Dynamic_Length_Check
+      (N : Node_Id; Val : Boolean := True) is
+   begin
+      Set_Flag10 (N, Val);
+   end Set_Has_Dynamic_Length_Check;
+
+   procedure Set_Has_Dynamic_Range_Check
+      (N : Node_Id; Val : Boolean := True) is
+   begin
+      Set_Flag12 (N, Val);
+   end Set_Has_Dynamic_Range_Check;
+
+   procedure Set_Has_No_Elaboration_Code
+      (N : Node_Id; Val : Boolean := True) is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_Compilation_Unit);
+      Set_Flag17 (N, Val);
+   end Set_Has_No_Elaboration_Code;
+
+   procedure Set_Has_Priority_Pragma
+      (N : Node_Id; Val : Boolean := True) is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_Protected_Definition
+        or else NT (N).Nkind = N_Subprogram_Body
+        or else NT (N).Nkind = N_Task_Definition);
+      Set_Flag6 (N, Val);
+   end Set_Has_Priority_Pragma;
+
+   procedure Set_Has_Private_View
+      (N : Node_Id; Val : Boolean := True) is
+   begin
+      pragma Assert (False
+         or else NT (N).Nkind in N_Op
+       or else NT (N).Nkind = N_Character_Literal
+       or else NT (N).Nkind = N_Expanded_Name
+       or else NT (N).Nkind = N_Identifier
+       or else NT (N).Nkind = N_Operator_Symbol);
+      Set_Flag11 (N, Val);
+   end Set_Has_Private_View;
+
+   procedure Set_Has_Storage_Size_Pragma
+      (N : Node_Id; Val : Boolean := True) is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_Task_Definition);
+      Set_Flag5 (N, Val);
+   end Set_Has_Storage_Size_Pragma;
+
+   procedure Set_Has_Task_Info_Pragma
+      (N : Node_Id; Val : Boolean := True) is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_Task_Definition);
+      Set_Flag7 (N, Val);
+   end Set_Has_Task_Info_Pragma;
+
+   procedure Set_Has_Task_Name_Pragma
+      (N : Node_Id; Val : Boolean := True) is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_Task_Definition);
+      Set_Flag8 (N, Val);
+   end Set_Has_Task_Name_Pragma;
+
+   procedure Set_Has_Wide_Character
+      (N : Node_Id; Val : Boolean := True) is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_String_Literal);
+      Set_Flag11 (N, Val);
+   end Set_Has_Wide_Character;
+
+   procedure Set_Hidden_By_Use_Clause
+     (N : Node_Id; Val : Elist_Id) is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_Use_Package_Clause
+        or else NT (N).Nkind = N_Use_Type_Clause);
+      Set_Elist4 (N, Val);
+   end Set_Hidden_By_Use_Clause;
+
+   procedure Set_High_Bound
+      (N : Node_Id; Val : Node_Id) is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_Range
+        or else NT (N).Nkind = N_Real_Range_Specification
+        or else NT (N).Nkind = N_Signed_Integer_Type_Definition);
+      Set_Node2_With_Parent (N, Val);
+   end Set_High_Bound;
+
+   procedure Set_Identifier
+      (N : Node_Id; Val : Node_Id) is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_At_Clause
+        or else NT (N).Nkind = N_Block_Statement
+        or else NT (N).Nkind = N_Designator
+        or else NT (N).Nkind = N_Enumeration_Representation_Clause
+        or else NT (N).Nkind = N_Label
+        or else NT (N).Nkind = N_Loop_Statement
+        or else NT (N).Nkind = N_Record_Representation_Clause
+        or else NT (N).Nkind = N_Subprogram_Info);
+      Set_Node1_With_Parent (N, Val);
+   end Set_Identifier;
+
+   procedure Set_Implicit_With
+      (N : Node_Id; Val : Boolean := True) is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_With_Clause);
+      Set_Flag17 (N, Val);
+   end Set_Implicit_With;
+
+   procedure Set_In_Present
+      (N : Node_Id; Val : Boolean := True) is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_Formal_Object_Declaration
+        or else NT (N).Nkind = N_Parameter_Specification);
+      Set_Flag15 (N, Val);
+   end Set_In_Present;
+
+   procedure Set_Includes_Infinities
+      (N : Node_Id; Val : Boolean := True) is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_Range);
+      Set_Flag11 (N, Val);
+   end Set_Includes_Infinities;
+
+   procedure Set_Instance_Spec
+      (N : Node_Id; Val : Node_Id) is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_Formal_Package_Declaration
+        or else NT (N).Nkind = N_Function_Instantiation
+        or else NT (N).Nkind = N_Package_Instantiation
+        or else NT (N).Nkind = N_Procedure_Instantiation);
+      Set_Node5 (N, Val); -- semantic field, no Parent set
+   end Set_Instance_Spec;
+
+   procedure Set_Intval
+      (N : Node_Id; Val : Uint) is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_Integer_Literal);
+      Set_Uint3 (N, Val);
+   end Set_Intval;
+
+   procedure Set_Is_Asynchronous_Call_Block
+      (N : Node_Id; Val : Boolean := True) is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_Block_Statement);
+      Set_Flag7 (N, Val);
+   end Set_Is_Asynchronous_Call_Block;
+
+   procedure Set_Is_Component_Left_Opnd
+      (N : Node_Id; Val : Boolean := True) is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_Op_Concat);
+      Set_Flag13 (N, Val);
+   end Set_Is_Component_Left_Opnd;
+
+   procedure Set_Is_Component_Right_Opnd
+      (N : Node_Id; Val : Boolean := True) is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_Op_Concat);
+      Set_Flag14 (N, Val);
+   end Set_Is_Component_Right_Opnd;
+
+   procedure Set_Is_Controlling_Actual
+      (N : Node_Id; Val : Boolean := True) is
+   begin
+      pragma Assert (False
+          or else NT (N).Nkind in N_Subexpr);
+      Set_Flag16 (N, Val);
+   end Set_Is_Controlling_Actual;
+
+   procedure Set_Is_Machine_Number
+      (N : Node_Id; Val : Boolean := True) is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_Real_Literal);
+      Set_Flag11 (N, Val);
+   end Set_Is_Machine_Number;
+
+   procedure Set_Is_Overloaded
+      (N : Node_Id; Val : Boolean := True) is
+   begin
+      pragma Assert (False
+          or else NT (N).Nkind in N_Subexpr);
+      Set_Flag5 (N, Val);
+   end Set_Is_Overloaded;
+
+   procedure Set_Is_Power_Of_2_For_Shift
+      (N : Node_Id; Val : Boolean := True) is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_Op_Expon);
+      Set_Flag13 (N, Val);
+   end Set_Is_Power_Of_2_For_Shift;
+
+   procedure Set_Is_Protected_Subprogram_Body
+      (N : Node_Id; Val : Boolean := True) is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_Subprogram_Body);
+      Set_Flag7 (N, Val);
+   end Set_Is_Protected_Subprogram_Body;
+
+   procedure Set_Is_Static_Expression
+      (N : Node_Id; Val : Boolean := True) is
+   begin
+      pragma Assert (False
+          or else NT (N).Nkind in N_Subexpr);
+      Set_Flag6 (N, Val);
+   end Set_Is_Static_Expression;
+
+   procedure Set_Is_Subprogram_Descriptor
+      (N : Node_Id; Val : Boolean := True) is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_Object_Declaration);
+      Set_Flag16 (N, Val);
+   end Set_Is_Subprogram_Descriptor;
+
+   procedure Set_Is_Task_Allocation_Block
+      (N : Node_Id; Val : Boolean := True) is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_Block_Statement);
+      Set_Flag6 (N, Val);
+   end Set_Is_Task_Allocation_Block;
+
+   procedure Set_Is_Task_Master
+      (N : Node_Id; Val : Boolean := True) is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_Block_Statement
+        or else NT (N).Nkind = N_Subprogram_Body
+        or else NT (N).Nkind = N_Task_Body);
+      Set_Flag5 (N, Val);
+   end Set_Is_Task_Master;
+
+   procedure Set_Iteration_Scheme
+      (N : Node_Id; Val : Node_Id) is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_Loop_Statement);
+      Set_Node2_With_Parent (N, Val);
+   end Set_Iteration_Scheme;
+
+   procedure Set_Itype
+      (N : Node_Id; Val : Entity_Id) is
+   begin
+      pragma Assert (False
+      or else NT (N).Nkind = N_Itype_Reference);
+      Set_Node1 (N, Val); -- no parent, semantic field
+   end Set_Itype;
+
+   procedure Set_Kill_Range_Check
+      (N : Node_Id; Val : Boolean := True) is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_Unchecked_Type_Conversion);
+      Set_Flag11 (N, Val);
+   end Set_Kill_Range_Check;
+
+   procedure Set_Label_Construct
+      (N : Node_Id; Val : Node_Id) is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_Implicit_Label_Declaration);
+      Set_Node2 (N, Val); -- semantic field, no parent set
+   end Set_Label_Construct;
+
+   procedure Set_Last_Bit
+      (N : Node_Id; Val : Node_Id) is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_Component_Clause);
+      Set_Node4_With_Parent (N, Val);
+   end Set_Last_Bit;
+
+   procedure Set_Last_Name
+      (N : Node_Id; Val : Boolean := True) is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_With_Clause);
+      Set_Flag6 (N, Val);
+   end Set_Last_Name;
+
+   procedure Set_Left_Opnd
+      (N : Node_Id; Val : Node_Id) is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_And_Then
+        or else NT (N).Nkind = N_In
+        or else NT (N).Nkind = N_Not_In
+        or else NT (N).Nkind = N_Or_Else
+          or else NT (N).Nkind in N_Binary_Op);
+      Set_Node2_With_Parent (N, Val);
+   end Set_Left_Opnd;
+
+   procedure Set_Library_Unit
+      (N : Node_Id; Val : Node_Id) is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_Compilation_Unit
+        or else NT (N).Nkind = N_Package_Body_Stub
+        or else NT (N).Nkind = N_Protected_Body_Stub
+        or else NT (N).Nkind = N_Subprogram_Body_Stub
+        or else NT (N).Nkind = N_Task_Body_Stub
+        or else NT (N).Nkind = N_With_Clause);
+      Set_Node4 (N, Val); -- semantic field, no parent set
+   end Set_Library_Unit;
+
+   procedure Set_Limited_Present
+      (N : Node_Id; Val : Boolean := True) is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_Formal_Private_Type_Definition
+        or else NT (N).Nkind = N_Private_Type_Declaration
+        or else NT (N).Nkind = N_Record_Definition);
+      Set_Flag17 (N, Val);
+   end Set_Limited_Present;
+
+   procedure Set_Literals
+      (N : Node_Id; Val : List_Id) is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_Enumeration_Type_Definition);
+      Set_List1_With_Parent (N, Val);
+   end Set_Literals;
+
+   procedure Set_Loop_Actions
+      (N : Node_Id; Val : List_Id) is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_Component_Association);
+      Set_List2 (N, Val); -- semantic field, no parent set
+   end Set_Loop_Actions;
+
+   procedure Set_Loop_Parameter_Specification
+      (N : Node_Id; Val : Node_Id) is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_Iteration_Scheme);
+      Set_Node4_With_Parent (N, Val);
+   end Set_Loop_Parameter_Specification;
+
+   procedure Set_Low_Bound
+      (N : Node_Id; Val : Node_Id) is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_Range
+        or else NT (N).Nkind = N_Real_Range_Specification
+        or else NT (N).Nkind = N_Signed_Integer_Type_Definition);
+      Set_Node1_With_Parent (N, Val);
+   end Set_Low_Bound;
+
+   procedure Set_Mod_Clause
+      (N : Node_Id; Val : Node_Id) is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_Record_Representation_Clause);
+      Set_Node2_With_Parent (N, Val);
+   end Set_Mod_Clause;
+
+   procedure Set_More_Ids
+      (N : Node_Id; Val : Boolean := True) is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_Component_Declaration
+        or else NT (N).Nkind = N_Discriminant_Specification
+        or else NT (N).Nkind = N_Exception_Declaration
+        or else NT (N).Nkind = N_Formal_Object_Declaration
+        or else NT (N).Nkind = N_Number_Declaration
+        or else NT (N).Nkind = N_Object_Declaration
+        or else NT (N).Nkind = N_Parameter_Specification);
+      Set_Flag5 (N, Val);
+   end Set_More_Ids;
+
+   procedure Set_Must_Not_Freeze
+      (N : Node_Id; Val : Boolean := True) is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_Subtype_Indication
+          or else NT (N).Nkind in N_Subexpr);
+      Set_Flag8 (N, Val);
+   end Set_Must_Not_Freeze;
+
+   procedure Set_Name
+      (N : Node_Id; Val : Node_Id) is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_Assignment_Statement
+        or else NT (N).Nkind = N_Attribute_Definition_Clause
+        or else NT (N).Nkind = N_Defining_Program_Unit_Name
+        or else NT (N).Nkind = N_Designator
+        or else NT (N).Nkind = N_Entry_Call_Statement
+        or else NT (N).Nkind = N_Exception_Renaming_Declaration
+        or else NT (N).Nkind = N_Exit_Statement
+        or else NT (N).Nkind = N_Formal_Package_Declaration
+        or else NT (N).Nkind = N_Function_Call
+        or else NT (N).Nkind = N_Function_Instantiation
+        or else NT (N).Nkind = N_Generic_Function_Renaming_Declaration
+        or else NT (N).Nkind = N_Generic_Package_Renaming_Declaration
+        or else NT (N).Nkind = N_Generic_Procedure_Renaming_Declaration
+        or else NT (N).Nkind = N_Goto_Statement
+        or else NT (N).Nkind = N_Object_Renaming_Declaration
+        or else NT (N).Nkind = N_Package_Instantiation
+        or else NT (N).Nkind = N_Package_Renaming_Declaration
+        or else NT (N).Nkind = N_Procedure_Call_Statement
+        or else NT (N).Nkind = N_Procedure_Instantiation
+        or else NT (N).Nkind = N_Raise_Statement
+        or else NT (N).Nkind = N_Requeue_Statement
+        or else NT (N).Nkind = N_Subprogram_Renaming_Declaration
+        or else NT (N).Nkind = N_Subunit
+        or else NT (N).Nkind = N_Variant_Part
+        or else NT (N).Nkind = N_With_Clause
+        or else NT (N).Nkind = N_With_Type_Clause);
+      Set_Node2_With_Parent (N, Val);
+   end Set_Name;
+
+   procedure Set_Names
+      (N : Node_Id; Val : List_Id) is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_Abort_Statement
+        or else NT (N).Nkind = N_Use_Package_Clause);
+      Set_List2_With_Parent (N, Val);
+   end Set_Names;
+
+   procedure Set_Next_Entity
+      (N : Node_Id; Val : Node_Id) is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_Defining_Character_Literal
+        or else NT (N).Nkind = N_Defining_Identifier
+        or else NT (N).Nkind = N_Defining_Operator_Symbol);
+      Set_Node2 (N, Val); -- semantic field, no parent set
+   end Set_Next_Entity;
+
+   procedure Set_Next_Named_Actual
+      (N : Node_Id; Val : Node_Id) is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_Parameter_Association);
+      Set_Node4 (N, Val); -- semantic field, no parent set
+   end Set_Next_Named_Actual;
+
+   procedure Set_Next_Rep_Item
+      (N : Node_Id; Val : Node_Id) is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_Attribute_Definition_Clause
+        or else NT (N).Nkind = N_Enumeration_Representation_Clause
+        or else NT (N).Nkind = N_Pragma
+        or else NT (N).Nkind = N_Record_Representation_Clause);
+      Set_Node4 (N, Val); -- semantic field, no parent set
+   end Set_Next_Rep_Item;
+
+   procedure Set_Next_Use_Clause
+      (N : Node_Id; Val : Node_Id) is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_Use_Package_Clause
+        or else NT (N).Nkind = N_Use_Type_Clause);
+      Set_Node3 (N, Val); -- semantic field, no parent set
+   end Set_Next_Use_Clause;
+
+   procedure Set_No_Ctrl_Actions
+      (N : Node_Id; Val : Boolean := True) is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_Assignment_Statement);
+      Set_Flag7 (N, Val);
+   end Set_No_Ctrl_Actions;
+
+   procedure Set_No_Entities_Ref_In_Spec
+      (N : Node_Id; Val : Boolean := True) is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_With_Clause);
+      Set_Flag8 (N, Val);
+   end Set_No_Entities_Ref_In_Spec;
+
+   procedure Set_No_Initialization
+      (N : Node_Id; Val : Boolean := True) is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_Allocator
+        or else NT (N).Nkind = N_Object_Declaration);
+      Set_Flag13 (N, Val);
+   end Set_No_Initialization;
+
+   procedure Set_Null_Present
+      (N : Node_Id; Val : Boolean := True) is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_Component_List
+        or else NT (N).Nkind = N_Record_Definition);
+      Set_Flag13 (N, Val);
+   end Set_Null_Present;
+
+   procedure Set_Null_Record_Present
+      (N : Node_Id; Val : Boolean := True) is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_Aggregate
+        or else NT (N).Nkind = N_Extension_Aggregate);
+      Set_Flag17 (N, Val);
+   end Set_Null_Record_Present;
+
+   procedure Set_Object_Definition
+      (N : Node_Id; Val : Node_Id) is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_Object_Declaration);
+      Set_Node4_With_Parent (N, Val);
+   end Set_Object_Definition;
+
+   procedure Set_OK_For_Stream
+      (N : Node_Id; Val : Boolean := True) is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_Attribute_Reference);
+      Set_Flag4 (N, Val);
+   end Set_OK_For_Stream;
+
+   procedure Set_Original_Discriminant
+      (N : Node_Id; Val : Node_Id) is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_Identifier);
+      Set_Node2 (N, Val); -- semantic field, no parent set
+   end Set_Original_Discriminant;
+
+   procedure Set_Others_Discrete_Choices
+      (N : Node_Id; Val : List_Id) is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_Others_Choice);
+      Set_List1_With_Parent (N, Val);
+   end Set_Others_Discrete_Choices;
+
+   procedure Set_Out_Present
+      (N : Node_Id; Val : Boolean := True) is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_Formal_Object_Declaration
+        or else NT (N).Nkind = N_Parameter_Specification);
+      Set_Flag17 (N, Val);
+   end Set_Out_Present;
+
+   procedure Set_Parameter_Associations
+      (N : Node_Id; Val : List_Id) is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_Entry_Call_Statement
+        or else NT (N).Nkind = N_Function_Call
+        or else NT (N).Nkind = N_Procedure_Call_Statement);
+      Set_List3_With_Parent (N, Val);
+   end Set_Parameter_Associations;
+
+   procedure Set_Parameter_List_Truncated
+      (N : Node_Id; Val : Boolean := True) is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_Function_Call
+        or else NT (N).Nkind = N_Procedure_Call_Statement);
+      Set_Flag17 (N, Val);
+   end Set_Parameter_List_Truncated;
+
+   procedure Set_Parameter_Specifications
+      (N : Node_Id; Val : List_Id) is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_Accept_Statement
+        or else NT (N).Nkind = N_Access_Function_Definition
+        or else NT (N).Nkind = N_Access_Procedure_Definition
+        or else NT (N).Nkind = N_Entry_Body_Formal_Part
+        or else NT (N).Nkind = N_Entry_Declaration
+        or else NT (N).Nkind = N_Function_Specification
+        or else NT (N).Nkind = N_Procedure_Specification);
+      Set_List3_With_Parent (N, Val);
+   end Set_Parameter_Specifications;
+
+   procedure Set_Parameter_Type
+      (N : Node_Id; Val : Node_Id) is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_Parameter_Specification);
+      Set_Node2_With_Parent (N, Val);
+   end Set_Parameter_Type;
+
+   procedure Set_Parent_Spec
+      (N : Node_Id; Val : Node_Id) is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_Function_Instantiation
+        or else NT (N).Nkind = N_Generic_Function_Renaming_Declaration
+        or else NT (N).Nkind = N_Generic_Package_Declaration
+        or else NT (N).Nkind = N_Generic_Package_Renaming_Declaration
+        or else NT (N).Nkind = N_Generic_Procedure_Renaming_Declaration
+        or else NT (N).Nkind = N_Generic_Subprogram_Declaration
+        or else NT (N).Nkind = N_Package_Declaration
+        or else NT (N).Nkind = N_Package_Instantiation
+        or else NT (N).Nkind = N_Package_Renaming_Declaration
+        or else NT (N).Nkind = N_Procedure_Instantiation
+        or else NT (N).Nkind = N_Subprogram_Declaration
+        or else NT (N).Nkind = N_Subprogram_Renaming_Declaration);
+      Set_Node4 (N, Val); -- semantic field, no parent set
+   end Set_Parent_Spec;
+
+   procedure Set_Position
+      (N : Node_Id; Val : Node_Id) is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_Component_Clause);
+      Set_Node2_With_Parent (N, Val);
+   end Set_Position;
+
+   procedure Set_Pragma_Argument_Associations
+      (N : Node_Id; Val : List_Id) is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_Pragma);
+      Set_List2_With_Parent (N, Val);
+   end Set_Pragma_Argument_Associations;
+
+   procedure Set_Pragmas_After
+      (N : Node_Id; Val : List_Id) is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_Compilation_Unit_Aux
+        or else NT (N).Nkind = N_Terminate_Alternative);
+      Set_List5_With_Parent (N, Val);
+   end Set_Pragmas_After;
+
+   procedure Set_Pragmas_Before
+      (N : Node_Id; Val : List_Id) is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_Accept_Alternative
+        or else NT (N).Nkind = N_Delay_Alternative
+        or else NT (N).Nkind = N_Entry_Call_Alternative
+        or else NT (N).Nkind = N_Mod_Clause
+        or else NT (N).Nkind = N_Terminate_Alternative
+        or else NT (N).Nkind = N_Triggering_Alternative);
+      Set_List4_With_Parent (N, Val);
+   end Set_Pragmas_Before;
+
+   procedure Set_Prefix
+      (N : Node_Id; Val : Node_Id) is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_Attribute_Reference
+        or else NT (N).Nkind = N_Expanded_Name
+        or else NT (N).Nkind = N_Explicit_Dereference
+        or else NT (N).Nkind = N_Indexed_Component
+        or else NT (N).Nkind = N_Reference
+        or else NT (N).Nkind = N_Selected_Component
+        or else NT (N).Nkind = N_Slice);
+      Set_Node3_With_Parent (N, Val);
+   end Set_Prefix;
+
+   procedure Set_Present_Expr
+      (N : Node_Id; Val : Uint) is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_Variant);
+      Set_Uint3 (N, Val);
+   end Set_Present_Expr;
+
+   procedure Set_Prev_Ids
+      (N : Node_Id; Val : Boolean := True) is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_Component_Declaration
+        or else NT (N).Nkind = N_Discriminant_Specification
+        or else NT (N).Nkind = N_Exception_Declaration
+        or else NT (N).Nkind = N_Formal_Object_Declaration
+        or else NT (N).Nkind = N_Number_Declaration
+        or else NT (N).Nkind = N_Object_Declaration
+        or else NT (N).Nkind = N_Parameter_Specification);
+      Set_Flag6 (N, Val);
+   end Set_Prev_Ids;
+
+   procedure Set_Print_In_Hex
+      (N : Node_Id; Val : Boolean := True) is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_Integer_Literal);
+      Set_Flag13 (N, Val);
+   end Set_Print_In_Hex;
+
+   procedure Set_Private_Declarations
+      (N : Node_Id; Val : List_Id) is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_Package_Specification
+        or else NT (N).Nkind = N_Protected_Definition
+        or else NT (N).Nkind = N_Task_Definition);
+      Set_List3_With_Parent (N, Val);
+   end Set_Private_Declarations;
+
+   procedure Set_Private_Present
+      (N : Node_Id; Val : Boolean := True) is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_Compilation_Unit
+        or else NT (N).Nkind = N_Formal_Derived_Type_Definition);
+      Set_Flag15 (N, Val);
+   end Set_Private_Present;
+
+   procedure Set_Procedure_To_Call
+      (N : Node_Id; Val : Node_Id) is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_Allocator
+        or else NT (N).Nkind = N_Free_Statement
+        or else NT (N).Nkind = N_Return_Statement);
+      Set_Node4 (N, Val); -- semantic field, no parent set
+   end Set_Procedure_To_Call;
+
+   procedure Set_Proper_Body
+      (N : Node_Id; Val : Node_Id) is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_Subunit);
+      Set_Node1_With_Parent (N, Val);
+   end Set_Proper_Body;
+
+   procedure Set_Protected_Definition
+      (N : Node_Id; Val : Node_Id) is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_Protected_Type_Declaration
+        or else NT (N).Nkind = N_Single_Protected_Declaration);
+      Set_Node3_With_Parent (N, Val);
+   end Set_Protected_Definition;
+
+   procedure Set_Protected_Present
+      (N : Node_Id; Val : Boolean := True) is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_Access_Function_Definition
+        or else NT (N).Nkind = N_Access_Procedure_Definition);
+      Set_Flag15 (N, Val);
+   end Set_Protected_Present;
+
+   procedure Set_Raises_Constraint_Error
+      (N : Node_Id; Val : Boolean := True) is
+   begin
+      pragma Assert (False
+          or else NT (N).Nkind in N_Subexpr);
+      Set_Flag7 (N, Val);
+   end Set_Raises_Constraint_Error;
+
+   procedure Set_Range_Constraint
+      (N : Node_Id; Val : Node_Id) is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_Delta_Constraint
+        or else NT (N).Nkind = N_Digits_Constraint);
+      Set_Node4_With_Parent (N, Val);
+   end Set_Range_Constraint;
+
+   procedure Set_Range_Expression
+      (N : Node_Id; Val : Node_Id) is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_Range_Constraint);
+      Set_Node4_With_Parent (N, Val);
+   end Set_Range_Expression;
+
+   procedure Set_Real_Range_Specification
+      (N : Node_Id; Val : Node_Id) is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_Decimal_Fixed_Point_Definition
+        or else NT (N).Nkind = N_Floating_Point_Definition
+        or else NT (N).Nkind = N_Ordinary_Fixed_Point_Definition);
+      Set_Node4_With_Parent (N, Val);
+   end Set_Real_Range_Specification;
+
+   procedure Set_Realval
+     (N : Node_Id; Val : Ureal) is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_Real_Literal);
+      Set_Ureal3 (N, Val);
+   end Set_Realval;
+
+   procedure Set_Record_Extension_Part
+      (N : Node_Id; Val : Node_Id) is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_Derived_Type_Definition);
+      Set_Node3_With_Parent (N, Val);
+   end Set_Record_Extension_Part;
+
+   procedure Set_Redundant_Use
+      (N : Node_Id; Val : Boolean := True) is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_Attribute_Reference
+        or else NT (N).Nkind = N_Expanded_Name
+        or else NT (N).Nkind = N_Identifier);
+      Set_Flag13 (N, Val);
+   end Set_Redundant_Use;
+
+   procedure Set_Return_Type
+      (N : Node_Id; Val : Node_Id) is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_Return_Statement);
+      Set_Node2 (N, Val); -- semantic field, no parent set
+   end Set_Return_Type;
+
+   procedure Set_Reverse_Present
+      (N : Node_Id; Val : Boolean := True) is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_Loop_Parameter_Specification);
+      Set_Flag15 (N, Val);
+   end Set_Reverse_Present;
+
+   procedure Set_Right_Opnd
+      (N : Node_Id; Val : Node_Id) is
+   begin
+      pragma Assert (False
+          or else NT (N).Nkind in N_Op
+        or else NT (N).Nkind = N_And_Then
+        or else NT (N).Nkind = N_In
+        or else NT (N).Nkind = N_Not_In
+        or else NT (N).Nkind = N_Or_Else);
+      Set_Node3_With_Parent (N, Val);
+   end Set_Right_Opnd;
+
+   procedure Set_Rounded_Result
+      (N : Node_Id; Val : Boolean := True) is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_Op_Divide
+        or else NT (N).Nkind = N_Op_Multiply
+        or else NT (N).Nkind = N_Type_Conversion);
+      Set_Flag18 (N, Val);
+   end Set_Rounded_Result;
+
+   procedure Set_Scope
+      (N : Node_Id; Val : Node_Id) is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_Defining_Character_Literal
+        or else NT (N).Nkind = N_Defining_Identifier
+        or else NT (N).Nkind = N_Defining_Operator_Symbol);
+      Set_Node3 (N, Val); -- semantic field, no parent set
+   end Set_Scope;
+
+   procedure Set_Select_Alternatives
+      (N : Node_Id; Val : List_Id) is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_Selective_Accept);
+      Set_List1_With_Parent (N, Val);
+   end Set_Select_Alternatives;
+
+   procedure Set_Selector_Name
+      (N : Node_Id; Val : Node_Id) is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_Expanded_Name
+        or else NT (N).Nkind = N_Generic_Association
+        or else NT (N).Nkind = N_Parameter_Association
+        or else NT (N).Nkind = N_Selected_Component);
+      Set_Node2_With_Parent (N, Val);
+   end Set_Selector_Name;
+
+   procedure Set_Selector_Names
+      (N : Node_Id; Val : List_Id) is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_Discriminant_Association);
+      Set_List1_With_Parent (N, Val);
+   end Set_Selector_Names;
+
+   procedure Set_Shift_Count_OK
+      (N : Node_Id; Val : Boolean := True) is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_Op_Rotate_Left
+        or else NT (N).Nkind = N_Op_Rotate_Right
+        or else NT (N).Nkind = N_Op_Shift_Left
+        or else NT (N).Nkind = N_Op_Shift_Right
+        or else NT (N).Nkind = N_Op_Shift_Right_Arithmetic);
+      Set_Flag4 (N, Val);
+   end Set_Shift_Count_OK;
+
+   procedure Set_Source_Type
+      (N : Node_Id; Val : Entity_Id) is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_Validate_Unchecked_Conversion);
+      Set_Node1 (N, Val); -- semantic field, no parent set
+   end Set_Source_Type;
+
+   procedure Set_Specification
+      (N : Node_Id; Val : Node_Id) is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_Abstract_Subprogram_Declaration
+        or else NT (N).Nkind = N_Formal_Subprogram_Declaration
+        or else NT (N).Nkind = N_Generic_Package_Declaration
+        or else NT (N).Nkind = N_Generic_Subprogram_Declaration
+        or else NT (N).Nkind = N_Package_Declaration
+        or else NT (N).Nkind = N_Subprogram_Body
+        or else NT (N).Nkind = N_Subprogram_Body_Stub
+        or else NT (N).Nkind = N_Subprogram_Declaration
+        or else NT (N).Nkind = N_Subprogram_Renaming_Declaration);
+      Set_Node1_With_Parent (N, Val);
+   end Set_Specification;
+
+   procedure Set_Statements
+      (N : Node_Id; Val : List_Id) is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_Abortable_Part
+        or else NT (N).Nkind = N_Accept_Alternative
+        or else NT (N).Nkind = N_Case_Statement_Alternative
+        or else NT (N).Nkind = N_Delay_Alternative
+        or else NT (N).Nkind = N_Entry_Call_Alternative
+        or else NT (N).Nkind = N_Exception_Handler
+        or else NT (N).Nkind = N_Handled_Sequence_Of_Statements
+        or else NT (N).Nkind = N_Loop_Statement
+        or else NT (N).Nkind = N_Triggering_Alternative);
+      Set_List3_With_Parent (N, Val);
+   end Set_Statements;
+
+   procedure Set_Static_Processing_OK
+      (N : Node_Id; Val : Boolean) is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_Aggregate);
+      Set_Flag4 (N, Val);
+   end Set_Static_Processing_OK;
+
+   procedure Set_Storage_Pool
+      (N : Node_Id; Val : Node_Id) is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_Allocator
+        or else NT (N).Nkind = N_Free_Statement
+        or else NT (N).Nkind = N_Return_Statement);
+      Set_Node1 (N, Val); -- semantic field, no parent set
+   end Set_Storage_Pool;
+
+   procedure Set_Strval
+      (N : Node_Id; Val : String_Id) is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_Operator_Symbol
+        or else NT (N).Nkind = N_String_Literal);
+      Set_Str3 (N, Val);
+   end Set_Strval;
+
+   procedure Set_Subtype_Indication
+      (N : Node_Id; Val : Node_Id) is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_Access_To_Object_Definition
+        or else NT (N).Nkind = N_Component_Declaration
+        or else NT (N).Nkind = N_Constrained_Array_Definition
+        or else NT (N).Nkind = N_Derived_Type_Definition
+        or else NT (N).Nkind = N_Private_Extension_Declaration
+        or else NT (N).Nkind = N_Subtype_Declaration
+        or else NT (N).Nkind = N_Unconstrained_Array_Definition);
+      Set_Node5_With_Parent (N, Val);
+   end Set_Subtype_Indication;
+
+   procedure Set_Subtype_Mark
+      (N : Node_Id; Val : Node_Id) is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_Access_Definition
+        or else NT (N).Nkind = N_Access_Function_Definition
+        or else NT (N).Nkind = N_Formal_Derived_Type_Definition
+        or else NT (N).Nkind = N_Formal_Object_Declaration
+        or else NT (N).Nkind = N_Function_Specification
+        or else NT (N).Nkind = N_Object_Renaming_Declaration
+        or else NT (N).Nkind = N_Qualified_Expression
+        or else NT (N).Nkind = N_Subtype_Indication
+        or else NT (N).Nkind = N_Type_Conversion
+        or else NT (N).Nkind = N_Unchecked_Type_Conversion);
+      Set_Node4_With_Parent (N, Val);
+   end Set_Subtype_Mark;
+
+   procedure Set_Subtype_Marks
+      (N : Node_Id; Val : List_Id) is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_Unconstrained_Array_Definition
+        or else NT (N).Nkind = N_Use_Type_Clause);
+      Set_List2_With_Parent (N, Val);
+   end Set_Subtype_Marks;
+
+   procedure Set_Tagged_Present
+      (N : Node_Id; Val : Boolean := True) is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_Formal_Private_Type_Definition
+        or else NT (N).Nkind = N_Private_Type_Declaration
+        or else NT (N).Nkind = N_Record_Definition
+        or else NT (N).Nkind = N_With_Type_Clause);
+      Set_Flag15 (N, Val);
+   end Set_Tagged_Present;
+
+   procedure Set_Target_Type
+      (N : Node_Id; Val : Entity_Id) is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_Validate_Unchecked_Conversion);
+      Set_Node2 (N, Val); -- semantic field, no parent set
+   end Set_Target_Type;
+
+   procedure Set_Task_Body_Procedure
+      (N : Node_Id; Val : Entity_Id) is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_Task_Type_Declaration);
+      Set_Node2 (N, Val); -- semantic field, no parent set
+   end Set_Task_Body_Procedure;
+
+   procedure Set_Task_Definition
+      (N : Node_Id; Val : Node_Id) is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_Single_Task_Declaration
+        or else NT (N).Nkind = N_Task_Type_Declaration);
+      Set_Node3_With_Parent (N, Val);
+   end Set_Task_Definition;
+
+   procedure Set_Then_Actions
+      (N : Node_Id; Val : List_Id) is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_Conditional_Expression);
+      Set_List2 (N, Val); -- semantic field, no parent set
+   end Set_Then_Actions;
+
+   procedure Set_Then_Statements
+      (N : Node_Id; Val : List_Id) is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_Elsif_Part
+        or else NT (N).Nkind = N_If_Statement);
+      Set_List2_With_Parent (N, Val);
+   end Set_Then_Statements;
+
+   procedure Set_Treat_Fixed_As_Integer
+      (N : Node_Id; Val : Boolean := True) is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_Op_Divide
+        or else NT (N).Nkind = N_Op_Mod
+        or else NT (N).Nkind = N_Op_Multiply
+        or else NT (N).Nkind = N_Op_Rem);
+      Set_Flag14 (N, Val);
+   end Set_Treat_Fixed_As_Integer;
+
+   procedure Set_Triggering_Alternative
+      (N : Node_Id; Val : Node_Id) is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_Asynchronous_Select);
+      Set_Node1_With_Parent (N, Val);
+   end Set_Triggering_Alternative;
+
+   procedure Set_Triggering_Statement
+      (N : Node_Id; Val : Node_Id) is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_Triggering_Alternative);
+      Set_Node1_With_Parent (N, Val);
+   end Set_Triggering_Statement;
+
+   procedure Set_TSS_Elist
+      (N : Node_Id; Val : Elist_Id) is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_Freeze_Entity);
+      Set_Elist3 (N, Val); -- semantic field, no parent set
+   end Set_TSS_Elist;
+
+   procedure Set_Type_Definition
+      (N : Node_Id; Val : Node_Id) is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_Full_Type_Declaration);
+      Set_Node3_With_Parent (N, Val);
+   end Set_Type_Definition;
+
+   procedure Set_Unit
+      (N : Node_Id; Val : Node_Id) is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_Compilation_Unit);
+      Set_Node2_With_Parent (N, Val);
+   end Set_Unit;
+
+   procedure Set_Unknown_Discriminants_Present
+      (N : Node_Id; Val : Boolean := True) is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_Formal_Type_Declaration
+        or else NT (N).Nkind = N_Incomplete_Type_Declaration
+        or else NT (N).Nkind = N_Private_Extension_Declaration
+        or else NT (N).Nkind = N_Private_Type_Declaration);
+      Set_Flag13 (N, Val);
+   end Set_Unknown_Discriminants_Present;
+
+   procedure Set_Unreferenced_In_Spec
+      (N : Node_Id; Val : Boolean := True) is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_With_Clause);
+      Set_Flag7 (N, Val);
+   end Set_Unreferenced_In_Spec;
+
+   procedure Set_Variant_Part
+      (N : Node_Id; Val : Node_Id) is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_Component_List);
+      Set_Node4_With_Parent (N, Val);
+   end Set_Variant_Part;
+
+   procedure Set_Variants
+      (N : Node_Id; Val : List_Id) is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_Variant_Part);
+      Set_List1_With_Parent (N, Val);
+   end Set_Variants;
+
+   procedure Set_Visible_Declarations
+      (N : Node_Id; Val : List_Id) is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_Package_Specification
+        or else NT (N).Nkind = N_Protected_Definition
+        or else NT (N).Nkind = N_Task_Definition);
+      Set_List2_With_Parent (N, Val);
+   end Set_Visible_Declarations;
+
+   procedure Set_Was_Originally_Stub
+      (N : Node_Id; Val : Boolean := True) is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_Package_Body
+        or else NT (N).Nkind = N_Protected_Body
+        or else NT (N).Nkind = N_Subprogram_Body
+        or else NT (N).Nkind = N_Task_Body);
+      Set_Flag13 (N, Val);
+   end Set_Was_Originally_Stub;
+
+   procedure Set_Zero_Cost_Handling
+      (N : Node_Id; Val : Boolean := True) is
+   begin
+      pragma Assert (False
+        or else NT (N).Nkind = N_Exception_Handler
+        or else NT (N).Nkind = N_Handled_Sequence_Of_Statements);
+      Set_Flag5 (N, Val);
+   end Set_Zero_Cost_Handling;
+
+   -------------------------
+   -- Iterator Procedures --
+   -------------------------
+
+   procedure Next_Entity       (N : in out Node_Id) is
+   begin
+      N := Next_Entity (N);
+   end Next_Entity;
+
+   procedure Next_Named_Actual (N : in out Node_Id) is
+   begin
+      N := Next_Named_Actual (N);
+   end Next_Named_Actual;
+
+   procedure Next_Rep_Item     (N : in out Node_Id) is
+   begin
+      N := Next_Rep_Item (N);
+   end Next_Rep_Item;
+
+   procedure Next_Use_Clause   (N : in out Node_Id) is
+   begin
+      N := Next_Use_Clause (N);
+   end Next_Use_Clause;
+
+   ------------------
+   -- End_Location --
+   ------------------
+
+   function End_Location (N : Node_Id) return Source_Ptr is
+      L : constant Uint := End_Span (N);
+
+   begin
+      if L = No_Uint then
+         return No_Location;
+      else
+         return Source_Ptr (Int (Sloc (N)) + UI_To_Int (L));
+      end if;
+   end End_Location;
+
+   ----------------------
+   -- Set_End_Location --
+   ----------------------
+
+   procedure Set_End_Location (N : Node_Id; S : Source_Ptr) is
+   begin
+      Set_End_Span (N,
+        UI_From_Int (Int (S) - Int (Sloc (N))));
+   end Set_End_Location;
+
+end Sinfo;
diff --git a/gcc/ada/sinfo.ads b/gcc/ada/sinfo.ads
new file mode 100644 (file)
index 0000000..335f9fa
--- /dev/null
@@ -0,0 +1,8684 @@
+------------------------------------------------------------------------------
+--                                                                          --
+--                         GNAT COMPILER COMPONENTS                         --
+--                                                                          --
+--                                S I N F O                                 --
+--                                                                          --
+--                                 S p e c                                  --
+--                                                                          --
+--                            $Revision: 1.430 $
+--                                                                          --
+--          Copyright (C) 1992-2001, 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- --
+-- ware  Foundation;  either version 2,  or (at your option) any later ver- --
+-- sion.  GNAT is distributed in the hope that it will be useful, but WITH- --
+-- OUT ANY WARRANTY;  without even the  implied warranty of MERCHANTABILITY --
+-- or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License --
+-- for  more details.  You should have  received  a copy of the GNU General --
+-- Public License  distributed with GNAT;  see file COPYING.  If not, write --
+-- to  the Free Software Foundation,  59 Temple Place - Suite 330,  Boston, --
+-- MA 02111-1307, USA.                                                      --
+--                                                                          --
+-- As a special exception,  if other files  instantiate  generics from this --
+-- unit, or you link  this unit with other files  to produce an executable, --
+-- this  unit  does not  by itself cause  the resulting  executable  to  be --
+-- covered  by the  GNU  General  Public  License.  This exception does not --
+-- however invalidate  any other reasons why  the executable file  might be --
+-- covered by the  GNU Public License.                                      --
+--                                                                          --
+-- GNAT was originally developed  by the GNAT team at  New York University. --
+-- It is now maintained by Ada Core Technologies Inc (http://www.gnat.com). --
+--                                                                          --
+------------------------------------------------------------------------------
+
+--  This package defines the structure of the abstract syntax tree. The Tree
+--  package provides a basic tree structure. Sinfo describes how this
+--  structure is used to represent the syntax of an Ada program.
+
+--  Note: the grammar used here is taken from Version 5.95 of the RM, dated
+--  November 1994. The grammar in the RM is followed very closely in the tree
+--  design, and is repeated as part of this source file.
+
+--  The tree contains not only the full syntactic representation of the
+--  program, but also the results of semantic analysis. In particular, the
+--  nodes for defining identifiers, defining character literals and defining
+--  operator symbols, collectively referred to as entities, represent what
+--  would normally be regarded as the symbol table information. In addition
+--  a number of the tree nodes contain semantic information.
+
+--  WARNING: There is a C version of this package. Any changes to this
+--  source file must be properly reflected in this C header file sinfo.h
+--  which is created automatically from sinfo.ads using xsinfo.spt.
+
+with Types;  use Types;
+with Uintp;  use Uintp;
+with Urealp; use Urealp;
+
+package Sinfo is
+
+   ---------------------------------
+   -- Making Changes to This File --
+   ---------------------------------
+
+   --  If changes are made to this file, a number of related steps must be
+   --  carried out to ensure consistency. First, if a field access function
+   --  is added, it appears in seven places:
+
+   --    The documentation associated with the node
+   --    The spec of the access function in sinfo.ads
+   --    The body of the access function in sinfo.adb
+   --    The pragma Inline at the end of sinfo.ads for the access function
+   --    The spec of the set procedure in sinfo.ads
+   --    The body of the set procedure in sinfo.adb
+   --    The pragma Inline at the end of sinfo.ads for the set procedure
+
+   --  The field chosen must be consistent in all places, and, for a node
+   --  that is a subexpression, must not overlap any of the standard
+   --  expression fields. In the body, the calls to the Dcheck_Node debug
+   --  procedure will need cross-references adding in alphabetical order.
+
+   --  In addition, if any of the standard expression fields is changed, then
+   --  the utiliy program which creates the Treeprs spec (in file treeprs.ads)
+   --  must be updated appropriately, since it special cases expression fields.
+
+   --  If a new tree node is added, then the following changes are made
+
+   --    Add it to the documentation in the appropriate place
+   --    Add its fields to this documentation section
+   --    Define it in the appropriate classification in Node_Kind
+   --    In the body (sinfo), add entries to the Dcheck calls for all
+   --     its fields (except standard expression fields) to include
+   --     the new node in the debug cross-reference list
+   --    Add an appropriate section to the case statement in sprint.adb
+   --    Add an appropriate section to the case statement in sem.adb
+   --    Add an appropraite section to the case statement in exp_util.adb
+   --     (Insert_Actions procedure)
+   --    For a subexpression, add an appropriate sections to the case
+   --     statement in sem_eval.adb
+   --    For a subexpression, add an appropriate sections to the case
+   --     statement in sem_res.adb
+
+   --  Finally, four utility programs must be run:
+
+   --    Run CSinfo to check that you have made the changes consistently.
+   --     It checks most of the rules given above, with clear error messages.
+   --     This utility reads sinfo.ads and sinfo.adb and generates a report
+   --     to standard output.
+
+   --    Run XSinfo to create a-sinfo.h, the corresponding C header. This
+   --     utility reads sinfo.ads and generates a-sinfo.h. Note that it
+   --     does not need to read sinfo.adb, since the contents of the body
+   --     are algorithmically determinable from the spec.
+
+   --    Run XTreeprs to create treeprs.ads, an updated version of
+   --     the module that is used to drive the tree print routine. This
+   --     utility reads (but does not modify) treeprs.adt, the template
+   --     that provides the basic structure of the file, and then fills
+   --     in the data from the comments in sinfo.ads.
+
+   --    Run XNmake to create nmake.ads and nmake.adb, the package body
+   --     and spec of the Nmake package which contains functions for
+   --     constructing nodes.
+
+   --  Note: sometime we could write a utility that actually generated the
+   --  body of sinfo from the spec instead of simply checking it, since, as
+   --  noted above, the contents of the body can be determined from the spec.
+
+   --------------------------------
+   -- Implicit Nodes in the Tree --
+   --------------------------------
+
+   --  Generally the structure of the tree very closely follows the grammar
+   --  as defined in the RM. However, certain nodes are omitted to save
+   --  space and simplify semantic processing. Two general classes of such
+   --  omitted nodes are as follows:
+
+   --   If the only possibilities for a non-terminal are one or more other
+   --   non terminals (i.e. the rule is a "skinny" rule), then usually the
+   --   corresponding node is omitted from the tree, and the target construct
+   --   appears directly. For example, a real type definition is either a
+   --   floating point definition or a fixed point definition. No explicit
+   --   node appears for real type definition. Instead either the floating
+   --   point definition or fixed point definition appears directly.
+
+   --   If a non-terminal corresponds to a list of some other non-terminal
+   --   (possibly with separating punctuation), then usually it is omitted
+   --   from the tree, and a list of components appears instead. For
+   --   example, sequence of statements does not appear explicitly in the
+   --   tree. Instead a list of statements appears directly.
+
+   --  Some additional cases of omitted nodes occur and are documented
+   --  individually. In particular, many nodes are omitted in the tree
+   --  generated for an expression.
+
+   -------------------------------------------
+   -- Handling of Defining Identifier Lists --
+   -------------------------------------------
+
+   --  In several declarative forms in the syntax, lists of defining
+   --  identifiers appear (object declarations, component declarations,
+   --  number declarations etc.)
+
+   --  The semantics of such statements are equivalent to a series of
+   --  identical declarations of single defining identifiers (except that
+   --  conformance checks require the same grouping of identifiers in the
+   --  parameter case).
+
+   --  To simplify semantic processing, the parser breaks down such multiple
+   --  declaration cases into sequences of single declarations, duplicating
+   --  type and initialization information as required. The flags More_Ids
+   --  and Prev_Ids are used to record the original form of the source in
+   --  the case where the original source used a list of names, More_Ids
+   --  being set on all but the last name and Prev_Ids being set on all
+   --  but the first name. These flags are used to reconstruct the original
+   --  source (e.g. in the Sprint package), and also are included in the
+   --  conformance checks, but otherwise have no semantic significance.
+
+   --  Note: the reason that we use More_Ids and Prev_Ids rather than
+   --  First_Name and Last_Name flags is so that the flags are off in the
+   --  normal one identifier case, which minimizes tree print output.
+
+   -----------------------
+   -- Use of Node Lists --
+   -----------------------
+
+   --  With a few exceptions, if a construction of the form {non-terminal}
+   --  appears in the tree, lists are used in the corresponding tree node
+   --  (see package Nlists for handling of node lists). In this case a field
+   --  of the parent node points to a list of nodes for the non-terminal. The
+   --  field name for such fields has a plural name which always ends in "s".
+   --  For example, a case statement has a field Alternatives pointing to a
+   --  list of case statement alternative nodes.
+
+   --  Only fields pointing to lists have names ending in "s", so generally
+   --  the structure is strongly typed, fields not ending in s point to
+   --  single nodes, and fields ending in s point to lists.
+
+   --  The following example shows how a traversal of a list is written. We
+   --  suppose here that Stmt points to a N_Case_Statement node which has
+   --  a list field called Alternatives:
+
+   --   Alt := First (Alternatives (Stmt));
+   --   while Present (Alt) loop
+   --      ..
+   --      -- processing for case statement alternative Alt
+   --      ..
+   --      Alt := Next (Alt);
+   --   end loop;
+
+   --  The Present function tests for Empty, which in this case signals the
+   --  end of the list. First returns Empty immediately if the list is empty.
+   --  Present is defined in Atree, First and Next are defined in Nlists.
+
+   --  The exceptions to this rule occur with {DEFINING_IDENTIFIERS} in all
+   --  contexts, which is handled as described in the previous section, and
+   --  with {,library_unit_NAME} in the N_With_Clause mode, which is handled
+   --  using the First_Name and Last_Name flags, as further detailed in the
+   --  description of the N_With_Clause node.
+
+   -------------
+   -- Pragmas --
+   -------------
+
+   --  Pragmas can appear in many different context, but are not included
+   --  in the grammar. Still they must appear in the tree, so they can be
+   --  properly processed.
+
+   --  Two approaches are used. In some cases, an extra field is defined
+   --  in an appropriate node that contains a list of pragmas appearing
+   --  in the expected context. For example pragmas can appear before an
+   --  Accept_Alternative in a Selective_Accept_Statement, and these pragmas
+   --  appear in the Pragmas_Before field of the N_Accept_Alternative node.
+
+   --  The other approach is to simply allow pragmas to appear in syntactic
+   --  lists where the grammar (of course) does not include the possibility.
+   --  For example, the Variants field of an N_Variant_Part node points to
+   --  a list that can contain both N_Pragma and N_Variant nodes.
+
+   --  To make processing easier in the latter case, the Nlists package
+   --  provides a set of routines (First_Non_Pragma, Last_Non_Pragma,
+   --  Next_Non_Pragma, Prev_Non_Pragma) that allow such lists to be
+   --  handled ignoring all pragmas.
+
+   --  In the case of the variants list, we can either write:
+
+   --      Variant := First (Variants (N));
+   --      while Present (Variant) loop
+   --         ...
+   --         Alt := Next (Alt);
+   --      end loop;
+
+   --  or
+
+   --      Variant := First_Non_Pragma (Variants (N));
+   --      while Present (Variant) loop
+   --         ...
+   --         Alt := Next_Non_Pragma (Alt);
+   --      end loop;
+
+   --  In the first form of the loop, Variant can either be an N_Pragma or
+   --  an N_Variant node. In the second form, Variant can only be N_Variant
+   --  since all pragmas are skipped.
+
+   ---------------------
+   -- Optional Fields --
+   ---------------------
+
+   --  Fields which correspond to a section of the syntax enclosed in square
+   --  brackets are generally omitted (and the corresponding field set to
+   --  Empty for a node, or No_List for a list). The documentation of such
+   --  fields notes these cases. One exception to this rule occurs in the
+   --  case of possibly empty statement sequences (such as the sequence of
+   --  statements in an entry call alternative). Such cases appear in the
+   --  syntax rules as [SEQUENCE_OF_STATEMENTS] and the fields corresponding
+   --  to such optional statement sequences always contain an empty list (not
+   --  No_List) if no statements are present.
+
+   --  Note: the utility program that constructs the body and spec of the
+   --  Nmake package relies on the format of the comments to determine if
+   --  a field should have a default value in the corresponding make routine.
+   --  The rule is that if the first line of the description of the field
+   --  contains the string "(set to xxx if", then a default value of xxx is
+   --  provided for this field in the corresponding Make_yyy routine.
+
+   -----------------------------------
+   -- Note on Body/Spec Terminology --
+   -----------------------------------
+
+   --  In informal discussions about Ada, it is customary to refer to package
+   --  and subprogram specs and bodies. However, this is not technically
+   --  correct, what is normally referred to as a spec or specification is in
+   --  fact a package declaration or subprogram declaration. We are careful
+   --  in GNAT to use the correct terminology and in particular, the full
+   --  word specification is never used as an incorrect substitute for
+   --  declaration. The structure and terminology used in the tree also
+   --  reflects the grammar and thus uses declaration and specification in
+   --  the technically correct manner.
+
+   --  However, there are contexts in which the informal terminology is
+   --  useful. We have the word "body" to refer to the Interp_Etype declared by
+   --  the declaration of a unit body, and in some contexts we need a
+   --  similar term to refer to the entity declared by the package or
+   --  subprogram declaration, and simply using declaration can be confusing
+   --  since the body also has a declaration.
+
+   --  An example of such a context is the link between the package body
+   --  and its declaration. With_Declaration is confusing, since
+   --  the package body itself is a declaration.
+
+   --  To deal with this problem, we reserve the informal term Spec, i.e.
+   --  the popular abbreviation used in this context, to refer to the entity
+   --  declared by the package or subprogram declaration. So in the above
+   --  example case, the field in the body is called With_Spec.
+
+   --  Another important context for the use of the word Spec is in error
+   --  messages, where a hyper-correct use of declaration would be confusing
+   --  to a typical Ada programmer, and even for an expert programmer can
+   --  cause confusion since the body has a declaration as well.
+
+   --  So, to summarize:
+
+   --     Declaration    always refers to the syntactic entity that is called
+   --                    a declaration. In particular, subprogram declaration
+   --                    and package declaration are used to describe the
+   --                    syntactic entity that includes the semicolon.
+
+   --     Specification  always refers to the syntactic entity that is called
+   --                    a specification. In particular, the terms procedure
+   --                    specification, function specification, package
+   --                    specification, subprogram specification always refer
+   --                    to the syntactic entity that has no semicolon.
+
+   --     Spec           is an informal term, used to refer to the entity
+   --                    that is declared by a task declaration, protected
+   --                    declaration, generic declaration, subprogram
+   --                    declaration or package declaration.
+
+   --  This convention is followed throughout the GNAT documentation
+   --  both internal and external, and in all error message text.
+
+   ------------------------
+   -- Internal Use Nodes --
+   ------------------------
+
+   --  These are Node_Kind settings used in the internal implementation
+   --  which are not logically part of the specification.
+
+   --  N_Unused_At_Start
+   --  Completely unused entry at the start of the enumeration type. This
+   --  is inserted so that no legitimate value is zero, which helps to get
+   --  better debugging behavior, since zero is a likely uninitialized value).
+
+   --  N_Unused_At_End
+   --  Completely unused entry at the end of the enumeration type. This is
+   --  handy so that arrays with Node_Kind as the index type have an extra
+   --  entry at the end (see for example the use of the Pchar_Pos_Array in
+   --  Treepr, where the extra entry provides the limit value when dealing
+   --  with the last used entry in the array).
+
+   -----------------------------------------
+   -- Note on the settings of Sloc fields --
+   -----------------------------------------
+
+   --  The Sloc field of nodes that come from the source is set by the
+   --  parser. For internal nodes, and nodes generated during expansion
+   --  the Sloc is usually set in the call to the constructor for the node.
+   --  In general the Sloc value chosen for an internal node is the Sloc of
+   --  the source node whose processing is responsible for the expansion. For
+   --  example, the Sloc of an inherited primitive operation is the Sloc of
+   --  the corresponding derived type declaration.
+
+   --  For the nodes of a generic instantiation, the Sloc value is encoded
+   --  to represent both the original Sloc in the generic unit, and the Sloc
+   --  of the instantiation itself. See Sinput.ads for details.
+
+   --  Subprogram instances create two callable entities: one is the visible
+   --  subprogram instance, and the other is an anonymous subprogram nested
+   --  within a wrapper package that contains the renamings for the actuals.
+   --  Both of these entities have the Sloc of the defining entity in the
+   --  instantiation node. This simplifies some ASIS queries.
+
+   -----------------------
+   -- Field Definitions --
+   -----------------------
+
+   --  In the following node definitions, all fields, both syntactic and
+   --  semantic, are documented. The one exception is in the case of entities
+   --  (defining indentifiers, character literals and operator symbols),
+   --  where the usage of the fields depends on the entity kind. Entity
+   --  fields are fully documented in the separate package Einfo.
+
+   --  In the node definitions, three common sets of fields are abbreviated
+   --  to save both space in the documentation, and also space in the string
+   --  (defined in Tree_Print_Strings) used to print trees. The following
+   --  abbreviations are used:
+
+   --  Note: the utility program that creates the Treeprs spec (in the file
+   --  treeprs.ads) knows about the special fields here, so it must be
+   --  modified if any change is made to these fields.
+
+   --    "plus fields for binary operator"
+   --       Chars                    (Name1)      Name_Id for the operator
+   --       Left_Opnd                (Node2)      left operand expression
+   --       Right_Opnd               (Node3)      right operand expression
+   --       Entity                   (Node4-Sem)  defining entity for operator
+   --       Do_Overflow_Check        (Flag17-Sem) set if overflow check needed
+   --       Has_Private_View         (Flag11-Sem) set in generic units.
+
+   --    "plus fields for unary operator"
+   --       Chars                    (Name1)      Name_Id for the operator
+   --       Right_Opnd               (Node3)      right operand expression
+   --       Entity                   (Node4-Sem)  defining entity for operator
+   --       Do_Overflow_Check        (Flag17-Sem) set if overflow check needed
+   --       Has_Private_View         (Flag11-Sem) set in generic units.
+
+   --    "plus fields for expression"
+   --       Paren_Count                           number of parentheses levels
+   --       Etype                    (Node5-Sem)  type of the expression
+   --       Is_Overloaded            (Flag5-Sem)  >1 type interpretation exists
+   --       Is_Static_Expression     (Flag6-Sem)  set for static expression
+   --       Raises_Constraint_Error  (Flag7-Sem)  evaluation raises CE
+   --       Must_Not_Freeze          (Flag8-Sem)  set if must not freeze
+   --       Do_Range_Check           (Flag9-Sem)  set if a range check needed
+   --       Assignment_OK            (Flag15-Sem) set if modification is OK
+   --       Is_Controlling_Actual    (Flag16-Sem) set for controlling argument
+
+   --  Note: see under (EXPRESSION) for further details on the use of
+   --  the Paren_Count field to record the number of parentheses levels.
+
+   --  Node_Kind is the type used in the Nkind field to indicate the node
+   --  kind. The actual definition of this type is given later (the reason
+   --  for this is that we want the descriptions ordered by logical chapter
+   --  in the RM, but the type definition is reordered to facilitate the
+   --  definition of some subtype ranges. The individual descriptions of
+   --  the nodes show how the various fields are used in each node kind,
+   --  as well as providing logical names for the fields. Functions and
+   --  procedures are provided for accessing and setting these fields
+   --  using these logical names.
+
+   -----------------------
+   -- Gigi Restrictions --
+   -----------------------
+
+   --  The tree passed to Gigi is more restricted than the general tree form.
+   --  For example, as a result of expansion, most of the tasking nodes can
+   --  never appear. For each node to which either a complete or partial
+   --  restriction applies, a note entitled "Gigi restriction" appears which
+   --  documents the restriction.
+
+   --  Note that most of these restrictions apply only to trees generated when
+   --  code is being generated, since they involved expander actions that
+   --  destroy the tree.
+
+   ------------------------
+   -- Common Flag Fields --
+   ------------------------
+
+   --  The following flag fields appear in all nodes
+
+   --  Analyzed
+   --    This flag is used to indicate that a node (and all its children
+   --    have been analyzed. It is used to avoid reanalysis of a node that
+   --    has already been analyzed, both for efficiency and functional
+   --    correctness reasons.
+
+   --  Error_Posted
+   --    This flag is used to avoid multiple error messages being posted
+   --    on or referring to the same node. This flag is set if an error
+   --    message refers to a node or is posted on its source location,
+   --    and has the effect of inhibiting further messages involving
+   --    this same node.
+
+   --  Comes_From_Source
+   --    This flag is on for any nodes built by the scanner or parser from
+   --    the source program, and off for any nodes built by the analyzer or
+   --    expander. It indicates that a node comes from the original source.
+   --    This flag is defined in Atree.
+
+   --  Has_Dynamic_Length_Check and Has_Dynamic_Range_Check also appear on
+   --  all nodes. They are fully described in the next section.
+
+   ------------------------------------
+   -- Description of Semantic Fields --
+   ------------------------------------
+
+   --  The meaning of the syntactic fields is generally clear from their
+   --  names without any further description, since the names are chosen
+   --  to correspond very closely to the syntax in the reference manual.
+   --  This section describes the usage of the semantic fields, which are
+   --  used to contain additional information determined during semantic
+   --  analysis.
+
+   --  ABE_Is_Certain (Flag18-Sem)
+   --    This flag is set in an instantiation node or a call node is
+   --    determined to be sure to raise an ABE. This is used to trigger
+   --    special handling of such cases, particularly in the instantiation
+   --    case where we avoid instantiating the body if this flag is set.
+   --    This flag is also present in an N_Formal_Package_Declaration_Node
+   --    since formal package declarations are treated like instantiations,
+   --    but it is always set to False in this context.
+
+   --  Accept_Handler_Records (List5-Sem)
+   --    This field is present only in an N_Accept_Alternative node. It is
+   --    used to temporarily hold the exception handler records from an
+   --    accept statement in a selective accept. These exception handlers
+   --    will eventually be placed in the Handler_Records list of the
+   --    procedure built for this accept (see Expand_N_Selective_Accept
+   --    procedure in Exp_Ch9 for further details).
+
+   --  Access_Types_To_Process (Elist2-Sem)
+   --    Present in N_Freeze_Entity nodes for Incomplete or private types.
+   --    Contains the list of access types which may require specific
+   --    treatment when the nature of the type completion is completely
+   --    known. An example of such treatement is the generation of the
+   --    associated_final_chain.
+
+   --  Actions (List1-Sem)
+   --    This field contains a sequence of actions that are associated
+   --    with the node holding the field. See the individual node types
+   --    for details of how this field is used, as well as the description
+   --    of the specific use for a particular node type.
+
+   --  Activation_Chain_Entity (Node3-Sem)
+   --    This is used in tree nodes representing task activators (blocks,
+   --    subprogram bodies, package declarations, and task bodies). It is
+   --    initially Empty, and then gets set to point to the entity for the
+   --    declared Activation_Chain variable when the first task is declared.
+   --    When tasks are declared in the corresponding declarative region
+   --    this entity is located by name (its name is always _Chain) and
+   --    the declared tasks are added to the chain.
+
+   --  Acts_As_Spec (Flag4-Sem)
+   --    A flag set in the N_Subprogram_Body node for a subprogram body
+   --    which is acting as its own spec. This flag also appears in the
+   --    compilation unit node at the library level for such a subprogram
+   --    (see further description in spec of Lib package).
+
+   --  Aggregate_Bounds (Node3-Sem)
+   --    Present in array N_Aggregate nodes. If the aggregate contains
+   --    component associations this field points to an N_Range node whose
+   --    bounds give the lowest and highest discrete choice values. If the
+   --    named aggregate contains a dynamic or null choice this field is
+   --    empty. If the aggregate contains positional elements this field
+   --    points to an N_Integer_Literal node giving the number of positional
+   --    elements. Note that if the aggregate contains positional elements
+   --    and an other choice the N_Integer_Literal only accounts for the
+   --    number of positional elements.
+
+   --  All_Others (Flag11-Sem)
+   --    Present in an N_Others_Choice node. This flag is set in the case
+   --    of an others exception where all exceptions, even those that are
+   --    not normally handled (in particular the tasking abort signal) by
+   --    others. This is used for translation of the at end handler into
+   --    a normal exception handler.
+
+   --  Assignment_OK (Flag15-Sem)
+   --    This flag is set in a subexpression node for an object, indicating
+   --    that the associated object can be modified, even if this would not
+   --    normally be permissible (either by direct assignment, or by being
+   --    passed as an out or in-out parameter). This is used by the expander
+   --    for a number of purposes, including initialzation of constants and
+   --    limited type objects (such as tasks), setting discriminant fields,
+   --    setting tag values, etc. N_Object_Declaration nodes also have this
+   --    flag defined. Here it is used to indicate that an initialization
+   --    expression is valid, even where it would normally not be allowed
+   --    (e.g. where the type involved is limited).
+
+   --  At_End_Proc (Node1)
+   --    This field is present in an N_Handled_Sequence_Of_Statements node.
+   --    It contains an identifier reference for the cleanup procedure to
+   --    be called. See description of this node for further details.
+
+   --  Backwards_OK (Flag6-Sem)
+   --    A flag present in the N_Assignment_Statement node. It is used only
+   --    if the type being assigned is an array type, and is set if analysis
+   --    determines that it is definitely safe to do the copy backwards, i.e.
+   --    starting at the highest addressed element. Note that if neither of
+   --    the flags Forwards_OK or Backwards_OK is set, it means that the
+   --    front end could not determine that either direction is definitely
+   --    safe, and a runtime check is required.
+
+   --  Body_To_Inline (Node3-Sem)
+   --    present in subprogram declarations. Denotes analyzed but unexpanded
+   --    body of subprogram, to be used when inlining calls. Present when the
+   --    subprogram has an Inline pragma and inlining is enabled. If the
+   --    declaration is completed by a renaming_as_body, and the renamed en-
+   --    tity is a subprogram, the Body_To_Inline is the name of that entity,
+   --    which is used directly in later calls to the original subprogram.
+
+   --  Body_Required (Flag13-Sem)
+   --    A flag that appears in the N_Compilation_Unit node indicating that
+   --    the corresponding unit requires a body. For the package case, this
+   --    indicates that a completion is required. In Ada 95, if the flag
+   --    is not set for the package case, then a body may not be present.
+   --    In Ada 83, if the flag is not set for the package case, then a
+   --    body is optional. For a subprogram declaration, the flag is set
+   --    except in the case where a pragma Import or Interface applies,
+   --    in which case no body is permitted (in Ada 83 or Ada 95).
+
+   --  By_Ref (Flag5-Sem)
+   --    A flag present in the N_Return_Statement_Node. It is set when the
+   --    returned expression is already allocated on the secondary stack
+   --    and thus the result is passed by reference rather than copied
+   --    another time.
+
+   --  Compile_Time_Known_Aggregate (Flag18-Sem)
+   --    Present in N_Aggregate nodes. Set for aggregates which can be
+   --    fully evaluated at compile time without raising constraint error.
+   --    Such aggregates can be passed as is to Gigi without any expansion.
+   --    See Sem_Aggr for the specific conditions under which an aggregate
+   --    has this flag set. See also the flag Static_Processing_OK.
+
+   --  Condition_Actions (List3-Sem)
+   --    This field appears in else-if nodes and in the iteration scheme
+   --    node for while loops. This field is only used during semantic
+   --    processing to temporarily hold actions inserted into the tree.
+   --    In the tree passed to gigi, the condition actions field is always
+   --    set to No_List. For details on how this field is used, see the
+   --    routine Insert_Actions in package Exp_Util, and also the expansion
+   --    routines for the relevant nodes.
+
+   --  Controlling_Argument (Node1-Sem)
+   --    This field is set in procedure and function call nodes if the call
+   --    is a dispatching call (it is Empty for a non-dispatching call).
+   --    It indicates the source of the controlling tag for the call. For
+   --    Procedure calls, the Controlling_Argument is one of the actuals.
+   --    For a function that has a dispatching result, it is an entity in
+   --    the context of the call that can provide a tag, or else it is the
+   --    tag of the root type of the class.
+
+   --  Conversion_OK (Flag14-Sem)
+   --    A flag set on type conversion nodes to indicate that the conversion
+   --    is to be considered as being valid, even though it is the case that
+   --    the conversion is not valid Ada. This is used for the Enum_Rep,
+   --    Fixed_Value and Integer_Value attributes, for internal conversions
+   --    done for fixed-point operations, and for certain conversions for
+   --    calls to initialization procedures. If Conversion_OK is set, then
+   --    Etype must be set (the analyzer assumes that Etype has been set).
+   --    For the case of fixed-point operands, it also indicates that the
+   --    conversion is to be a direct conversion of the underlying integer
+   --    result, with no regard to the small operand.
+
+   --  Corresponding_Body (Node5-Sem)
+   --    This field is set in subprogram declarations, where it is needed
+   --    if a pragma Inline is present and the subprogram is called, in
+   --    generic declarations if the generic is instantiated, and also in
+   --    package declarations that contain inlined subprograms that are
+   --    called, or generic declarations that are instantiated. It points
+   --    to the defining entity for the corresponding body.
+
+   --  Corresponding_Generic_Association (Node5-Sem)
+   --    This field is defined for object declarations and object renaming
+   --    declarations. It is set for the declarations within an instance that
+   --    map generic formals to their actuals.  If set, the field points to
+   --    a generic_association which is the original parent of the expression
+   --    or name appearing in the declaration. This simplifies ASIS queries.
+
+   --  Corresponding_Integer_Value (Uint4-Sem)
+   --    This field is set in real literals of fixed-point types (it is not
+   --    used for floating-point types). It contains the integer value used
+   --    to represent the fixed-point value. It is also set on the universal
+   --    real literals used to represent bounds of fixed-point base types
+   --    and their first named subtypes.
+
+   --  Corresponding_Spec (Node5-Sem)
+   --    This field is set in subprogram, package, task, and protected body
+   --    nodes, where it points to the defining entity in the corresponding
+   --    spec. The attribute is also set in N_With_Clause nodes, where
+   --    it points to the defining entity for the with'ed spec, and in
+   --    a subprogram renaming declaration when it is a Renaming_As_Body.
+   --    The field is Empty if there is no corresponding spec, as in the
+   --    case of a subprogram body that serves as its own spec.
+
+   --  Corresponding_Stub (Node3-Sem)
+   --    This field is present in an N_Subunit node. It holds the node in
+   --    the parent unit that is the stub declaration for the subunit. it is
+   --    set when analysis of the stub forces loading of the proper body. If
+   --    expansion of the proper body creates new declarative nodes, they are
+   --    inserted at the point of the corresponding_stub.
+
+   --  Dcheck_Function (Node5-Sem)
+   --    This field is present in an N_Variant node, It references the entity
+   --    for the discriminant checking function for the variant.
+
+   --  Debug_Statement (Node3)
+   --    This field is present in an N_Pragma node. It is used only for
+   --    a Debug pragma or pragma Assert with a second parameter. The
+   --    parameter is of the form of an expression, as required by the
+   --    pragma syntax, but is actually a procedure call. To simplify
+   --    semantic processing, the parser creates a copy of the argument
+   --    rearranged into a procedure call statement and places it in the
+   --    Debug_Statement field. Note that this field is considered a
+   --    syntactic field, since it is created by the parser.
+
+   --  Default_Expression (Node5-Sem)
+   --    This field is Empty if there is no default expression. If there
+   --    is a simple default expression (one with no side effects), then
+   --    this field simply contains a copy of the Expression field (both
+   --    point to the tree for the default expression). Default_Expression
+   --    is used for conformance checking.
+
+   --  Delay_Finalize_Attach (Flag14-Sem)
+   --    This flag is present in an N_Object_Declaration node. If it is set,
+   --    then in the case of a controlled type being declared and initialized,
+   --    the normal code for attaching the result to the appropriate local
+   --    finalization list is suppressed. This is used for functions that
+   --    return controlled types without using the secondary stack, where
+   --    it is the caller who must do the attachment.
+
+   --  Discr_Check_Funcs_Built (Flag11-Sem)
+   --    This flag is present in N_Full_Type_Declaration nodes. It is set when
+   --    discriminant checking functions are constructed. The purpose is to
+   --    avoid attempting to set these functions more than once.
+
+   --  Do_Access_Check (Flag11-Sem)
+   --    This flag is set on nodes with a Prefix field that can be an object
+   --    of an access type. If the flag is set, it indicates that a check is
+   --    required to ensure that the value of the referenced object is not
+   --    null. The actual check (which may be explicit or implicit by means
+   --    of some trap), is generated by Gigi (all the front end does is to
+   --    set this flag to request the trap).
+
+   --  Do_Accessibility_Check (Flag13-Sem)
+   --    This flag is set on N_Parameter_Specification nodes to indicate
+   --    that an accessibility check is required for the parameter. It is
+   --    not yet decided who takes care of this check (TBD ???).
+
+   --  Do_Discriminant_Check (Flag13-Sem)
+   --    This flag is set on N_Selected_Component nodes to indicate that a
+   --    discriminant check is required using the discriminant check routine
+   --    associated with the selector. The actual check is dealt with by
+   --    Gigi (all the front end does is to set the flag).
+
+   --  Do_Division_Check (Flag13-Sem)
+   --    This flag is set on a division operator (/ mod rem) to indicate
+   --    that a zero divide check is required. The actual check is dealt
+   --    with by the backend (all the front end does is to set the flag).
+
+   --  Do_Length_Check (Flag4-Sem)
+   --    This flag is set in an N_Assignment_Statement, N_Op_And, N_Op_Or,
+   --    N_Op_Xor, or N_Type_Conversion node to indicate that a length check
+   --    is required. It is not determined who deals with this flag (???).
+
+   --  Do_Overflow_Check (Flag17-Sem)
+   --    This flag is set on an operator where an overflow check is required
+   --    on the operation. The actual check is dealt with by the backend
+   --    (all the front end does is to set the flag). The other cases where
+   --    this flag is used is on a Type_Conversion node and for attribute
+   --    reference nodes. For a type conversion, it means that the conversion
+   --    is from one base type to another, and the value may not fit in the
+   --    target base type. See also the description of Do_Range_Check for
+   --    this case. The only attribute references which use this flag are
+   --    Pred and Succ, where it means that the result should be checked
+   --    for going outside the base range.
+
+   --  Do_Range_Check (Flag9-Sem)
+   --    This flag is set on an expression which appears in a context where
+   --    a range check is required. The target type is clear from the
+   --    context. The contexts in which this flag can appear are limited to
+   --    the following.
+
+   --      Right side of an assignment. In this case the target type is
+   --      taken from the left side of the assignment, which is referenced
+   --      by the Name of the N_Assignment_Statement node.
+
+   --      Subscript expressions in an indexed component. In this case the
+   --      target type is determined from the type of the array, which is
+   --      referenced by the Prefix of the N_Indexed_Component node.
+
+   --      Argument expression for a parameter, appearing either directly
+   --      in the Parameter_Associations list of a call or as the Expression
+   --      of an N_Parameter_Association node that appears in this list. In
+   --      either case, the check is against the type of the formal. Note
+   --      that the flag is relevant only in IN and IN OUT parameters, and
+   --      will be ignored for OUT parameters, where no check is required
+   --      in the call, and if a check is required on the return, it is
+   --      generated explicitly with a type conversion.
+
+   --      Initialization expression for the initial value in an object
+   --      declaration. In this case the Do_Range_Check flag is set on
+   --      the initialization expression, and the check is against the
+   --      range of the type of the object being declared.
+
+   --      The expression of a type conversion. In this case the range check
+   --      is against the target type of the conversion. See also the use of
+   --      Do_Overflow_Check on a type conversion. The distinction is that
+   --      the ovrflow check protects against a value that is outside the
+   --      range of the target base type, whereas a range check checks that
+   --      the resulting value (which is a value of the base type of the
+   --      target type), satisfies the range constraint of the target type.
+
+   --    Note: when a range check is required in contexts other than those
+   --    listed above (e.g. in a return statement), an additional type
+   --    conversion node is introduced to represent the required check.
+
+   --  Do_Storage_Check (Flag17-Sem)
+   --    This flag is set in an N_Allocator node to indicate that a storage
+   --    check is required for the allocation, or in an N_Subprogram_Body
+   --    node to indicate that a stack check is required in the subprogram
+   --    prolog. The N_Allocator case is handled by the routine that expands
+   --    the call to the runtime routine. The N_Subprogram_Body case is
+   --    handled by the backend, and all the semantics does is set the flag.
+
+   --  Do_Tag_Check (Flag13-Sem)
+   --    This flag is set on an N_Assignment_Statement, N_Function_Call,
+   --    N_Procedure_Call_Statement, N_Type_Conversion or N_Return_Statememt
+   --    node to indicate that the tag check can be suppressed. It is not
+   --    yet decided how this flag is used (TBD ???).
+
+   --  Elaborate_Present (Flag4-Sem)
+   --    This flag is set in the N_With_Clause node to indicate that a
+   --    pragma Elaborate pragma appears for the with'ed units.
+
+   --  Elaborate_All_Present (Flag15-Sem)
+   --    This flag is set in the N_With_Clause node to indicate that a
+   --    pragma Elaborate_All pragma appears for the with'ed units.
+
+   --  Elaboration_Boolean (Node2-Sem)
+   --    This field is present in function and procedure specification
+   --    nodes. If set, it points to the entity for a Boolean flag that
+   --    must be tested for certain calls to check for access before
+   --    elaboration. See body of Sem_Elab for further details. This
+   --    field is Empty if no elaboration boolean is required.
+
+   --  Else_Actions (List3-Sem)
+   --    This field is present in conditional expression nodes. During code
+   --    expansion we use the Insert_Actions procedure (in Exp_Util) to insert
+   --    actions at an appropriate place in the tree to get elaborated at the
+   --    right time. For conditional expressions, we have to be sure that the
+   --    actions for the Else branch are only elaborated if the condition is
+   --    False. The Else_Actions field is used as a temporary parking place
+   --    for these actions. The final tree is always rewritten to eliminate
+   --    the need for this field, so in the tree passed to Gigi, this field
+   --    is always set to No_List.
+
+   --  Enclosing_Variant (Node2-Sem)
+   --    This field is present in the N_Variant node and identifies the
+   --    Node_Id corresponding to the immediately enclosing variant when
+   --    the variant is nested, and N_Empty otherwise. Set during semantic
+   --    processing of the variant part of a record type.
+
+   --  Entity (Node4-Sem)
+   --    Appears in all direct names (identifier, character literal,
+   --    operator symbol), as well as expanded names, and attributes that
+   --    denote entities, such as 'Class. Points to the entity for the
+   --    corresponding defining occurrence. Set after name resolution.
+   --    In the case of identifiers in a WITH list, the corresponding
+   --    defining occurrence is in a separately compiled file, and this
+   --    pointer must be set using the library Load procedure. Note that
+   --    during name resolution, the value in Entity may be temporarily
+   --    incorrect (e.g. during overload resolution, Entity is
+   --    initially set to the first possible correct interpretation, and
+   --    then later modified if necessary to contain the correct value
+   --    after resolution).
+
+   --  Etype (Node5-Sem)
+   --    Appears in all expression nodes, all direct names, and all
+   --    entities. Points to the entity for the related type. Set after
+   --    type resolution. Normally this is the actual subtype of the
+   --    expression. However, in certain contexts such as the right side
+   --    of an assignment, subscripts, arguments to calls, returned value
+   --    in a function, initial value etc. it is the desired target type.
+   --    In the event that this is different from the actual type, the
+   --    Do_Range_Check flag will be set if a range check is required.
+   --    Note: if the Is_Overloaded flag is set, then Etype points to
+   --    an essentially arbitrary choice from the possible set of types.
+
+   --  Exception_Junk (Flag11-Sem)
+   --    This flag is set in a various nodes appearing in a statement
+   --    sequence to indicate that the corresponding node is an artifact
+   --    of the generated code for exception handling, and should be
+   --    ignored when analyzing the control flow of the relevant sequence
+   --    of statements (e.g. to check that it does not end with a bad
+   --    return statement).
+
+   --  Expansion_Delayed (Flag11-Sem)
+   --    Set on aggregates and extension aggregates that need a top-down
+   --    rather than bottom up expansion. Typically aggregate expansion
+   --    happens bottom up. For nested aggregates the expansion is delayed
+   --    until the enclosing aggregate itself is expanded, e.g. in the context
+   --    of a declaration. To delay it we set this flag. This is done to
+   --    avoid creating a temporary for each level of a nested aggregates,
+   --    and also to prevent the premature generation of constraint checks.
+   --    This is also a requirement if we want to generate the proper
+   --    attachment to the internal finalization lists (for record with
+   --    controlled components). Top down expansion of aggregates is also
+   --    used for in-place array aggregate assignment or initialization.
+   --    When the full context is known, the target of the assignment or
+   --    initialization is used to generate the left-hand side of individual
+   --    assignment to each sub-component.
+
+   --  First_Inlined_Subprogram (Node3-Sem)
+   --    Present in the N_Compilation_Unit node for the main program. Points
+   --    to a chain of entities for subprograms that are to be inlined. The
+   --    Next_Inlined_Subprogram field of these entities is used as a link
+   --    pointer with Empty marking the end of the list. This field is Empty
+   --    if there are no inlined subprograms or inlining is not active.
+
+   --  First_Named_Actual (Node4-Sem)
+   --    Present in procedure call statement and function call nodes, and
+   --    also in Intrinsic nodes. Set during semantic analysis to point to
+   --    the first named parameter where parameters are ordered by declaration
+   --    order (as opposed to the actual order in the call which may be
+   --    different due to named associations). Note: this field points to the
+   --    explicit actual parameter itself, not the N_Parameter_Association
+   --    node (its parent).
+
+   --  First_Real_Statement (Node2-Sem)
+   --    Present in N_Handled_Sequence_Of_Statements node. Normally set to
+   --    Empty. Used only when declarations are moved into the statement
+   --    part of a construct as a result of wrapping an AT END handler that
+   --    is required to cover the declarations. In this case, this field is
+   --    used to remember the location in the statements list of the first
+   --    real statement, i.e. the statement that used to be first in the
+   --    statement list before the declarations were prepended.
+
+   --  First_Subtype_Link (Node5-Sem)
+   --    Present in N_Freeze_Entity node for an anonymous base type that
+   --    is implicitly created by the declaration of a first subtype. It
+   --    points to the entity for the first subtype.
+
+   --  Float_Truncate (Flag11-Sem)
+   --    A flag present in type conversion nodes. This is used for float
+   --    to integer conversions where truncation is required rather than
+   --    rounding. Note that Gigi does not handle type conversions from real
+   --    to integer with rounding (see Expand_N_Type_Conversion).
+
+   --  Forwards_OK (Flag5-Sem)
+   --    A flag present in the N_Assignment_Statement node. It is used only
+   --    if the type being assigned is an array type, and is set if analysis
+   --    determines that it is definitely safe to do the copy forwards, i.e.
+   --    starting at the lowest addressed element. Note that if neither of
+   --    the flags Forwards_OK or Backwards_OK is set, it means that the
+   --    front end could not determine that either direction is definitely
+   --    safe, and a runtime check is required.
+
+   --  From_At_Mod (Flag4-Sem)
+   --    This flag is set on the attribute definition clause node that is
+   --    generated by a transformation of an at mod phrase in a record
+   --    representation clause. This is used to give slightly different
+   --    (Ada 83 compatible) semantics to such a clause, namely it is
+   --    used to specify a minimum acceptable alignment for the base type
+   --    and all subtypes. In Ada 95 terms, the actual alignment of the
+   --    base type and all subtypes must be a multiple of the given value,
+   --    and the representation clause is considered to be type specific
+   --    instead of subtype specific.
+
+   --  Generic_Parent (Node5-Sem)
+   --    Generic_parent is defined on declaration nodes that are instances.
+   --    The value of Generic_Parent is the generic entity from which the
+   --    instance is obtained. Generic_Parent is also defined for the renaming
+   --    declarations and object declarations created for the actuals in an
+   --    instantiation. The generic parent of such a declaration is the
+   --    corresponding generic association in the Instantiation node.
+
+   --  Generic_Parent_Type (Node4-Sem)
+   --    Generic_Parent_Type is defined on Subtype_Declaration nodes for
+   --    the actuals of formal private and derived types. Within the instance,
+   --    the operations on the actual are those inherited from the parent.
+   --    For a formal private type, the parent type is the generic type
+   --    itself. The Generic_Parent_Type is also used in an instance to
+   --    determine whether a private operation overrides an inherited one.
+
+   --  Handler_List_Entry (Node2-Sem)
+   --    This field is present in N_Object_Declaration nodes. It is set only
+   --    for the Handler_Record entry generated for an exception in zero cost
+   --    exception handling mode. It references the corresponding item in the
+   --    handler list, and is used to delete this entry if the corresponding
+   --    handler is deleted during optimization. For further details on why
+   --    this is required, see Exp_Ch11.Remove_Handler_Entries.
+
+   --  Has_Dynamic_Length_Check (Flag10-Sem)
+   --    This flag is present on all nodes. It is set to indicate that one
+   --    of the routines in unit Checks has generated a length check action
+   --    which has been inserted at the flagged node. This is used to avoid
+   --    the generation of duplicate checks.
+
+   --  Has_Dynamic_Range_Check (Flag12-Sem)
+   --    This flag is present on all nodes. It is set to indicate that one
+   --    of the routines in unit Checks has generated a range check action
+   --    which has been inserted at the flagged node. This is used to avoid
+   --    the generation of duplicate checks.
+
+   --  Has_No_Elaboration_Code (Flag17-Sem)
+   --    A flag that appears in the N_Compilation_Unit node to indicate
+   --    whether or not elaboration code is present for this unit. It is
+   --    initially set true for subprogram specs and bodies and for all
+   --    generic units and false for non-generic package specs and bodies.
+   --    Gigi may set the flag in the non-generic package case if it
+   --    determines that no elaboration code is generated. Note that this
+   --    flag is not related to the Is_Preelaborated status, there can be
+   --    preelaborated packages that generate elaboration code, and non-
+   --    preelaborated packages which do not generate elaboration code.
+
+   --  Has_Priority_Pragma (Flag6-Sem)
+   --    A flag present in N_Subprogram_Body, N_Task_Definition and
+   --    N_Protected_Definition nodes to flag the presence of either
+   --    a Priority or Interrupt_Priority pragma in the declaration
+   --    sequence (public or private in the task and protected cases)
+
+   --  Has_Private_View (Flag11-Sem)
+   --    A flag present in generic nodes that have an entity, to indicate
+   --    that the node has a private type. Used to exchange private
+   --    and full declarations if the visibility at instantiation is
+   --    different from the visibility at generic definition.
+
+   --  Has_Storage_Size_Pragma (Flag5-Sem)
+   --    A flag present in an N_Task_Definition node to flag the presence
+   --    of a Storage_Size pragma
+
+   --  Has_Task_Info_Pragma (Flag7-Sem)
+   --    A flag present in an N_Task_Definition node to flag the presence
+   --    of a Task_Info pragma. Used to detect duplicate pragmas.
+
+   --  Has_Task_Name_Pragma (Flag8-Sem)
+   --    A flag present in N_Task_Definition nodes to flag the presence
+   --    of a Task_Name pragma in the declaration sequence for the task.
+
+   --  Has_Wide_Character (Flag11-Sem)
+   --    Present in string literals, set if any wide character (i.e. a
+   --    character code outside the Character range) appears in the string.
+
+   --  Hidden_By_Use_Clause (Elist4-Sem)
+   --     An entity list present in use clauses that appear within
+   --     instantiations. For the resolution of local entities, entities
+   --     introduced by these use clauses have priority over global ones,
+   --     and outer entities must be explicitly hidden/restored on exit.
+
+   --  Implicit_With (Flag17-Sem)
+   --    This flag is set in the N_With_Clause node that is implicitly
+   --    generated for runtime units that are loaded by the expander, and
+   --    also for package System, if it is loaded implicitly by a use of
+   --    the 'Address or 'Tag attribute
+
+   --  Includes_Infinities (Flag11-Sem)
+   --    This flag is present in N_Range nodes. It is set for the range
+   --    of unconstrained float types defined in Standard, which include
+   --    not only the given range of values, but also legtitimately can
+   --    include infinite values. This flag is false for any float type
+   --    for which an explicit range is given by the programmer, even if
+   --    that range is identical to the range for float.
+
+   --  Instance_Spec (Node5-Sem)
+   --    This field is present in generic instantiation nodes, and also in
+   --    formal package declaration nodes (formal package declarations are
+   --    treated in a manner very similar to package instantiations). It
+   --    points to the node for the spec of the instance, inserted as part
+   --    of the semantic processing for instantiations in Sem_Ch12.
+
+   --  Is_Asynchronous_Call_Block (Flag7-Sem)
+   --    A flag set in a Block_Statement node to indicate that it is the
+   --    expansion of an asynchronous entry call. Such a block needs a
+   --    cleanup handler to assure that the call is cancelled.
+
+   --  Is_Component_Left_Opnd  (Flag13-Sem)
+   --  Is_Component_Right_Opnd (Flag14-Sem)
+   --    Present in concatenation nodes, to indicate that the corresponding
+   --    operand is of the component type of the result. Used in resolving
+   --    concatenation nodes in instances.
+
+   --  Is_Controlling_Actual (Flag16-Sem)
+   --    This flag is set on in an expression that is a controlling argument
+   --    in a dispatching call. It is off in all other cases. See Sem_Disp
+   --    for details of its use.
+
+   --  Is_Machine_Number (Flag11-Sem)
+   --    This flag is set in an N_Real_Literal node to indicate that the
+   --    value is a machine number. This avoids some unnecessary cases
+   --    of converting real literals to machine numbers.
+
+   --  Is_Power_Of_2_For_Shift (Flag13-Sem)
+   --    A flag present only in N_Op_Expon nodes. It is set when the
+   --    exponentiation is of the forma 2 ** N, where the type of N is
+   --    an unsigned integral subtype whose size does not exceed the size
+   --    of Standard_Integer (i.e. a type that can be safely converted to
+   --    Natural), and the exponentiation appears as the right operand of
+   --    an integer multiplication or an integer division where the dividend
+   --    is unsigned. It is also required that overflow checking is off for
+   --    both the exponentiation and the multiply/divide node. If this set
+   --    of conditions holds, and the flag is set, then the division or
+   --    multiplication can be (and is) converted to a shift.
+
+   --  Is_Overloaded (Flag5-Sem)
+   --    A flag present in all expression nodes. Used temporarily during
+   --    overloading determination. The setting of this flag is not
+   --    relevant once overloading analysis is complete.
+
+   --  Is_Protected_Subprogram_Body (Flag7-Sem)
+   --    A flag set in a Subprogram_Body block to indicate that it is the
+   --    implemenation of a protected subprogram. Such a body needs a
+   --    cleanup handler to make sure that the associated protected object
+   --    is unlocked when the subprogram completes.
+
+   --  Is_Static_Expression (Flag6-Sem)
+   --    Indicates that an expression is a static expression (RM 4.9). See
+   --    spec of package Sem_Eval for full details on the use of this flag.
+
+   --  Is_Subprogram_Descriptor (Flag16-Sem)
+   --    Present in N_Object_Declaration, and set only for the object
+   --    declaration generated for a subprogram descriptor in fast exception
+   --    mode. See Exp_Ch11 for details of use.
+
+   --  Is_Task_Allocation_Block (Flag6-Sem)
+   --    A flag set in a Block_Statement node to indicate that it is the
+   --    expansion of a task allocator, or the allocator of an object
+   --    containing tasks. Such a block requires a cleanup handler to call
+   --    Expunge_Unactivted_Tasks to complete any tasks that have been
+   --    allocated but not activated when the allocator completes abnormally.
+
+   --  Is_Task_Master (Flag5-Sem)
+   --    A flag set in a Subprogram_Body, Block_Statement or Task_Body node
+   --    to indicate that the construct is a task master (i.e. has declared
+   --    tasks or declares an access to a task type).
+
+   --  Itype (Node1-Sem)
+   --    Used in N_Itype_Reference node to reference an itype for which it
+   --    is important to ensure that it is defined. See description of this
+   --    node for further details.
+
+   --  Kill_Range_Check (Flag11-Sem)
+   --    Used in an N_Unchecked_Type_Conversion node to indicate that the
+   --    result should not be subjected to range checks. This is used for
+   --    the implementation of Normalize_Scalars.
+
+   --  Label_Construct (Node2-Sem)
+   --    Used in an N_Implicit_Label_Declaration node. Refers to an N_Label,
+   --    N_Block_Statement or N_Loop_Statement node to which the label
+   --    declaration applies. This is not currently used in the compiler
+   --    itself, but it is useful in the implementation of ASIS queries.
+
+   --  Library_Unit (Node4-Sem)
+   --    In a stub node, the Library_Unit field points to the compilation unit
+   --    node of the corresponding subunit.
+   --
+   --    In a with clause node, the Library_Unit field points to the spec
+   --    of the with'ed unit.
+   --
+   --    In a compilation unit node, the use of this field depends on
+   --    the unit type:
+   --
+   --     For a subprogram body, the Library_Unit field points to the
+   --     compilation unit node of the corresponding spec, unless
+   --     Acts_As_Spec is set, in which case it points to itself.
+   --
+   --     For a package body, the Library_Unit field points to the
+   --     compilation unit node of the corresponding spec.
+   --
+   --     For a subprogram spec to which pragma Inline applies, the
+   --     Library_Unit field points to the compilation unit node of
+   --     the corresponding body, if inlining is active.
+   --
+   --     For a generic declaration, the Library_Unit field points
+   --     to the compilation unit node of the corresponding generic body.
+   --
+   --     For a subunit, the Library_Unit field points to the compilation
+   --     unit node of the parent body.
+   --
+   --    Note that this field is not used to hold the parent pointer for a
+   --    child unit (which might in any case need to use it for some other
+   --    purpose as described above). Instead for a child unit, implicit
+   --    with's are generated for all parents.
+
+   --  Loop_Actions (List2-Sem)
+   --    A list present in Component_Association nodes in array aggregates.
+   --    Used to collect actions that must be executed within the loop because
+   --    they may need to be evaluated anew each time through.
+
+   --  Must_Not_Freeze (Flag8-Sem)
+   --    A flag present in all expression nodes. Normally expressions cause
+   --    freezing as described in the RM. If this flag is set, then this
+   --    is inhibited. This is used by the analyzer and expander to label
+   --    nodes that are created by semantic analysis or expansion and which
+   --    must not cause freezing even though they normally would. This flag
+   --    is also present in an N_Subtype_Indication node, since we also use
+   --    these in calls to Freeze_Expression.
+
+   --  Next_Entity (Node2-Sem)
+   --    Present in defining identifiers, defining character literals and
+   --    defining operator symbols (i.e. in all entities). The entities of
+   --    a scope are chained, and this field is used as the forward pointer
+   --    for this list. See Einfo for further details.
+
+   --  Next_Named_Actual (Node4-Sem)
+   --    Present in parameter association node. Set during semantic
+   --    analysis to point to the next named parameter, where parameters
+   --    are ordered by declaration order (as opposed to the actual order
+   --    in the call, which may be different due to named associations).
+   --    Not that this field points to the explicit actual parameter itself,
+   --    not to the N_Parameter_Association node (its parent).
+
+   --  Next_Rep_Item (Node4-Sem)
+   --    Present in pragma nodes and attribute definition nodes. Used to
+   --    link representation items that apply to an entity. See description
+   --    of First_Rep_Item field in Einfo for full details.
+
+   --  Next_Use_Clause (Node3-Sem)
+   --    While use clauses are active during semantic processing, they
+   --    are chained from the scope stack entry, using Next_Use_Clause
+   --    as a link pointer, with Empty marking the end of the list. The
+   --    head pointer is in the scope stack entry (First_Use_Clause). At
+   --    the end of semantic processing (i.e. when Gigi sees the tree,
+   --    the contents of this field is undefined and should not be read).
+
+   --  No_Ctrl_Actions (Flag7-Sem)
+   --    Present in N_Assignment_Statement to indicate that no finalize nor
+   --    nor adjust should take place on this assignment eventhough the rhs
+   --    is controlled. This is used in init_procs and aggregate expansions
+   --    where the generated assignments are more initialisations than real
+   --    assignments.
+
+   --  No_Entities_Ref_In_Spec (Flag8-Sem)
+   --    Present in N_With_Clause nodes. Set if the with clause is on the
+   --    package or subprogram spec where the main unit is the corresponding
+   --    body, and no entities of the with'ed unit are referenced by the spec
+   --    (an entity may still be referenced in the body, so this flag is used
+   --    to generate the proper message (see Sem_Util.Check_Unused_Withs for
+   --    full details)
+
+   --  No_Initialization (Flag13-Sem)
+   --    Present in N_Object_Declaration & N_Allocator to indicate
+   --    that the object must not be initialized (by Initialize or a
+   --    call to _init_proc). This is needed for controlled aggregates.
+   --    When the Object declaration has an expression, this flag means
+   --    that this expression should not be taken into account (needed
+   --    for in place initialization with aggregates)
+
+   --  OK_For_Stream (Flag4-Sem)
+   --    Present in N_Attribute_Definition clauses for stream attributes. If
+   --    set, indicates that the attribute is permitted even though the type
+   --    involved is a limited type. In the case of a protected type, the
+   --    result is to stream all components (including discriminants) in
+   --    lexical order. For other limited types, the effect is simply to
+   --    use the corresponding stream routine for the full type. This flag
+   --    is used for internally generated code, where the streaming of these
+   --    types is required, even though not normally allowed by the language.
+
+   --  Original_Discriminant (Node2-Sem)
+   --    Present in identifiers. Used in references to discriminants that
+   --    appear in generic units. Because the names of the discriminants
+   --    may be different in  an instance, we use this field to recover the
+   --    position of the discriminant in the original type, and replace it
+   --    with the discriminant at the same position in the instantiated type.
+
+   --  Others_Discrete_Choices (List1-Sem)
+   --    When a case statement or variant is analyzed, the semantic checks
+   --    determine the actual list of choices that correspond to an others
+   --    choice. This list is materialized for later use by the expander
+   --    and the Others_Discrete_Choices field of an N_Others_Choice node
+   --    points to this materialized list of choices, which is in standard
+   --    format for a list of discrete choices, except that of course it
+   --    cannot contain an N_Others_Choice entry.
+
+   --  Parameter_List_Truncated (Flag17-Sem)
+   --    Present in N_Function_Call and N_Procedure_Call_Statement nodes.
+   --    Set (for OpenVMS ports of GNAT only) if the parameter list is
+   --    truncated as a result of a First_Optional_Parameter specification
+   --    in an Import_Function, Import_Procedure, or Import_Valued_Procedure
+   --    pragma. The truncation is done by the expander by removing trailing
+   --    parameters from the argument list, in accordance with the set of
+   --    rules allowing such parameter removal. In particular, parameters
+   --    can be removed working from the end of the parameter list backwards
+   --    up to and including the entry designated by First_Optional_Parameter
+   --    in the Import pragma. Parameters can be removed if they are implicit
+   --    and the default value is a known-at-compile-time value, including
+   --    the use of the Null_Parameter attribute, or if explicit parameter
+   --    values are present that match the corresponding defaults.
+
+   --  Parent_Spec (Node4-Sem)
+   --    For a library unit that is a child unit spec (package or subprogram
+   --    declaration, generic declaration or instantiation, or library level
+   --    rename, this field points to the compilation unit node for the parent
+   --    package specification. This field is Empty for library bodies (the
+   --    parent spec in this case can be found from the corresponding spec).
+
+   --  Present_Expr (Uint3-Sem)
+   --    Present in an N_Variant node. This has a meaningful value only after
+   --    Gigi has back annotated the tree with representation information.
+   --    At this point, it contains a reference to a gcc expression that
+   --    depends on the values of one or more discriminants. Give a set of
+   --    discriminant values, this expression evaluates to False (zero) if
+   --    variant is not present, and True (non-zero) if it is present. See
+   --    unit Repinfo for further details on gigi back annotation. This
+   --    field is used during ASIS processing (data decomposition annex)
+   --    to determine if a field is present or not.
+
+   --  Print_In_Hex (Flag13-Sem)
+   --    Set on an N_Integer_Literal node to indicate that the value should
+   --    be printed in hexadecimal in the sprint listing. Has no effect on
+   --    legality or semantics of program, only on the displayed output.
+   --    This is used to clarify output from the packed array cases.
+
+   --  Procedure_To_Call (Node4-Sem)
+   --    Present in N_Allocator. N_Free_Statement, and N_Return_Statement
+   --    nodes. References the entity for the declaration of the procedure
+   --    to be called to accomplish the required operation (i.e. for the
+   --    Allocate procedure in the case of N_Allocator and N_Return_Statement
+   --    (for allocating the return value), and for the Deallocate procedure
+   --    in the case of N_Free_Statement.
+
+   --  Raises_Constraint_Error (Flag7-Sem)
+   --    Set on an expression whose evaluation will definitely fail a
+   --    constraint error check. In the case of static expressions, this
+   --    flag must be set accurately (and if it is set, the expression is
+   --    typically illegal unless it appears as a non-elaborated branch of
+   --    a short-circuit form). For a non-static expression, this flag may
+   --    be set whenever an expression (e.g. an aggregate) is known to raise
+   --    constraint error. If set, the expression definitely will raise CE
+   --    if elaborated at runtime. If not set, the expression may or may
+   --    not raise CE. In other words, on static expressions, the flag is
+   --    set accurately, on non-static expressions it is set conservatively.
+
+   --  Redundant_Use (Flag13-Sem)
+   --    A flag present in nodes that can appear as an operand in a use
+   --    clause or use type clause (identifiers, expanded names, attribute
+   --    references). Set to indicate that a use is redundant (and therefore
+   --    need not be undone on scope exit).
+
+   --  Return_Type (Node2-Sem)
+   --    Present in N_Return_Statement node. For a procedure, this is set
+   --    to Standard_Void_Type. For a function it references the entity
+   --    for the returned type.
+
+   --  Rounded_Result (Flag18-Sem)
+   --    Present in N_Type_Conversion, N_Op_Divide and N_Op_Multiply nodes.
+   --    Used in the fixed-point cases to indicate that the result must be
+   --    rounded as a result of the use of the 'Round attribute. Also used
+   --    for integer N_Op_Divide nodes to indicate that the result should
+   --    be rounded to the nearest integer (breaking ties away from zero),
+   --    rather than truncated towards zero as usual. These rounded integer
+   --    operations are the result of expansion of rounded fixed-point
+   --    divide, conersion and multiplication operations.
+
+   --  Scope (Node3-Sem)
+   --    Present in defining identifiers, defining character literals and
+   --    defining operator symbols (i.e. in all entities). The entities of
+   --    a scope all use this field to reference the corresponding scope
+   --    entity. See Einfo for further details.
+
+   --  Shift_Count_OK (Flag4-Sem)
+   --    A flag present in shift nodes to indicate that the shift count is
+   --    known to be in range, i.e. is in the range from zero to word length
+   --    minus one. If this flag is not set, then the shift count may be
+   --    outside this range, i.e. larger than the word length, and the code
+   --    must ensure that such shift counts give the appropriate result.
+
+   --  Source_Type (Node1-Sem)
+   --    Used in an N_Validate_Unchecked_Conversion node to point to the
+   --    source type entity for the unchecked conversion instantiation
+   --    which gigi must do size validation for.
+
+   --  Static_Processing_OK (Flag4-Sem)
+   --    Present in N_Aggregate nodes. When the Compile_Time_Known_Aggregate
+   --    flag is set, the full value of the aggregate can be determined at
+   --    compile time and the aggregate can be passed as is to the back-end.
+   --    In this event it is irrelevant whether this flag is set or not.
+   --    However, if the Compile_Time_Known_Aggregate flag is not set but
+   --    Static_Processing_OK is set, the aggregate can (but need not) be
+   --    converted into a compile time known aggregate by the expander.
+   --    See Sem_Aggr for the specific conditions under which an aggregate
+   --    has its Static_Processing_OK flag set.
+
+   --  Storage_Pool (Node1-Sem)
+   --    Present in N_Allocator, N_Free_Statement and N_Return_Statement
+   --    nodes. References the entity for the storage pool to be used for
+   --    the allocate or free call or for the allocation of the returned
+   --    value from a function. Empty indicates that the global default
+   --    default pool is to be used. Note that in the case of a return
+   --    statement, this field is set only if the function returns a
+   --    value of a type whose size is not known at compile time on the
+   --    secondary stack. It is never set on targets for which the target
+   --    parameter Targparm.Functions_Return_By_DSP_On_Target is True.
+
+   --  Target_Type (Node2-Sem)
+   --    Used in an N_Validate_Unchecked_Conversion node to point to the
+   --    target type entity for the unchecked conversion instantiation
+   --    which gigi must do size validation for.
+
+   --  Task_Body_Procedure (Node2-Sem)
+   --    Present in task type declaration nodes. Points to the entity for
+   --    the task body procedure (as further described in Exp_Ch9, task
+   --    bodies are expanded into procedures). A convenient function to
+   --    retrieve this field is Sem_Util.Get_Task_Body_Procedure.
+
+   --  Then_Actions (List3-Sem)
+   --    This field is present in conditional expression nodes. During code
+   --    expansion we use the Insert_Actions procedure (in Exp_Util) to insert
+   --    actions at an appropriate place in the tree to get elaborated at the
+   --    right time. For conditional expressions, we have to be sure that the
+   --    actions for the Then branch are only elaborated if the condition is
+   --    True. The Then_Actions field is used as a temporary parking place
+   --    for these actions. The final tree is always rewritten to eliminate
+   --    the need for this field, so in the tree passed to Gigi, this field
+   --    is always set to No_List.
+
+   --  Treat_Fixed_As_Integer (Flag14-Sem)
+   --    This flag appears in operator nodes for divide, multiply, mod and
+   --    rem on fixed-point operands. It indicates that the operands are
+   --    to be treated as integer values, ignoring small values. This flag
+   --    is only set as a result of expansion of fixed-point operations.
+   --    Typically a fixed-point multplication in the source generates
+   --    subsidiary multiplication and division operations that work with
+   --    the underlying integer values and have this flag set. Note that
+   --    this flag is not needed on other arithmetic operations (add, neg,
+   --    subtract etc) since in these cases it is always the case that fixed
+   --    is treated as integer. The Etype field MUST be set if this flag
+   --    is set. The analyzer knows to leave such nodes alone, and whoever
+   --    makes them must set the correct Etype value.
+
+   --  TSS_Elist (Elist3-Sem)
+   --    Present in N_Freeze_Entity nodes. Holds an element list containing
+   --    entries for each TSS (type support subprogram) associated with the
+   --    frozen type. The elements of the list are the entities for the
+   --    subprograms (see package Exp_TSS for further details). Set to
+   --    No_Elist if there are no type support subprograms for the type
+   --    or if the freeze node is not for a type.
+
+   --  Unreferenced_In_Spec (Flag7-Sem)
+   --    Present in N_With_Clause nodes. Set if the with clause is on the
+   --    package or subprogram spec where the main unit is the corresponding
+   --    body, and is not referenced by the spec (it may still be referenced
+   --    by the body, so this flag is used to generate the proper message
+   --    (see Sem_Util.Check_Unused_Withs for details)
+
+   --  Was_Originally_Stub (Flag13-Sem)
+   --    This flag is set in the node for a proper body that replaces a
+   --    stub. During the analysis procedure, stubs in some situations
+   --    get rewritten by the corresponding bodies, and we set this flag
+   --    to remember that this happened. Note that it is not good enough
+   --    to rely on the use of Original_Tree here because of the case of
+   --    nested instantiations where the substituted node can be copied.
+
+   --  Zero_Cost_Handling (Flag5-Sem)
+   --    This flag is set in all handled sequence of statement and exception
+   --    handler nodes if eceptions are to be handled using the zero-cost
+   --    mechanism (see Ada.Exceptions and System.Exceptions in files
+   --    a-except.ads/adb and s-except.ads for full details). What gigi
+   --    needs to do for such a handler is simply to put the code in the
+   --    handler somewhere. The front end has generated all necessary labels.
+
+   --------------------------------------------------
+   -- Note on Use of End_Label and End_Span Fields --
+   --------------------------------------------------
+
+   --  Several constructs have end lines:
+
+   --    Loop Statement             end loop [loop_IDENTIFIER];
+   --    Package Specification      end [[PARENT_UNIT_NAME .] IDENTIFIER]
+   --    Task Definition            end [task_IDENTIFIER]
+   --    Protected Definition       end [protected_IDENTIFIER]
+   --    Protected Body             end [protected_IDENTIFIER]
+
+   --    Block Statement            end [block_IDENTIFIER];
+   --    Subprogram Body            end [DESIGNATOR];
+   --    Package Body               end [[PARENT_UNIT_NAME .] IDENTIFIER];
+   --    Task Body                  end [task_IDENTIFIER];
+   --    Accept Statement           end [entry_IDENTIFIER]];
+   --    Entry Body                 end [entry_IDENTIFIER];
+
+   --    If Statement               end if;
+   --    Case Statement             end case;
+
+   --    Record Definition          end record;
+
+   --  The End_Label and End_Span fields are used to mark the locations
+   --  of these lines, and also keep track of the label in the case where
+   --  a label is present.
+
+   --  For the first group above, the End_Label field of the corresponding
+   --  node is used to point to the label identifier. In the case where
+   --  there is no label in the source, the parser supplies a dummy
+   --  identifier (with Comes_From_Source set to False), and the Sloc
+   --  of this dummy identifier marks the location of the token following
+   --  the END token.
+
+   --  For the second group, the use of End_Label is similar, but the
+   --  End_Label is found in the N_Handled_Sequence_Of_Statements node.
+   --  This is done simply because in some cases there is no room in
+   --  the parent node.
+
+   --  For the third group, there is never any label, and instead of
+   --  using End_Label, we use the End_Span field which gives the
+   --  location of the token following END, relative to the starting
+   --  Sloc of the construct, i.e. add Sloc (Node) + End_Span (Node)
+   --  to get the Sloc of the IF or CASE following the End_Label.
+
+   --  The record definition case is handled specially, we treat it
+   --  as though it required an optional label which is never present,
+   --  and so the parser always builds a dummy identifier with Comes
+   --  From Source set False. The reason we do this, rather than using
+   --  End_Span in this case, is that we want to generate a cross-ref
+   --  entry for the end of a record, since it represents a scope for
+   --  name declaration purposes.
+
+   --  Note: the reason we store the difference as a Uint, instead of
+   --  storing the Source_Ptr value directly, is that Source_Ptr values
+   --  cannot be distinguished from other types of values, and we count
+   --  on all general use fields being self describing. To make things
+   --  easier for clients, note that we provide function End_Location,
+   --  and procedure Set_End_Location to allow access to the logical
+   --  value (which is the Source_Ptr value for the end token).
+
+   ---------------------
+   -- Syntactic Nodes --
+   ---------------------
+
+      ---------------------
+      -- 2.3  Identifier --
+      ---------------------
+
+      --  IDENTIFIER ::= IDENTIFIER_LETTER {[UNDERLINE] LETTER_OR_DIGIT}
+      --  LETTER_OR_DIGIT ::= IDENTIFIER_LETTER | DIGIT
+
+      --  An IDENTIFIER shall not be a reserved word
+
+      --  In the Ada grammar identifiers are the bottom level tokens which
+      --  have very few semantics. Actual program identifiers are direct
+      --  names. If we were being 100% honest with the grammar, then we would
+      --  have a node called N_Direct_Name which would point to an identifier.
+      --  However, that's too many extra nodes, so we just use the N_Identifier
+      --  node directly as a direct name, and it contains the expression fields
+      --  and Entity field that correspond to its use as a direct name. In
+      --  those few cases where identifiers appear in contexts where they are
+      --  not direct names (pragmas, pragma argument associations, attribute
+      --  references and attribute definition clauses), the Chars field of the
+      --  node contains the Name_Id for the identifier name.
+
+      --  Note: in GNAT, a reserved word can be treated as an identifier
+      --  in two cases. First, an incorrect use of a reserved word as an
+      --  identifier is diagnosed and then treated as a normal identifier.
+      --  Second, an attribute designator of the form of a reserved word
+      --  (access, delta, digits, range) is treated as an identifier.
+
+      --  Note: The set of letters that is permitted in an identifier depends
+      --  on the character set in use. See package Csets for full details.
+
+      --  N_Identifier
+      --  Sloc points to identifier
+      --  Chars (Name1) contains the Name_Id for the identifier
+      --  Entity (Node4-Sem)
+      --  Original_Discriminant (Node2-Sem)
+      --  Redundant_Use (Flag13-Sem)
+      --  Has_Private_View (Flag11-Sem) (set in generic units)
+      --  plus fields for expression
+
+      --------------------------
+      -- 2.4  Numeric Literal --
+      --------------------------
+
+      --  NUMERIC_LITERAL ::= DECIMAL_LITERAL | BASED_LITERAL
+
+      ----------------------------
+      -- 2.4.1  Decimal Literal --
+      ----------------------------
+
+      --  DECIMAL_LITERAL ::= NUMERAL [.NUMERAL] [EXPONENT]
+
+      --  NUMERAL ::= DIGIT {[UNDERLINE] DIGIT}
+
+      --  EXPONENT ::= E [+] NUMERAL | E - NUMERAL
+
+      --  Decimal literals appear in the tree as either integer literal nodes
+      --  or real literal nodes, depending on whether a period is present.
+
+      --  Note: literal nodes appear as a result of direct use of literals
+      --  in the source program, and also as the result of evaluating
+      --  expressions at compile time. In the latter case, it is possible
+      --  to construct real literals that have no syntactic representation
+      --  using the standard literal format. Such literals are listed by
+      --  Sprint using the notation [numerator / denominator].
+
+      --  N_Integer_Literal
+      --  Sloc points to literal
+      --  Intval (Uint3) contains integer value of literal
+      --  plus fields for expression
+      --  Print_In_Hex (Flag13-Sem)
+
+      --  N_Real_Literal
+      --  Sloc points to literal
+      --  Realval (Ureal3) contains real value of literal
+      --  Corresponding_Integer_Value (Uint4-Sem)
+      --  Is_Machine_Number (Flag11-Sem)
+      --  plus fields for expression
+
+      --------------------------
+      -- 2.4.2  Based Literal --
+      --------------------------
+
+      --  BASED_LITERAL ::=
+      --   BASE # BASED_NUMERAL [.BASED_NUMERAL] # [EXPONENT]
+
+      --  BASE ::= NUMERAL
+
+      --  BASED_NUMERAL ::=
+      --    EXTENDED_DIGIT {[UNDERLINE] EXTENDED_DIGIT}
+
+      --  EXTENDED_DIGIT ::= DIGIT | A | B | C | D | E | F
+
+      --  Based literals appear in the tree as either integer literal nodes
+      --  or real literal nodes, depending on whether a period is present.
+
+      ----------------------------
+      -- 2.5  Character Literal --
+      ----------------------------
+
+      --  CHARACTER_LITERAL ::= ' GRAPHIC_CHARACTER '
+
+      --  N_Character_Literal
+      --  Sloc points to literal
+      --  Chars (Name1) contains the Name_Id for the identifier
+      --  Char_Literal_Value (Char_Code2) contains the literal value
+      --  Entity (Node4-Sem)
+      --  Has_Private_View (Flag11-Sem) set in generic units.
+      --  plus fields for expression
+
+      --  Note: the Entity field will be missing (and set to Empty) for
+      --  character literals whose type is Standard.Wide_Character or
+      --  Standard.Character or a type derived from one of these two.
+      --  In this case the character literal stands for its own coding.
+      --  The reason we take this irregular short cut is to avoid the
+      --  need to build lots of junk defining character literal nodes.
+
+      -------------------------
+      -- 2.6  String Literal --
+      -------------------------
+
+      --  STRING LITERAL ::= "{STRING_ELEMENT}"
+
+      --  A STRING_ELEMENT is either a pair of quotation marks ("), or a
+      --  single GRAPHIC_CHARACTER other than a quotation mark.
+
+      --  N_String_Literal
+      --  Sloc points to literal
+      --  Strval (Str3) contains Id of string value
+      --  Has_Wide_Character (Flag11-Sem)
+      --  plus fields for expression
+
+      ------------------
+      -- 2.7  Comment --
+      ------------------
+
+      --  A COMMENT starts with two adjacent hyphens and extends up to the
+      --  end of the line. A COMMENT may appear on any line of a program.
+
+      --  Comments are skipped by the scanner and do not appear in the tree.
+      --  It is possible to reconstruct the position of comments with respect
+      --  to the elements of the tree by using the source position (Sloc)
+      --  pointers that appear in every tree node.
+
+      -----------------
+      -- 2.8  Pragma --
+      -----------------
+
+      --  PRAGMA ::= pragma IDENTIFIER
+      --    [(PRAGMA_ARGUMENT_ASSOCIATION {, PRAGMA_ARGUMENT_ASSOCIATION})];
+
+      --  Note that a pragma may appear in the tree anywhere a declaration
+      --  or a statement may appear, as well as in some other situations
+      --  which are explicitly documented.
+
+      --  N_Pragma
+      --  Sloc points to PRAGMA
+      --  Chars (Name1) identifier name from pragma identifier
+      --  Pragma_Argument_Associations (List2) (set to No_List if none)
+      --  Debug_Statement (Node3) (set to Empty if not Debug, Assert)
+      --  Next_Rep_Item (Node4-Sem)
+
+      --------------------------------------
+      -- 2.8  Pragma Argument Association --
+      --------------------------------------
+
+      --  PRAGMA_ARGUMENT_ASSOCIATION ::=
+      --    [pragma_argument_IDENTIFIER =>] NAME
+      --  | [pragma_argument_IDENTIFIER =>] EXPRESSION
+
+      --  N_Pragma_Argument_Association
+      --  Sloc points to first token in association
+      --  Chars (Name1) (set to No_Name if no pragma argument identifier)
+      --  Expression (Node3)
+
+      ------------------------
+      -- 2.9  Reserved Word --
+      ------------------------
+
+      --  Reserved words are parsed by the scanner, and returned as the
+      --  corresponding token types (e.g. PACKAGE is returned as Tok_Package)
+
+      ----------------------------
+      -- 3.1  Basic Declaration --
+      ----------------------------
+
+      --  BASIC_DECLARATION ::=
+      --    TYPE_DECLARATION          | SUBTYPE_DECLARATION
+      --  | OBJECT_DECLARATION        | NUMBER_DECLARATION
+      --  | SUBPROGRAM_DECLARATION    | ABSTRACT_SUBPROGRAM_DECLARATION
+      --  | PACKAGE_DECLARATION       | RENAMING_DECLARATION
+      --  | EXCEPTION_DECLARATION     | GENERIC_DECLARATION
+      --  | GENERIC_INSTANTIATION
+
+      --  Basic declaration also includes IMPLICIT_LABEL_DECLARATION
+      --  see further description in section on semantic nodes.
+
+      --  Also, in the tree that is constructed, a pragma may appear
+      --  anywhere that a declaration may appear.
+
+      ------------------------------
+      -- 3.1  Defining Identifier --
+      ------------------------------
+
+      --  DEFINING_IDENTIFIER ::= IDENTIFIER
+
+      --  A defining identifier is an entity, which has additional fields
+      --  depending on the setting of the Ekind field. These additional
+      --  fields are defined (and access subprograms declared) in package
+      --  Einfo.
+
+      --  Note: N_Defining_Identifier is an extended node whose fields are
+      --  deliberate layed out to match the layout of fields in an ordinary
+      --  N_Identifier node allowing for easy alteration of an identifier
+      --  node into a defining identifier node. For details, see procedure
+      --  Sinfo.CN.Change_Identifier_To_Defining_Identifier.
+
+      --  N_Defining_Identifier
+      --  Sloc points to identifier
+      --  Chars (Name1) contains the Name_Id for the identifier
+      --  Next_Entity (Node2-Sem)
+      --  Scope (Node3-Sem)
+      --  Etype (Node5-Sem)
+
+      -----------------------------
+      -- 3.2.1  Type Declaration --
+      -----------------------------
+
+      --  TYPE_DECLARATION ::=
+      --    FULL_TYPE_DECLARATION
+      --  | INCOMPLETE_TYPE_DECLARATION
+      --  | PRIVATE_TYPE_DECLARATION
+      --  | PRIVATE_EXTENSION_DECLARATION
+
+      ----------------------------------
+      -- 3.2.1  Full Type Declaration --
+      ----------------------------------
+
+      --  FULL_TYPE_DECLARATION ::=
+      --    type DEFINING_IDENTIFIER [KNOWN_DISCRIMINANT_PART]
+      --      is TYPE_DEFINITION;
+      --  | TASK_TYPE_DECLARATION
+      --  | PROTECTED_TYPE_DECLARATION
+
+      --  The full type declaration node is used only for the first case. The
+      --  second case (concurrent type declaration), is represented directly
+      --  by a task type declaration or a protected type declaration.
+
+      --  N_Full_Type_Declaration
+      --  Sloc points to TYPE
+      --  Defining_Identifier (Node1)
+      --  Discriminant_Specifications (List4) (set to No_List if none)
+      --  Type_Definition (Node3)
+      --  Discr_Check_Funcs_Built (Flag11-Sem)
+
+      ----------------------------
+      -- 3.2.1  Type Definition --
+      ----------------------------
+
+      --  TYPE_DEFINITION ::=
+      --    ENUMERATION_TYPE_DEFINITION  | INTEGER_TYPE_DEFINITION
+      --  | REAL_TYPE_DEFINITION         | ARRAY_TYPE_DEFINITION
+      --  | RECORD_TYPE_DEFINITION       | ACCESS_TYPE_DEFINITION
+      --  | DERIVED_TYPE_DEFINITION
+
+      --------------------------------
+      -- 3.2.2  Subtype Declaration --
+      --------------------------------
+
+      --  SUBTYPE_DECLARATION ::=
+      --    subtype DEFINING_IDENTIFIER is SUBTYPE_INDICATION;
+
+      --  The subtype indication field is set to Empty for subtypes
+      --  declared in package Standard (Positive, Natural).
+
+      --  N_Subtype_Declaration
+      --  Sloc points to SUBTYPE
+      --  Defining_Identifier (Node1)
+      --  Subtype_Indication (Node5)
+      --  Generic_Parent_Type (Node4-Sem) (set for an actual derived type).
+      --  Exception_Junk (Flag11-Sem)
+
+      -------------------------------
+      -- 3.2.2  Subtype Indication --
+      -------------------------------
+
+      --  SUBTYPE_INDICATION ::= SUBTYPE_MARK [CONSTRAINT]
+
+      --  Note: if no constraint is present, the subtype indication appears
+      --  directly in the tree as a subtype mark. The N_Subtype_Indication
+      --  node is used only if a constraint is present.
+
+      --  Note: the reason that this node has expression fields is that a
+      --  subtype indication can appear as an operand of a membership test.
+
+      --  N_Subtype_Indication
+      --  Sloc points to first token of subtype mark
+      --  Subtype_Mark (Node4)
+      --  Constraint (Node3)
+      --  Etype (Node5-Sem)
+      --  Must_Not_Freeze (Flag8-Sem)
+
+      --  Note: Etype is a copy of the Etype field of the Subtype_Mark. The
+      --  reason for this redundancy is so that in a list of array index types,
+      --  the Etype can be uniformly accessed to determine the subscript type.
+      --  This means that no Itype is constructed for the actual subtype that
+      --  is created by the subtype indication. If such an Itype is required,
+      --  it is constructed in the context in which the indication appears.
+
+      -------------------------
+      -- 3.2.2  Subtype Mark --
+      -------------------------
+
+      --  SUBTYPE_MARK ::= subtype_NAME
+
+      -----------------------
+      -- 3.2.2  Constraint --
+      -----------------------
+
+      --  CONSTRAINT ::= SCALAR_CONSTRAINT | COMPOSITE_CONSTRAINT
+
+      ------------------------------
+      -- 3.2.2  Scalar Constraint --
+      ------------------------------
+
+      --  SCALAR_CONSTRAINT ::=
+      --    RANGE_CONSTRAINT | DIGITS_CONSTRAINT | DELTA_CONSTRAINT
+
+      ---------------------------------
+      -- 3.2.2  Composite Constraint --
+      ---------------------------------
+
+      --  COMPOSITE_CONSTRAINT ::=
+      --    INDEX_CONSTRAINT | DISCRIMINANT_CONSTRAINT
+
+      -------------------------------
+      -- 3.3.1  Object Declaration --
+      -------------------------------
+
+      --  OBJECT_DECLARATION ::=
+      --    DEFINING_IDENTIFIER_LIST : [aliased] [constant]
+      --      SUBTYPE_INDICATION [:= EXPRESSION];
+      --  | DEFINING_IDENTIFIER_LIST : [aliased] [constant]
+      --      ARRAY_TYPE_DEFINITION [:= EXPRESSION];
+      --  | SINGLE_TASK_DECLARATION
+      --  | SINGLE_PROTECTED_DECLARATION
+
+      --  Note: aliased is not permitted in Ada 83 mode
+
+      --  The N_Object_Declaration node is only for the first two cases.
+      --  Single task declaration is handled by P_Task (9.1)
+      --  Single protected declaration is handled by P_protected (9.5)
+
+      --  Although the syntax allows multiple identifiers in the list, the
+      --  semantics is as though successive declarations were given with
+      --  identical type definition and expression components. To simplify
+      --  semantic processing, the parser represents a multiple declaration
+      --  case as a sequence of single declarations, using the More_Ids and
+      --  Prev_Ids flags to preserve the original source form as described
+      --  in the section on "Handling of Defining Identifier Lists".
+
+      --  Note: if a range check is required for the initialization
+      --  expression then the Do_Range_Check flag is set in the Expression,
+      --  with the check being done against the type given by the object
+      --  definition, which is also the Etype of the defining identifier.
+
+      --  Note: the contents of the Expression field must be ignored (i.e.
+      --  treated as though it were Empty) if No_Initialization is set True.
+
+      --  N_Object_Declaration
+      --  Sloc points to first identifier
+      --  Defining_Identifier (Node1)
+      --  Aliased_Present (Flag4) set if ALIASED appears
+      --  Constant_Present (Flag17) set if CONSTANT appears
+      --  Object_Definition (Node4) subtype indication/array type definition
+      --  Expression (Node3) (set to Empty if not present)
+      --  Handler_List_Entry (Node2-Sem)
+      --  Corresponding_Generic_Association (Node5-Sem)
+      --  More_Ids (Flag5) (set to False if no more identifiers in list)
+      --  Prev_Ids (Flag6) (set to False if no previous identifiers in list)
+      --  No_Initialization (Flag13-Sem)
+      --  Assignment_OK (Flag15-Sem)
+      --  Exception_Junk (Flag11-Sem)
+      --  Delay_Finalize_Attach (Flag14-Sem)
+      --  Is_Subprogram_Descriptor (Flag16-Sem)
+
+      -------------------------------------
+      -- 3.3.1  Defining Identifier List --
+      -------------------------------------
+
+      --  DEFINING_IDENTIFIER_LIST ::=
+      --    DEFINING_IDENTIFIER {, DEFINING_IDENTIFIER}
+
+      -------------------------------
+      -- 3.3.2  Number Declaration --
+      -------------------------------
+
+      --  NUMBER_DECLARATION ::=
+      --    DEFINING_IDENTIFIER_LIST : constant := static_EXPRESSION;
+
+      --  Although the syntax allows multiple identifiers in the list, the
+      --  semantics is as though successive declarations were given with
+      --  identical expressions. To simplify semantic processing, the parser
+      --  represents a multiple declaration case as a sequence of single
+      --  declarations, using the More_Ids and Prev_Ids flags to preserve
+      --  the original source form as described in the section on "Handling
+      --  of Defining Identifier Lists".
+
+      --  N_Number_Declaration
+      --  Sloc points to first identifier
+      --  Defining_Identifier (Node1)
+      --  Expression (Node3)
+      --  More_Ids (Flag5) (set to False if no more identifiers in list)
+      --  Prev_Ids (Flag6) (set to False if no previous identifiers in list)
+
+      ----------------------------------
+      -- 3.4  Derived Type Definition --
+      ----------------------------------
+
+      --  DERIVED_TYPE_DEFINITION ::=
+      --    [abstract] new parent_SUBTYPE_INDICATION [RECORD_EXTENSION_PART]
+
+      --  Note: ABSTRACT, record extension part not permitted in Ada 83 mode
+
+      --  Note: a record extension part is required if ABSTRACT is present
+
+      --  N_Derived_Type_Definition
+      --  Sloc points to NEW
+      --  Abstract_Present (Flag4)
+      --  Subtype_Indication (Node5)
+      --  Record_Extension_Part (Node3) (set to Empty if not present)
+
+      ---------------------------
+      -- 3.5  Range Constraint --
+      ---------------------------
+
+      --  RANGE_CONSTRAINT ::= range RANGE
+
+      --  N_Range_Constraint
+      --  Sloc points to RANGE
+      --  Range_Expression (Node4)
+
+      ----------------
+      -- 3.5  Range --
+      ----------------
+
+      --  RANGE ::=
+      --    RANGE_ATTRIBUTE_REFERENCE
+      --  | SIMPLE_EXPRESSION .. SIMPLE_EXPRESSION
+
+      --  Note: the case of a range given as a range attribute reference
+      --  appears directly in the tree as an attribute reference.
+
+      --  Note: the field name for a reference to a range is Range_Expression
+      --  rather than Range, because range is a reserved keyword in Ada!
+
+      --  Note: the reason that this node has expression fields is that a
+      --  range can appear as an operand of a membership test. The Etype
+      --  field is the type of the range (we do NOT construct an implicit
+      --  subtype to represent the range exactly).
+
+      --  N_Range
+      --  Sloc points to ..
+      --  Low_Bound (Node1)
+      --  High_Bound (Node2)
+      --  Includes_Infinities (Flag11)
+      --  plus fields for expression
+
+      --  Note: if the range appears in a context, such as a subtype
+      --  declaration, where range checks are required on one or both of
+      --  the expression fields, then type conversion nodes are inserted
+      --  to represent the required checks.
+
+      ----------------------------------------
+      -- 3.5.1  Enumeration Type Definition --
+      ----------------------------------------
+
+      --  ENUMERATION_TYPE_DEFINITION ::=
+      --    (ENUMERATION_LITERAL_SPECIFICATION
+      --      {, ENUMERATION_LITERAL_SPECIFICATION})
+
+      --  Note: the Literals field in the node described below is null for
+      --  the case of the standard types CHARACTER and WIDE_CHARACTER, for
+      --  which special processing handles these types as special cases.
+
+      --  N_Enumeration_Type_Definition
+      --  Sloc points to left parenthesis
+      --  Literals (List1) (Empty for CHARACTER or WIDE_CHARACTER)
+
+      ----------------------------------------------
+      -- 3.5.1  Enumeration Literal Specification --
+      ----------------------------------------------
+
+      --  ENUMERATION_LITERAL_SPECIFICATION ::=
+      --    DEFINING_IDENTIFIER | DEFINING_CHARACTER_LITERAL
+
+      ---------------------------------------
+      -- 3.5.1  Defining Character Literal --
+      ---------------------------------------
+
+      --  DEFINING_CHARACTER_LITERAL ::= CHARACTER_LITERAL
+
+      --  A defining character literal is an entity, which has additional
+      --  fields depending on the setting of the Ekind field. These
+      --  additional fields are defined (and access subprograms declared)
+      --  in package Einfo.
+
+      --  Note: N_Defining_Character_Literal is an extended node whose fields
+      --  are deliberate layed out to match the layout of fields in an ordinary
+      --  N_Character_Literal node allowing for easy alteration of a character
+      --  literal node into a defining character literal node. For details, see
+      --  Sinfo.CN.Change_Character_Literal_To_Defining_Character_Literal.
+
+      --  N_Defining_Character_Literal
+      --  Sloc points to literal
+      --  Chars (Name1) contains the Name_Id for the identifier
+      --  Next_Entity (Node2-Sem)
+      --  Scope (Node3-Sem)
+      --  Etype (Node5-Sem)
+
+      ------------------------------------
+      -- 3.5.4  Integer Type Definition --
+      ------------------------------------
+
+      --  Note: there is an error in this rule in the latest version of the
+      --  grammar, so we have retained the old rule pending clarification.
+
+      --  INTEGER_TYPE_DEFINITION ::=
+      --    SIGNED_INTEGER_TYPE_DEFINITION
+      --    MODULAR_TYPE_DEFINITION
+
+      -------------------------------------------
+      -- 3.5.4  Signed Integer Type Definition --
+      -------------------------------------------
+
+      --  SIGNED_INTEGER_TYPE_DEFINITION ::=
+      --    range static_SIMPLE_EXPRESSION .. static_SIMPLE_EXPRESSION
+
+      --  Note: the Low_Bound and High_Bound fields are set to Empty for
+      --  integer types defined in package Standard.
+
+      --  N_Signed_Integer_Type_Definition
+      --  Sloc points to RANGE
+      --  Low_Bound (Node1)
+      --  High_Bound (Node2)
+
+      -----------------------------------------
+      -- 3.5.4  Unsigned Range Specification --
+      -----------------------------------------
+
+      --  MODULAR_TYPE_DEFINITION ::= mod static_EXPRESSION
+
+      --  N_Modular_Type_Definition
+      --  Sloc points to MOD
+      --  Expression (Node3)
+
+      ---------------------------------
+      -- 3.5.6  Real Type Definition --
+      ---------------------------------
+
+      --  REAL_TYPE_DEFINITION ::=
+      --    FLOATING_POINT_DEFINITION | FIXED_POINT_DEFINITION
+
+      --------------------------------------
+      -- 3.5.7  Floating Point Definition --
+      --------------------------------------
+
+      --  FLOATING_POINT_DEFINITION ::=
+      --    digits static_SIMPLE_EXPRESSION [REAL_RANGE_SPECIFICATION]
+
+      --  Note: The Digits_Expression and Real_Range_Specifications fields
+      --  are set to Empty for floating-point types declared in Standard.
+
+      --  N_Floating_Point_Definition
+      --  Sloc points to DIGITS
+      --  Digits_Expression (Node2)
+      --  Real_Range_Specification (Node4) (set to Empty if not present)
+
+      -------------------------------------
+      -- 3.5.7  Real Range Specification --
+      -------------------------------------
+
+      --  REAL_RANGE_SPECIFICATION ::=
+      --    range static_SIMPLE_EXPRESSION .. static_SIMPLE_EXPRESSION
+
+      --  N_Real_Range_Specification
+      --  Sloc points to RANGE
+      --  Low_Bound (Node1)
+      --  High_Bound (Node2)
+
+      -----------------------------------
+      -- 3.5.9  Fixed Point Definition --
+      -----------------------------------
+
+      --  FIXED_POINT_DEFINITION ::=
+      --    ORDINARY_FIXED_POINT_DEFINITION | DECIMAL_FIXED_POINT_DEFINITION
+
+      --------------------------------------------
+      -- 3.5.9  Ordinary Fixed Point Definition --
+      --------------------------------------------
+
+      --  ORDINARY_FIXED_POINT_DEFINITION ::=
+      --    delta static_EXPRESSION REAL_RANGE_SPECIFICATION
+
+      --  Note: In Ada 83, the EXPRESSION must be a SIMPLE_EXPRESSION
+
+      --  Note: the Delta_Expression and Real_Range_Specification fields
+      --  are set to Empty for fixed point types declared in Standard.
+
+      --  N_Ordinary_Fixed_Point_Definition
+      --  Sloc points to DELTA
+      --  Delta_Expression (Node3)
+      --  Real_Range_Specification (Node4)
+
+      -------------------------------------------
+      -- 3.5.9  Decimal Fixed Point Definition --
+      -------------------------------------------
+
+      --  DECIMAL_FIXED_POINT_DEFINITION ::=
+      --    delta static_EXPRESSION
+      --      digits static_EXPRESSION [REAL_RANGE_SPECIFICATION]
+
+      --  Note: decimal types are not permitted in Ada 83 mode
+
+      --  N_Decimal_Fixed_Point_Definition
+      --  Sloc points to DELTA
+      --  Delta_Expression (Node3)
+      --  Digits_Expression (Node2)
+      --  Real_Range_Specification (Node4) (set to Empty if not present)
+
+      ------------------------------
+      -- 3.5.9  Digits Constraint --
+      ------------------------------
+
+      --  DIGITS_CONSTRAINT ::=
+      --    digits static_EXPRESSION [RANGE_CONSTRAINT]
+
+      --  Note: in Ada 83, the EXPRESSION must be a SIMPLE_EXPRESSION
+      --  Note: in Ada 95, reduced accuracy subtypes are obsolescent
+
+      --  N_Digits_Constraint
+      --  Sloc points to DIGITS
+      --  Digits_Expression (Node2)
+      --  Range_Constraint (Node4) (set to Empty if not present)
+
+      --------------------------------
+      -- 3.6  Array Type Definition --
+      --------------------------------
+
+      --  ARRAY_TYPE_DEFINITION ::=
+      --    UNCONSTRAINED_ARRAY_DEFINITION | CONSTRAINED_ARRAY_DEFINITION
+
+      -----------------------------------------
+      -- 3.6  Unconstrained Array Definition --
+      -----------------------------------------
+
+      --  UNCONSTRAINED_ARRAY_DEFINITION ::=
+      --    array (INDEX_SUBTYPE_DEFINITION {, INDEX_SUBTYPE_DEFINITION}) of
+      --      COMPONENT_DEFINITION
+
+      --  Note: dimensionality of array is indicated by number of entries in
+      --  the Subtype_Marks list, which has one entry for each dimension.
+
+      --  N_Unconstrained_Array_Definition
+      --  Sloc points to ARRAY
+      --  Subtype_Marks (List2)
+      --  Aliased_Present (Flag4) from component definition
+      --  Subtype_Indication (Node5) from component definition
+
+      -----------------------------------
+      -- 3.6  Index Subtype Definition --
+      -----------------------------------
+
+      --  INDEX_SUBTYPE_DEFINITION ::= SUBTYPE_MARK range <>
+
+      --  There is no explicit node in the tree for an index subtype
+      --  definition since the N_Unconstrained_Array_Definition node
+      --  incorporates the type marks which appear in this context.
+
+      ---------------------------------------
+      -- 3.6  Constrained Array Definition --
+      ---------------------------------------
+
+      --  CONSTRAINED_ARRAY_DEFINITION ::=
+      --    array (DISCRETE_SUBTYPE_DEFINITION
+      --      {, DISCRETE_SUBTYPE_DEFINITION})
+      --        of COMPONENT_DEFINITION
+
+      --  Note: dimensionality of array is indicated by number of entries
+      --  in the Discrete_Subtype_Definitions list, which has one entry
+      --  for each dimension.
+
+      --  N_Constrained_Array_Definition
+      --  Sloc points to ARRAY
+      --  Discrete_Subtype_Definitions (List2)
+      --  Aliased_Present (Flag4) from component definition
+      --  Subtype_Indication (Node5) from component definition
+
+      --------------------------------------
+      -- 3.6  Discrete Subtype Definition --
+      --------------------------------------
+
+      --  DISCRETE_SUBTYPE_DEFINITION ::=
+      --    discrete_SUBTYPE_INDICATION | RANGE
+
+      -------------------------------
+      -- 3.6  Component Definition --
+      -------------------------------
+
+      --  COMPONENT_DEFINITION ::= [aliased] SUBTYPE_INDICATION
+
+      --  There is no explicit node in the tree for a component definition.
+      --  Instead the subtype indication appears directly, and the ALIASED
+      --  indication (Aliased_Present flag) is in the parent node.
+
+      --  Note: although the syntax does not permit a component definition to
+      --  be an anonymous array (and the parser will diagnose such an attempt
+      --  with an appropriate message), it is possible for anonymous arrays
+      --  to appear as component definitions. The semantics and back end handle
+      --  this case properly, and the expander in fact generates such cases.
+
+      -----------------------------
+      -- 3.6.1  Index Constraint --
+      -----------------------------
+
+      --  INDEX_CONSTRAINT ::= (DISCRETE_RANGE {, DISCRETE_RANGE})
+
+      --  It is not in general possible to distinguish between discriminant
+      --  constraints and index constraints at parse time, since a simple
+      --  name could be either the subtype mark of a discrete range, or an
+      --  expression in a discriminant association with no name. Either
+      --  entry appears simply as the name, and the semantic parse must
+      --  distinguish between the two cases. Thus we use a common tree
+      --  node format for both of these constraint types.
+
+      --  See Discriminant_Constraint for format of node
+
+      ---------------------------
+      -- 3.6.1  Discrete Range --
+      ---------------------------
+
+      --  DISCRETE_RANGE ::= discrete_SUBTYPE_INDICATION | RANGE
+
+      ----------------------------
+      -- 3.7  Discriminant Part --
+      ----------------------------
+
+      --  DISCRIMINANT_PART ::=
+      --    UNKNOWN_DISCRIMINANT_PART | KNOWN_DISCRIMINANT_PART
+
+      ------------------------------------
+      -- 3.7  Unknown Discriminant Part --
+      ------------------------------------
+
+      --  UNKNOWN_DISCRIMINANT_PART ::= (<>)
+
+      --  Note: unknown discriminant parts are not permitted in Ada 83 mode
+
+      --  There is no explicit node in the tree for an unknown discriminant
+      --  part. Instead the Unknown_Discriminants_Present flag is set in the
+      --  parent node.
+
+      ----------------------------------
+      -- 3.7  Known Discriminant Part --
+      ----------------------------------
+
+      --  KNOWN_DISCRIMINANT_PART ::=
+      --    (DISCRIMINANT_SPECIFICATION {; DISCRIMINANT_SPECIFICATION})
+
+      -------------------------------------
+      -- 3.7  Discriminant Specification --
+      -------------------------------------
+
+      --  DISCRIMINANT_SPECIFICATION ::=
+      --    DEFINING_IDENTIFIER_LIST : SUBTYPE_MARK
+      --      [:= DEFAULT_EXPRESSION]
+      --  | DEFINING_IDENTIFIER_LIST : ACCESS_DEFINITION
+      --      [:= DEFAULT_EXPRESSION]
+
+      --  Although the syntax allows multiple identifiers in the list, the
+      --  semantics is as though successive specifications were given with
+      --  identical type definition and expression components. To simplify
+      --  semantic processing, the parser represents a multiple declaration
+      --  case as a sequence of single specifications, using the More_Ids and
+      --  Prev_Ids flags to preserve the original source form as described
+      --  in the section on "Handling of Defining Identifier Lists".
+
+      --  N_Discriminant_Specification
+      --  Sloc points to first identifier
+      --  Defining_Identifier (Node1)
+      --  Discriminant_Type (Node5) subtype mark or
+      --    access parameter definition
+      --  Expression (Node3) (set to Empty if no default expression)
+      --  More_Ids (Flag5) (set to False if no more identifiers in list)
+      --  Prev_Ids (Flag6) (set to False if no previous identifiers in list)
+
+      -----------------------------
+      -- 3.7  Default Expression --
+      -----------------------------
+
+      --  DEFAULT_EXPRESSION ::= EXPRESSION
+
+      ------------------------------------
+      -- 3.7.1  Discriminant Constraint --
+      ------------------------------------
+
+      --  DISCRIMINANT_CONSTRAINT ::=
+      --    (DISCRIMINANT_ASSOCIATION {, DISCRIMINANT_ASSOCIATION})
+
+      --  It is not in general possible to distinguish between discriminant
+      --  constraints and index constraints at parse time, since a simple
+      --  name could be either the subtype mark of a discrete range, or an
+      --  expression in a discriminant association with no name. Either
+      --  entry appears simply as the name, and the semantic parse must
+      --  distinguish between the two cases. Thus we use a common tree
+      --  node format for both of these constraint types.
+
+      --  N_Index_Or_Discriminant_Constraint
+      --  Sloc points to left paren
+      --  Constraints (List1) points to list of discrete ranges or
+      --    discriminant associations
+
+      -------------------------------------
+      -- 3.7.1  Discriminant Association --
+      -------------------------------------
+
+      --  DISCRIMINANT_ASSOCIATION ::=
+      --    [discriminant_SELECTOR_NAME
+      --      {| discriminant_SELECTOR_NAME} =>] EXPRESSION
+
+      --  Note: a discriminant association that has no selector name list
+      --  appears directly as an expression in the tree.
+
+      --  N_Discriminant_Association
+      --  Sloc points to first token of discriminant association
+      --  Selector_Names (List1) (always non-empty, since if no selector
+      --   names are present, this node is not used, see comment above)
+      --  Expression (Node3)
+
+      ---------------------------------
+      -- 3.8  Record Type Definition --
+      ---------------------------------
+
+      --  RECORD_TYPE_DEFINITION ::=
+      --    [[abstract] tagged] [limited] RECORD_DEFINITION
+
+      --  Note: ABSTRACT, TAGGED, LIMITED are not permitted in Ada 83 mode
+
+      --  There is no explicit node in the tree for a record type definition.
+      --  Instead the flags for Tagged_Present and Limited_Present appear in
+      --  the N_Record_Definition node for a record definition appearing in
+      --  the context of a record type definition.
+
+      ----------------------------
+      -- 3.8  Record Definition --
+      ----------------------------
+
+      --  RECORD_DEFINITION ::=
+      --    record
+      --      COMPONENT_LIST
+      --    end record
+      --  | null record
+
+      --  Note: the Abstract_Present, Tagged_Present and Limited_Present
+      --  flags appear only for a record definition appearing in a record
+      --  type definition.
+
+      --  Note: the NULL RECORD case is not permitted in Ada 83
+
+      --  N_Record_Definition
+      --  Sloc points to RECORD or NULL
+      --  End_Label (Node4) (set to Empty if internally generated record)
+      --  Abstract_Present (Flag4)
+      --  Tagged_Present (Flag15)
+      --  Limited_Present (Flag17)
+      --  Component_List (Node1) empty in null record case
+      --  Null_Present (Flag13) set in null record case
+
+      -------------------------
+      -- 3.8  Component List --
+      -------------------------
+
+      --  COMPONENT_LIST ::=
+      --    COMPONENT_ITEM {COMPONENT_ITEM}
+      --  | {COMPONENT_ITEM} VARIANT_PART
+      --  | null;
+
+      --  N_Component_List
+      --  Sloc points to first token of component list
+      --  Component_Items (List3)
+      --  Variant_Part (Node4) (set to Empty if no variant part)
+      --  Null_Present (Flag13)
+
+      -------------------------
+      -- 3.8  Component Item --
+      -------------------------
+
+      --  COMPONENT_ITEM ::= COMPONENT_DECLARATION | REPRESENTATION_CLAUSE
+
+      --  Note: A component item can also be a pragma, and in the tree
+      --  that is obtained after semantic processing, a component item
+      --  can be an N_Null node resulting from a non-recognized pragma.
+
+      --------------------------------
+      -- 3.8  Component Declaration --
+      --------------------------------
+
+      --  COMPONENT_DECLARATION ::=
+      --    DEFINING_IDENTIFIER_LIST : COMPONENT_DEFINITION
+      --      [:= DEFAULT_EXPRESSION]
+
+      --  Note: although the syntax does not permit a component definition to
+      --  be an anonymous array (and the parser will diagnose such an attempt
+      --  with an appropriate message), it is possible for anonymous arrays
+      --  to appear as component definitions. The semantics and back end handle
+      --  this case properly, and the expander in fact generates such cases.
+
+      --  Although the syntax allows multiple identifiers in the list, the
+      --  semantics is as though successive declarations were given with the
+      --  same component definition and expression components. To simplify
+      --  semantic processing, the parser represents a multiple declaration
+      --  case as a sequence of single declarations, using the More_Ids and
+      --  Prev_Ids flags to preserve the original source form as described
+      --  in the section on "Handling of Defining Identifier Lists".
+
+      --  N_Component_Declaration
+      --  Sloc points to first identifier
+      --  Defining_Identifier (Node1)
+      --  Aliased_Present (Flag4) from component definition
+      --  Subtype_Indication (Node5) from component definition
+      --  Expression (Node3) (set to Empty if no default expression)
+      --  More_Ids (Flag5) (set to False if no more identifiers in list)
+      --  Prev_Ids (Flag6) (set to False if no previous identifiers in list)
+
+      -------------------------
+      -- 3.8.1  Variant Part --
+      -------------------------
+
+      --  VARIANT_PART ::=
+      --    case discriminant_DIRECT_NAME is
+      --      VARIANT
+      --      {VARIANT}
+      --    end case;
+
+      --  Note: the variants list can contain pragmas as well as variants.
+      --  In a properly formed program there is at least one variant.
+
+      --  N_Variant_Part
+      --  Sloc points to CASE
+      --  Name (Node2)
+      --  Variants (List1)
+
+      --------------------
+      -- 3.8.1  Variant --
+      --------------------
+
+      --  VARIANT ::=
+      --    when DISCRETE_CHOICE_LIST =>
+      --      COMPONENT_LIST
+
+      --  N_Variant
+      --  Sloc points to WHEN
+      --  Discrete_Choices (List4)
+      --  Component_List (Node1)
+      --  Enclosing_Variant (Node2-Sem)
+      --  Present_Expr (Uint3-Sem)
+      --  Dcheck_Function (Node5-Sem)
+
+      ---------------------------------
+      -- 3.8.1  Discrete Choice List --
+      ---------------------------------
+
+      --  DISCRETE_CHOICE_LIST ::= DISCRETE_CHOICE {| DISCRETE_CHOICE}
+
+      ----------------------------
+      -- 3.8.1  Discrete Choice --
+      ----------------------------
+
+      --  DISCRETE_CHOICE ::= EXPRESSION | DISCRETE_RANGE | others
+
+      --  Note: in Ada 83 mode, the expression must be a simple expression
+
+      --  The only choice that appears explicitly is the OTHERS choice, as
+      --  defined here. Other cases of discrete choice (expression and
+      --  discrete range) appear directly. This production is also used
+      --  for the OTHERS possibility of an exception choice.
+
+      --  Note: in accordance with the syntax, the parser does not check that
+      --  OTHERS appears at the end on its own in a choice list context. This
+      --  is a semantic check.
+
+      --  N_Others_Choice
+      --  Sloc points to OTHERS
+      --  Others_Discrete_Choices (List1-Sem)
+      --  All_Others (Flag11-Sem)
+
+      ----------------------------------
+      -- 3.9.1  Record Extension Part --
+      ----------------------------------
+
+      --  RECORD_EXTENSION_PART ::= with RECORD_DEFINITION
+
+      --  Note: record extension parts are not permitted in Ada 83 mode
+
+      ----------------------------------
+      -- 3.10  Access Type Definition --
+      ----------------------------------
+
+      --  ACCESS_TYPE_DEFINITION ::=
+      --    ACCESS_TO_OBJECT_DEFINITION
+      --  | ACCESS_TO_SUBPROGRAM_DEFINITION
+
+      ---------------------------------------
+      -- 3.10  Access To Object Definition --
+      ---------------------------------------
+
+      --  ACCESS_TO_OBJECT_DEFINITION ::=
+      --    access [GENERAL_ACCESS_MODIFIER] SUBTYPE_INDICATION
+
+      --  N_Access_To_Object_Definition
+      --  Sloc points to ACCESS
+      --  All_Present (Flag15)
+      --  Subtype_Indication (Node5)
+      --  Constant_Present (Flag17)
+
+      -----------------------------------
+      -- 3.10  General Access Modifier --
+      -----------------------------------
+
+      --  GENERAL_ACCESS_MODIFIER ::= all | constant
+
+      --  Note: general access modifiers are not permitted in Ada 83 mode
+
+      --  There is no explicit node in the tree for general access modifier.
+      --  Instead the All_Present or Constant_Present flags are set in the
+      --  parent node.
+
+      -------------------------------------------
+      -- 3.10  Access To Subprogram Definition --
+      -------------------------------------------
+
+      --  ACCESS_TO_SUBPROGRAM_DEFINITION
+      --    access [protected] procedure PARAMETER_PROFILE
+      --  | access [protected] function PARAMETER_AND_RESULT_PROFILE
+
+      --  Note: access to subprograms are not permitted in Ada 83 mode
+
+      --  N_Access_Function_Definition
+      --  Sloc points to ACCESS
+      --  Protected_Present (Flag15)
+      --  Parameter_Specifications (List3) (set to No_List if no formal part)
+      --  Subtype_Mark (Node4) result subtype
+
+      --  N_Access_Procedure_Definition
+      --  Sloc points to ACCESS
+      --  Protected_Present (Flag15)
+      --  Parameter_Specifications (List3) (set to No_List if no formal part)
+
+      -----------------------------
+      -- 3.10  Access Definition --
+      -----------------------------
+
+      --  ACCESS_DEFINITION ::= access SUBTYPE_MARK
+
+      --  N_Access_Definition
+      --  Sloc points to ACCESS
+      --  Subtype_Mark (Node4)
+
+      -----------------------------------------
+      -- 3.10.1  Incomplete Type Declaration --
+      -----------------------------------------
+
+      --  INCOMPLETE_TYPE_DECLARATION ::=
+      --    type DEFINING_IDENTIFIER [DISCRIMINANT_PART];
+
+      --  N_Incomplete_Type_Declaration
+      --  Sloc points to TYPE
+      --  Defining_Identifier (Node1)
+      --  Discriminant_Specifications (List4) (set to No_List if no
+      --   discriminant part, or if the discriminant part is an
+      --   unknown discriminant part)
+      --  Unknown_Discriminants_Present (Flag13) set if (<>) discriminant
+
+      ----------------------------
+      -- 3.11  Declarative Part --
+      ----------------------------
+
+      --  DECLARATIVE_PART ::= {DECLARATIVE_ITEM}
+
+      --  Note: although the parser enforces the syntactic requirement that
+      --  a declarative part can contain only declarations, the semantic
+      --  processing may add statements to the list of actions in a
+      --  declarative part, so the code generator should be prepared
+      --  to accept a statement in this position.
+
+      ----------------------------
+      -- 3.11  Declarative Item --
+      ----------------------------
+
+      --  DECLARATIVE_ITEM ::= BASIC_DECLARATIVE_ITEM | BODY
+
+      ----------------------------------
+      -- 3.11  Basic Declarative Item --
+      ----------------------------------
+
+      --  BASIC_DECLARATIVE_ITEM ::=
+      --    BASIC_DECLARATION | REPRESENTATION_CLAUSE | USE_CLAUSE
+
+      ----------------
+      -- 3.11  Body --
+      ----------------
+
+      --  BODY ::= PROPER_BODY | BODY_STUB
+
+      -----------------------
+      -- 3.11  Proper Body --
+      -----------------------
+
+      --  PROPER_BODY ::=
+      --    SUBPROGRAM_BODY | PACKAGE_BODY | TASK_BODY | PROTECTED_BODY
+
+      ---------------
+      -- 4.1  Name --
+      ---------------
+
+      --  NAME ::=
+      --    DIRECT_NAME        | EXPLICIT_DEREFERENCE
+      --  | INDEXED_COMPONENT  | SLICE
+      --  | SELECTED_COMPONENT | ATTRIBUTE_REFERENCE
+      --  | TYPE_CONVERSION    | FUNCTION_CALL
+      --  | CHARACTER_LITERAL
+
+      ----------------------
+      -- 4.1  Direct Name --
+      ----------------------
+
+      --  DIRECT_NAME ::= IDENTIFIER | OPERATOR_SYMBOL
+
+      -----------------
+      -- 4.1  Prefix --
+      -----------------
+
+      --  PREFIX ::= NAME | IMPLICIT_DEREFERENCE
+
+      -------------------------------
+      -- 4.1  Explicit Dereference --
+      -------------------------------
+
+      --  EXPLICIT_DEREFERENCE ::= NAME . all
+
+      --  N_Explicit_Dereference
+      --  Sloc points to ALL
+      --  Prefix (Node3)
+      --  Do_Access_Check (Flag11-Sem)
+      --  plus fields for expression
+
+      -------------------------------
+      -- 4.1  Implicit Dereference --
+      -------------------------------
+
+      --  IMPLICIT_DEREFERENCE ::= NAME
+
+      ------------------------------
+      -- 4.1.1  Indexed Component --
+      ------------------------------
+
+      --  INDEXED_COMPONENT ::= PREFIX (EXPRESSION {, EXPRESSION})
+
+      --  Note: the parser may generate this node in some situations where it
+      --  should be a function call. The semantic  pass must correct this
+      --  misidentification (which is inevitable at the parser level).
+
+      --  N_Indexed_Component
+      --  Sloc contains a copy of the Sloc value of the Prefix
+      --  Prefix (Node3)
+      --  Expressions (List1)
+      --  Do_Access_Check (Flag11-Sem)
+      --  plus fields for expression
+
+      --  Note: if any of the subscripts requires a range check, then the
+      --  Do_Range_Check flag is set on the corresponding expression, with
+      --  the index type being determined from the type of the Prefix, which
+      --  references the array being indexed.
+
+      --  Note: in a fully analyzed and expanded indexed component node, and
+      --  hence in any such node that gigi sees, if the prefix is an access
+      --  type, then an explicit dereference operation has been inserted.
+
+      ------------------
+      -- 4.1.2  Slice --
+      ------------------
+
+      --  SLICE ::= PREFIX (DISCRETE_RANGE)
+
+      --  Note: an implicit subtype is created to describe the resulting
+      --  type, so that the bounds of this type are the bounds of the slice.
+
+      --  N_Slice
+      --  Sloc points to first token of prefix
+      --  Prefix (Node3)
+      --  Discrete_Range (Node4)
+      --  Do_Access_Check (Flag11-Sem)
+      --  plus fields for expression
+
+      -------------------------------
+      -- 4.1.3  Selected Component --
+      -------------------------------
+
+      --  SELECTED_COMPONENT ::= PREFIX . SELECTOR_NAME
+
+      --  Note: selected components that are semantically expanded names get
+      --  changed during semantic processing into the separate N_Expanded_Name
+      --  node. See description of this node in the section on semantic nodes.
+
+      --  N_Selected_Component
+      --  Sloc points to period
+      --  Prefix (Node3)
+      --  Selector_Name (Node2)
+      --  Do_Access_Check (Flag11-Sem)
+      --  Do_Discriminant_Check (Flag13-Sem)
+      --  plus fields for expression
+
+      --------------------------
+      -- 4.1.3  Selector Name --
+      --------------------------
+
+      --  SELECTOR_NAME ::= IDENTIFIER | CHARACTER_LITERAL | OPERATOR_SYMBOL
+
+      --------------------------------
+      -- 4.1.4  Attribute Reference --
+      --------------------------------
+
+      --  ATTRIBUTE_REFERENCE ::= PREFIX ' ATTRIBUTE_DESIGNATOR
+
+      --  Note: the syntax is quite ambiguous at this point. Consider:
+
+      --    A'Length (X)  X is part of the attribute designator
+      --    A'Pos (X)     X is an explicit actual parameter of function A'Pos
+      --    A'Class (X)   X is the expression of a type conversion
+
+      --  It would be possible for the parser to distinguish these cases
+      --  by looking at the attribute identifier. However, that would mean
+      --  more work in introducing new implementation defined attributes,
+      --  and also it would mean that special processing for attributes
+      --  would be scattered around, instead of being centralized in the
+      --  semantic routine that handles an N_Attribute_Reference node.
+      --  Consequently, the parser in all the above cases stores the
+      --  expression (X in these examples) as a single element list in
+      --  in the Expressions field of the N_Attribute_Reference node.
+
+      --  Similarly, for attributes like Max which take two arguments,
+      --  we store the two arguments as a two element list in the
+      --  Expressions field. Of course it is clear at parse time that
+      --  this case is really a function call with an attribute as the
+      --  prefix, but it turns out to be convenient to handle the two
+      --  argument case in a similar manner to the one argument case,
+      --  and indeed in general the parser will accept any number of
+      --  expressions in this position and store them as a list in the
+      --  attribute reference node. This allows for future addition of
+      --  attributes that take more than two arguments.
+
+      --  Note: named associates are not permitted in function calls where
+      --  the function is an attribute (see RM 6.4(3)) so it is legitimate
+      --  to skip the normal subprogram argument processing.
+
+      --  Note: for the attributes whose designators are technically keywords,
+      --  i.e. digits, access, delta, range, the Attribute_Name field contains
+      --  the corresponding name, even though no identifier is involved.
+
+      --  The flag OK_For_Stream is used in generated code to indicate that
+      --  a stream attribute is permissible for a limited type, and results
+      --  in the use of the stream attribute for the underlying full type,
+      --  or in the case of a protected type, the components (including any
+      --  disriminants) are merely streamed in order.
+
+      --  See Exp_Attr for a complete description of which attributes are
+      --  passed onto Gigi, and which are handled entirely by the front end.
+
+      --  Gigi restriction: For the Pos attribute, the prefix cannot be
+      --  a non-standard enumeration type or a nonzero/zero semantics
+      --  boolean type, so the value is simply the stored representation.
+
+      --  N_Attribute_Reference
+      --  Sloc points to apostrophe
+      --  Prefix (Node3)
+      --  Attribute_Name (Name2) identifier name from attribute designator
+      --  Expressions (List1) (set to No_List if no associated expressions)
+      --  Entity (Node4-Sem) used if the attribute yields a type
+      --  Do_Access_Check (Flag11-Sem)
+      --  Do_Overflow_Check (Flag17-Sem)
+      --  Redundant_Use (Flag13-Sem)
+      --  OK_For_Stream (Flag4-Sem)
+      --  plus fields for expression
+
+      ---------------------------------
+      -- 4.1.4  Attribute Designator --
+      ---------------------------------
+
+      --  ATTRIBUTE_DESIGNATOR ::=
+      --    IDENTIFIER [(static_EXPRESSION)]
+      --  | access | delta | digits
+
+      --  There is no explicit node in the tree for an attribute designator.
+      --  Instead the Attribute_Name and Expressions fields of the parent
+      --  node (N_Attribute_Reference node) hold the information.
+
+      --  Note: if ACCESS, DELTA or DIGITS appears in an attribute
+      --  designator, then they are treated as identifiers internally
+      --  rather than the keywords of the same name.
+
+      --------------------------------------
+      -- 4.1.4  Range Attribute Reference --
+      --------------------------------------
+
+      --  RANGE_ATTRIBUTE_REFERENCE ::= PREFIX ' RANGE_ATTRIBUTE_DESIGNATOR
+
+      --  A range attribute reference is represented in the tree using the
+      --  normal N_Attribute_Reference node.
+
+      ---------------------------------------
+      -- 4.1.4  Range Attribute Designator --
+      ---------------------------------------
+
+      --  RANGE_ATTRIBUTE_DESIGNATOR ::= Range [(static_EXPRESSION)]
+
+      --  A range attribute designator is represented in the tree using the
+      --  normal N_Attribute_Reference node.
+
+      --------------------
+      -- 4.3  Aggregate --
+      --------------------
+
+      --  AGGREGATE ::=
+      --    RECORD_AGGREGATE | EXTENSION_AGGREGATE | ARRAY_AGGREGATE
+
+      -----------------------------
+      -- 4.3.1  Record Aggregate --
+      -----------------------------
+
+      --  RECORD_AGGREGATE ::= (RECORD_COMPONENT_ASSOCIATION_LIST)
+
+      --  N_Aggregate
+      --  Sloc points to left parenthesis
+      --  Expressions (List1) (set to No_List if none or null record case)
+      --  Component_Associations (List2) (set to No_List if none)
+      --  Null_Record_Present (Flag17)
+      --  Aggregate_Bounds (Node3-Sem)
+      --  Static_Processing_OK (Flag4-Sem)
+      --  Compile_Time_Known_Aggregate (Flag18-Sem)
+      --  Expansion_Delayed (Flag11-Sem)
+      --  plus fields for expression
+
+      --  Note: this structure is used for both record and array aggregates
+      --  since the two cases are not separable by the parser. The parser
+      --  makes no attempt to enforce consistency here, so it is up to the
+      --  semantic phase to make sure that the aggregate is consistent (i.e.
+      --  that it is not a "half-and-half" case that mixes record and array
+      --  syntax. In particular, for a record aggregate, the expressions
+      --  field will be set if there are positional associations.
+
+      --  Note: gigi/gcc can handle array aggregates correctly providing that
+      --  they are entirely positional, and the array subtype involved has a
+      --  known at compile time length and is not bit packed, or a convention
+      --  Fortran array with more than one dimension. If these conditions
+      --  are not met, then the front end must translate the aggregate into
+      --  an appropriate set  of assignments into a temporary.
+
+      --  Note: for the record aggregate case, gigi/gcc can handle all cases
+      --  of record aggregates, including those for packed, and rep-claused
+      --  records, and also variant records, providing that there are no
+      --  variable length fields whose size is not known at runtime, and
+      --  providing that the aggregate is presented in fully named form.
+
+      ----------------------------------------------
+      -- 4.3.1  Record Component Association List --
+      ----------------------------------------------
+
+      --  RECORD_COMPONENT_ASSOCIATION_LIST ::=
+      --     RECORD_COMPONENT_ASSOCIATION {, RECORD_COMPONENT_ASSOCIATION}
+      --   | null record
+
+      --  There is no explicit node in the tree for a record component
+      --  association list. Instead the Null_Record_Present flag is set in
+      --  the parent node for the NULL RECORD case.
+
+      ------------------------------------------------------
+      -- 4.3.1  Record Component Association (also 4.3.3) --
+      ------------------------------------------------------
+
+      --  RECORD_COMPONENT_ASSOCIATION ::=
+      --    [COMPONENT_CHOICE_LIST =>] EXPRESSION
+
+      --  N_Component_Association
+      --  Sloc points to first selector name
+      --  Choices (List1)
+      --  Loop_Actions (List2-Sem)
+      --  Expression (Node3)
+
+      --  Note: this structure is used for both record component associations
+      --  and array component associations, since the two cases aren't always
+      --  separable by the parser. The choices list may represent either a
+      --  list of selector names in the record aggregate case, or a list of
+      --  discrete choices in the array aggregate case or an N_Others_Choice
+      --  node (which appears as a singleton list).
+
+      ------------------------------------
+      --  4.3.1  Commponent Choice List --
+      ------------------------------------
+
+      --  COMPONENT_CHOICE_LIST ::=
+      --    component_SELECTOR_NAME {| component_SELECTOR_NAME}
+      --  | others
+
+      --  The entries of a component choice list appear in the Choices list
+      --  of the associated N_Component_Association, as either selector
+      --  names, or as an N_Others_Choice node.
+
+      --------------------------------
+      -- 4.3.2  Extension Aggregate --
+      --------------------------------
+
+      --  EXTENSION_AGGREGATE ::=
+      --    (ANCESTOR_PART with RECORD_COMPONENT_ASSOCIATION_LIST)
+
+      --  Note: extension aggregates are not permitted in Ada 83 mode
+
+      --  N_Extension_Aggregate
+      --  Sloc points to left parenthesis
+      --  Ancestor_Part (Node3)
+      --  Expressions (List1) (set to No_List if none or null record case)
+      --  Component_Associations (List2) (set to No_List if none)
+      --  Null_Record_Present (Flag17)
+      --  Expansion_Delayed (Flag11-Sem)
+      --  plus fields for expression
+
+      --------------------------
+      -- 4.3.2  Ancestor Part --
+      --------------------------
+
+      --  ANCESTOR_PART ::= EXPRESSION | SUBTYPE_MARK
+
+      ----------------------------
+      -- 4.3.3  Array Aggregate --
+      ----------------------------
+
+      --  ARRAY_AGGREGATE ::=
+      --    POSITIONAL_ARRAY_AGGREGATE | NAMED_ARRAY_AGGREGATE
+
+      ---------------------------------------
+      -- 4.3.3  Positional Array Aggregate --
+      ---------------------------------------
+
+      --  POSITIONAL_ARRAY_AGGREGATE ::=
+      --    (EXPRESSION, EXPRESSION {, EXPRESSION})
+      --  | (EXPRESSION {, EXPRESSION}, others => EXPRESSION)
+
+      --  See Record_Aggregate (4.3.1) for node structure
+
+      ----------------------------------
+      -- 4.3.3  Named Array Aggregate --
+      ----------------------------------
+
+      --  NAMED_ARRAY_AGGREGATE ::=
+      --  | (ARRAY_COMPONENT_ASSOCIATION {, ARRAY_COMPONENT_ASSOCIATION})
+
+      --  See Record_Aggregate (4.3.1) for node structure
+
+      ----------------------------------------
+      -- 4.3.3  Array Component Association --
+      ----------------------------------------
+
+      --  ARRAY_COMPONENT_ASSOCIATION ::=
+      --    DISCRETE_CHOICE_LIST => EXPRESSION
+
+      --  See Record_Component_Association (4.3.1) for node structure
+
+      --------------------------------------------------
+      -- 4.4  Expression/Relation/Term/Factor/Primary --
+      --------------------------------------------------
+
+      --  EXPRESSION ::=
+      --    RELATION {and RELATION} | RELATION {and then RELATION}
+      --  | RELATION {or RELATION}  | RELATION {or else RELATION}
+      --  | RELATION {xor RELATION}
+
+      --  RELATION ::=
+      --    SIMPLE_EXPRESSION [RELATIONAL_OPERATOR SIMPLE_EXPRESSION]
+      --  | SIMPLE_EXPRESSION [not] in RANGE
+      --  | SIMPLE_EXPRESSION [not] in SUBTYPE_MARK
+
+      --  SIMPLE_EXPRESSION ::=
+      --    [UNARY_ADDING_OPERATOR] TERM {BINARY_ADDING_OPERATOR TERM}
+
+      --  TERM ::= FACTOR {MULTIPLYING_OPERATOR FACTOR}
+
+      --  FACTOR ::= PRIMARY [** PRIMARY] | abs PRIMARY | not PRIMARY
+
+      --  No nodes are generated for any of these constructs. Instead, the
+      --  node for the operator appears directly. When we refer to an
+      --  expression in this description, we mean any of the possible
+      --  consistuent components of an expression (e.g. identifier is
+      --  an example of an expression).
+
+      ------------------
+      -- 4.4  Primary --
+      ------------------
+
+      --  PRIMARY ::=
+      --    NUMERIC_LITERAL  | null
+      --  | STRING_LITERAL   | AGGREGATE
+      --  | NAME             | QUALIFIED_EXPRESSION
+      --  | ALLOCATOR        | (EXPRESSION)
+
+      --  Usually there is no explicit node in the tree for primary. Instead
+      --  the constituent (e.g. AGGREGATE) appears directly. There are two
+      --  exceptions. First, there is an explicit node for a null primary.
+
+      --  N_Null
+      --  Sloc points to NULL
+      --  plus fields for expression
+
+      --  Second, the case of (EXPRESSION) is handled specially. Ada requires
+      --  that the parser keep track of which subexpressions are enclosed
+      --  in parentheses, and how many levels of parentheses are used. This
+      --  information is required for optimization purposes, and also for
+      --  some semantic checks (e.g. (((1))) in a procedure spec does not
+      --  conform with ((((1)))) in the body).
+
+      --  The parentheses are recorded by keeping a Paren_Count field in every
+      --  subexpression node (it is actually present in all nodes, but only
+      --  used in subexpression nodes). This count records the number of
+      --  levels of parentheses. If the number of levels in the source exceeds
+      --  the maximum accomodated by this count, then the count is simply left
+      --  at the maximum value. This means that there are some pathalogical
+      --  cases of failure to detect conformance failures (e.g. an expression
+      --  with 500 levels of parens will conform with one with 501 levels),
+      --  but we do not need to lose sleep over this.
+
+      --  Historical note: in versions of GNAT prior to 1.75, there was a node
+      --  type N_Parenthesized_Expression used to accurately record unlimited
+      --  numbers of levels of parentheses. However, it turned out to be a
+      --  real nuisance to have to take into account the possible presence of
+      --  this node during semantic analysis, since basically parentheses have
+      --  zero relevance to semantic analysis.
+
+      --  Note: the level of parentheses always present in things like
+      --  aggregates does not count, only the parentheses in the primary
+      --  (EXPRESSION) affect the setting of the Paren_Count field.
+
+      --  2nd Note: the contents of the Expression field must be ignored (i.e.
+      --  treated as though it were Empty) if No_Initialization is set True.
+
+      --------------------------------------
+      -- 4.5  Short Circuit Control Forms --
+      --------------------------------------
+
+      --  EXPRESSION ::=
+      --    RELATION {and then RELATION} | RELATION {or else RELATION}
+
+      --  Gigi restriction: For both these control forms, the operand and
+      --  result types are always Standard.Boolean. The expander inserts the
+      --  required conversion operations where needed to ensure this is the
+      --  case.
+
+      --  N_And_Then
+      --  Sloc points to AND of AND THEN
+      --  Left_Opnd (Node2)
+      --  Right_Opnd (Node3)
+      --  Actions (List1-Sem)
+      --  plus fields for expression
+
+      --  N_Or_Else
+      --  Sloc points to OR of OR ELSE
+      --  Left_Opnd (Node2)
+      --  Right_Opnd (Node3)
+      --  Actions (List1-Sem)
+      --  plus fields for expression
+
+      --  Note: The Actions field is used to hold actions associated with
+      --  the right hand operand. These have to be treated specially since
+      --  they are not unconditionally executed. See Insert_Actions for a
+      --  more detailed description of how these actions are handled.
+
+      ---------------------------
+      -- 4.5  Membership Tests --
+      ---------------------------
+
+      --  RELATION ::=
+      --    SIMPLE_EXPRESSION [not] in RANGE
+      --  | SIMPLE_EXPRESSION [not] in SUBTYPE_MARK
+
+      --  Note: although the grammar above allows only a range or a
+      --  subtype mark, the parser in fact will accept any simple
+      --  expression in place of a subtype mark. This means that the
+      --  semantic analyzer must be prepared to deal with, and diagnose
+      --  a simple expression other than a name for the right operand.
+      --  This simplifies error recovery in the parser.
+
+      --  N_In
+      --  Sloc points to IN
+      --  Left_Opnd (Node2)
+      --  Right_Opnd (Node3)
+      --  plus fields for expression
+
+      --  N_Not_In
+      --  Sloc points to NOT of NOT IN
+      --  Left_Opnd (Node2)
+      --  Right_Opnd (Node3)
+      --  plus fields for expression
+
+      --------------------
+      -- 4.5  Operators --
+      --------------------
+
+      --  LOGICAL_OPERATOR             ::=  and | or  | xor
+
+      --  RELATIONAL_OPERATOR          ::=  =   | /=  | <   | <= | > | >=
+
+      --  BINARY_ADDING_OPERATOR       ::=  +   |  -  | &
+
+      --  UNARY_ADDING_OPERATOR        ::=  +   |  -
+
+      --  MULTIPLYING_OPERATOR         ::=  *   |  /  | mod | rem
+
+      --  HIGHEST_PRECEDENCE_OPERATOR  ::=  **  | abs | not
+
+      --  Sprint syntax if Treat_Fixed_As_Integer is set:
+
+      --     x #* y
+      --     x #/ y
+      --     x #mod y
+      --     x #rem y
+
+      --  Gigi restriction: For * / mod rem with fixed-point operands, Gigi
+      --  will only be given nodes with the Treat_Fixed_As_Integer flag set.
+      --  All handling of smalls for multiplication and division is handled
+      --  by the front end (mod and rem result only from expansion). Gigi
+      --  thus never needs to worry about small values (for other operators
+      --  operating on fixed-point, e.g. addition, the small value does not
+      --  have any semantic effect anyway, these are always integer operations.
+
+      --  Gigi restriction: For all operators taking Boolean operands, the
+      --  type is always Standard.Boolean. The expander inserts the required
+      --  conversion operations where needed to ensure this is the case.
+
+      --  N_Op_And
+      --  Sloc points to AND
+      --  Do_Length_Check (Flag4-Sem)
+      --  plus fields for binary operator
+      --  plus fields for expression
+
+      --  N_Op_Or
+      --  Sloc points to OR
+      --  Do_Length_Check (Flag4-Sem)
+      --  plus fields for binary operator
+      --  plus fields for expression
+
+      --  N_Op_Xor
+      --  Sloc points to XOR
+      --  Do_Length_Check (Flag4-Sem)
+      --  plus fields for binary operator
+      --  plus fields for expression
+
+      --  N_Op_Eq
+      --  Sloc points to =
+      --  plus fields for binary operator
+      --  plus fields for expression
+
+      --  N_Op_Ne
+      --  Sloc points to /=
+      --  plus fields for binary operator
+      --  plus fields for expression
+
+      --  N_Op_Lt
+      --  Sloc points to <
+      --  plus fields for binary operator
+      --  plus fields for expression
+
+      --  N_Op_Le
+      --  Sloc points to <=
+      --  plus fields for binary operator
+      --  plus fields for expression
+
+      --  N_Op_Gt
+      --  Sloc points to >
+      --  plus fields for binary operator
+      --  plus fields for expression
+
+      --  N_Op_Ge
+      --  Sloc points to >=
+      --  plus fields for binary operator
+      --  plus fields for expression
+
+      --  N_Op_Add
+      --  Sloc points to + (binary)
+      --  plus fields for binary operator
+      --  plus fields for expression
+
+      --  N_Op_Subtract
+      --  Sloc points to - (binary)
+      --  plus fields for binary operator
+      --  plus fields for expression
+
+      --  N_Op_Concat
+      --  Sloc points to &
+      --  Is_Component_Left_Opnd (Flag13-Sem)
+      --  Is_Component_Right_Opnd (Flag14-Sem)
+      --  plus fields for binary operator
+      --  plus fields for expression
+
+      --  N_Op_Multiply
+      --  Sloc points to *
+      --  Treat_Fixed_As_Integer (Flag14-Sem)
+      --  Rounded_Result (Flag18-Sem)
+      --  plus fields for binary operator
+      --  plus fields for expression
+
+      --  N_Op_Divide
+      --  Sloc points to /
+      --  Treat_Fixed_As_Integer (Flag14-Sem)
+      --  Do_Division_Check (Flag13-Sem)
+      --  Rounded_Result (Flag18-Sem)
+      --  plus fields for binary operator
+      --  plus fields for expression
+
+      --  N_Op_Mod
+      --  Sloc points to MOD
+      --  Treat_Fixed_As_Integer (Flag14-Sem)
+      --  Do_Division_Check (Flag13-Sem)
+      --  plus fields for binary operator
+      --  plus fields for expression
+
+      --  N_Op_Rem
+      --  Sloc points to REM
+      --  Treat_Fixed_As_Integer (Flag14-Sem)
+      --  Do_Division_Check (Flag13-Sem)
+      --  plus fields for binary operator
+      --  plus fields for expression
+
+      --  N_Op_Expon
+      --  Is_Power_Of_2_For_Shift (Flag13-Sem)
+      --  Sloc points to **
+      --  plus fields for binary operator
+      --  plus fields for expression
+
+      --  N_Op_Plus
+      --  Sloc points to + (unary)
+      --  plus fields for unary operator
+      --  plus fields for expression
+
+      --  N_Op_Minus
+      --  Sloc points to - (unary)
+      --  plus fields for unary operator
+      --  plus fields for expression
+
+      --  N_Op_Abs
+      --  Sloc points to ABS
+      --  plus fields for unary operator
+      --  plus fields for expression
+
+      --  N_Op_Not
+      --  Sloc points to NOT
+      --  plus fields for unary operator
+      --  plus fields for expression
+
+      --  See also shift operators in section B.2
+
+      --  Note on fixed-point operations passed to Gigi: For adding operators,
+      --  the semantics is to treat these simply as integer operations, with
+      --  the small values being ignored (the bounds are already stored in
+      --  units of small, so that constraint checking works as usual). For the
+      --  case of multiply/divide/rem/mod operations, Gigi will only see fixed
+      --  point operands if the Treat_Fixed_As_Integer flag is set and will
+      --  thus treat these nodes in identical manner, ignoring small values.
+
+      --------------------------
+      -- 4.6  Type Conversion --
+      --------------------------
+
+      --  TYPE_CONVERSION ::=
+      --    SUBTYPE_MARK (EXPRESSION) | SUBTYPE_MARK (NAME)
+
+      --  In the (NAME) case, the name is stored as the expression
+
+      --  Note: the parser never generates a type conversion node, since it
+      --  looks like an indexed component which is generated by preference.
+      --  The semantic pass must correct this misidentification.
+
+      --  Gigi handles conversions that involve no change in the root type,
+      --  and also all conversions from integer to floating-point types.
+      --  Conversions from floating-point to integer are only handled in
+      --  the case where Float_Truncate flag set. Other conversions from
+      --  floating-point to integer (involving rounding) and all conversions
+      --  involving fixed-point types are handled by the expander.
+
+      --  Sprint syntax if Float_Truncate set: X^(Y)
+      --  Sprint syntax if Conversion_OK set X?(Y)
+      --  Sprint syntax if both flags set X?^(Y)
+
+      --  Note: If either the operand or result type is fixed-point, Gigi will
+      --  only see a type conversion node with Conversion_OK set. The front end
+      --  takes care of all handling of small's for fixed-point conversions.
+
+      --  N_Type_Conversion
+      --  Sloc points to first token of subtype mark
+      --  Subtype_Mark (Node4)
+      --  Expression (Node3)
+      --  Do_Overflow_Check (Flag17-Sem)
+      --  Do_Tag_Check (Flag13-Sem)
+      --  Do_Length_Check (Flag4-Sem)
+      --  Float_Truncate (Flag11-Sem)
+      --  Rounded_Result (Flag18-Sem)
+      --  Conversion_OK (Flag14-Sem)
+      --  plus fields for expression
+
+      --  Note: if a range check is required, then the Do_Range_Check flag
+      --  is set in the Expression with the check being done against the
+      --  target type range (after the base type conversion, if any).
+
+      -------------------------------
+      -- 4.7  Qualified Expression --
+      -------------------------------
+
+      --  QUALIFIED_EXPRESSION ::=
+      --    SUBTYPE_MARK ' (EXPRESSION) | SUBTYPE_MARK ' AGGREGATE
+
+      --  Note: the parentheses in the (EXPRESSION) case are deemed to enclose
+      --  the expression, so the Expression field of this node always points
+      --  to a parenthesized expression in this case (i.e. Paren_Count will
+      --  always be non-zero for the referenced expression if it is not an
+      --  aggregate).
+
+      --  N_Qualified_Expression
+      --  Sloc points to apostrophe
+      --  Subtype_Mark (Node4)
+      --  Expression (Node3) expression or aggregate
+      --  plus fields for expression
+
+      --------------------
+      -- 4.8  Allocator --
+      --------------------
+
+      --  ALLOCATOR ::=
+      --    new SUBTYPE_INDICATION | new QUALIFIED_EXPRESSION
+
+      --  Sprint syntax (when storage pool present)
+      --    new xxx (storage_pool = pool)
+
+      --  N_Allocator
+      --  Sloc points to NEW
+      --  Expression (Node3) subtype indication or qualified expression
+      --  Storage_Pool (Node1-Sem)
+      --  Procedure_To_Call (Node4-Sem)
+      --  No_Initialization (Flag13-Sem)
+      --  Do_Storage_Check (Flag17-Sem)
+      --  plus fields for expression
+
+      ---------------------------------
+      -- 5.1  Sequence Of Statements --
+      ---------------------------------
+
+      --  SEQUENCE_OF_STATEMENTS ::= STATEMENT {STATEMENT}
+
+      --  Note: Although the parser will not accept a declaration as a
+      --  statement, the semantic analyzer may insert declarations (e.g.
+      --  declarations of implicit types needed for execution of other
+      --  statements) into a sequence of statements, so the code genmerator
+      --  should be prepared to accept a declaration where a statement is
+      --  expected. Note also that pragmas can appear as statements.
+
+      --------------------
+      -- 5.1  Statement --
+      --------------------
+
+      --  STATEMENT ::=
+      --    {LABEL} SIMPLE_STATEMENT | {LABEL} COMPOUND_STATEMENT
+
+      --  There is no explicit node in the tree for a statement. Instead, the
+      --  individual statement appears directly. Labels are treated  as a
+      --  kind of statement, i.e. they are linked into a statement list at
+      --  the point they appear, so the labeled statement appears following
+      --  the label or labels in the statement list.
+
+      ---------------------------
+      -- 5.1  Simple Statement --
+      ---------------------------
+
+      --  SIMPLE_STATEMENT ::=      NULL_STATEMENT
+      --  | ASSIGNMENT_STATEMENT  | EXIT_STATEMENT
+      --  | GOTO_STATEMENT        | PROCEDURE_CALL_STATEMENT
+      --  | RETURN_STATEMENT      | ENTRY_CALL_STATEMENT
+      --  | REQUEUE_STATEMENT     | DELAY_STATEMENT
+      --  | ABORT_STATEMENT       | RAISE_STATEMENT
+      --  | CODE_STATEMENT
+
+      -----------------------------
+      -- 5.1  Compound Statement --
+      -----------------------------
+
+      --  COMPOUND_STATEMENT ::=
+      --    IF_STATEMENT         | CASE_STATEMENT
+      --  | LOOP_STATEMENT       | BLOCK_STATEMENT
+      --  | ACCEPT_STATEMENT     | SELECT_STATEMENT
+
+      -------------------------
+      -- 5.1  Null Statement --
+      -------------------------
+
+      --  NULL_STATEMENT ::= null;
+
+      --  N_Null_Statement
+      --  Sloc points to NULL
+
+      ----------------
+      -- 5.1  Label --
+      ----------------
+
+      --  LABEL ::= <<label_STATEMENT_IDENTIFIER>>
+
+      --  Note that the occurrence of a label is not a defining identifier,
+      --  but rather a referencing occurrence. The defining occurrence is
+      --  in the implicit label declaration which occurs in the innermost
+      --  enclosing block.
+
+      --  N_Label
+      --  Sloc points to <<
+      --  Identifier (Node1) direct name of statement identifier
+      --  Exception_Junk (Flag11-Sem)
+
+      -------------------------------
+      -- 5.1  Statement Identifier --
+      -------------------------------
+
+      --  STATEMENT_INDENTIFIER ::= DIRECT_NAME
+
+      --  The IDENTIFIER of a STATEMENT_IDENTIFIER shall be an identifier
+      --  (not an OPERATOR_SYMBOL)
+
+      -------------------------------
+      -- 5.2  Assignment Statement --
+      -------------------------------
+
+      --  ASSIGNMENT_STATEMENT ::=
+      --    variable_NAME := EXPRESSION;
+
+      --  N_Assignment_Statement
+      --  Sloc points to :=
+      --  Name (Node2)
+      --  Expression (Node3)
+      --  Do_Tag_Check (Flag13-Sem)
+      --  Do_Length_Check (Flag4-Sem)
+      --  Forwards_OK (Flag5-Sem)
+      --  Backwards_OK (Flag6-Sem)
+      --  No_Ctrl_Actions (Flag7-Sem)
+
+      --  Note: if a range check is required, then the Do_Range_Check flag
+      --  is set in the Expression (right hand side), with the check being
+      --  done against the type of the Name (left hand side).
+
+      -----------------------
+      -- 5.3  If Statement --
+      -----------------------
+
+      --  IF_STATEMENT ::=
+      --    if CONDITION then
+      --      SEQUENCE_OF_STATEMENTS
+      --    {elsif CONDITION then
+      --      SEQUENCE_OF_STATEMENTS}
+      --    [else
+      --      SEQUENCE_OF_STATEMENTS]
+      --    end if;
+
+      --  Gigi restriction: This expander ensures that the type of the
+      --  Condition fields is always Standard.Boolean, even if the type
+      --  in the source is some non-standard boolean type.
+
+      --  N_If_Statement
+      --  Sloc points to IF
+      --  Condition (Node1)
+      --  Then_Statements (List2)
+      --  Elsif_Parts (List3) (set to No_List if none present)
+      --  Else_Statements (List4) (set to No_List if no else part present)
+      --  End_Span (Uint5) (set to No_Uint if expander generated)
+
+      --  N_Elsif_Part
+      --  Sloc points to ELSIF
+      --  Condition (Node1)
+      --  Then_Statements (List2)
+      --  Condition_Actions (List3-Sem)
+
+      --------------------
+      -- 5.3  Condition --
+      --------------------
+
+      --  CONDITION ::= boolean_EXPRESSION
+
+      -------------------------
+      -- 5.4  Case Statement --
+      -------------------------
+
+      --  CASE_STATEMENT ::=
+      --    case EXPRESSION is
+      --      CASE_STATEMENT_ALTERNATIVE
+      --      {CASE_STATEMENT_ALTERNATIVE}
+      --    end case;
+
+      --  Note: the Alternatives can contain pragmas. These only occur at
+      --  the start of the list, since any pragmas occurring after the first
+      --  alternative are absorbed into the corresponding statement sequence.
+
+      --  N_Case_Statement
+      --  Sloc points to CASE
+      --  Expression (Node3)
+      --  Alternatives (List4)
+      --  End_Span (Uint5) (set to No_Uint if expander generated)
+
+      -------------------------------------
+      -- 5.4  Case Statement Alternative --
+      -------------------------------------
+
+      --  CASE_STATEMENT_ALTERNATIVE ::=
+      --    when DISCRETE_CHOICE_LIST =>
+      --      SEQUENCE_OF_STATEMENTS
+
+      --  N_Case_Statement_Alternative
+      --  Sloc points to WHEN
+      --  Discrete_Choices (List4)
+      --  Statements (List3)
+
+      -------------------------
+      -- 5.5  Loop Statement --
+      -------------------------
+
+      --  LOOP_STATEMENT ::=
+      --    [loop_STATEMENT_IDENTIFIER :]
+      --      [ITERATION_SCHEME] loop
+      --        SEQUENCE_OF_STATEMENTS
+      --      end loop [loop_IDENTIFIER];
+
+      --  Note: The occurrence of a loop label is not a defining identifier
+      --  but rather a referencing occurrence. The defining occurrence is in
+      --  the implicit label declaration which occurs in the innermost
+      --  enclosing block.
+
+      --  Note: there is always a loop statement identifier present in
+      --  the tree, even if none was given in the source. In the case where
+      --  no loop identifier is given in the source, the parser creates
+      --  a name of the form _Loop_n, where n is a decimal integer (the
+      --  two underlines ensure that the loop names created in this manner
+      --  do not conflict with any user defined identifiers), and the flag
+      --  Has_Created_Identifier is set to True. The only exception to the
+      --  rule that all loop statement nodes have identifiers occurs for
+      --  loops constructed by the expander, and the semantic analyzer will
+      --  create and supply dummy loop identifiers in these cases.
+
+      --  N_Loop_Statement
+      --  Sloc points to LOOP
+      --  Identifier (Node1) loop identifier (set to Empty if no identifier)
+      --  Iteration_Scheme (Node2) (set to Empty if no iteration scheme)
+      --  Statements (List3)
+      --  End_Label (Node4)
+      --  Has_Created_Identifier (Flag15)
+
+      --------------------------
+      -- 5.5 Iteration Scheme --
+      --------------------------
+
+      --  ITERATION_SCHEME ::=
+      --    while CONDITION | for LOOP_PARAMETER_SPECIFICATION
+
+      --  Gigi restriction: This expander ensures that the type of the
+      --  Condition field is always Standard.Boolean, even if the type
+      --  in the source is some non-standard boolean type.
+
+      --  N_Iteration_Scheme
+      --  Sloc points to WHILE or FOR
+      --  Condition (Node1) (set to Empty if FOR case)
+      --  Condition_Actions (List3-Sem)
+      --  Loop_Parameter_Specification (Node4) (set to Empty if WHILE case)
+
+      ---------------------------------------
+      -- 5.5  Loop parameter specification --
+      ---------------------------------------
+
+      --  LOOP_PARAMETER_SPECIFICATION ::=
+      --    DEFINING_IDENTIFIER in [reverse] DISCRETE_SUBTYPE_DEFINITION
+
+      --  N_Loop_Parameter_Specification
+      --  Sloc points to first identifier
+      --  Defining_Identifier (Node1)
+      --  Reverse_Present (Flag15)
+      --  Discrete_Subtype_Definition (Node4)
+
+      --------------------------
+      -- 5.6  Block Statement --
+      --------------------------
+
+      --  BLOCK_STATEMENT ::=
+      --    [block_STATEMENT_IDENTIFIER:]
+      --      [declare
+      --        DECLARATIVE_PART]
+      --      begin
+      --        HANDLED_SEQUENCE_OF_STATEMENTS
+      --      end [block_IDENTIFIER];
+
+      --  Note that the occurrence of a block identifier is not a defining
+      --  identifier, but rather a referencing occurrence. The defining
+      --  occurrence is in the implicit label declaration which occurs in
+      --  the innermost enclosing block.
+
+      --  Note: there is always a block statement identifier present in
+      --  the tree, even if none was given in the source. In the case where
+      --  no block identifier is given in the source, the parser creates
+      --  a name of the form _Block_n, where n is a decimal integer (the
+      --  two underlines ensure that the block names created in this manner
+      --  do not conflict with any user defined identifiers), and the flag
+      --  Has_Created_Identifier is set to True. The only exception to the
+      --  rule that all loop statement nodes have identifiers occurs for
+      --  blocks constructed by the expander, and the semantic analyzer
+      --  creates and supplies dummy names for the blocks).
+
+      --  N_Block_Statement
+      --  Sloc points to DECLARE or BEGIN
+      --  Identifier (Node1) block direct name (set to Empty if not present)
+      --  Declarations (List2) (set to No_List if no DECLARE part)
+      --  Handled_Statement_Sequence (Node4)
+      --  Is_Task_Master (Flag5-Sem)
+      --  Activation_Chain_Entity (Node3-Sem)
+      --  Has_Created_Identifier (Flag15)
+      --  Is_Task_Allocation_Block (Flag6)
+      --  Is_Asynchronous_Call_Block (Flag7)
+
+      -------------------------
+      -- 5.7  Exit Statement --
+      -------------------------
+
+      --  EXIT_STATEMENT ::= exit [loop_NAME] [when CONDITION];
+
+      --  Gigi restriction: This expander ensures that the type of the
+      --  Condition field is always Standard.Boolean, even if the type
+      --  in the source is some non-standard boolean type.
+
+      --  N_Exit_Statement
+      --  Sloc points to EXIT
+      --  Name (Node2) (set to Empty if no loop name present)
+      --  Condition (Node1) (set to Empty if no when part present)
+
+      -------------------------
+      -- 5.9  Goto Statement --
+      -------------------------
+
+      --  GOTO_STATEMENT ::= goto label_NAME;
+
+      --  N_Goto_Statement
+      --  Sloc points to GOTO
+      --  Name (Node2)
+      --  Exception_Junk (Flag11-Sem)
+
+      ---------------------------------
+      -- 6.1  Subprogram Declaration --
+      ---------------------------------
+
+      --  SUBPROGRAM_DECLARATION ::= SUBPROGRAM_SPECIFICATION;
+
+      --  N_Subprogram_Declaration
+      --  Sloc points to FUNCTION or PROCEDURE
+      --  Specification (Node1)
+      --  Body_To_Inline (Node3-Sem)
+      --  Corresponding_Body (Node5-Sem)
+      --  Parent_Spec (Node4-Sem)
+
+      ------------------------------------------
+      -- 6.1  Abstract Subprogram Declaration --
+      ------------------------------------------
+
+      --  ABSTRACT_SUBPROGRAM_DECLARATION ::=
+      --    SUBPROGRAM_SPECIFICATION is abstract;
+
+      --  N_Abstract_Subprogram_Declaration
+      --  Sloc points to ABSTRACT
+      --  Specification (Node1)
+
+      -----------------------------------
+      -- 6.1  Subprogram Specification --
+      -----------------------------------
+
+      --  SUBPROGRAM_SPECIFICATION ::=
+      --    procedure DEFINING_PROGRAM_UNIT_NAME PARAMETER_PROFILE
+      --  | function DEFINING_DESIGNATOR PARAMETER_AND_RESULT_PROFILE
+
+      --  Note: there are no separate nodes for the profiles, instead the
+      --  information appears directly in the following nodes.
+
+      --  N_Function_Specification
+      --  Sloc points to FUNCTION
+      --  Defining_Unit_Name (Node1) (the designator)
+      --  Elaboration_Boolean (Node2-Sem)
+      --  Parameter_Specifications (List3) (set to No_List if no formal part)
+      --  Subtype_Mark (Node4) for return type
+      --  Generic_Parent (Node5-Sem)
+
+      --  N_Procedure_Specification
+      --  Sloc points to PROCEDURE
+      --  Defining_Unit_Name (Node1)
+      --  Elaboration_Boolean (Node2-Sem)
+      --  Parameter_Specifications (List3) (set to No_List if no formal part)
+      --  Generic_Parent (Node5-Sem)
+
+      ---------------------
+      -- 6.1  Designator --
+      ---------------------
+
+      --  DESIGNATOR ::=
+      --    [PARENT_UNIT_NAME .] IDENTIFIER | OPERATOR_SYMBOL
+
+      --  Designators that are simply identifiers or operator symbols appear
+      --  directly in the tree in this form. The following node is used only
+      --  in the case where the designator has a parent unit name component.
+
+      --  N_Designator
+      --  Sloc points to period
+      --  Name (Node2) holds the parent unit name. Note that this is always
+      --   non-Empty, since this node is only used for the case where a
+      --   parent library unit package name is present.
+      --  Identifier (Node1)
+
+      --  Note that the identifier can also be an operator symbol here.
+
+      ------------------------------
+      -- 6.1  Defining Designator --
+      ------------------------------
+
+      --  DEFINING_DESIGNATOR ::=
+      --    DEFINING_PROGRAM_UNIT_NAME | DEFINING_OPERATOR_SYMBOL
+
+      -------------------------------------
+      -- 6.1  Defining Program Unit Name --
+      -------------------------------------
+
+      --  DEFINING_PROGRAM_UNIT_NAME ::=
+      --    [PARENT_UNIT_NAME .] DEFINING_IDENTIFIER
+
+      --  The parent unit name is present only in the case of a child unit
+      --  name (permissible only for Ada 95 for a library level unit, i.e.
+      --  a unit at scope level one). If no such name is present, the defining
+      --  program unit name is represented simply as the defining identifier.
+      --  In the child unit case, the following node is used to represent the
+      --  child unit name.
+
+      --  N_Defining_Program_Unit_Name
+      --  Sloc points to period
+      --  Name (Node2) holds the parent unit name. Note that this is always
+      --   non-Empty, since this node is only used for the case where a
+      --   parent unit name is present.
+      --  Defining_Identifier (Node1)
+
+      --------------------------
+      -- 6.1  Operator Symbol --
+      --------------------------
+
+      --  OPERATOR_SYMBOL ::= STRING_LITERAL
+
+      --  Note: the fields of the N_Operator_Symbol node are laid out to
+      --  match the corresponding fields of an N_Character_Literal node. This
+      --  allows easy conversion of the operator symbol node into a character
+      --  literal node in the case where a string constant of the form of an
+      --  operator symbol is scanned out as such, but turns out semantically
+      --  to be a string literal that is not an operator. For details see
+      --  Sinfo.CN.Change_Operator_Symbol_To_String_Literal.
+
+      --  N_Operator_Symbol
+      --  Sloc points to literal
+      --  Chars (Name1) contains the Name_Id for the operator symbol
+      --  Strval (Str3) Id of string value. This is used if the operator
+      --   symbol turns out to be a normal string after all.
+      --  Entity (Node4-Sem)
+      --  Has_Private_View (Flag11-Sem) set in generic units.
+      --  Etype (Node5-Sem)
+
+      --  Note: the Strval field may be set to No_String for generated
+      --  operator symbols that are known not to be string literals
+      --  semantically.
+
+      -----------------------------------
+      -- 6.1  Defining Operator Symbol --
+      -----------------------------------
+
+      --  DEFINING_OPERATOR_SYMBOL ::= OPERATOR_SYMBOL
+
+      --  A defining operator symbol is an entity, which has additional
+      --  fields depending on the setting of the Ekind field. These
+      --  additional fields are defined (and access subprograms declared)
+      --  in package Einfo.
+
+      --  Note: N_Defining_Operator_Symbol is an extended node whose fields
+      --  are deliberately layed out to match the layout of fields in an
+      --  ordinary N_Operator_Symbol node allowing for easy alteration of
+      --  an operator symbol node into a defining operator symbol node.
+      --  See Sinfo.CN.Change_Operator_Symbol_To_Defining_Operator_Symbol
+      --  for further details.
+
+      --  N_Defining_Operator_Symbol
+      --  Sloc points to literal
+      --  Chars (Name1) contains the Name_Id for the operator symbol
+      --  Next_Entity (Node2-Sem)
+      --  Scope (Node3-Sem)
+      --  Etype (Node5-Sem)
+
+      ----------------------------
+      -- 6.1  Parameter Profile --
+      ----------------------------
+
+      --  PARAMETER_PROFILE ::= [FORMAL_PART]
+
+      ---------------------------------------
+      -- 6.1  Parameter and Result Profile --
+      ---------------------------------------
+
+      --  PARAMETER_AND_RESULT_PROFILE ::= [FORMAL_PART] return SUBTYPE_MARK
+
+      --  There is no explicit node in the tree for a parameter and result
+      --  profile. Instead the information appears directly in the parent.
+
+      ----------------------
+      -- 6.1  Formal part --
+      ----------------------
+
+      --  FORMAL_PART ::=
+      --    (PARAMETER_SPECIFICATION {; PARAMETER_SPECIFICATION})
+
+      ----------------------------------
+      -- 6.1  Parameter specification --
+      ----------------------------------
+
+      --  PARAMETER_SPECIFICATION ::=
+      --    DEFINING_IDENTIFIER_LIST : MODE SUBTYPE_MARK
+      --      [:= DEFAULT_EXPRESSION]
+      --  | DEFINING_IDENTIFIER_LIST : ACCESS_DEFINITION
+      --      [:= DEFAULT_EXPRESSION]
+
+      --  Although the syntax allows multiple identifiers in the list, the
+      --  semantics is as though successive specifications were given with
+      --  identical type definition and expression components. To simplify
+      --  semantic processing, the parser represents a multiple declaration
+      --  case as a sequence of single Specifications, using the More_Ids and
+      --  Prev_Ids flags to preserve the original source form as described
+      --  in the section on "Handling of Defining Identifier Lists".
+
+      --  N_Parameter_Specification
+      --  Sloc points to first identifier
+      --  Defining_Identifier (Node1)
+      --  In_Present (Flag15)
+      --  Out_Present (Flag17)
+      --  Parameter_Type (Node2) subtype mark or access definition
+      --  Expression (Node3) (set to Empty if no default expression present)
+      --  Do_Accessibility_Check (Flag13-Sem)
+      --  More_Ids (Flag5) (set to False if no more identifiers in list)
+      --  Prev_Ids (Flag6) (set to False if no previous identifiers in list)
+      --  Default_Expression (Node5-Sem)
+
+      ---------------
+      -- 6.1  Mode --
+      ---------------
+
+      --  MODE ::= [in] | in out | out
+
+      --  There is no explicit node in the tree for the Mode. Instead the
+      --  In_Present and Out_Present flags are set in the parent node to
+      --  record the presence of keywords specifying the mode.
+
+      --------------------------
+      -- 6.3  Subprogram Body --
+      --------------------------
+
+      --  SUBPROGRAM_BODY ::=
+      --    SUBPROGRAM_SPECIFICATION is
+      --      DECLARATIVE_PART
+      --    begin
+      --      HANDLED_SEQUENCE_OF_STATEMENTS
+      --    end [DESIGNATOR];
+
+      --  N_Subprogram_Body
+      --  Sloc points to FUNCTION or PROCEDURE
+      --  Specification (Node1)
+      --  Declarations (List2)
+      --  Handled_Statement_Sequence (Node4)
+      --  Activation_Chain_Entity (Node3-Sem)
+      --  Corresponding_Spec (Node5-Sem)
+      --  Acts_As_Spec (Flag4-Sem)
+      --  Bad_Is_Detected (Flag15) used only by parser
+      --  Do_Storage_Check (Flag17-Sem)
+      --  Has_Priority_Pragma (Flag6-Sem)
+      --  Is_Protected_Subprogram_Body (Flag7-Sem)
+      --  Is_Task_Master (Flag5-Sem)
+      --  Was_Originally_Stub (Flag13-Sem)
+
+      -----------------------------------
+      -- 6.4  Procedure Call Statement --
+      -----------------------------------
+
+      --  PROCEDURE_CALL_STATEMENT ::=
+      --    procedure_NAME; | procedure_PREFIX ACTUAL_PARAMETER_PART;
+
+      --  Note: the reason that a procedure call has expression fields is
+      --  that it semantically resembles an expression, e.g. overloading is
+      --  allowed and a type is concocted for semantic processing purposes.
+      --  Certain of these fields, such as Parens are not relevant, but it
+      --  is easier to just supply all of them together!
+
+      --  N_Procedure_Call_Statement
+      --  Sloc points to first token of name or prefix
+      --  Name (Node2) stores name or prefix
+      --  Parameter_Associations (List3) (set to No_List if no
+      --   actual parameter part)
+      --  First_Named_Actual (Node4-Sem)
+      --  Controlling_Argument (Node1-Sem) (set to Empty if not dispatching)
+      --  Do_Tag_Check (Flag13-Sem)
+      --  Parameter_List_Truncated (Flag17-Sem)
+      --  ABE_Is_Certain (Flag18-Sem)
+      --  plus fields for expression
+
+      --  If any IN parameter requires a range check, then the corresponding
+      --  argument expression has the Do_Range_Check flag set, and the range
+      --  check is done against the formal type. Note that this argument
+      --  expression may appear directly in the Parameter_Associations list,
+      --  or may be a descendent of an N_Parameter_Association node that
+      --  appears in this list.
+
+      ------------------------
+      -- 6.4  Function Call --
+      ------------------------
+
+      --  FUNCTION_CALL ::=
+      --    function_NAME | function_PREFIX ACTUAL_PARAMETER_PART
+
+      --  Note: the parser may generate an indexed component node or simply
+      --  a name node instead of a function call node. The semantic pass must
+      --  correct this misidentification.
+
+      --  N_Function_Call
+      --  Sloc points to first token of name or prefix
+      --  Name (Node2) stores name or prefix
+      --  Parameter_Associations (List3) (set to No_List if no
+      --   actual parameter part)
+      --  First_Named_Actual (Node4-Sem)
+      --  Controlling_Argument (Node1-Sem) (set to Empty if not dispatching)
+      --  Do_Tag_Check (Flag13-Sem)
+      --  Parameter_List_Truncated (Flag17-Sem)
+      --  ABE_Is_Certain (Flag18-Sem)
+      --  plus fields for expression
+
+      --------------------------------
+      -- 6.4  Actual Parameter Part --
+      --------------------------------
+
+      --  ACTUAL_PARAMETER_PART ::=
+      --    (PARAMETER_ASSOCIATION {,PARAMETER_ASSOCIATION})
+
+      --------------------------------
+      -- 6.4  Parameter Association --
+      --------------------------------
+
+      --  PARAMETER_ASSOCIATION ::=
+      --    [formal_parameter_SELECTOR_NAME =>] EXPLICIT_ACTUAL_PARAMETER
+
+      --  Note: the N_Parameter_Association node is built only if a formal
+      --  parameter selector name is present, otherwise the parameter
+      --  association appears in the tree simply as the node for the
+      --  explicit actual parameter.
+
+      --  N_Parameter_Association
+      --  Sloc points to formal parameter
+      --  Selector_Name (Node2) (always non-Empty, since this node is
+      --   only used if a formal parameter selector name is present)
+      --  Explicit_Actual_Parameter (Node3)
+      --  Next_Named_Actual (Node4-Sem)
+
+      ---------------------------
+      -- 6.4  Actual Parameter --
+      ---------------------------
+
+      --  EXPLICIT_ACTUAL_PARAMETER ::= EXPRESSION | variable_NAME
+
+      ---------------------------
+      -- 6.5  Return Statement --
+      ---------------------------
+
+      --  RETURN_STATEMENT ::= return [EXPRESSION];
+
+      --  N_Return_Statement
+      --  Sloc points to RETURN
+      --  Expression (Node3) (set to Empty if no expression present)
+      --  Storage_Pool (Node1-Sem)
+      --  Procedure_To_Call (Node4-Sem)
+      --  Do_Tag_Check (Flag13-Sem)
+      --  Return_Type (Node2-Sem)
+      --  By_Ref (Flag5-Sem)
+
+      --  Note: if a range check is required, then Do_Range_Check is set
+      --  on the Expression. The range check is against Return_Type.
+
+      ------------------------------
+      -- 7.1  Package Declaration --
+      ------------------------------
+
+      --  PACKAGE_DECLARATION ::= PACKAGE_SPECIFICATION;
+
+      --  Note: the activation chain entity for a package spec is used for
+      --  all tasks declared in the package spec, or in the package body.
+
+      --  N_Package_Declaration
+      --  Sloc points to PACKAGE
+      --  Specification (Node1)
+      --  Corresponding_Body (Node5-Sem)
+      --  Parent_Spec (Node4-Sem)
+      --  Activation_Chain_Entity (Node3-Sem)
+
+      --------------------------------
+      -- 7.1  Package Specification --
+      --------------------------------
+
+      --  PACKAGE_SPECIFICATION ::=
+      --    package DEFINING_PROGRAM_UNIT_NAME is
+      --      {BASIC_DECLARATIVE_ITEM}
+      --    [private
+      --      {BASIC_DECLARATIVE_ITEM}]
+      --    end [[PARENT_UNIT_NAME .] IDENTIFIER]
+
+      --  N_Package_Specification
+      --  Sloc points to PACKAGE
+      --  Defining_Unit_Name (Node1)
+      --  Visible_Declarations (List2)
+      --  Private_Declarations (List3) (set to No_List if no private
+      --   part present)
+      --  End_Label (Node4)
+      --  Generic_Parent (Node5-Sem)
+
+      -----------------------
+      -- 7.1  Package Body --
+      -----------------------
+
+      --  PACKAGE_BODY ::=
+      --    package body DEFINING_PROGRAM_UNIT_NAME is
+      --      DECLARATIVE_PART
+      --    [begin
+      --      HANDLED_SEQUENCE_OF_STATEMENTS]
+      --    end [[PARENT_UNIT_NAME .] IDENTIFIER];
+
+      --  N_Package_Body
+      --  Sloc points to PACKAGE
+      --  Defining_Unit_Name (Node1)
+      --  Declarations (List2)
+      --  Handled_Statement_Sequence (Node4) (set to Empty if no HSS present)
+      --  Corresponding_Spec (Node5-Sem)
+      --  Was_Originally_Stub (Flag13-Sem)
+
+      --  Note: if a source level package does not contain a handled sequence
+      --  of statements, then the parser supplies a dummy one with a null
+      --  sequence of statements. Comes_From_Source will be False in this
+      --  constructed sequence. The reason we need this is for the End_Label
+      --  field in the HSS.
+
+      -----------------------------------
+      -- 7.4  Private Type Declaration --
+      -----------------------------------
+
+      --  PRIVATE_TYPE_DECLARATION ::=
+      --    type DEFINING_IDENTIFIER [DISCRIMINANT_PART]
+      --      is [[abstract] tagged] [limited] private;
+
+      --  Note: TAGGED is not permitted in Ada 83 mode
+
+      --  N_Private_Type_Declaration
+      --  Sloc points to TYPE
+      --  Defining_Identifier (Node1)
+      --  Discriminant_Specifications (List4) (set to No_List if no
+      --   discriminant part)
+      --  Unknown_Discriminants_Present (Flag13) set if (<>) discriminant
+      --  Abstract_Present (Flag4)
+      --  Tagged_Present (Flag15)
+      --  Limited_Present (Flag17)
+
+      ----------------------------------------
+      -- 7.4  Private Extension Declaration --
+      ----------------------------------------
+
+      --  PRIVATE_EXTENSION_DECLARATION ::=
+      --    type DEFINING_IDENTIFIER [DISCRIMINANT_PART] is
+      --      [abstract] new ancestor_SUBTYPE_INDICATION with private;
+
+      --  Note: private extension declarations are not allowed in Ada 83 mode
+
+      --  N_Private_Extension_Declaration
+      --  Sloc points to TYPE
+      --  Defining_Identifier (Node1)
+      --  Discriminant_Specifications (List4) (set to No_List if no
+      --   discriminant part)
+      --  Unknown_Discriminants_Present (Flag13) set if (<>) discriminant
+      --  Abstract_Present (Flag4)
+      --  Subtype_Indication (Node5)
+
+      ---------------------
+      -- 8.4  Use Clause --
+      ---------------------
+
+      --  USE_CLAUSE ::= USE_PACKAGE_CLAUSE | USE_TYPE_CLAUSE
+
+      -----------------------------
+      -- 8.4  Use Package Clause --
+      -----------------------------
+
+      --  USE_PACKAGE_CLAUSE ::= use package_NAME {, package_NAME};
+
+      --  N_Use_Package_Clause
+      --  Sloc points to USE
+      --  Names (List2)
+      --  Next_Use_Clause (Node3-Sem)
+      --  Hidden_By_Use_Clause (Elist4-Sem)
+
+      --------------------------
+      -- 8.4  Use Type Clause --
+      --------------------------
+
+      --  USE_TYPE_CLAUSE ::= use type SUBTYPE_MARK {, SUBTYPE_MARK};
+
+      --  Note: use type clause is not permitted in Ada 83 mode
+
+      --  N_Use_Type_Clause
+      --  Sloc points to USE
+      --  Subtype_Marks (List2)
+      --  Next_Use_Clause (Node3-Sem)
+      --  Hidden_By_Use_Clause (Elist4-Sem)
+
+      -------------------------------
+      -- 8.5  Renaming Declaration --
+      -------------------------------
+
+      --  RENAMING_DECLARATION ::=
+      --    OBJECT_RENAMING_DECLARATION
+      --  | EXCEPTION_RENAMING_DECLARATION
+      --  | PACKAGE_RENAMING_DECLARATION
+      --  | SUBPROGRAM_RENAMING_DECLARATION
+      --  | GENERIC_RENAMING_DECLARATION
+
+      --------------------------------------
+      -- 8.5  Object Renaming Declaration --
+      --------------------------------------
+
+      --  OBJECT_RENAMING_DECLARATION ::=
+      --    DEFINING_IDENTIFIER : SUBTYPE_MARK renames object_NAME;
+
+      --  N_Object_Renaming_Declaration
+      --  Sloc points to first identifier
+      --  Defining_Identifier (Node1)
+      --  Subtype_Mark (Node4)
+      --  Name (Node2)
+      --  Corresponding_Generic_Association (Node5-Sem)
+
+      -----------------------------------------
+      -- 8.5  Exception Renaming Declaration --
+      -----------------------------------------
+
+      --  EXCEPTION_RENAMING_DECLARATION ::=
+      --    DEFINING_IDENTIFIER : exception renames exception_NAME;
+
+      --  N_Exception_Renaming_Declaration
+      --  Sloc points to first identifier
+      --  Defining_Identifier (Node1)
+      --  Name (Node2)
+
+      ---------------------------------------
+      -- 8.5  Package Renaming Declaration --
+      ---------------------------------------
+
+      --  PACKAGE_RENAMING_DECLARATION ::=
+      --    package DEFINING_PROGRAM_UNIT_NAME renames package_NAME;
+
+      --  N_Package_Renaming_Declaration
+      --  Sloc points to PACKAGE
+      --  Defining_Unit_Name (Node1)
+      --  Name (Node2)
+      --  Parent_Spec (Node4-Sem)
+
+      ------------------------------------------
+      -- 8.5  Subprogram Renaming Declaration --
+      ------------------------------------------
+
+      --  SUBPROGRAM_RENAMING_DECLARATION ::=
+      --    SUBPROGRAM_SPECIFICATION renames callable_entity_NAME;
+
+      --  N_Subprogram_Renaming_Declaration
+      --  Sloc points to RENAMES
+      --  Specification (Node1)
+      --  Name (Node2)
+      --  Parent_Spec (Node4-Sem)
+      --  Corresponding_Spec (Node5-Sem)
+
+      -----------------------------------------
+      -- 8.5.5  Generic Renaming Declaration --
+      -----------------------------------------
+
+      --  GENERIC_RENAMING_DECLARATION ::=
+      --    generic package DEFINING_PROGRAM_UNIT_NAME
+      --      renames generic_package_NAME
+      --  | generic procedure DEFINING_PROGRAM_UNIT_NAME
+      --      renames generic_procedure_NAME
+      --  | generic function DEFINING_PROGRAM_UNIT_NAME
+      --      renames generic_function_NAME
+
+      --  N_Generic_Package_Renaming_Declaration
+      --  Sloc points to GENERIC
+      --  Defining_Unit_Name (Node1)
+      --  Name (Node2)
+      --  Parent_Spec (Node4-Sem)
+
+      --  N_Generic_Procedure_Renaming_Declaration
+      --  Sloc points to GENERIC
+      --  Defining_Unit_Name (Node1)
+      --  Name (Node2)
+      --  Parent_Spec (Node4-Sem)
+
+      --  N_Generic_Function_Renaming_Declaration
+      --  Sloc points to GENERIC
+      --  Defining_Unit_Name (Node1)
+      --  Name (Node2)
+      --  Parent_Spec (Node4-Sem)
+
+      --------------------------------
+      -- 9.1  Task Type Declaration --
+      --------------------------------
+
+      --  TASK_TYPE_DECLARATION ::=
+      --    task type DEFINING_IDENTIFIER [KNOWN_DISCRIMINANT_PART]
+      --      [is TASK_DEFINITITION];
+
+      --  N_Task_Type_Declaration
+      --  Sloc points to TASK
+      --  Defining_Identifier (Node1)
+      --  Task_Body_Procedure (Node2-Sem)
+      --  Discriminant_Specifications (List4) (set to No_List if no
+      --   discriminant part)
+      --  Task_Definition (Node3) (set to Empty if not present)
+      --  Corresponding_Body (Node5-Sem)
+
+      ----------------------------------
+      -- 9.1  Single Task Declaration --
+      ----------------------------------
+
+      --  SINGLE_TASK_DECLARATION ::=
+      --    task DEFINING_IDENTIFIER [is TASK_DEFINITION];
+
+      --  N_Single_Task_Declaration
+      --  Sloc points to TASK
+      --  Defining_Identifier (Node1)
+      --  Task_Definition (Node3) (set to Empty if not present)
+
+      --------------------------
+      -- 9.1  Task Definition --
+      --------------------------
+
+      --  TASK_DEFINITION ::=
+      --      {TASK_ITEM}
+      --    [private
+      --      {TASK_ITEM}]
+      --    end [task_IDENTIFIER]
+
+      --  Note: as a result of semantic analysis, the list of task items can
+      --  include implicit type declarations resulting from entry families.
+
+      --  N_Task_Definition
+      --  Sloc points to first token of task definition
+      --  Visible_Declarations (List2)
+      --  Private_Declarations (List3) (set to No_List if no private part)
+      --  End_Label (Node4)
+      --  Has_Priority_Pragma (Flag6-Sem)
+      --  Has_Storage_Size_Pragma (Flag5-Sem)
+      --  Has_Task_Info_Pragma (Flag7-Sem)
+      --  Has_Task_Name_Pragma (Flag8-Sem)
+
+      --------------------
+      -- 9.1  Task Item --
+      --------------------
+
+      --  TASK_ITEM ::= ENTRY_DECLARATION | REPRESENTATION_CLAUSE
+
+      --------------------
+      -- 9.1  Task Body --
+      --------------------
+
+      --  TASK_BODY ::=
+      --    task body task_DEFINING_IDENTIFIER is
+      --      DECLARATIVE_PART
+      --    begin
+      --      HANDLED_SEQUENCE_OF_STATEMENTS
+      --    end [task_IDENTIFIER];
+
+      --  Gigi restriction: This node never appears.
+
+      --  N_Task_Body
+      --  Sloc points to TASK
+      --  Defining_Identifier (Node1)
+      --  Declarations (List2)
+      --  Handled_Statement_Sequence (Node4)
+      --  Is_Task_Master (Flag5-Sem)
+      --  Activation_Chain_Entity (Node3-Sem)
+      --  Corresponding_Spec (Node5-Sem)
+      --  Was_Originally_Stub (Flag13-Sem)
+
+      -------------------------------------
+      -- 9.4  Protected Type Declaration --
+      -------------------------------------
+
+      --  PROTECTED_TYPE_DECLARATION ::=
+      --    protected type DEFINING_IDENTIFIER [KNOWN_DISCRIMINANT_PART]
+      --      is PROTECTED_DEFINITION;
+
+      --  Note: protected type declarations are not permitted in Ada 83 mode
+
+      --  N_Protected_Type_Declaration
+      --  Sloc points to PROTECTED
+      --  Defining_Identifier (Node1)
+      --  Discriminant_Specifications (List4) (set to No_List if no
+      --   discriminant part)
+      --  Protected_Definition (Node3)
+      --  Corresponding_Body (Node5-Sem)
+
+      ---------------------------------------
+      -- 9.4  Single Protected Declaration --
+      ---------------------------------------
+
+      --  SINGLE_PROTECTED_DECLARATION ::=
+      --    protected DEFINING_IDENTIFIER is PROTECTED_DEFINITION;
+
+      --  Note: single protected declarations are not allowed in Ada 83 mode
+
+      --  N_Single_Protected_Declaration
+      --  Sloc points to PROTECTED
+      --  Defining_Identifier (Node1)
+      --  Protected_Definition (Node3)
+
+      -------------------------------
+      -- 9.4  Protected Definition --
+      -------------------------------
+
+      --  PROTECTED_DEFINITION ::=
+      --      {PROTECTED_OPERATION_DECLARATION}
+      --    [private
+      --      {PROTECTED_ELEMENT_DECLARATION}]
+      --    end [protected_IDENTIFIER]
+
+      --  N_Protected_Definition
+      --  Sloc points to first token of protected definition
+      --  Visible_Declarations (List2)
+      --  Private_Declarations (List3) (set to No_List if no private part)
+      --  End_Label (Node4)
+      --  Has_Priority_Pragma (Flag6-Sem)
+
+      ------------------------------------------
+      -- 9.4  Protected Operation Declaration --
+      ------------------------------------------
+
+      --  PROTECTED_OPERATION_DECLARATION ::=
+      --    SUBPROGRAM_DECLARATION
+      --  | ENTRY_DECLARATION
+      --  | REPRESENTATION_CLAUSE
+
+      ----------------------------------------
+      -- 9.4  Protected Element Declaration --
+      ----------------------------------------
+
+      --  PROTECTED_ELEMENT_DECLARATION ::=
+      --    PROTECTED_OPERATION_DECLARATION | COMPONENT_DECLARATION
+
+      -------------------------
+      -- 9.4  Protected Body --
+      -------------------------
+
+      --  PROTECTED_BODY ::=
+      --    protected body DEFINING_IDENTIFIER is
+      --      {PROTECTED_OPERATION_ITEM}
+      --    end [protected_IDENTIFIER];
+
+      --  Note: protected bodies are not allowed in Ada 83 mode
+
+      --  Gigi restriction: This node never appears.
+
+      --  N_Protected_Body
+      --  Sloc points to PROTECTED
+      --  Defining_Identifier (Node1)
+      --  Declarations (List2) protected operation items (and pragmas)
+      --  End_Label (Node4)
+      --  Corresponding_Spec (Node5-Sem)
+      --  Was_Originally_Stub (Flag13-Sem)
+
+      -----------------------------------
+      -- 9.4  Protected Operation Item --
+      -----------------------------------
+
+      --  PROTECTED_OPERATION_ITEM ::=
+      --    SUBPROGRAM_DECLARATION
+      --  | SUBPROGRAM_BODY
+      --  | ENTRY_BODY
+      --  | REPRESENTATION_CLAUSE
+
+      ------------------------------
+      -- 9.5.2  Entry Declaration --
+      ------------------------------
+
+      --  ENTRY_DECLARATION ::=
+      --    entry DEFINING_IDENTIFIER
+      --      [(DISCRETE_SUBTYPE_DEFINITION)] PARAMETER_PROFILE;
+
+      --  N_Entry_Declaration
+      --  Sloc points to ENTRY
+      --  Defining_Identifier (Node1)
+      --  Discrete_Subtype_Definition (Node4) (set to Empty if not present)
+      --  Parameter_Specifications (List3) (set to No_List if no formal part)
+
+      -----------------------------
+      -- 9.5.2  Accept statement --
+      -----------------------------
+
+      --  ACCEPT_STATEMENT ::=
+      --    accept entry_DIRECT_NAME
+      --      [(ENTRY_INDEX)] PARAMETER_PROFILE [do
+      --        HANDLED_SEQUENCE_OF_STATEMENTS
+      --    end [entry_IDENTIFIER]];
+
+      --  Gigi restriction: This node never appears.
+
+      --  Note: there are no explicit declarations allowed in an accept
+      --  statement. However, the implicit declarations for any statement
+      --  identifiers (labels and block/loop identifiers) are declarations
+      --  that belong logically to the accept statement, and that is why
+      --  there is a Declarations field in this node.
+
+      --  N_Accept_Statement
+      --  Sloc points to ACCEPT
+      --  Entry_Direct_Name (Node1)
+      --  Entry_Index (Node5) (set to Empty if not present)
+      --  Parameter_Specifications (List3) (set to No_List if no formal part)
+      --  Handled_Statement_Sequence (Node4)
+      --  Declarations (List2) (set to No_List if no declarations)
+
+      ------------------------
+      -- 9.5.2  Entry Index --
+      ------------------------
+
+      --  ENTRY_INDEX ::= EXPRESSION
+
+      -----------------------
+      -- 9.5.2  Entry Body --
+      -----------------------
+
+      --  ENTRY_BODY ::=
+      --    entry DEFINING_IDENTIFIER ENTRY_BODY_FORMAL_PART ENTRY_BARRIER is
+      --      DECLARATIVE_PART
+      --    begin
+      --      HANDLED_SEQUENCE_OF_STATEMENTS
+      --    end [entry_IDENTIFIER];
+
+      --  ENTRY_BARRIER ::= when CONDITION
+
+      --  Note: we store the CONDITION of the ENTRY_BARRIER in the node for
+      --  the ENTRY_BODY_FORMAL_PART to avoid the N_Entry_Body node getting
+      --  too full (it would otherwise have too many fields)
+
+      --  Gigi restriction: This node never appears.
+
+      --  N_Entry_Body
+      --  Sloc points to ENTRY
+      --  Defining_Identifier (Node1)
+      --  Entry_Body_Formal_Part (Node5)
+      --  Declarations (List2)
+      --  Handled_Statement_Sequence (Node4)
+      --  Activation_Chain_Entity (Node3-Sem)
+
+      -----------------------------------
+      -- 9.5.2  Entry Body Formal Part --
+      -----------------------------------
+
+      --  ENTRY_BODY_FORMAL_PART ::=
+      --    [(ENTRY_INDEX_SPECIFICATION)] PARAMETER_PROFILE
+
+      --  Note that an entry body formal part node is present even if it is
+      --  empty. This reflects the grammar, in which it is the components of
+      --  the entry body formal part that are optional, not the entry body
+      --  formal part itself. Also this means that the barrier condition
+      --  always has somewhere to be stored.
+
+      --  Gigi restriction: This node never appears.
+
+      --  N_Entry_Body_Formal_Part
+      --  Sloc points to first token
+      --  Entry_Index_Specification (Node4) (set to Empty if not present)
+      --  Parameter_Specifications (List3) (set to No_List if no formal part)
+      --  Condition (Node1) from entry barrier of entry body
+
+      --------------------------
+      -- 9.5.2  Entry Barrier --
+      --------------------------
+
+      --  ENTRY_BARRIER ::= when CONDITION
+
+      --------------------------------------
+      -- 9.5.2  Entry Index Specification --
+      --------------------------------------
+
+      --  ENTRY_INDEX_SPECIFICATION ::=
+      --    for DEFINING_IDENTIFIER in DISCRETE_SUBTYPE_DEFINITION
+
+      --  Gigi restriction: This node never appears.
+
+      --  N_Entry_Index_Specification
+      --  Sloc points to FOR
+      --  Defining_Identifier (Node1)
+      --  Discrete_Subtype_Definition (Node4)
+
+      ---------------------------------
+      -- 9.5.3  Entry Call Statement --
+      ---------------------------------
+
+      --  ENTRY_CALL_STATEMENT ::= entry_NAME [ACTUAL_PARAMETER_PART];
+
+      --  The parser may generate a procedure call for this construct. The
+      --  semantic pass must correct this misidentification where needed.
+
+      --  Gigi restriction: This node never appears.
+
+      --  N_Entry_Call_Statement
+      --  Sloc points to first token of name
+      --  Name (Node2)
+      --  Parameter_Associations (List3) (set to No_List if no
+      --   actual parameter part)
+      --  First_Named_Actual (Node4-Sem)
+
+      ------------------------------
+      -- 9.5.4  Requeue Statement --
+      ------------------------------
+
+      --  REQUEUE_STATEMENT ::= requeue entry_NAME [with abort];
+
+      --  Note: requeue statements are not permitted in Ada 83 mode
+
+      --  Gigi restriction: This node never appears.
+
+      --  N_Requeue_Statement
+      --  Sloc points to REQUEUE
+      --  Name (Node2)
+      --  Abort_Present (Flag15)
+
+      --------------------------
+      -- 9.6  Delay Statement --
+      --------------------------
+
+      --  DELAY_STATEMENT ::=
+      --    DELAY_UNTIL_STATEMENT
+      --  | DELAY_RELATIVE_STATEMENT
+
+      --------------------------------
+      -- 9.6  Delay Until Statement --
+      --------------------------------
+
+      --  DELAY_UNTIL_STATEMENT ::= delay until delay_EXPRESSION;
+
+      --  Note: delay until statements are not permitted in Ada 83 mode
+
+      --  Gigi restriction: This node never appears.
+
+      --  N_Delay_Until_Statement
+      --  Sloc points to DELAY
+      --  Expression (Node3)
+
+      -----------------------------------
+      -- 9.6  Delay Relative Statement --
+      -----------------------------------
+
+      --  DELAY_RELATIVE_STATEMENT ::= delay delay_EXPRESSION;
+
+      --  Gigi restriction: This node never appears.
+
+      --  N_Delay_Relative_Statement
+      --  Sloc points to DELAY
+      --  Expression (Node3)
+
+      ---------------------------
+      -- 9.7  Select Statement --
+      ---------------------------
+
+      --  SELECT_STATEMENT ::=
+      --    SELECTIVE_ACCEPT
+      --  | TIMED_ENTRY_CALL
+      --  | CONDITIONAL_ENTRY_CALL
+      --  | ASYNCHRONOUS_SELECT
+
+      -----------------------------
+      -- 9.7.1  Selective Accept --
+      -----------------------------
+
+      --  SELECTIVE_ACCEPT ::=
+      --    select
+      --      [GUARD]
+      --        SELECT_ALTERNATIVE
+      --    {or
+      --      [GUARD]
+      --        SELECT_ALTERNATIVE}
+      --    [else
+      --      SEQUENCE_OF_STATEMENTS]
+      --    end select;
+
+      --  Gigi restriction: This node never appears.
+
+      --  Note: the guard expression, if present, appears in the node for
+      --  the select alternative.
+
+      --  N_Selective_Accept
+      --  Sloc points to SELECT
+      --  Select_Alternatives (List1)
+      --  Else_Statements (List4) (set to No_List if no else part)
+
+      ------------------
+      -- 9.7.1  Guard --
+      ------------------
+
+      --  GUARD ::= when CONDITION =>
+
+      --  As noted above, the CONDITION that is part of a GUARD is included
+      --  in the node for the select alernative for convenience.
+
+      -------------------------------
+      -- 9.7.1  Select Alternative --
+      -------------------------------
+
+      --  SELECT_ALTERNATIVE ::=
+      --    ACCEPT_ALTERNATIVE
+      --  | DELAY_ALTERNATIVE
+      --  | TERMINATE_ALTERNATIVE
+
+      -------------------------------
+      -- 9.7.1  Accept Alternative --
+      -------------------------------
+
+      --  ACCEPT_ALTERNATIVE ::=
+      --    ACCEPT_STATEMENT [SEQUENCE_OF_STATEMENTS]
+
+      --  Gigi restriction: This node never appears.
+
+      --  N_Accept_Alternative
+      --  Sloc points to ACCEPT
+      --  Accept_Statement (Node2)
+      --  Condition (Node1) from the guard (set to Empty if no guard present)
+      --  Statements (List3) (set to Empty_List if no statements)
+      --  Pragmas_Before (List4) pragmas before alt (set to No_List if none)
+      --  Accept_Handler_Records (List5-Sem)
+
+      ------------------------------
+      -- 9.7.1  Delay Alternative --
+      ------------------------------
+
+      --  DELAY_ALTERNATIVE ::=
+      --    DELAY_STATEMENT [SEQUENCE_OF_STATEMENTS]
+
+      --  Gigi restriction: This node never appears.
+
+      --  N_Delay_Alternative
+      --  Sloc points to DELAY
+      --  Delay_Statement (Node2)
+      --  Condition (Node1) from the guard (set to Empty if no guard present)
+      --  Statements (List3) (set to Empty_List if no statements)
+      --  Pragmas_Before (List4) pragmas before alt (set to No_List if none)
+
+      ----------------------------------
+      -- 9.7.1  Terminate Alternative --
+      ----------------------------------
+
+      --  TERMINATE_ALTERNATIVE ::= terminate;
+
+      --  Gigi restriction: This node never appears.
+
+      --  N_Terminate_Alternative
+      --  Sloc points to TERMINATE
+      --  Condition (Node1) from the guard (set to Empty if no guard present)
+      --  Pragmas_Before (List4) pragmas before alt (set to No_List if none)
+      --  Pragmas_After (List5) pragmas after alt (set to No_List if none)
+
+      -----------------------------
+      -- 9.7.2  Timed Entry Call --
+      -----------------------------
+
+      --  TIMED_ENTRY_CALL ::=
+      --    select
+      --      ENTRY_CALL_ALTERNATIVE
+      --    or
+      --      DELAY_ALTERNATIVE
+      --    end select;
+
+      --  Gigi restriction: This node never appears.
+
+      --  N_Timed_Entry_Call
+      --  Sloc points to SELECT
+      --  Entry_Call_Alternative (Node1)
+      --  Delay_Alternative (Node4)
+
+      -----------------------------------
+      -- 9.7.2  Entry Call Alternative --
+      -----------------------------------
+
+      --  ENTRY_CALL_ALTERNATIVE ::=
+      --    ENTRY_CALL_STATEMENT [SEQUENCE_OF_STATEMENTS]
+
+      --  Gigi restriction: This node never appears.
+
+      --  N_Entry_Call_Alternative
+      --  Sloc points to first token of entry call statement
+      --  Entry_Call_Statement (Node1)
+      --  Statements (List3) (set to Empty_List if no statements)
+      --  Pragmas_Before (List4) pragmas before alt (set to No_List if none)
+
+      -----------------------------------
+      -- 9.7.3  Conditional Entry Call --
+      -----------------------------------
+
+      --  CONDITIONAL_ENTRY_CALL ::=
+      --    select
+      --      ENTRY_CALL_ALTERNATIVE
+      --    else
+      --      SEQUENCE_OF_STATEMENTS
+      --    end select;
+
+      --  Gigi restriction: This node never appears.
+
+      --  N_Conditional_Entry_Call
+      --  Sloc points to SELECT
+      --  Entry_Call_Alternative (Node1)
+      --  Else_Statements (List4)
+
+      --------------------------------
+      -- 9.7.4  Asynchronous Select --
+      --------------------------------
+
+      --  ASYNCHRONOUS_SELECT ::=
+      --    select
+      --      TRIGGERING_ALTERNATIVE
+      --    then abort
+      --      ABORTABLE_PART
+      --    end select;
+
+      --  Note: asynchronous select is not permitted in Ada 83 mode
+
+      --  Gigi restriction: This node never appears.
+
+      --  N_Asynchronous_Select
+      --  Sloc points to SELECT
+      --  Triggering_Alternative (Node1)
+      --  Abortable_Part (Node2)
+
+      -----------------------------------
+      -- 9.7.4  Triggering Alternative --
+      -----------------------------------
+
+      --  TRIGGERING_ALTERNATIVE ::=
+      --    TRIGGERING_STATEMENT [SEQUENCE_OF_STATEMENTS]
+
+      --  Gigi restriction: This node never appears.
+
+      --  N_Triggering_Alternative
+      --  Sloc points to first token of triggering statement
+      --  Triggering_Statement (Node1)
+      --  Statements (List3) (set to Empty_List if no statements)
+      --  Pragmas_Before (List4) pragmas before alt (set to No_List if none)
+
+      ---------------------------------
+      -- 9.7.4  Triggering Statement --
+      ---------------------------------
+
+      --  TRIGGERING_STATEMENT ::= ENTRY_CALL_STATEMENT | DELAY_STATEMENT
+
+      ---------------------------
+      -- 9.7.4  Abortable Part --
+      ---------------------------
+
+      --  ABORTABLE_PART ::= SEQUENCE_OF_STATEMENTS
+
+      --  Gigi restriction: This node never appears.
+
+      --  N_Abortable_Part
+      --  Sloc points to ABORT
+      --  Statements (List3)
+
+      --------------------------
+      -- 9.8  Abort Statement --
+      --------------------------
+
+      --  ABORT_STATEMENT ::= abort task_NAME {, task_NAME};
+
+      --  Gigi restriction: This node never appears.
+
+      --  N_Abort_Statement
+      --  Sloc points to ABORT
+      --  Names (List2)
+
+      -------------------------
+      -- 10.1.1  Compilation --
+      -------------------------
+
+      --  COMPILATION ::= {COMPILATION_UNIT}
+
+      --  There is no explicit node in the tree for a compilation, since in
+      --  general the compiler is processing only a single compilation unit
+      --  at a time. It is possible to parse multiple units in syntax check
+      --  only mode, but they the trees are discarded in any case.
+
+      ------------------------------
+      -- 10.1.1  Compilation Unit --
+      ------------------------------
+
+      --  COMPILATION_UNIT ::=
+      --    CONTEXT_CLAUSE LIBRARY_ITEM
+      --  | CONTEXT_CLAUSE SUBUNIT
+
+      --  The N_Compilation_Unit node itself respresents the above syntax.
+      --  However, there are two additional items not reflected in the above
+      --  syntax. First we have the global declarations that are added by the
+      --  code generator. These are outer level declarations (so they cannot
+      --  be represented as being inside the units). An example is the wrapper
+      --  subprograms that are created to do ABE checking. As always a list of
+      --  declarations can contain actions as well (i.e. statements), and such
+      --  statements are executed as part of the elaboration of the unit. Note
+      --  that all such declarations are elaborated before the library unit.
+
+      --  Similarly, certain actions need to be elaborated at the completion
+      --  of elaboration of the library unit (notably the statement that sets
+      --  the Boolean flag indicating that elaboration is complete).
+
+      --  The third item not reflected in the syntax is pragmas that appear
+      --  after the compilation unit. As always pragmas are a problem since
+      --  they are not part of the formal syntax, but can be stuck into the
+      --  source following a set of ad hoc rules, and we have to find an ad
+      --  hoc way of sticking them into the tree. For pragmas that appear
+      --  before the library unit, we just consider them to be part of the
+      --  context clause, and pragmas can appear in the Context_Items list
+      --  of the compilation unit. However, pragmas can also appear after
+      --  the library item.
+
+      --  To deal with all these problems, we create an auxiliary node for
+      --  a compilation unit, referenced from the N_Compilation_Unit node
+      --  that contains these three items.
+
+      --  N_Compilation_Unit
+      --  Sloc points to first token of defining unit name
+      --  Library_Unit (Node4-Sem) corresponding/parent spec/body
+      --  Context_Items (List1) context items and pragmas preceding unit
+      --  Private_Present (Flag15) set if library unit has private keyword
+      --  Unit (Node2) library item or subunit
+      --  Aux_Decls_Node (Node5) points to the N_Compilation_Unit_Aux node
+      --  Has_No_Elaboration_Code (Flag17-Sem)
+      --  Body_Required (Flag13-Sem) set for spec if body is required
+      --  Acts_As_Spec (Flag4-Sem) flag for subprogram body with no spec
+      --  First_Inlined_Subprogram (Node3-Sem)
+
+      --  N_Compilation_Unit_Aux
+      --  Sloc is a copy of the Sloc from the N_Compilation_Unit node
+      --  Declarations (List2) (set to No_List if no global declarations)
+      --  Actions (List1) (set to No_List if no actions)
+      --  Pragmas_After (List5) pragmas after unit (set to No_List if none)
+
+      --------------------------
+      -- 10.1.1  Library Item --
+      --------------------------
+
+      --  LIBRARY_ITEM ::=
+      --    [private] LIBRARY_UNIT_DECLARATION
+      --  | LIBRARY_UNIT_BODY
+      --  | [private] LIBRARY_UNIT_RENAMING_DECLARATION
+
+      --  Note: PRIVATE is not allowed in Ada 83 mode
+
+      --  There is no explicit node in the tree for library item, instead
+      --  the declaration or body, and the flag for private if present,
+      --  appear in the N_Compilation_Unit clause.
+
+      ----------------------------------------
+      -- 10.1.1  Library Unit Declararation --
+      ----------------------------------------
+
+      --  LIBRARY_UNIT_DECLARATION ::=
+      --    SUBPROGRAM_DECLARATION | PACKAGE_DECLARATION
+      --  | GENERIC_DECLARATION    | GENERIC_INSTANTIATION
+
+      -------------------------------------------------
+      -- 10.1.1  Library Unit Renaming Declararation --
+      -------------------------------------------------
+
+      --  LIBRARY_UNIT_RENAMING_DECLARATION ::=
+      --    PACKAGE_RENAMING_DECLARATION
+      --  | GENERIC_RENAMING_DECLARATION
+      --  | SUBPROGRAM_RENAMING_DECLARATION
+
+      -------------------------------
+      -- 10.1.1  Library unit body --
+      -------------------------------
+
+      --  LIBRARY_UNIT_BODY ::= SUBPROGRAM_BODY | PACKAGE_BODY
+
+      ------------------------------
+      -- 10.1.1  Parent Unit Name --
+      ------------------------------
+
+      --  PARENT_UNIT_NAME ::= NAME
+
+      ----------------------------
+      -- 10.1.2  Context clause --
+      ----------------------------
+
+      --  CONTEXT_CLAUSE ::= {CONTEXT_ITEM}
+
+      --  The context clause can include pragmas, and any pragmas that appear
+      --  before the context clause proper (i.e. all configuration pragmas,
+      --  also appear at the front of this list).
+
+      --------------------------
+      -- 10.1.2  Context_Item --
+      --------------------------
+
+      --  CONTEXT_ITEM ::= WITH_CLAUSE | USE_CLAUSE  | WITH_TYPE_CLAUSE
+
+      -------------------------
+      -- 10.1.2  With clause --
+      -------------------------
+
+      --  WITH_CLAUSE ::=
+      --    with library_unit_NAME {,library_unit_NAME};
+
+      --  A separate With clause is built for each name, so that we have
+      --  a Corresponding_Spec field for each with'ed spec. The flags
+      --  First_Name and Last_Name are used to reconstruct the exact
+      --  source form. When a list of names appears in one with clause,
+      --  the first name in the list has First_Name set, and the last
+      --  has Last_Name set. If the with clause has only one name, then
+      --  both of the flags First_Name and Last_Name are set in this name.
+
+      --  Note: in the case of implicit with's that are installed by the
+      --  Rtsfind routine, Implicit_With is set, and the Sloc is typically
+      --  set to Standard_Location, but it is incorrect to test the Sloc
+      --  to find out if a with clause is implicit, test the flag instead.
+
+      --  N_With_Clause
+      --  Sloc points to first token of library unit name
+      --  Name (Node2)
+      --  Library_Unit (Node4-Sem)
+      --  Corresponding_Spec (Node5-Sem)
+      --  First_Name (Flag5) (set to True if first name or only one name)
+      --  Last_Name (Flag6) (set to True if last name or only one name)
+      --  Context_Installed (Flag13-Sem)
+      --  Elaborate_Present (Flag4-Sem)
+      --  Elaborate_All_Present (Flag15-Sem)
+      --  Implicit_With (Flag17-Sem)
+      --  Unreferenced_In_Spec (Flag7-Sem)
+      --  No_Entities_Ref_In_Spec (Flag8-Sem)
+
+      ----------------------
+      -- With_Type clause --
+      ----------------------
+
+      --  This is a GNAT extension, used to implement mutually recursive
+      --  types declared in different packages.
+
+      --  WITH_TYPE_CLAUSE ::=
+      --    with type type_NAME is access | with type type_NAME is tagged
+
+      --  N_With_Type_Clause
+      --  Sloc points to first token of type name
+      --  Name (Node2)
+      --  Tagged_Present (Flag15)
+
+      ---------------------
+      -- 10.2  Body stub --
+      ---------------------
+
+      --  BODY_STUB ::=
+      --    SUBPROGRAM_BODY_STUB
+      --  | PACKAGE_BODY_STUB
+      --  | TASK_BODY_STUB
+      --  | PROTECTED_BODY_STUB
+
+      ----------------------------------
+      -- 10.1.3  Subprogram Body Stub --
+      ----------------------------------
+
+      --  SUBPROGRAM_BODY_STUB ::=
+      --    SUBPROGRAM_SPECIFICATION is separate;
+
+      --  N_Subprogram_Body_Stub
+      --  Sloc points to FUNCTION or PROCEDURE
+      --  Specification (Node1)
+      --  Library_Unit (Node4-Sem) points to the subunit
+      --  Corresponding_Body (Node5-Sem)
+
+      -------------------------------
+      -- 10.1.3  Package Body Stub --
+      -------------------------------
+
+      --  PACKAGE_BODY_STUB ::=
+      --    package body DEFINING_IDENTIFIER is separate;
+
+      --  N_Package_Body_Stub
+      --  Sloc points to PACKAGE
+      --  Defining_Identifier (Node1)
+      --  Library_Unit (Node4-Sem) points to the subunit
+      --  Corresponding_Body (Node5-Sem)
+
+      ----------------------------
+      -- 10.1.3  Task Body Stub --
+      ----------------------------
+
+      --  TASK_BODY_STUB ::=
+      --    task body DEFINING_IDENTIFIER is separate;
+
+      --  N_Task_Body_Stub
+      --  Sloc points to TASK
+      --  Defining_Identifier (Node1)
+      --  Library_Unit (Node4-Sem) points to the subunit
+      --  Corresponding_Body (Node5-Sem)
+
+      ---------------------------------
+      -- 10.1.3  Protected Body Stub --
+      ---------------------------------
+
+      --  PROTECTED_BODY_STUB ::=
+      --    protected body DEFINING_IDENTIFIER is separate;
+
+      --  Note: protected body stubs are not allowed in Ada 83 mode
+
+      --  N_Protected_Body_Stub
+      --  Sloc points to PROTECTED
+      --  Defining_Identifier (Node1)
+      --  Library_Unit (Node4-Sem) points to the subunit
+      --  Corresponding_Body (Node5-Sem)
+
+      ---------------------
+      -- 10.1.3  Subunit --
+      ---------------------
+
+      --  SUBUNIT ::= separate (PARENT_UNIT_NAME) PROPER_BODY
+
+      --  N_Subunit
+      --  Sloc points to SEPARATE
+      --  Name (Node2) is the name of the parent unit
+      --  Proper_Body (Node1) is the subunit body
+      --  Corresponding_Stub (Node3-Sem) is the stub declaration for the unit.
+
+      ---------------------------------
+      -- 11.1  Exception Declaration --
+      ---------------------------------
+
+      --  EXCEPTION_DECLARATION ::= DEFINING_IDENTIFIER_LIST : exception;
+
+      --  For consistency with object declarations etc, the parser converts
+      --  the case of multiple identifiers being declared to a series of
+      --  declarations in which the expression is copied, using the More_Ids
+      --  and Prev_Ids flags to remember the souce form as described in the
+      --  section on "Handling of Defining Identifier Lists".
+
+      --  N_Exception_Declaration
+      --  Sloc points to EXCEPTION
+      --  Defining_Identifier (Node1)
+      --  Expression (Node3-Sem)
+      --  More_Ids (Flag5) (set to False if no more identifiers in list)
+      --  Prev_Ids (Flag6) (set to False if no previous identifiers in list)
+
+      ------------------------------------------
+      -- 11.2  Handled Sequence Of Statements --
+      ------------------------------------------
+
+      --  HANDLED_SEQUENCE_OF_STATEMENTS ::=
+      --      SEQUENCE_OF_STATEMENTS
+      --    [exception
+      --      EXCEPTION_HANDLER
+      --      {EXCEPTION_HANDLER}]
+      --    [at end
+      --      cleanup_procedure_call (param, param, param, ...);]
+
+      --  The AT END phrase is a GNAT extension to provide for cleanups. It is
+      --  used only internally currently, but is considered to be syntactic.
+      --  At the moment, the only cleanup action allowed is a single call to
+      --  a parameterless procedure, and the Identifier field of the node is
+      --  the procedure to be called. Also there is a current restriction
+      --  that exception handles and a cleanup cannot be present in the same
+      --  frame, so at least one of Exception_Handlers or the Identifier must
+      --  be missing.
+
+      --  Actually, more accurately, this restriction applies to the original
+      --  source program. In the expanded tree, if the At_End_Proc field is
+      --  present, then there will also be an exception handler of the form:
+
+      --     when all others =>
+      --        cleanup;
+      --        raise;
+
+      --  where cleanup is the procedure to be generated. The reason we do
+      --  this is so that the front end can handle the necessary entries in
+      --  the exception tables, and other exception handler actions required
+      --  as part of the normal handling for exception handlers.
+
+      --  The AT END cleanup handler protects only the sequence of statements
+      --  (not the associated declarations of the parent), just like exception
+      --  handlers. The big difference is that the cleanup procedure is called
+      --  on either a normal or an abnormal exit from the statement sequence.
+
+      --  Note: the list of Exception_Handlers can contain pragmas as well
+      --  as actual handlers. In practice these pragmas can only occur at
+      --  the start of the list, since any pragmas occurring later on will
+      --  be included in the statement list of the corresponding handler.
+
+      --  Note: although in the Ada syntax, the sequence of statements in
+      --  a handled sequence of statements can only contain statements, we
+      --  allow free mixing of declarations and statements in the resulting
+      --  expanded tree. This is for example used to deal with the case of
+      --  a cleanup procedure that must handle declarations as well as the
+      --  statements of a block.
+
+      --  N_Handled_Sequence_Of_Statements
+      --  Sloc points to first token of first statement
+      --  Statements (List3)
+      --  End_Label (Node4) (set to Empty if expander generated)
+      --  Exception_Handlers (List5) (set to No_List if none present)
+      --  At_End_Proc (Node1) (set to Empty if no clean up procedure)
+      --  First_Real_Statement (Node2-Sem)
+      --  Zero_Cost_Handling (Flag5-Sem)
+
+      --  Note: the parent always contains a Declarations field which contains
+      --  declarations associated with the handled sequence of statements. This
+      --  is true even in the case of an accept statement (see description of
+      --  the N_Accept_Statement node).
+
+      --  End_Label refers to the containing construct.
+
+      -----------------------------
+      -- 11.2  Exception Handler --
+      -----------------------------
+
+      --  EXCEPTION_HANDLER ::=
+      --    when [CHOICE_PARAMETER_SPECIFICATION :]
+      --      EXCEPTION_CHOICE {| EXCEPTION_CHOICE} =>
+      --        SEQUENCE_OF_STATEMENTS
+
+      --  Note: choice parameter specification is not allowed in Ada 83 mode
+
+      --  N_Exception_Handler
+      --  Sloc points to WHEN
+      --  Choice_Parameter (Node2) (set to Empty if not present)
+      --  Exception_Choices (List4)
+      --  Statements (List3)
+      --  Zero_Cost_Handling (Flag5-Sem)
+
+      ------------------------------------------
+      -- 11.2  Choice parameter specification --
+      ------------------------------------------
+
+      --  CHOICE_PARAMETER_SPECIFICATION ::= DEFINING_IDENTIFIER
+
+      ----------------------------
+      -- 11.2  Exception Choice --
+      ----------------------------
+
+      --  EXCEPTION_CHOICE ::= exception_NAME | others
+
+      --  Except in the case of OTHERS, no explicit node appears in the tree
+      --  for exception choice. Instead the exception name appears directly.
+      --  An OTHERS choice is represented by a N_Others_Choice node (see
+      --  section 3.8.1.
+
+      --  Note: for the exception choice created for an at end handler, the
+      --  exception choice is an N_Others_Choice node with All_Others set.
+
+      ---------------------------
+      -- 11.3  Raise Statement --
+      ---------------------------
+
+      --  RAISE_STATEMENT ::= raise [exception_NAME];
+
+      --  N_Raise_Statement
+      --  Sloc points to RAISE
+      --  Name (Node2) (set to Empty if no exception name present)
+
+      -------------------------------
+      -- 12.1  Generic Declaration --
+      -------------------------------
+
+      --  GENERIC_DECLARATION ::=
+      --    GENERIC_SUBPROGRAM_DECLARATION | GENERIC_PACKAGE_DECLARATION
+
+      ------------------------------------------
+      -- 12.1  Generic Subprogram Declaration --
+      ------------------------------------------
+
+      --  GENERIC_SUBPROGRAM_DECLARATION ::=
+      --    GENERIC_FORMAL_PART SUBPROGRAM_SPECIFICATION;
+
+      --  Note: Generic_Formal_Declarations can include pragmas
+
+      --  N_Generic_Subprogram_Declaration
+      --  Sloc points to GENERIC
+      --  Specification (Node1) subprogram specification
+      --  Corresponding_Body (Node5-Sem)
+      --  Generic_Formal_Declarations (List2) from generic formal part
+      --  Parent_Spec (Node4-Sem)
+
+      ---------------------------------------
+      -- 12.1  Generic Package Declaration --
+      ---------------------------------------
+
+      --  GENERIC_PACKAGE_DECLARATION ::=
+      --    GENERIC_FORMAL_PART PACKAGE_SPECIFICATION;
+
+      --  Note: when we do generics right, the Activation_Chain_Entity entry
+      --  for this node can be removed (since the expander won't see generic
+      --  units any more)???.
+
+      --  Note: Generic_Formal_Declarations can include pragmas
+
+      --  N_Generic_Package_Declaration
+      --  Sloc points to GENERIC
+      --  Specification (Node1) package specification
+      --  Corresponding_Body (Node5-Sem)
+      --  Generic_Formal_Declarations (List2) from generic formal part
+      --  Parent_Spec (Node4-Sem)
+      --  Activation_Chain_Entity (Node3-Sem)
+
+      -------------------------------
+      -- 12.1  Generic Formal Part --
+      -------------------------------
+
+      --  GENERIC_FORMAL_PART ::=
+      --    generic {GENERIC_FORMAL_PARAMETER_DECLARATION | USE_CLAUSE}
+
+      ------------------------------------------------
+      -- 12.1  Generic Formal Parameter Declaration --
+      ------------------------------------------------
+
+      --  GENERIC_FORMAL_PARAMETER_DECLARATION ::=
+      --    FORMAL_OBJECT_DECLARATION
+      --  | FORMAL_TYPE_DECLARATION
+      --  | FORMAL_SUBPROGRAM_DECLARATION
+      --  | FORMAL_PACKAGE_DECLARATION
+
+      ---------------------------------
+      -- 12.3  Generic Instantiation --
+      ---------------------------------
+
+      --  GENERIC_INSTANTIATION ::=
+      --    package DEFINING_PROGRAM_UNIT_NAME is
+      --      new generic_package_NAME [GENERIC_ACTUAL_PART];
+      --  | procedure DEFINING_PROGRAM_UNIT_NAME is
+      --      new generic_procedure_NAME [GENERIC_ACTUAL_PART];
+      --  | function DEFINING_DESIGNATOR is
+      --      new generic_function_NAME [GENERIC_ACTUAL_PART];
+
+      --  N_Package_Instantiation
+      --  Sloc points to PACKAGE
+      --  Defining_Unit_Name (Node1)
+      --  Name (Node2)
+      --  Generic_Associations (List3) (set to No_List if no
+      --   generic actual part)
+      --  Parent_Spec (Node4-Sem)
+      --  Instance_Spec (Node5-Sem)
+      --  ABE_Is_Certain (Flag18-Sem)
+
+      --  N_Procedure_Instantiation
+      --  Sloc points to PROCEDURE
+      --  Defining_Unit_Name (Node1)
+      --  Name (Node2)
+      --  Parent_Spec (Node4-Sem)
+      --  Generic_Associations (List3) (set to No_List if no
+      --   generic actual part)
+      --  Instance_Spec (Node5-Sem)
+      --  ABE_Is_Certain (Flag18-Sem)
+
+      --  N_Function_Instantiation
+      --  Sloc points to FUNCTION
+      --  Defining_Unit_Name (Node1)
+      --  Name (Node2)
+      --  Generic_Associations (List3) (set to No_List if no
+      --   generic actual part)
+      --  Parent_Spec (Node4-Sem)
+      --  Instance_Spec (Node5-Sem)
+      --  ABE_Is_Certain (Flag18-Sem)
+
+      ------------------------------
+      -- 12.3 Generic Actual Part --
+      ------------------------------
+
+      --  GENERIC_ACTUAL_PART ::=
+      --    (GENERIC_ASSOCIATION {, GENERIC_ASSOCIATION})
+
+      -------------------------------
+      -- 12.3  Generic Association --
+      -------------------------------
+
+      --  GENERIC_ASSOCIATION ::=
+      --    [generic_formal_parameter_SELECTOR_NAME =>]
+      --      EXPLICIT_GENERIC_ACTUAL_PARAMETER
+
+      --  Note: unlike the procedure call case, a generic association node
+      --  is generated for every association, even if no formal is present.
+      --  In this case the parser will leave the Selector_Name field set
+      --  to Empty, to be filled in later by the semantic pass.
+
+      --  N_Generic_Association
+      --  Sloc points to first token of generic association
+      --  Selector_Name (Node2) (set to Empty if no formal
+      --   parameter selector name)
+      --  Explicit_Generic_Actual_Parameter (Node1)
+
+      ---------------------------------------------
+      -- 12.3  Explicit Generic Actual Parameter --
+      ---------------------------------------------
+
+      --  EXPLICIT_GENERIC_ACTUAL_PARAMETER ::=
+      --    EXPRESSION      | variable_NAME   | subprogram_NAME
+      --  | entry_NAME      | SUBTYPE_MARK    | package_instance_NAME
+
+      -------------------------------------
+      -- 12.4  Formal Object Declaration --
+      -------------------------------------
+
+      --  FORMAL_OBJECT_DECLARATION ::=
+      --    DEFINING_IDENTIFIER_LIST :
+      --      MODE SUBTYPE_MARK [:= DEFAULT_EXPRESSION];
+
+      --  Although the syntax allows multiple identifiers in the list, the
+      --  semantics is as though successive declarations were given with
+      --  identical type definition and expression components. To simplify
+      --  semantic processing, the parser represents a multiple declaration
+      --  case as a sequence of single declarations, using the More_Ids and
+      --  Prev_Ids flags to preserve the original source form as described
+      --  in the section on "Handling of Defining Identifier Lists".
+
+      --  N_Formal_Object_Declaration
+      --  Sloc points to first identifier
+      --  Defining_Identifier (Node1)
+      --  In_Present (Flag15)
+      --  Out_Present (Flag17)
+      --  Subtype_Mark (Node4)
+      --  Expression (Node3) (set to Empty if no default expression)
+      --  More_Ids (Flag5) (set to False if no more identifiers in list)
+      --  Prev_Ids (Flag6) (set to False if no previous identifiers in list)
+
+      -----------------------------------
+      -- 12.5  Formal Type Declaration --
+      -----------------------------------
+
+      --  FORMAL_TYPE_DECLARATION ::=
+      --    type DEFINING_IDENTIFIER [DISCRIMINANT_PART]
+      --      is FORMAL_TYPE_DEFINITION;
+
+      --  N_Formal_Type_Declaration
+      --  Sloc points to TYPE
+      --  Defining_Identifier (Node1)
+      --  Formal_Type_Definition (Node3)
+      --  Discriminant_Specifications (List4) (set to No_List if no
+      --   discriminant part)
+      --  Unknown_Discriminants_Present (Flag13) set if (<>) discriminant
+
+      ----------------------------------
+      -- 12.5  Formal type definition --
+      ----------------------------------
+
+      --  FORMAL_TYPE_DEFINITION ::=
+      --    FORMAL_PRIVATE_TYPE_DEFINITION
+      --  | FORMAL_DERIVED_TYPE_DEFINITION
+      --  | FORMAL_DISCRETE_TYPE_DEFINITION
+      --  | FORMAL_SIGNED_INTEGER_TYPE_DEFINITION
+      --  | FORMAL_MODULAR_TYPE_DEFINITION
+      --  | FORMAL_FLOATING_POINT_DEFINITION
+      --  | FORMAL_ORDINARY_FIXED_POINT_DEFINITION
+      --  | FORMAL_DECIMAL_FIXED_POINT_DEFINITION
+      --  | FORMAL_ARRAY_TYPE_DEFINITION
+      --  | FORMAL_ACCESS_TYPE_DEFINITION
+
+      ---------------------------------------------
+      -- 12.5.1  Formal Private Type Definition --
+      ---------------------------------------------
+
+      --  FORMAL_PRIVATE_TYPE_DEFINITION ::=
+      --    [[abstract] tagged] [limited] private
+
+      --  Note: TAGGED is not allowed in Ada 83 mode
+
+      --  N_Formal_Private_Type_Definition
+      --  Sloc points to PRIVATE
+      --  Abstract_Present (Flag4)
+      --  Tagged_Present (Flag15)
+      --  Limited_Present (Flag17)
+
+      --------------------------------------------
+      -- 12.5.1  Formal Derived Type Definition --
+      --------------------------------------------
+
+      --  FORMAL_DERIVED_TYPE_DEFINITION ::=
+      --    [abstract] new SUBTYPE_MARK [with private]
+
+      --  Note: this construct is not allowed in Ada 83 mode
+
+      --  N_Formal_Derived_Type_Definition
+      --  Sloc points to NEW
+      --  Subtype_Mark (Node4)
+      --  Private_Present (Flag15)
+      --  Abstract_Present (Flag4)
+
+      ---------------------------------------------
+      -- 12.5.2  Formal Discrete Type Definition --
+      ---------------------------------------------
+
+      --  FORMAL_DISCRETE_TYPE_DEFINITION ::= (<>)
+
+      --  N_Formal_Discrete_Type_Definition
+      --  Sloc points to (
+
+      ---------------------------------------------------
+      -- 12.5.2  Formal Signed Integer Type Definition --
+      ---------------------------------------------------
+
+      --  FORMAL_SIGNED_INTEGER_TYPE_DEFINITION ::= range <>
+
+      --  N_Formal_Signed_Integer_Type_Definition
+      --  Sloc points to RANGE
+
+      --------------------------------------------
+      -- 12.5.2  Formal Modular Type Definition --
+      --------------------------------------------
+
+      --  FORMAL_MODULAR_TYPE_DEFINITION ::= mod <>
+
+      --  N_Formal_Modular_Type_Definition
+      --  Sloc points to MOD
+
+      ----------------------------------------------
+      -- 12.5.2  Formal Floating Point Definition --
+      ----------------------------------------------
+
+      --  FORMAL_FLOATING_POINT_DEFINITION ::= digits <>
+
+      --  N_Formal_Floating_Point_Definition
+      --  Sloc points to DIGITS
+
+      ----------------------------------------------------
+      -- 12.5.2  Formal Ordinary Fixed Point Definition --
+      ----------------------------------------------------
+
+      --  FORMAL_ORDINARY_FIXED_POINT_DEFINITION ::= delta <>
+
+      --  N_Formal_Ordinary_Fixed_Point_Definition
+      --  Sloc points to DELTA
+
+      ---------------------------------------------------
+      -- 12.5.2  Formal Decimal Fixed Point Definition --
+      ---------------------------------------------------
+
+      --  FORMAL_DECIMAL_FIXED_POINT_DEFINITION ::= delta <> digits <>
+
+      --  Note: formal decimal fixed point definition not allowed in Ada 83
+
+      --  N_Formal_Decimal_Fixed_Point_Definition
+      --  Sloc points to DELTA
+
+      ------------------------------------------
+      -- 12.5.3  Formal Array Type Definition --
+      ------------------------------------------
+
+      --  FORMAL_ARRAY_TYPE_DEFINITION ::= ARRAY_TYPE_DEFINITION
+
+      -------------------------------------------
+      -- 12.5.4  Formal Access Type Definition --
+      -------------------------------------------
+
+      --  FORMAL_ACCESS_TYPE_DEFINITION ::= ACCESS_TYPE_DEFINITION
+
+      -----------------------------------------
+      -- 12.6  Formal Subprogram Declaration --
+      -----------------------------------------
+
+      --  FORMAL_SUBPROGRAM_DECLARATION ::=
+      --    with SUBPROGRAM_SPECIFICATION [is SUBPROGRAM_DEFAULT];
+
+      --  N_Formal_Subprogram_Declaration
+      --  Sloc points to WITH
+      --  Specification (Node1)
+      --  Default_Name (Node2) (set to Empty if no subprogram default)
+      --  Box_Present (Flag15)
+
+      --  Note: if no subprogram default is present, then Name is set
+      --  to Empty, and Box_Present is False.
+
+      ------------------------------
+      -- 12.6  Subprogram Default --
+      ------------------------------
+
+      --  SUBPROGRAM_DEFAULT ::= DEFAULT_NAME | <>
+
+      --  There is no separate node in the tree for a subprogram default.
+      --  Instead the parent (N_Formal_Subprogram_Declaration) node contains
+      --  the default name or box indication, as needed.
+
+      ------------------------
+      -- 12.6  Default Name --
+      ------------------------
+
+      --  DEFAULT_NAME ::= NAME
+
+      --------------------------------------
+      -- 12.7  Formal Package Declaration --
+      --------------------------------------
+
+      --  FORMAL_PACKAGE_DECLARATION ::=
+      --    with package DEFINING_IDENTIFIER
+      --      is new generic_package_NAME FORMAL_PACKAGE_ACTUAL_PART;
+
+      --  Note: formal package declarations not allowed in Ada 83 mode
+
+      --  N_Formal_Package_Declaration
+      --  Sloc points to WITH
+      --  Defining_Identifier (Node1)
+      --  Name (Node2)
+      --  Generic_Associations (List3) (set to No_List if (<>) case or
+      --   empty generic actual part)
+      --  Box_Present (Flag15)
+      --  Instance_Spec (Node5-Sem)
+      --  ABE_Is_Certain (Flag18-Sem)
+
+      --------------------------------------
+      -- 12.7  Formal Package Actual Part --
+      --------------------------------------
+
+      --  FORMAL_PACKAGE_ACTUAL_PART ::=
+      --    (<>) | [GENERIC_ACTUAL_PART]
+
+      --  There is no explicit node in the tree for a formal package
+      --  actual part. Instead the information appears in the parent node
+      --  (i.e. the formal package declaration node itself).
+
+      ---------------------------------
+      -- 13.1  Representation clause --
+      ---------------------------------
+
+      --  REPRESENTATION_CLAUSE ::=
+      --    ATTRIBUTE_DEFINITION_CLAUSE
+      --  | ENUMERATION_REPRESENTATION_CLAUSE
+      --  | RECORD_REPRESENTATION_CLAUSE
+      --  | AT_CLAUSE
+
+      ----------------------
+      -- 13.1  Local Name --
+      ----------------------
+
+      --  LOCAL_NAME :=
+      --    DIRECT_NAME
+      --  | DIRECT_NAME'ATTRIBUTE_DESIGNATOR
+      --  | library_unit_NAME
+
+      --  The construct DIRECT_NAME'ATTRIBUTE_DESIGNATOR appears in the tree
+      --  as an attribute reference, which has essentially the same form.
+
+      ---------------------------------------
+      -- 13.3  Attribute definition clause --
+      ---------------------------------------
+
+      --  ATTRIBUTE_DEFINITION_CLAUSE ::=
+      --    for LOCAL_NAME'ATTRIBUTE_DESIGNATOR use EXPRESSION;
+      --  | for LOCAL_NAME'ATTRIBUTE_DESIGNATOR use NAME;
+
+      --  In Ada 83, the expression must be a simple expression and the
+      --  local name must be a direct name.
+
+      --  Note: The only attribute definition clause that is processed
+      --  by Gigi is the alignment clause (for all other cases, the
+      --  information is extracted by the front end and either results
+      --  in setting entity information, e.g. Esize for the Size case,
+      --  or in appropriate expansion actions (e.g. in the storage size
+      --  case). For the alignment case, Gigi requires that the expression
+      --  be an integer literal.
+
+      --  N_Attribute_Definition_Clause
+      --  Sloc points to FOR
+      --  Name (Node2) the local name
+      --  Chars (Name1) the identifier name from the attribute designator
+      --  Expression (Node3) the expression or name
+      --  Next_Rep_Item (Node4-Sem)
+      --  From_At_Mod (Flag4-Sem)
+
+      ---------------------------------------------
+      -- 13.4  Enumeration representation clause --
+      ---------------------------------------------
+
+      --  ENUMERATION_REPRESENTATION_CLAUSE ::=
+      --    for first_subtype_LOCAL_NAME use ENUMERATION_AGGREGATE;
+
+      --  In Ada 83, the name must be a direct name
+
+      --  N_Enumeration_Representation_Clause
+      --  Sloc points to FOR
+      --  Identifier (Node1) direct name
+      --  Array_Aggregate (Node3)
+      --  Next_Rep_Item (Node4-Sem)
+
+      ---------------------------------
+      -- 13.4  Enumeration aggregate --
+      ---------------------------------
+
+      --  ENUMERATION_AGGREGATE ::= ARRAY_AGGREGATE
+
+      ------------------------------------------
+      -- 13.5.1  Record representation clause --
+      ------------------------------------------
+
+      --  RECORD_REPRESENTATION_CLAUSE ::=
+      --    for first_subtype_LOCAL_NAME use
+      --      record [MOD_CLAUSE]
+      --        {COMPONENT_CLAUSE}
+      --      end record;
+
+      --  Gigi restriction: Mod_Clause is always Empty (if present it is
+      --  replaced by a corresponding Alignment attribute definition clause).
+
+      --  Note: Component_Clauses can include pragmas
+
+      --  N_Record_Representation_Clause
+      --  Sloc points to FOR
+      --  Identifier (Node1) direct name
+      --  Mod_Clause (Node2) (set to Empty if no mod clause present)
+      --  Component_Clauses (List3)
+      --  Next_Rep_Item (Node4-Sem)
+
+      ------------------------------
+      -- 13.5.1  Component clause --
+      ------------------------------
+
+      --  COMPONENT_CLAUSE ::=
+      --    component_LOCAL_NAME at POSITION
+      --      range FIRST_BIT .. LAST_BIT;
+
+      --  N_Component_Clause
+      --  Sloc points to AT
+      --  Component_Name (Node1) points to Name or Attribute_Reference
+      --  Position (Node2)
+      --  First_Bit (Node3)
+      --  Last_Bit (Node4)
+
+      ----------------------
+      -- 13.5.1  Position --
+      ----------------------
+
+      --  POSITION ::= static_EXPRESSION
+
+      -----------------------
+      -- 13.5.1  First_Bit --
+      -----------------------
+
+      --  FIRST_BIT ::= static_SIMPLE_EXPRESSION
+
+      ----------------------
+      -- 13.5.1  Last_Bit --
+      ----------------------
+
+      --  LAST_BIT ::= static_SIMPLE_EXPRESSION
+
+      --------------------------
+      -- 13.8  Code statement --
+      --------------------------
+
+      --  CODE_STATEMENT ::= QUALIFIED_EXPRESSION;
+
+      --  Note: in GNAT, the qualified expression has the form
+
+      --    Asm_Insn'(Asm (...));
+
+      --      or
+
+      --    Asm_Insn'(Asm_Volatile (...))
+
+      --  See package System.Machine_Code in file s-maccod.ads for details
+      --  on the allowed parameters to Asm[_Volatile]. There are two ways
+      --  this node can arise, as a code statement, in which case the
+      --  expression is the qualified expression, or as a result of the
+      --  expansion of an intrinsic call to the Asm or Asm_Input procedure.
+
+      --  N_Code_Statement
+      --  Sloc points to first token of the expression
+      --  Expression (Node3)
+
+      --  Note: package Exp_Code contains an abstract functional interface
+      --  for use by Gigi in accessing the data from N_Code_Statement nodes.
+
+      ------------------------
+      -- 13.12  Restriction --
+      ------------------------
+
+      --  RESTRICTION ::=
+      --    restriction_IDENTIFIER
+      --  | restriction_parameter_IDENTIFIER => EXPRESSION
+
+      --  There is no explicit node for restrictions. Instead the restriction
+      --  appears in normal pragma syntax as a pragma argument association,
+      --  which has the same syntactic form.
+
+      --------------------------
+      -- B.2  Shift Operators --
+      --------------------------
+
+      --  Calls to the intrinsic shift functions are converted to one of
+      --  the following shift nodes, which have the form of normal binary
+      --  operator names. Note that for a given shift operation, one node
+      --  covers all possible types, as for normal operators.
+
+      --  Note: it is perfectly permissible for the expander to generate
+      --  shift operation nodes directly, in which case they will be analyzed
+      --  and parsed in the usual manner.
+
+      --  Sprint syntax: shift-function-name!(expr, count)
+
+      --  Note: the Left_Opnd field holds the first argument (the value to
+      --  be shifted). The Right_Opnd field holds the second argument (the
+      --  shift count). The Chars field is the name of the intrinsic function.
+
+      --  N_Op_Rotate_Left
+      --  Sloc points to the function name
+      --  plus fields for binary operator
+      --  plus fields for expression
+      --  Shift_Count_OK (Flag4-Sem)
+
+      --  N_Op_Rotate_Right
+      --  Sloc points to the function name
+      --  plus fields for binary operator
+      --  plus fields for expression
+      --  Shift_Count_OK (Flag4-Sem)
+
+      --  N_Op_Shift_Left
+      --  Sloc points to the function name
+      --  plus fields for binary operator
+      --  plus fields for expression
+      --  Shift_Count_OK (Flag4-Sem)
+
+      --  N_Op_Shift_Right_Arithmetic
+      --  Sloc points to the function name
+      --  plus fields for binary operator
+      --  plus fields for expression
+      --  Shift_Count_OK (Flag4-Sem)
+
+      --  N_Op_Shift_Right
+      --  Sloc points to the function name
+      --  plus fields for binary operator
+      --  plus fields for expression
+      --  Shift_Count_OK (Flag4-Sem)
+
+   --------------------------
+   -- Obsolescent Features --
+   --------------------------
+
+      --  The syntax descriptions and tree nodes for obsolescent features are
+      --  grouped together, corresponding to their location in appendix I in
+      --  the RM. However, parsing and semantic analysis for these constructs
+      --  is located in an appropriate chapter (see individual notes).
+
+      ---------------------------
+      -- J.3  Delta Constraint --
+      ---------------------------
+
+      --  Note: the parse routine for this construct is located in section
+      --  3.5.9 of Par-Ch3, and semantic analysis is in Sem_Ch3, which is
+      --  where delta constraint logically belongs.
+
+      --  DELTA_CONSTRAINT ::= DELTA static_EXPRESSION [RANGE_CONSTRAINT]
+
+      --  N_Delta_Constraint
+      --  Sloc points to DELTA
+      --  Delta_Expression (Node3)
+      --  Range_Constraint (Node4) (set to Empty if not present)
+
+      --------------------
+      -- J.7  At Clause --
+      --------------------
+
+      --  AT_CLAUSE ::= for DIRECT_NAME use at EXPRESSION;
+
+      --  Note: the parse routine for this construct is located in Par-Ch13,
+      --  and the semantic analysis is in Sem_Ch13, where at clause logically
+      --  belongs if it were not obsolescent.
+
+      --  Note: in Ada 83 the expression must be a simple expression
+
+      --  Gigi restriction: This node never appears, it is rewritten as an
+      --  address attribute definition clause.
+
+      --  N_At_Clause
+      --  Sloc points to FOR
+      --  Identifier (Node1)
+      --  Expression (Node3)
+
+      ---------------------
+      -- J.8  Mod clause --
+      ---------------------
+
+      --  MOD_CLAUSE ::= at mod static_EXPRESSION;
+
+      --  Note: the parse routine for this construct is located in Par-Ch13,
+      --  and the semantic analysis is in Sem_Ch13, where mod clause logically
+      --  belongs if it were not obsolescent.
+
+      --  Note: in Ada 83, the expression must be a simple expression
+
+      --  Gigi restriction: this node never appears. It is replaced
+      --  by a corresponding Alignment attribute definition clause.
+
+      --  Note: pragmas can appear before and after the MOD_CLAUSE since
+      --  its name has "clause" in it. This is rather strange, but is quite
+      --  definitely specified. The pragmas before are collected in the
+      --  Pragmas_Before field of the mod clause node itself, and pragmas
+      --  after are simply swallowed up in the list of component clauses.
+
+      --  N_Mod_Clause
+      --  Sloc points to AT
+      --  Expression (Node3)
+      --  Pragmas_Before (List4) Pragmas before mod clause (No_List if none)
+
+   --------------------
+   -- Semantic Nodes --
+   --------------------
+
+   --  These semantic nodes are used to hold additional semantic information.
+   --  They are inserted into the tree as a result of semantic processing.
+   --  Although there are no legitimate source syntax constructions that
+   --  correspond directly to these nodes, we need a source syntax for the
+   --  reconstructed tree printed by Sprint, and the node descriptions here
+   --  show this syntax.
+
+      ----------------------------
+      -- Conditional Expression --
+      ----------------------------
+
+      --  This node is used to represent an expression corresponding to the
+      --  C construct (condition ? then-expression : else_expression), where
+      --  Expressions is a three element list, whose first expression is the
+      --  condition, and whose second and third expressions are the then and
+      --  else expressions respectively.
+
+      --  Note: the Then_Actions and Else_Actions fields are always set to
+      --  No_List in the tree passed to Gigi. These fields are used only
+      --  for temporary processing purposes in the expander.
+
+      --  Sprint syntax: (if expr then expr else expr)
+
+      --  N_Conditional_Expression
+      --  Sloc points to related node
+      --  Expressions (List1)
+      --  Then_Actions (List2-Sem)
+      --  Else_Actions (List3-Sem)
+      --  plus fields for expression
+
+      --  Note: in the case where a debug source file is generated, the Sloc
+      --  for this node points to the IF keyword in the Sprint file output.
+
+      -------------------
+      -- Expanded_Name --
+      -------------------
+
+      --  The N_Expanded_Name node is used to represent a selected component
+      --  name that has been resolved to an expanded name. The semantic phase
+      --  replaces N_Selected_Component nodes that represent names by the use
+      --  of this node, leaving the N_Selected_Component node used only when
+      --  the prefix is a record or protected type.
+
+      --  The fields of the N_Expanded_Name node are layed out identically
+      --  to those of the N_Selected_Component node, allowing conversion of
+      --  an expanded name node to a selected component node to be done
+      --  easily, see Sinfo.CN.Change_Selected_Component_To_Expanded_Name.
+
+      --  There is no special sprint syntax for an expanded name.
+
+      --  N_Expanded_Name
+      --  Sloc points to the period
+      --  Chars (Name1) copy of Chars field of selector name
+      --  Prefix (Node3)
+      --  Selector_Name (Node2)
+      --  Entity (Node4-Sem)
+      --  Redundant_Use (Flag13-Sem)
+      --  Has_Private_View (Flag11-Sem) set in generic units.
+      --  plus fields for expression
+
+      --------------------
+      -- Free Statement --
+      --------------------
+
+      --  The N_Free_Statement node is generated as a result of a call to an
+      --  instantiation of Unchecked_Deallocation. The instantiation of this
+      --  generic is handled specially and generates this node directly.
+
+      --  Sprint syntax: free expression
+
+      --  N_Free_Statement
+      --  Sloc is copied from the unchecked deallocation call
+      --  Expression (Node3) argument to unchecked deallocation call
+      --  Storage_Pool (Node1-Sem)
+      --  Procedure_To_Call (Node4-Sem)
+
+      --  Note: in the case where a debug source file is generated, the Sloc
+      --  for this node points to the FREE keyword in the Sprint file output.
+
+      -------------------
+      -- Freeze Entity --
+      -------------------
+
+      --  This node marks the point in a declarative part at which an entity
+      --  declared therein becomes frozen. The expander places initialization
+      --  procedures for types at those points. Gigi uses the freezing point
+      --  to elaborate entities that may depend on previous private types.
+
+      --  See the section in Einfo "Delayed Freezing and Elaboration" for
+      --  a full description of the use of this node.
+
+      --  The Entity field points back to the entity for the type (whose
+      --  Freeze_Node field points back to this freeze node).
+
+      --  The Actions field contains a list of declarations and statements
+      --  generated by the expander which are associated with the freeze
+      --  node, and are elaborated as though the freeze node were replaced
+      --  by this sequence of actions.
+
+      --  Note: the Sloc field in the freeze node references a construct
+      --  associated with the freezing point. This is used for posting
+      --  messages in some error/warning situations, e.g. the case where
+      --  a primitive operation of a tagged type is declared too late.
+
+      --  Sprint syntax: freeze entity-name [
+      --                   freeze actions
+      --                 ]
+
+      --  N_Freeze_Entity
+      --  Sloc points near freeze point (see above special note)
+      --  Entity (Node4-Sem)
+      --  Access_Types_To_Process (Elist2-Sem) (set to No_Elist if none)
+      --  TSS_Elist (Elist3-Sem) (set to No_Elist if no associated TSS's)
+      --  Actions (List1) (set to No_List if no freeze actions)
+      --  First_Subtype_Link (Node5-Sem) (set to Empty if no link)
+
+      --  The Actions field holds actions associated with the freeze. These
+      --  actions are elaborated at the point where the type is frozen.
+
+      --  Note: in the case where a debug source file is generated, the Sloc
+      --  for this node points to the FREEZE keyword in the Sprint file output.
+
+      --------------------------------
+      -- Implicit Label Declaration --
+      --------------------------------
+
+      --  An implicit label declaration is created for every occurrence of a
+      --  label on a statement or a label on a block or loop. It is chained
+      --  in the declarations of the innermost enclosing block as specified
+      --  in RM section 5.1 (3).
+
+      --  The Defining_Identifier is the actual identifier for the
+      --  statement identifier. Note that the occurrence of the label
+      --  is a reference, NOT the defining occurrence. The defining
+      --  occurrence occurs at the head of the innermost enclosing
+      --  block, and is represented by this node.
+
+      --  Note: from the grammar, this might better be called an implicit
+      --  statement identifier declaration, but the term we choose seems
+      --  friendlier, since at least informally statement identifiers are
+      --  called labels in both cases (i.e. when used in labels, and when
+      --  used as the identifiers of blocks and loops).
+
+      --  Note: although this is logically a semantic node, since it does
+      --  not correspond directly to a source syntax construction, these
+      --  nodes are actually created by the parser in a post pass done just
+      --  after parsing is complete, before semantic analysis is started (see
+      --  the Par.Labl subunit in file par-labl.adb).
+
+      --  Sprint syntax: labelname : label;
+
+      --  N_Implicit_Label_Declaration
+      --  Sloc points to the << of the label
+      --  Defining_Identifier (Node1)
+      --  Label_Construct (Node2-Sem)
+
+      --  Note: in the case where a debug source file is generated, the Sloc
+      --  for this node points to the label name in the generated declaration.
+
+      ---------------------
+      -- Itype_Reference --
+      ---------------------
+
+      --  This node is used to create a reference to an Itype. The only
+      --  purpose is to make sure that the Itype is defined if this is the
+      --  first reference.
+
+      --  A typical use of this node is when an Itype is to be referenced in
+      --  two branches of an if statement. In this case it is important that
+      --  the first use of the Itype not be inside the conditional, since
+      --  then it might not be defined if the wrong branch of the if is
+      --  taken in the case where the definition generates elaboration code.
+
+      --  The Itype field points to the referenced Itype
+
+      --  sprint syntax: reference itype-name
+
+      --  N_Itype_Reference
+      --  Sloc points to the node generating the reference
+      --  Itype (Node1-Sem)
+
+      --  Note: in the case where a debug source file is generated, the Sloc
+      --  for this node points to the REFERENCE keyword in the file output.
+
+      ---------------------
+      -- Raise_xxx_Error --
+      ---------------------
+
+      --  One of these nodes is created during semantic analysis to replace
+      --  a node for an expression that is determined to definitely raise
+      --  the corresponding exception.
+
+      --  The N_Raise_xxx_Error node may also stand alone in place
+      --  of a declaration or statement, in which case it simply causes
+      --  the exception to be raised (i.e. it is equivalent to a raise
+      --  statement that raises the corresponding exception). This use
+      --  is distinguished by the fact that the Etype in this case is
+      --  Standard_Void_Type, In the subexprssion case, the Etype is the
+      --  same as the type of the subexpression which it replaces.
+
+      --  If Condition is empty, then the raise is unconditional. If the
+      --  Condition field is non-empty, it is a boolean expression which
+      --  is first evaluated, and the exception is raised only if the
+      --  value of the expression is True. In the unconditional case, the
+      --  creation of this node is usually accompanied by a warning message
+      --  error. The creation of this node will usually be accompanied by a
+      --  message (unless it appears within the right operand of a short
+      --  circuit form whose left argument is static and decisively
+      --  eliminates elaboration of the raise operation.
+
+      --  Gigi restriction: This expander ensures that the type of the
+      --  Condition field is always Standard.Boolean, even if the type
+      --  in the source is some non-standard boolean type.
+
+      --  Sprint syntax: [xxx_error]
+      --             or: [xxx_error when condition]
+
+      --  N_Raise_Constraint_Error
+      --  Sloc references related construct
+      --  Condition (Node1) (set to Empty if no condition)
+      --  Sloc is copied from the expression generating the exception
+      --  plus fields for expression
+
+      --  N_Raise_Program_Error
+      --  Sloc references related construct
+      --  Condition (Node1) (set to Empty if no condition)
+      --  Sloc is copied from the construct generating the exception
+      --  plus fields for expression
+
+      --  N_Raise_Storage_Error
+      --  Sloc references related construct
+      --  Condition (Node1) (set to Empty if no condition)
+      --  Sloc is copied from the construct generating the exception
+      --  plus fields for expression
+
+      --  Note: in the case where a debug source file is generated, the Sloc
+      --  for this node points to the left bracket in the Sprint file output.
+
+      ---------------
+      -- Reference --
+      ---------------
+
+      --  For a number of purposes, we need to construct references to objects.
+      --  These references are subsequently treated as normal access values.
+      --  An example is the construction of the parameter block passed to a
+      --  task entry. The N_Reference node is provided for this purpose. It is
+      --  similar in effect to the use of the Unrestricted_Access attribute,
+      --  and like Unrestricted_Access can be applied to objects which would
+      --  not be valid prefixes for the Unchecked_Access attribute (e.g.
+      --  objects which are not aliased, and slices). In addition it can be
+      --  applied to composite type values as well as objects, including string
+      --  values and aggregates.
+
+      --  Note: we use the Prefix field for this expression so that the
+      --  resulting node can be treated using common code with the attribute
+      --  nodes for the 'Access and related attributes. Logically it would make
+      --  more sense to call it an Expression field, but then we would have to
+      --  special case the treatment of the N_Reference node.
+
+      --  Sprint syntax: prefix'reference
+
+      --  N_Reference
+      --  Sloc is copied from the expression
+      --  Prefix (Node3)
+      --  plus fields for expression
+
+      --  Note: in the case where a debug source file is generated, the Sloc
+      --  for this node points to the quote in the Sprint file output.
+
+      ---------------------
+      -- Subprogram_Info --
+      ---------------------
+
+      --  This node generates the appropriate Subprogram_Info value for a
+      --  given procedure. See Ada.Exceptions for further details
+
+      --  Sprint syntax: subprog'subprogram_info
+
+      --  N_Subprogram_Info
+      --  Sloc points to the entity for the procedure
+      --  Identifier (Node1) identifier referencing the procedure
+      --  Etype (Node5-Sem) type (always set to Ada.Exceptions.Code_Loc
+
+      --  Note: in the case where a debug source file is generated, the Sloc
+      --  for this node points to the quote in the Sprint file output.
+
+      --------------------------
+      -- Unchecked Expression --
+      --------------------------
+
+      --  An unchecked expression is one that must be analyzed and resolved
+      --  with all checks off, regardless of the current setting of scope
+      --  suppress flags.
+
+      --  Sprint syntax: `(expression).
+
+      --  Note: this node is always removed from the tree (and replaced by
+      --  its constituent expression) on completion of analysis, so it only
+      --  appears in intermediate trees, and will never be seen by Gigi.
+
+      --  N_Unchecked_Expression
+      --  Sloc is a copy of the Sloc of the expression
+      --  Expression (Node3)
+      --  plus fields for expression
+
+      --  Note: in the case where a debug source file is generated, the Sloc
+      --  for this node points to the back quote in the Sprint file output.
+
+      -------------------------------
+      -- Unchecked Type Conversion --
+      -------------------------------
+
+      --  An unchecked type conversion node represents the semantic action
+      --  corresponding to a call to an instantiation of Unchecked_Conversion.
+      --  It is generated as a result of actual use of Unchecked_Conversion
+      --  and also the expander generates unchecked type conversion nodes
+      --  directly for expansion of complex semantic actions.
+
+      --  Note: an unchecked type conversion is a variable as far as the
+      --  semantics are concerned, which is convenient for the expander.
+      --  This does not change what Ada source programs are legal, since
+      --  clearly a function call to an instantiation of Unchecked_Conversion
+      --  is not a variable in any case.
+
+      --  Sprint syntax: subtype-mark!(expression).
+
+      --  N_Unchecked_Type_Conversion
+      --  Sloc points to related node in source
+      --  Subtype_Mark (Node4)
+      --  Expression (Node3)
+      --  Kill_Range_Check (Flag11-Sem)
+      --  plus fields for expression
+
+      --  Note: in the case where a debug source file is generated, the Sloc
+      --  for this node points to the exclamation in the Sprint file output.
+
+      -----------------------------------
+      -- Validate_Unchecked_Conversion --
+      -----------------------------------
+
+      --  The front end does most of the validation of unchecked conversion,
+      --  including checking sizes (this is done after the back end is called
+      --  to take advantage of back-annotation of calculated sizes).
+
+      --  The front end also deals with specific cases that are not allowed
+      --  e.g. involving unconstrained array types.
+
+      --  For the case of the standard gigi backend, this means that all
+      --  checks are done in the front-end.
+
+      --  However, in the case of specialized back-ends, notably the JVM
+      --  backend for JGNAT, additional requirements and restrictions apply
+      --  to unchecked conversion, and these are most conveniently performed
+      --  in the specialized back-end.
+
+      --  To accomodate this requirement, for such back ends, the following
+      --  special node is generated recording an unchecked conversion that
+      --  needs to be validated. The back end should post an appropriate
+      --  error message if the unchecked conversion is invalid or warrants
+      --  a special warning message.
+
+      --  Source_Type and Target_Type point to the entities for the two
+      --  types involved in the unchecked conversion instantiation that
+      --  is to be validated.
+
+      --  Sprint syntax: validate Unchecked_Conversion (source, target);
+
+      --  N_Validate_Unchecked_Conversion
+      --  Sloc points to instantiation (location for warning message)
+      --  Source_Type (Node1-Sem)
+      --  Target_Type (Node2-Sem)
+
+      --  Note: in the case where a debug source file is generated, the Sloc
+      --  for this node points to the VALIDATE keyword in the file output.
+
+   -----------
+   -- Empty --
+   -----------
+
+   --  N_Empty
+   --  Chars (Name1) is set to No_Name
+   --  Used as the contents of the Nkind field of the dummy Empty node
+   --  and in some other situations to indicate an uninitialized value.
+
+   -----------
+   -- Error --
+   -----------
+
+   --  N_Error
+   --  Chars (Name1) is set to Error_Name
+   --  Used as the contents of the Nkind field of the dummy Error node
+
+   --------------------------
+   -- Node Type Definition --
+   --------------------------
+
+   --  The following is the definition of the Node_Kind type. As previously
+   --  discussed, this is separated off to allow rearrangement of the order
+   --  to facilitiate definition of subtype ranges. The comments show the
+   --  subtype classes which apply to each set of node kinds. The first
+   --  entry in the comment characterizes the following list of nodes.
+
+   type Node_Kind is (
+      N_Unused_At_Start,
+
+      --  N_Representation_Clause
+      N_At_Clause,
+      N_Component_Clause,
+      N_Enumeration_Representation_Clause,
+      N_Mod_Clause,
+      N_Record_Representation_Clause,
+
+      --  N_Representation_Clause, N_Has_Chars
+      N_Attribute_Definition_Clause,
+
+      --  N_Has_Chars
+      N_Empty,
+      N_Error,
+      N_Pragma,
+      N_Pragma_Argument_Association,
+
+      --  N_Entity, N_Has_Etype, N_Has_Chars
+      N_Defining_Character_Literal,
+      N_Defining_Identifier,
+      N_Defining_Operator_Symbol,
+
+      --  N_Subexpr, N_Has_Etype, N_Has_Chars, N_Has_Entity
+      N_Expanded_Name,
+
+      --  N_Direct_Name, N_Subexpr, N_Has_Etype,
+      --  N_Has_Chars, N_Has_Entity
+      N_Identifier,
+      N_Operator_Symbol,
+
+      --  N_Direct_Name, N_Subexpr, N_Has_Etype,
+      --  N_Has_Chars, N_Has_Entity
+      N_Character_Literal,
+
+      --  N_Binary_Op, N_Op, N_Subexpr,
+      --  N_Has_Etype, N_Has_Chars, N_Has_Entity
+      N_Op_Add,
+      N_Op_Concat,
+      N_Op_Divide,
+      N_Op_Expon,
+      N_Op_Mod,
+      N_Op_Multiply,
+      N_Op_Rem,
+      N_Op_Subtract,
+
+      --  N_Binary_Op, N_Op, N_Subexpr, N_Has_Etype
+      --  N_Has_Entity, N_Has_Chars, N_Op_Boolean
+      N_Op_And,
+
+      --  N_Binary_Op, N_Op, N_Subexpr, N_Has_Etype
+      --  N_Has_Entity, N_Has_Chars, N_Op_Boolean,
+      --  N_Op_Compare
+      N_Op_Eq,
+      N_Op_Ge,
+      N_Op_Gt,
+      N_Op_Le,
+      N_Op_Lt,
+      N_Op_Ne,
+
+      --  N_Binary_Op, N_Op, N_Subexpr, N_Has_Etype
+      --  N_Has_Entity, N_Has_Chars, N_Op_Boolean
+      N_Op_Or,
+      N_Op_Xor,
+
+      --  N_Binary_Op, N_Op, N_Subexpr, N_Has_Etype,
+      --  N_Op_Shift, N_Has_Chars, N_Has_Entity
+      N_Op_Rotate_Left,
+      N_Op_Rotate_Right,
+      N_Op_Shift_Left,
+      N_Op_Shift_Right,
+      N_Op_Shift_Right_Arithmetic,
+
+      --  N_Unary_Op, N_Op, N_Subexpr, N_Has_Etype,
+      --  N_Has_Chars, N_Has_Entity
+      N_Op_Abs,
+      N_Op_Minus,
+      N_Op_Not,
+      N_Op_Plus,
+
+      --  N_Subexpr, N_Has_Etype, N_Has_Entity
+      N_Attribute_Reference,
+
+      --  N_Subexpr, N_Has_Etype
+      N_And_Then,
+      N_Conditional_Expression,
+      N_Explicit_Dereference,
+      N_Function_Call,
+      N_In,
+      N_Indexed_Component,
+      N_Integer_Literal,
+      N_Not_In,
+      N_Null,
+      N_Or_Else,
+      N_Procedure_Call_Statement,
+      N_Qualified_Expression,
+
+      --  N_Raise_xxx_Error, N_Subexpr, N_Has_Etype
+
+      N_Raise_Constraint_Error,
+      N_Raise_Program_Error,
+      N_Raise_Storage_Error,
+
+      --  N_Subexpr, N_Has_Etype
+
+      N_Aggregate,
+      N_Allocator,
+      N_Extension_Aggregate,
+      N_Range,
+      N_Real_Literal,
+      N_Reference,
+      N_Selected_Component,
+      N_Slice,
+      N_String_Literal,
+      N_Subprogram_Info,
+      N_Type_Conversion,
+      N_Unchecked_Expression,
+      N_Unchecked_Type_Conversion,
+
+      --  N_Has_Etype
+      N_Subtype_Indication,
+
+      --  N_Declaration
+      N_Component_Declaration,
+      N_Entry_Declaration,
+      N_Formal_Object_Declaration,
+      N_Formal_Type_Declaration,
+      N_Full_Type_Declaration,
+      N_Incomplete_Type_Declaration,
+      N_Loop_Parameter_Specification,
+      N_Object_Declaration,
+      N_Protected_Type_Declaration,
+      N_Private_Extension_Declaration,
+      N_Private_Type_Declaration,
+      N_Subtype_Declaration,
+
+      --  N_Subprogram_Specification, N_Declaration
+      N_Function_Specification,
+      N_Procedure_Specification,
+
+      --  (nothing special)
+      N_Entry_Index_Specification,
+      N_Freeze_Entity,
+
+      --  N_Access_To_Subprogram_Definition
+      N_Access_Function_Definition,
+      N_Access_Procedure_Definition,
+
+      --  N_Later_Decl_Item,
+      N_Task_Type_Declaration,
+
+      --  N_Body_Stub, N_Later_Decl_Item
+      N_Package_Body_Stub,
+      N_Protected_Body_Stub,
+      N_Subprogram_Body_Stub,
+      N_Task_Body_Stub,
+
+      --  N_Generic_Instantiation, N_Later_Decl_Item
+      N_Function_Instantiation,
+      N_Package_Instantiation,
+      N_Procedure_Instantiation,
+
+      --  N_Unit_Body, N_Later_Decl_Item, N_Proper_Body
+      N_Package_Body,
+      N_Subprogram_Body,
+
+      --  N_Later_Decl_Item, N_Proper_Body
+      N_Protected_Body,
+      N_Task_Body,
+
+      --  N_Later_Decl_Item
+      N_Implicit_Label_Declaration,
+      N_Package_Declaration,
+      N_Single_Task_Declaration,
+      N_Subprogram_Declaration,
+      N_Use_Package_Clause,
+
+      --  N_Generic_Declaration, N_Later_Decl_Item
+      N_Generic_Package_Declaration,
+      N_Generic_Subprogram_Declaration,
+
+      --  N_Array_Type_Definition
+      N_Constrained_Array_Definition,
+      N_Unconstrained_Array_Definition,
+
+      --  N_Renaming_Declaration
+      N_Exception_Renaming_Declaration,
+      N_Object_Renaming_Declaration,
+      N_Package_Renaming_Declaration,
+      N_Subprogram_Renaming_Declaration,
+
+      --  N_Generic_Renaming_Declarations, N_Renaming_Declaration
+      N_Generic_Function_Renaming_Declaration,
+      N_Generic_Package_Renaming_Declaration,
+      N_Generic_Procedure_Renaming_Declaration,
+
+      --  N_Statement_Other_Than_Procedure_Call
+      N_Abort_Statement,
+      N_Accept_Statement,
+      N_Assignment_Statement,
+      N_Asynchronous_Select,
+      N_Block_Statement,
+      N_Case_Statement,
+      N_Code_Statement,
+      N_Conditional_Entry_Call,
+      N_Delay_Relative_Statement,
+      N_Delay_Until_Statement,
+      N_Entry_Call_Statement,
+      N_Free_Statement,
+      N_Goto_Statement,
+      N_Loop_Statement,
+      N_Null_Statement,
+      N_Raise_Statement,
+      N_Requeue_Statement,
+      N_Return_Statement,
+      N_Selective_Accept,
+      N_Timed_Entry_Call,
+
+      --  N_Statement_Other_Than_Procedure_Call, N_Has_Condition
+      N_Exit_Statement,
+      N_If_Statement,
+
+      --  N_Has_Condition
+      N_Accept_Alternative,
+      N_Delay_Alternative,
+      N_Elsif_Part,
+      N_Entry_Body_Formal_Part,
+      N_Iteration_Scheme,
+      N_Terminate_Alternative,
+
+      --  Other nodes (not part of any subtype class)
+      N_Abortable_Part,
+      N_Abstract_Subprogram_Declaration,
+      N_Access_Definition,
+      N_Access_To_Object_Definition,
+      N_Case_Statement_Alternative,
+      N_Compilation_Unit,
+      N_Compilation_Unit_Aux,
+      N_Component_Association,
+      N_Component_List,
+      N_Derived_Type_Definition,
+      N_Decimal_Fixed_Point_Definition,
+      N_Defining_Program_Unit_Name,
+      N_Delta_Constraint,
+      N_Designator,
+      N_Digits_Constraint,
+      N_Discriminant_Association,
+      N_Discriminant_Specification,
+      N_Enumeration_Type_Definition,
+      N_Entry_Body,
+      N_Entry_Call_Alternative,
+      N_Exception_Declaration,
+      N_Exception_Handler,
+      N_Floating_Point_Definition,
+      N_Formal_Decimal_Fixed_Point_Definition,
+      N_Formal_Derived_Type_Definition,
+      N_Formal_Discrete_Type_Definition,
+      N_Formal_Floating_Point_Definition,
+      N_Formal_Modular_Type_Definition,
+      N_Formal_Ordinary_Fixed_Point_Definition,
+      N_Formal_Package_Declaration,
+      N_Formal_Private_Type_Definition,
+      N_Formal_Signed_Integer_Type_Definition,
+      N_Formal_Subprogram_Declaration,
+      N_Generic_Association,
+      N_Handled_Sequence_Of_Statements,
+      N_Index_Or_Discriminant_Constraint,
+      N_Itype_Reference,
+      N_Label,
+      N_Modular_Type_Definition,
+      N_Number_Declaration,
+      N_Ordinary_Fixed_Point_Definition,
+      N_Others_Choice,
+      N_Package_Specification,
+      N_Parameter_Association,
+      N_Parameter_Specification,
+      N_Protected_Definition,
+      N_Range_Constraint,
+      N_Real_Range_Specification,
+      N_Record_Definition,
+      N_Signed_Integer_Type_Definition,
+      N_Single_Protected_Declaration,
+      N_Subunit,
+      N_Task_Definition,
+      N_Triggering_Alternative,
+      N_Use_Type_Clause,
+      N_Validate_Unchecked_Conversion,
+      N_Variant,
+      N_Variant_Part,
+      N_With_Clause,
+      N_With_Type_Clause,
+      N_Unused_At_End);
+
+   for Node_Kind'Size use 8;
+   --  The data structures in Atree assume this!
+
+   ----------------------------
+   -- Node Class Definitions --
+   ----------------------------
+
+   subtype N_Access_To_Subprogram_Definition is Node_Kind range
+     N_Access_Function_Definition ..
+     N_Access_Procedure_Definition;
+
+   subtype N_Array_Type_Definition is Node_Kind range
+     N_Constrained_Array_Definition ..
+     N_Unconstrained_Array_Definition;
+
+   subtype N_Binary_Op is Node_Kind range
+     N_Op_Add ..
+     N_Op_Shift_Right_Arithmetic;
+
+   subtype N_Body_Stub is Node_Kind range
+     N_Package_Body_Stub ..
+     N_Task_Body_Stub;
+
+   subtype N_Declaration is Node_Kind range
+     N_Component_Declaration ..
+     N_Procedure_Specification;
+   --  Note: this includes all constructs normally thought of as declarations
+   --  except those which are separately grouped as later declarations.
+
+   subtype N_Direct_Name is Node_Kind range
+     N_Identifier ..
+     N_Character_Literal;
+
+   subtype N_Entity is Node_Kind range
+     N_Defining_Character_Literal ..
+     N_Defining_Operator_Symbol;
+
+   subtype N_Generic_Declaration is Node_Kind range
+     N_Generic_Package_Declaration ..
+     N_Generic_Subprogram_Declaration;
+
+   subtype N_Generic_Instantiation is Node_Kind range
+     N_Function_Instantiation ..
+     N_Procedure_Instantiation;
+
+   subtype N_Generic_Renaming_Declaration is Node_Kind range
+     N_Generic_Function_Renaming_Declaration ..
+     N_Generic_Procedure_Renaming_Declaration;
+
+   subtype N_Has_Chars is Node_Kind range
+     N_Attribute_Definition_Clause ..
+     N_Op_Plus;
+
+   subtype N_Has_Entity is Node_Kind range
+     N_Expanded_Name ..
+     N_Attribute_Reference;
+   --  Nodes that have Entity fields
+   --  Warning: DOES NOT INCLUDE N_Freeze_Entity!
+
+   subtype N_Has_Etype is Node_Kind range
+     N_Defining_Character_Literal ..
+     N_Subtype_Indication;
+
+   subtype N_Later_Decl_Item is Node_Kind range
+     N_Task_Type_Declaration ..
+     N_Generic_Subprogram_Declaration;
+   --  Note: this is Ada 83 relevant only (see Ada 83 RM 3.9 (2)) and
+   --  includes only those items which can appear as later declarative
+   --  items. This also includes N_Implicit_Label_Declaration which is
+   --  not specifically in the grammar but may appear as a valid later
+   --  declarative items. It does NOT include N_Pragma which can also
+   --  appear among later declarative items. It does however include
+   --  N_Protected_Body, which is a bit peculiar, but harmless since
+   --  this cannot appear in Ada 83 mode anyway.
+
+   subtype N_Op is Node_Kind range
+     N_Op_Add ..
+     N_Op_Plus;
+
+   subtype N_Op_Boolean is Node_Kind range
+     N_Op_And ..
+     N_Op_Xor;
+   --  Binary operators which take operands of a boolean type, and yield
+   --  a result of a boolean type.
+
+   subtype N_Op_Compare is Node_Kind range
+     N_Op_Eq ..
+     N_Op_Ne;
+
+   subtype N_Op_Shift is Node_Kind range
+     N_Op_Rotate_Left ..
+     N_Op_Shift_Right_Arithmetic;
+
+   subtype N_Proper_Body is Node_Kind range
+     N_Package_Body ..
+     N_Task_Body;
+
+   subtype N_Raise_xxx_Error is Node_Kind range
+     N_Raise_Constraint_Error ..
+     N_Raise_Storage_Error;
+
+   subtype N_Renaming_Declaration is Node_Kind range
+     N_Exception_Renaming_Declaration ..
+     N_Generic_Procedure_Renaming_Declaration;
+
+   subtype N_Representation_Clause is Node_Kind range
+     N_At_Clause ..
+     N_Attribute_Definition_Clause;
+
+   subtype N_Statement_Other_Than_Procedure_Call is Node_Kind range
+     N_Abort_Statement ..
+     N_If_Statement;
+   --  Note that this includes all statement types except for the cases of the
+   --  N_Procedure_Call_Statement which is considered to be a subexpression
+   --  (since overloading is possible, so it needs to go through the normal
+   --  overloading resolution for expressions).
+
+   subtype N_Has_Condition is Node_Kind range
+     N_Exit_Statement ..
+     N_Terminate_Alternative;
+   --  Nodes with condition fields (does not include N_Raise_xxx_Error)
+
+   subtype N_Subexpr is Node_Kind range
+     N_Expanded_Name ..
+     N_Unchecked_Type_Conversion;
+   --  Nodes with expression fields
+
+   subtype N_Subprogram_Specification is Node_Kind range
+     N_Function_Specification ..
+     N_Procedure_Specification;
+
+   subtype N_Unary_Op is Node_Kind range
+     N_Op_Abs ..
+     N_Op_Plus;
+
+   subtype N_Unit_Body is Node_Kind range
+     N_Package_Body ..
+     N_Subprogram_Body;
+
+   ---------------------------
+   -- Node Access Functions --
+   ---------------------------
+
+   --  The following functions return the contents of the indicated field of
+   --  the node referenced by the argument, which is a Node_Id. They provide
+   --  logical access to fields in the node which could be accessed using the
+   --  Atree.Unchecked_Access package, but the idea is always to use these
+   --  higher level routines which preserve strong typing. In debug mode,
+   --  these routines check that they are being applied to an appropriate
+   --  node, as well as checking that the node is in range.
+
+   function ABE_Is_Certain
+     (N : Node_Id) return Boolean;    -- Flag18
+
+   function Abort_Present
+     (N : Node_Id) return Boolean;    -- Flag15
+
+   function Abortable_Part
+     (N : Node_Id) return Node_Id;    -- Node2
+
+   function Abstract_Present
+     (N : Node_Id) return Boolean;    -- Flag4
+
+   function Accept_Handler_Records
+     (N : Node_Id) return List_Id;    -- List5
+
+   function Accept_Statement
+     (N : Node_Id) return Node_Id;    -- Node2
+
+   function Access_Types_To_Process
+     (N : Node_Id) return Elist_Id;   -- Elist2
+
+   function Actions
+     (N : Node_Id) return List_Id;    -- List1
+
+   function Activation_Chain_Entity
+     (N : Node_Id) return Node_Id;    -- Node3
+
+   function Acts_As_Spec
+     (N : Node_Id) return Boolean;    -- Flag4
+
+   function Aggregate_Bounds
+     (N : Node_Id) return Node_Id;    -- Node3
+
+   function Aliased_Present
+     (N : Node_Id) return Boolean;    -- Flag4
+
+   function All_Others
+     (N : Node_Id) return Boolean;    -- Flag11
+
+   function All_Present
+     (N : Node_Id) return Boolean;    -- Flag15
+
+   function Alternatives
+     (N : Node_Id) return List_Id;    -- List4
+
+   function Ancestor_Part
+     (N : Node_Id) return Node_Id;    -- Node3
+
+   function Array_Aggregate
+     (N : Node_Id) return Node_Id;    -- Node3
+
+   function Assignment_OK
+     (N : Node_Id) return Boolean;    -- Flag15
+
+   function At_End_Proc
+     (N : Node_Id) return Node_Id;    -- Node1
+
+   function Attribute_Name
+     (N : Node_Id) return Name_Id;    -- Name2
+
+   function Aux_Decls_Node
+     (N : Node_Id) return Node_Id;    -- Node5
+
+   function Backwards_OK
+     (N : Node_Id) return Boolean;    -- Flag6
+
+   function Bad_Is_Detected
+     (N : Node_Id) return Boolean;    -- Flag15
+
+   function By_Ref
+     (N : Node_Id) return Boolean;    -- Flag5
+
+   function Body_Required
+     (N : Node_Id) return Boolean;    -- Flag13
+
+   function Body_To_Inline
+     (N : Node_Id) return Node_Id;    -- Node3
+
+   function Box_Present
+     (N : Node_Id) return Boolean;    -- Flag15
+
+   function Char_Literal_Value
+     (N : Node_Id) return Char_Code;  -- Char_Code2
+
+   function Chars
+     (N : Node_Id) return Name_Id;    -- Name1
+
+   function Choice_Parameter
+     (N : Node_Id) return Node_Id;    -- Node2
+
+   function Choices
+     (N : Node_Id) return List_Id;    -- List1
+
+   function Compile_Time_Known_Aggregate
+     (N : Node_Id) return Boolean;    -- Flag18
+
+   function Component_Associations
+     (N : Node_Id) return List_Id;    -- List2
+
+   function Component_Clauses
+     (N : Node_Id) return List_Id;    -- List3
+
+   function Component_Items
+     (N : Node_Id) return List_Id;    -- List3
+
+   function Component_List
+     (N : Node_Id) return Node_Id;    -- Node1
+
+   function Component_Name
+     (N : Node_Id) return Node_Id;    -- Node1
+
+   function Condition
+     (N : Node_Id) return Node_Id;    -- Node1
+
+   function Condition_Actions
+     (N : Node_Id) return List_Id;    -- List3
+
+   function Constant_Present
+     (N : Node_Id) return Boolean;    -- Flag17
+
+   function Constraint
+     (N : Node_Id) return Node_Id;    -- Node3
+
+   function Constraints
+     (N : Node_Id) return List_Id;    -- List1
+
+   function Context_Installed
+     (N : Node_Id) return Boolean;    -- Flag13
+
+   function Context_Items
+     (N : Node_Id) return List_Id;    -- List1
+
+   function Controlling_Argument
+     (N : Node_Id) return Node_Id;    -- Node1
+
+   function Conversion_OK
+     (N : Node_Id) return Boolean;    -- Flag14
+
+   function Corresponding_Body
+     (N : Node_Id) return Node_Id;    -- Node5
+
+   function Corresponding_Generic_Association
+     (N : Node_Id) return Node_Id;    -- Node5
+
+   function Corresponding_Integer_Value
+     (N : Node_Id) return Uint;       -- Uint4
+
+   function Corresponding_Spec
+     (N : Node_Id) return Node_Id;    -- Node5
+
+   function Corresponding_Stub
+     (N : Node_Id) return Node_Id;    -- Node3
+
+   function Dcheck_Function
+     (N : Node_Id) return Entity_Id;  -- Node5
+
+   function Debug_Statement
+     (N : Node_Id) return Node_Id;    -- Node3
+
+   function Declarations
+     (N : Node_Id) return List_Id;    -- List2
+
+   function Default_Expression
+     (N : Node_Id) return Node_Id;    -- Node5
+
+   function Default_Name
+     (N : Node_Id) return Node_Id;    -- Node2
+
+   function Defining_Identifier
+     (N : Node_Id) return Entity_Id;  -- Node1
+
+   function Defining_Unit_Name
+     (N : Node_Id) return Node_Id;    -- Node1
+
+   function Delay_Alternative
+     (N : Node_Id) return Node_Id;    -- Node4
+
+   function Delay_Finalize_Attach
+     (N : Node_Id) return Boolean;    -- Flag14
+
+   function Delay_Statement
+     (N : Node_Id) return Node_Id;    -- Node2
+
+   function Delta_Expression
+     (N : Node_Id) return Node_Id;    -- Node3
+
+   function Digits_Expression
+     (N : Node_Id) return Node_Id;    -- Node2
+
+   function Discr_Check_Funcs_Built
+     (N : Node_Id) return Boolean;    -- Flag11
+
+   function Discrete_Choices
+     (N : Node_Id) return List_Id;    -- List4
+
+   function Discrete_Range
+     (N : Node_Id) return Node_Id;    -- Node4
+
+   function Discrete_Subtype_Definition
+     (N : Node_Id) return Node_Id;    -- Node4
+
+   function Discrete_Subtype_Definitions
+     (N : Node_Id) return List_Id;    -- List2
+
+   function Discriminant_Specifications
+     (N : Node_Id) return List_Id;    -- List4
+
+   function Discriminant_Type
+     (N : Node_Id) return Node_Id;    -- Node5
+
+   function Do_Access_Check
+     (N : Node_Id) return Boolean;    -- Flag11
+
+   function Do_Accessibility_Check
+     (N : Node_Id) return Boolean;    -- Flag13
+
+   function Do_Discriminant_Check
+     (N : Node_Id) return Boolean;    -- Flag13
+
+   function Do_Division_Check
+     (N : Node_Id) return Boolean;    -- Flag13
+
+   function Do_Length_Check
+     (N : Node_Id) return Boolean;    -- Flag4
+
+   function Do_Overflow_Check
+     (N : Node_Id) return Boolean;    -- Flag17
+
+   function Do_Range_Check
+     (N : Node_Id) return Boolean;    -- Flag9
+
+   function Do_Storage_Check
+     (N : Node_Id) return Boolean;    -- Flag17
+
+   function Do_Tag_Check
+     (N : Node_Id) return Boolean;    -- Flag13
+
+   function Elaborate_All_Present
+     (N : Node_Id) return Boolean;    -- Flag15
+
+   function Elaborate_Present
+     (N : Node_Id) return Boolean;    -- Flag4
+
+   function Elaboration_Boolean
+     (N : Node_Id) return Node_Id;    -- Node2
+
+   function Else_Actions
+     (N : Node_Id) return List_Id;    -- List3
+
+   function Else_Statements
+     (N : Node_Id) return List_Id;    -- List4
+
+   function Elsif_Parts
+     (N : Node_Id) return List_Id;    -- List3
+
+   function Enclosing_Variant
+     (N : Node_Id) return Node_Id;    -- Node2
+
+   function End_Label
+     (N : Node_Id) return Node_Id;    -- Node4
+
+   function End_Span
+     (N : Node_Id) return Uint;       -- Uint5
+
+   function Entity
+     (N : Node_Id) return Node_Id;    -- Node4
+
+   function Entry_Body_Formal_Part
+     (N : Node_Id) return Node_Id;    -- Node5
+
+   function Entry_Call_Alternative
+     (N : Node_Id) return Node_Id;    -- Node1
+
+   function Entry_Call_Statement
+     (N : Node_Id) return Node_Id;    -- Node1
+
+   function Entry_Direct_Name
+     (N : Node_Id) return Node_Id;    -- Node1
+
+   function Entry_Index
+     (N : Node_Id) return Node_Id;    -- Node5
+
+   function Entry_Index_Specification
+     (N : Node_Id) return Node_Id;    -- Node4
+
+   function Etype
+     (N : Node_Id) return Node_Id;    -- Node5
+
+   function Exception_Choices
+     (N : Node_Id) return List_Id;    -- List4
+
+   function Exception_Handlers
+     (N : Node_Id) return List_Id;    -- List5
+
+   function Exception_Junk
+     (N : Node_Id) return Boolean;    -- Flag11
+
+   function Explicit_Actual_Parameter
+     (N : Node_Id) return Node_Id;    -- Node3
+
+   function Expansion_Delayed
+     (N : Node_Id) return Boolean;    -- Flag11
+
+   function Explicit_Generic_Actual_Parameter
+     (N : Node_Id) return Node_Id;    -- Node1
+
+   function Expression
+     (N : Node_Id) return Node_Id;    -- Node3
+
+   function Expressions
+     (N : Node_Id) return List_Id;    -- List1
+
+   function First_Bit
+     (N : Node_Id) return Node_Id;    -- Node3
+
+   function First_Inlined_Subprogram
+     (N : Node_Id) return Entity_Id;  -- Node3
+
+   function First_Name
+     (N : Node_Id) return Boolean;    -- Flag5
+
+   function First_Named_Actual
+     (N : Node_Id) return Node_Id;    -- Node4
+
+   function First_Real_Statement
+     (N : Node_Id) return Node_Id;    -- Node2
+
+   function First_Subtype_Link
+     (N : Node_Id) return Entity_Id;  -- Node5
+
+   function Float_Truncate
+     (N : Node_Id) return Boolean;    -- Flag11
+
+   function Formal_Type_Definition
+     (N : Node_Id) return Node_Id;    -- Node3
+
+   function Forwards_OK
+     (N : Node_Id) return Boolean;    -- Flag5
+
+   function From_At_Mod
+     (N : Node_Id) return Boolean;    -- Flag4
+
+   function Generic_Associations
+     (N : Node_Id) return List_Id;    -- List3
+
+   function Generic_Formal_Declarations
+     (N : Node_Id) return List_Id;    -- List2
+
+   function Generic_Parent
+     (N : Node_Id) return Node_Id;    -- Node5
+
+   function Generic_Parent_Type
+     (N : Node_Id) return Node_Id;    -- Node4
+
+   function Handled_Statement_Sequence
+     (N : Node_Id) return Node_Id;    -- Node4
+
+   function Handler_List_Entry
+     (N : Node_Id) return Node_Id;    -- Node2
+
+   function Has_Created_Identifier
+     (N : Node_Id) return Boolean;    -- Flag15
+
+   function Has_Dynamic_Length_Check
+     (N : Node_Id) return Boolean;    -- Flag10
+
+   function Has_Dynamic_Range_Check
+     (N : Node_Id) return Boolean;    -- Flag12
+
+   function Has_No_Elaboration_Code
+     (N : Node_Id) return Boolean;    -- Flag17
+
+   function Has_Priority_Pragma
+     (N : Node_Id) return Boolean;    -- Flag6
+
+   function Has_Private_View
+     (N : Node_Id) return Boolean;    -- Flag11
+
+   function Has_Storage_Size_Pragma
+     (N : Node_Id) return Boolean;    -- Flag5
+
+   function Has_Task_Info_Pragma
+     (N : Node_Id) return Boolean;    -- Flag7
+
+   function Has_Task_Name_Pragma
+     (N : Node_Id) return Boolean;    -- Flag8
+
+   function Has_Wide_Character
+     (N : Node_Id) return Boolean;    -- Flag11
+
+   function Hidden_By_Use_Clause
+     (N : Node_Id) return Elist_Id;   -- Elist4
+
+   function High_Bound
+     (N : Node_Id) return Node_Id;    -- Node2
+
+   function Identifier
+     (N : Node_Id) return Node_Id;    -- Node1
+
+   function Implicit_With
+     (N : Node_Id) return Boolean;    -- Flag17
+
+   function In_Present
+     (N : Node_Id) return Boolean;    -- Flag15
+
+   function Includes_Infinities
+     (N : Node_Id) return Boolean;    -- Flag11
+
+   function Instance_Spec
+     (N : Node_Id) return Node_Id;    -- Node5
+
+   function Intval
+     (N : Node_Id) return Uint;       -- Uint3
+
+   function Is_Asynchronous_Call_Block
+     (N : Node_Id) return Boolean;    -- Flag7
+
+   function Is_Component_Left_Opnd
+     (N : Node_Id) return Boolean;    -- Flag13
+
+   function Is_Component_Right_Opnd
+     (N : Node_Id) return Boolean;    -- Flag14
+
+   function Is_Controlling_Actual
+     (N : Node_Id) return Boolean;    -- Flag16
+
+   function Is_Machine_Number
+     (N : Node_Id) return Boolean;    -- Flag11
+
+   function Is_Overloaded
+     (N : Node_Id) return Boolean;    -- Flag5
+
+   function Is_Power_Of_2_For_Shift
+     (N : Node_Id) return Boolean;    -- Flag13
+
+   function Is_Protected_Subprogram_Body
+     (N : Node_Id) return Boolean;    -- Flag7
+
+   function Is_Static_Expression
+     (N : Node_Id) return Boolean;    -- Flag6
+
+   function Is_Subprogram_Descriptor
+     (N : Node_Id) return Boolean;    -- Flag16
+
+   function Is_Task_Allocation_Block
+     (N : Node_Id) return Boolean;    -- Flag6
+
+   function Is_Task_Master
+     (N : Node_Id) return Boolean;    -- Flag5
+
+   function Iteration_Scheme
+     (N : Node_Id) return Node_Id;    -- Node2
+
+   function Itype
+     (N : Node_Id) return Entity_Id;  -- Node1
+
+   function Kill_Range_Check
+     (N : Node_Id) return Boolean;    -- Flag11
+
+   function Label_Construct
+     (N : Node_Id) return Node_Id;    -- Node2
+
+   function Left_Opnd
+     (N : Node_Id) return Node_Id;    -- Node2
+
+   function Last_Bit
+     (N : Node_Id) return Node_Id;    -- Node4
+
+   function Last_Name
+     (N : Node_Id) return Boolean;    -- Flag6
+
+   function Library_Unit
+     (N : Node_Id) return Node_Id;    -- Node4
+
+   function Limited_Present
+     (N : Node_Id) return Boolean;    -- Flag17
+
+   function Literals
+     (N : Node_Id) return List_Id;    -- List1
+
+   function Loop_Actions
+     (N : Node_Id) return List_Id;    -- List2
+
+   function Loop_Parameter_Specification
+     (N : Node_Id) return Node_Id;    -- Node4
+
+   function Low_Bound
+     (N : Node_Id) return Node_Id;    -- Node1
+
+   function Mod_Clause
+     (N : Node_Id) return Node_Id;    -- Node2
+
+   function More_Ids
+     (N : Node_Id) return Boolean;    -- Flag5
+
+   function Must_Not_Freeze
+     (N : Node_Id) return Boolean;    -- Flag8
+
+   function Name
+     (N : Node_Id) return Node_Id;    -- Node2
+
+   function Names
+     (N : Node_Id) return List_Id;    -- List2
+
+   function Next_Entity
+     (N : Node_Id) return Node_Id;    -- Node2
+
+   function Next_Named_Actual
+     (N : Node_Id) return Node_Id;    -- Node4
+
+   function Next_Rep_Item
+     (N : Node_Id) return Node_Id;    -- Node4
+
+   function Next_Use_Clause
+     (N : Node_Id) return Node_Id;    -- Node3
+
+   function No_Ctrl_Actions
+     (N : Node_Id) return Boolean;    -- Flag7
+
+   function No_Entities_Ref_In_Spec
+     (N : Node_Id) return Boolean;    -- Flag8
+
+   function No_Initialization
+     (N : Node_Id) return Boolean;    -- Flag13
+
+   function Null_Present
+     (N : Node_Id) return Boolean;    -- Flag13
+
+   function Null_Record_Present
+     (N : Node_Id) return Boolean;    -- Flag17
+
+   function Object_Definition
+     (N : Node_Id) return Node_Id;    -- Node4
+
+   function OK_For_Stream
+     (N : Node_Id) return Boolean;    -- Flag4
+
+   function Original_Discriminant
+     (N : Node_Id) return Node_Id;    -- Node2
+
+   function Others_Discrete_Choices
+     (N : Node_Id) return List_Id;    -- List1
+
+   function Out_Present
+     (N : Node_Id) return Boolean;    -- Flag17
+
+   function Parameter_Associations
+     (N : Node_Id) return List_Id;    -- List3
+
+   function Parameter_List_Truncated
+     (N : Node_Id) return Boolean;    -- Flag17
+
+   function Parameter_Specifications
+     (N : Node_Id) return List_Id;    -- List3
+
+   function Parameter_Type
+     (N : Node_Id) return Node_Id;    -- Node2
+
+   function Parent_Spec
+     (N : Node_Id) return Node_Id;    -- Node4
+
+   function Position
+     (N : Node_Id) return Node_Id;    -- Node2
+
+   function Pragma_Argument_Associations
+     (N : Node_Id) return List_Id;    -- List2
+
+   function Pragmas_After
+     (N : Node_Id) return List_Id;    -- List5
+
+   function Pragmas_Before
+     (N : Node_Id) return List_Id;    -- List4
+
+   function Prefix
+     (N : Node_Id) return Node_Id;    -- Node3
+
+   function Present_Expr
+     (N : Node_Id) return Uint;       -- Uint3
+
+   function Prev_Ids
+     (N : Node_Id) return Boolean;    -- Flag6
+
+   function Print_In_Hex
+     (N : Node_Id) return Boolean;    -- Flag13
+
+   function Private_Declarations
+     (N : Node_Id) return List_Id;    -- List3
+
+   function Private_Present
+     (N : Node_Id) return Boolean;    -- Flag15
+
+   function Procedure_To_Call
+     (N : Node_Id) return Node_Id;    -- Node4
+
+   function Proper_Body
+     (N : Node_Id) return Node_Id;    -- Node1
+
+   function Protected_Definition
+     (N : Node_Id) return Node_Id;    -- Node3
+
+   function Protected_Present
+     (N : Node_Id) return Boolean;    -- Flag15
+
+   function Raises_Constraint_Error
+     (N : Node_Id) return Boolean;    -- Flag7
+
+   function Range_Constraint
+     (N : Node_Id) return Node_Id;    -- Node4
+
+   function Range_Expression
+     (N : Node_Id) return Node_Id;    -- Node4
+
+   function Real_Range_Specification
+     (N : Node_Id) return Node_Id;    -- Node4
+
+   function Realval
+     (N : Node_Id) return Ureal;      -- Ureal3
+
+   function Record_Extension_Part
+     (N : Node_Id) return Node_Id;    -- Node3
+
+   function Redundant_Use
+     (N : Node_Id) return Boolean;    -- Flag13
+
+   function Return_Type
+     (N : Node_Id) return Node_Id;    -- Node2
+
+   function Reverse_Present
+     (N : Node_Id) return Boolean;    -- Flag15
+
+   function Right_Opnd
+     (N : Node_Id) return Node_Id;    -- Node3
+
+   function Rounded_Result
+     (N : Node_Id) return Boolean;    -- Flag18
+
+   function Scope
+     (N : Node_Id) return Node_Id;    -- Node3
+
+   function Select_Alternatives
+     (N : Node_Id) return List_Id;    -- List1
+
+   function Selector_Name
+     (N : Node_Id) return Node_Id;    -- Node2
+
+   function Selector_Names
+     (N : Node_Id) return List_Id;    -- List1
+
+   function Shift_Count_OK
+     (N : Node_Id) return Boolean;    -- Flag4
+
+   function Source_Type
+     (N : Node_Id) return Entity_Id;  -- Node1
+
+   function Specification
+     (N : Node_Id) return Node_Id;    -- Node1
+
+   function Statements
+     (N : Node_Id) return List_Id;    -- List3
+
+   function Static_Processing_OK
+     (N : Node_Id) return Boolean;    -- Flag4
+
+   function Storage_Pool
+     (N : Node_Id) return Node_Id;    -- Node1
+
+   function Strval
+     (N : Node_Id) return String_Id;  -- Str3
+
+   function Subtype_Indication
+     (N : Node_Id) return Node_Id;    -- Node5
+
+   function Subtype_Mark
+     (N : Node_Id) return Node_Id;    -- Node4
+
+   function Subtype_Marks
+     (N : Node_Id) return List_Id;    -- List2
+
+   function Tagged_Present
+     (N : Node_Id) return Boolean;    -- Flag15
+
+   function Target_Type
+     (N : Node_Id) return Entity_Id;  -- Node2
+
+   function Task_Body_Procedure
+     (N : Node_Id) return Entity_Id;  -- Node2
+
+   function Task_Definition
+     (N : Node_Id) return Node_Id;    -- Node3
+
+   function Then_Actions
+     (N : Node_Id) return List_Id;    -- List2
+
+   function Then_Statements
+     (N : Node_Id) return List_Id;    -- List2
+
+   function Treat_Fixed_As_Integer
+     (N : Node_Id) return Boolean;    -- Flag14
+
+   function Triggering_Alternative
+     (N : Node_Id) return Node_Id;    -- Node1
+
+   function Triggering_Statement
+     (N : Node_Id) return Node_Id;    -- Node1
+
+   function TSS_Elist
+     (N : Node_Id) return Elist_Id;   -- Elist3
+
+   function Type_Definition
+     (N : Node_Id) return Node_Id;    -- Node3
+
+   function Unit
+     (N : Node_Id) return Node_Id;    -- Node2
+
+   function Unknown_Discriminants_Present
+     (N : Node_Id) return Boolean;    -- Flag13
+
+   function Unreferenced_In_Spec
+     (N : Node_Id) return Boolean;    -- Flag7
+
+   function Variant_Part
+     (N : Node_Id) return Node_Id;    -- Node4
+
+   function Variants
+     (N : Node_Id) return List_Id;    -- List1
+
+   function Visible_Declarations
+     (N : Node_Id) return List_Id;    -- List2
+
+   function Was_Originally_Stub
+     (N : Node_Id) return Boolean;    -- Flag13
+
+   function Zero_Cost_Handling
+     (N : Node_Id) return Boolean;    -- Flag5
+
+   --  End functions (note used by xsinfo utility program to end processing)
+
+   ----------------------------
+   -- Node Update Procedures --
+   ----------------------------
+
+   --  These are the corresponding node update routines, which again provide
+   --  a high level logical access with type checking. In addition to setting
+   --  the indicated field of the node N to the given Val, in the case of
+   --  tree pointers (List1-4), the parent pointer of the Val node is set to
+   --  point back to node N. This automates the setting of the parent pointer.
+
+   procedure Set_ABE_Is_Certain
+     (N : Node_Id; Val : Boolean := True);    -- Flag18
+
+   procedure Set_Abort_Present
+     (N : Node_Id; Val : Boolean := True);    -- Flag15
+
+   procedure Set_Abortable_Part
+     (N : Node_Id; Val : Node_Id);            -- Node2
+
+   procedure Set_Abstract_Present
+     (N : Node_Id; Val : Boolean := True);    -- Flag4
+
+   procedure Set_Accept_Handler_Records
+     (N : Node_Id; Val : List_Id);            -- List5
+
+   procedure Set_Accept_Statement
+     (N : Node_Id; Val : Node_Id);            -- Node2
+
+   procedure Set_Access_Types_To_Process
+     (N : Node_Id; Val : Elist_Id);           -- Elist2
+
+   procedure Set_Actions
+     (N : Node_Id; Val : List_Id);            -- List1
+
+   procedure Set_Activation_Chain_Entity
+     (N : Node_Id; Val : Node_Id);            -- Node3
+
+   procedure Set_Acts_As_Spec
+     (N : Node_Id; Val : Boolean := True);    -- Flag4
+
+   procedure Set_Aggregate_Bounds
+     (N : Node_Id; Val : Node_Id);            -- Node3
+
+   procedure Set_Aliased_Present
+     (N : Node_Id; Val : Boolean := True);    -- Flag4
+
+   procedure Set_All_Others
+     (N : Node_Id; Val : Boolean := True);    -- Flag11
+
+   procedure Set_All_Present
+     (N : Node_Id; Val : Boolean := True);    -- Flag15
+
+   procedure Set_Alternatives
+     (N : Node_Id; Val : List_Id);            -- List4
+
+   procedure Set_Ancestor_Part
+     (N : Node_Id; Val : Node_Id);            -- Node3
+
+   procedure Set_Array_Aggregate
+     (N : Node_Id; Val : Node_Id);            -- Node3
+
+   procedure Set_Assignment_OK
+     (N : Node_Id; Val : Boolean := True);    -- Flag15
+
+   procedure Set_Attribute_Name
+     (N : Node_Id; Val : Name_Id);            -- Name2
+
+   procedure Set_At_End_Proc
+     (N : Node_Id; Val : Node_Id);            -- Node1
+
+   procedure Set_Aux_Decls_Node
+     (N : Node_Id; Val : Node_Id);            -- Node5
+
+   procedure Set_Backwards_OK
+     (N : Node_Id; Val : Boolean := True);    -- Flag6
+
+   procedure Set_Bad_Is_Detected
+     (N : Node_Id; Val : Boolean := True);    -- Flag15
+
+   procedure Set_Body_Required
+     (N : Node_Id; Val : Boolean := True);    -- Flag13
+
+   procedure Set_Body_To_Inline
+     (N : Node_Id; Val : Node_Id);            -- Node3
+
+   procedure Set_Box_Present
+     (N : Node_Id; Val : Boolean := True);    -- Flag15
+
+   procedure Set_By_Ref
+     (N : Node_Id; Val : Boolean := True);    -- Flag5
+
+   procedure Set_Char_Literal_Value
+     (N : Node_Id; Val : Char_Code);          -- Char_Code2
+
+   procedure Set_Chars
+     (N : Node_Id; Val : Name_Id);            -- Name1
+
+   procedure Set_Choice_Parameter
+     (N : Node_Id; Val : Node_Id);            -- Node2
+
+   procedure Set_Choices
+     (N : Node_Id; Val : List_Id);            -- List1
+
+   procedure Set_Compile_Time_Known_Aggregate
+     (N : Node_Id; Val : Boolean := True);    -- Flag18
+
+   procedure Set_Component_Associations
+     (N : Node_Id; Val : List_Id);            -- List2
+
+   procedure Set_Component_Clauses
+     (N : Node_Id; Val : List_Id);            -- List3
+
+   procedure Set_Component_Items
+     (N : Node_Id; Val : List_Id);            -- List3
+
+   procedure Set_Component_List
+     (N : Node_Id; Val : Node_Id);            -- Node1
+
+   procedure Set_Component_Name
+     (N : Node_Id; Val : Node_Id);            -- Node1
+
+   procedure Set_Condition
+     (N : Node_Id; Val : Node_Id);            -- Node1
+
+   procedure Set_Condition_Actions
+     (N : Node_Id; Val : List_Id);            -- List3
+
+   procedure Set_Constant_Present
+     (N : Node_Id; Val : Boolean := True);    -- Flag17
+
+   procedure Set_Constraint
+     (N : Node_Id; Val : Node_Id);            -- Node3
+
+   procedure Set_Constraints
+     (N : Node_Id; Val : List_Id);            -- List1
+
+   procedure Set_Context_Installed
+     (N : Node_Id; Val : Boolean := True);    -- Flag13
+
+   procedure Set_Context_Items
+     (N : Node_Id; Val : List_Id);            -- List1
+
+   procedure Set_Controlling_Argument
+     (N : Node_Id; Val : Node_Id);            -- Node1
+
+   procedure Set_Conversion_OK
+     (N : Node_Id; Val : Boolean := True);    -- Flag14
+
+   procedure Set_Corresponding_Body
+     (N : Node_Id; Val : Node_Id);            -- Node5
+
+   procedure Set_Corresponding_Generic_Association
+     (N : Node_Id; Val : Node_Id);            -- Node5
+
+   procedure Set_Corresponding_Integer_Value
+     (N : Node_Id; Val : Uint);               -- Uint4
+
+   procedure Set_Corresponding_Spec
+     (N : Node_Id; Val : Node_Id);            -- Node5
+
+   procedure Set_Corresponding_Stub
+     (N : Node_Id; Val : Node_Id);            -- Node3
+
+   procedure Set_Dcheck_Function
+     (N : Node_Id; Val : Entity_Id);          -- Node5
+
+   procedure Set_Debug_Statement
+     (N : Node_Id; Val : Node_Id);            -- Node3
+
+   procedure Set_Declarations
+     (N : Node_Id; Val : List_Id);            -- List2
+
+   procedure Set_Default_Expression
+     (N : Node_Id; Val : Node_Id);            -- Node5
+
+   procedure Set_Default_Name
+     (N : Node_Id; Val : Node_Id);            -- Node2
+
+   procedure Set_Defining_Identifier
+     (N : Node_Id; Val : Entity_Id);          -- Node1
+
+   procedure Set_Defining_Unit_Name
+     (N : Node_Id; Val : Node_Id);            -- Node1
+
+   procedure Set_Delay_Alternative
+     (N : Node_Id; Val : Node_Id);            -- Node4
+
+   procedure Set_Delay_Finalize_Attach
+     (N : Node_Id; Val : Boolean := True);    -- Flag14
+
+   procedure Set_Delay_Statement
+     (N : Node_Id; Val : Node_Id);            -- Node2
+
+   procedure Set_Delta_Expression
+     (N : Node_Id; Val : Node_Id);            -- Node3
+
+   procedure Set_Digits_Expression
+     (N : Node_Id; Val : Node_Id);            -- Node2
+
+   procedure Set_Discr_Check_Funcs_Built
+     (N : Node_Id; Val : Boolean := True);    -- Flag11
+
+   procedure Set_Discrete_Choices
+     (N : Node_Id; Val : List_Id);            -- List4
+
+   procedure Set_Discrete_Range
+     (N : Node_Id; Val : Node_Id);            -- Node4
+
+   procedure Set_Discrete_Subtype_Definition
+     (N : Node_Id; Val : Node_Id);            -- Node4
+
+   procedure Set_Discrete_Subtype_Definitions
+     (N : Node_Id; Val : List_Id);            -- List2
+
+   procedure Set_Discriminant_Specifications
+     (N : Node_Id; Val : List_Id);            -- List4
+
+   procedure Set_Discriminant_Type
+     (N : Node_Id; Val : Node_Id);            -- Node5
+
+   procedure Set_Do_Access_Check
+     (N : Node_Id; Val : Boolean := True);    -- Flag11
+
+   procedure Set_Do_Accessibility_Check
+     (N : Node_Id; Val : Boolean := True);    -- Flag13
+
+   procedure Set_Do_Discriminant_Check
+     (N : Node_Id; Val : Boolean := True);    -- Flag13
+
+   procedure Set_Do_Division_Check
+     (N : Node_Id; Val : Boolean := True);    -- Flag13
+
+   procedure Set_Do_Length_Check
+     (N : Node_Id; Val : Boolean := True);    -- Flag4
+
+   procedure Set_Do_Overflow_Check
+     (N : Node_Id; Val : Boolean := True);    -- Flag17
+
+   procedure Set_Do_Range_Check
+     (N : Node_Id; Val : Boolean := True);    -- Flag9
+
+   procedure Set_Do_Storage_Check
+     (N : Node_Id; Val : Boolean := True);    -- Flag17
+
+   procedure Set_Do_Tag_Check
+     (N : Node_Id; Val : Boolean := True);    -- Flag13
+
+   procedure Set_Elaborate_All_Present
+     (N : Node_Id; Val : Boolean := True);    -- Flag15
+
+   procedure Set_Elaborate_Present
+     (N : Node_Id; Val : Boolean := True);    -- Flag4
+
+   procedure Set_Elaboration_Boolean
+     (N : Node_Id; Val : Node_Id);            -- Node2
+
+   procedure Set_Else_Actions
+     (N : Node_Id; Val : List_Id);            -- List3
+
+   procedure Set_Else_Statements
+     (N : Node_Id; Val : List_Id);            -- List4
+
+   procedure Set_Elsif_Parts
+     (N : Node_Id; Val : List_Id);            -- List3
+
+   procedure Set_Enclosing_Variant
+     (N : Node_Id; Val : Node_Id);            -- Node2
+
+   procedure Set_End_Label
+     (N : Node_Id; Val : Node_Id);            -- Node4
+
+   procedure Set_End_Span
+     (N : Node_Id; Val : Uint);               -- Uint5
+
+   procedure Set_Entity
+     (N : Node_Id; Val : Node_Id);            -- Node4
+
+   procedure Set_Entry_Body_Formal_Part
+     (N : Node_Id; Val : Node_Id);            -- Node5
+
+   procedure Set_Entry_Call_Alternative
+     (N : Node_Id; Val : Node_Id);            -- Node1
+
+   procedure Set_Entry_Call_Statement
+     (N : Node_Id; Val : Node_Id);            -- Node1
+
+   procedure Set_Entry_Direct_Name
+     (N : Node_Id; Val : Node_Id);            -- Node1
+
+   procedure Set_Entry_Index
+     (N : Node_Id; Val : Node_Id);            -- Node5
+
+   procedure Set_Entry_Index_Specification
+     (N : Node_Id; Val : Node_Id);            -- Node4
+
+   procedure Set_Etype
+     (N : Node_Id; Val : Node_Id);            -- Node5
+
+   procedure Set_Exception_Choices
+     (N : Node_Id; Val : List_Id);            -- List4
+
+   procedure Set_Exception_Handlers
+     (N : Node_Id; Val : List_Id);            -- List5
+
+   procedure Set_Exception_Junk
+     (N : Node_Id; Val : Boolean := True);    -- Flag11
+
+   procedure Set_Expansion_Delayed
+     (N : Node_Id; Val : Boolean := True);    -- Flag11
+
+   procedure Set_Explicit_Actual_Parameter
+     (N : Node_Id; Val : Node_Id);            -- Node3
+
+   procedure Set_Explicit_Generic_Actual_Parameter
+     (N : Node_Id; Val : Node_Id);            -- Node1
+
+   procedure Set_Expression
+     (N : Node_Id; Val : Node_Id);            -- Node3
+
+   procedure Set_Expressions
+     (N : Node_Id; Val : List_Id);            -- List1
+
+   procedure Set_First_Bit
+     (N : Node_Id; Val : Node_Id);            -- Node3
+
+   procedure Set_First_Inlined_Subprogram
+     (N : Node_Id; Val : Entity_Id);          -- Node3
+
+   procedure Set_First_Name
+     (N : Node_Id; Val : Boolean := True);    -- Flag5
+
+   procedure Set_First_Named_Actual
+     (N : Node_Id; Val : Node_Id);            -- Node4
+
+   procedure Set_First_Real_Statement
+     (N : Node_Id; Val : Node_Id);            -- Node2
+
+   procedure Set_First_Subtype_Link
+     (N : Node_Id; Val : Entity_Id);          -- Node5
+
+   procedure Set_Float_Truncate
+     (N : Node_Id; Val : Boolean := True);    -- Flag11
+
+   procedure Set_Formal_Type_Definition
+     (N : Node_Id; Val : Node_Id);            -- Node3
+
+   procedure Set_Forwards_OK
+     (N : Node_Id; Val : Boolean := True);    -- Flag5
+
+   procedure Set_From_At_Mod
+     (N : Node_Id; Val : Boolean := True);    -- Flag4
+
+   procedure Set_Generic_Associations
+     (N : Node_Id; Val : List_Id);            -- List3
+
+   procedure Set_Generic_Formal_Declarations
+     (N : Node_Id; Val : List_Id);            -- List2
+
+   procedure Set_Generic_Parent
+     (N : Node_Id; Val : Node_Id);            -- Node5
+
+   procedure Set_Generic_Parent_Type
+     (N : Node_Id; Val : Node_Id);            -- Node4
+
+   procedure Set_Handled_Statement_Sequence
+     (N : Node_Id; Val : Node_Id);            -- Node4
+
+   procedure Set_Handler_List_Entry
+     (N : Node_Id; Val : Node_Id);            -- Node2
+
+   procedure Set_Has_Created_Identifier
+     (N : Node_Id; Val : Boolean := True);    -- Flag15
+
+   procedure Set_Has_Dynamic_Length_Check
+     (N : Node_Id; Val : Boolean := True);    -- Flag10
+
+   procedure Set_Has_Dynamic_Range_Check
+     (N : Node_Id; Val : Boolean := True);    -- Flag12
+
+   procedure Set_Has_No_Elaboration_Code
+     (N : Node_Id; Val : Boolean := True);    -- Flag17
+
+   procedure Set_Has_Priority_Pragma
+     (N : Node_Id; Val : Boolean := True);    -- Flag6
+
+   procedure Set_Has_Private_View
+     (N : Node_Id; Val : Boolean := True);    -- Flag11
+
+   procedure Set_Has_Storage_Size_Pragma
+     (N : Node_Id; Val : Boolean := True);    -- Flag5
+
+   procedure Set_Has_Task_Info_Pragma
+     (N : Node_Id; Val : Boolean := True);    -- Flag7
+
+   procedure Set_Has_Task_Name_Pragma
+     (N : Node_Id; Val : Boolean := True);    -- Flag8
+
+   procedure Set_Has_Wide_Character
+     (N : Node_Id; Val : Boolean := True);    -- Flag11
+
+   procedure Set_Hidden_By_Use_Clause
+     (N : Node_Id; Val : Elist_Id);           -- Elist4
+
+   procedure Set_High_Bound
+     (N : Node_Id; Val : Node_Id);            -- Node2
+
+   procedure Set_Identifier
+     (N : Node_Id; Val : Node_Id);            -- Node1
+
+   procedure Set_Implicit_With
+     (N : Node_Id; Val : Boolean := True);    -- Flag17
+
+   procedure Set_In_Present
+     (N : Node_Id; Val : Boolean := True);    -- Flag15
+
+   procedure Set_Includes_Infinities
+     (N : Node_Id; Val : Boolean := True);    -- Flag11
+
+   procedure Set_Instance_Spec
+     (N : Node_Id; Val : Node_Id);            -- Node5
+
+   procedure Set_Intval
+     (N : Node_Id; Val : Uint);               -- Uint3
+
+   procedure Set_Is_Asynchronous_Call_Block
+     (N : Node_Id; Val : Boolean := True);    -- Flag7
+
+   procedure Set_Is_Component_Left_Opnd
+     (N : Node_Id; Val : Boolean := True);    -- Flag13
+
+   procedure Set_Is_Component_Right_Opnd
+     (N : Node_Id; Val : Boolean := True);    -- Flag14
+
+   procedure Set_Is_Controlling_Actual
+     (N : Node_Id; Val : Boolean := True);    -- Flag16
+
+   procedure Set_Is_Machine_Number
+     (N : Node_Id; Val : Boolean := True);    -- Flag11
+
+   procedure Set_Is_Overloaded
+     (N : Node_Id; Val : Boolean := True);    -- Flag5
+
+   procedure Set_Is_Power_Of_2_For_Shift
+     (N : Node_Id; Val : Boolean := True);    -- Flag13
+
+   procedure Set_Is_Protected_Subprogram_Body
+     (N : Node_Id; Val : Boolean := True);    -- Flag7
+
+   procedure Set_Is_Static_Expression
+     (N : Node_Id; Val : Boolean := True);    -- Flag6
+
+   procedure Set_Is_Subprogram_Descriptor
+     (N : Node_Id; Val : Boolean := True);    -- Flag16
+
+   procedure Set_Is_Task_Allocation_Block
+     (N : Node_Id; Val : Boolean := True);    -- Flag6
+
+   procedure Set_Is_Task_Master
+     (N : Node_Id; Val : Boolean := True);    -- Flag5
+
+   procedure Set_Iteration_Scheme
+     (N : Node_Id; Val : Node_Id);            -- Node2
+
+   procedure Set_Itype
+     (N : Node_Id; Val : Entity_Id);          -- Node1
+
+   procedure Set_Kill_Range_Check
+     (N : Node_Id; Val : Boolean := True);    -- Flag11
+
+   procedure Set_Last_Bit
+     (N : Node_Id; Val : Node_Id);            -- Node4
+
+   procedure Set_Last_Name
+     (N : Node_Id; Val : Boolean := True);    -- Flag6
+
+   procedure Set_Library_Unit
+     (N : Node_Id; Val : Node_Id);            -- Node4
+
+   procedure Set_Label_Construct
+     (N : Node_Id; Val : Node_Id);            -- Node2
+
+   procedure Set_Left_Opnd
+     (N : Node_Id; Val : Node_Id);            -- Node2
+
+   procedure Set_Limited_Present
+     (N : Node_Id; Val : Boolean := True);    -- Flag17
+
+   procedure Set_Literals
+     (N : Node_Id; Val : List_Id);            -- List1
+
+   procedure Set_Loop_Actions
+     (N : Node_Id; Val : List_Id);            -- List2
+
+   procedure Set_Loop_Parameter_Specification
+     (N : Node_Id; Val : Node_Id);            -- Node4
+
+   procedure Set_Low_Bound
+     (N : Node_Id; Val : Node_Id);            -- Node1
+
+   procedure Set_Mod_Clause
+     (N : Node_Id; Val : Node_Id);            -- Node2
+
+   procedure Set_More_Ids
+     (N : Node_Id; Val : Boolean := True);    -- Flag5
+
+   procedure Set_Must_Not_Freeze
+     (N : Node_Id; Val : Boolean := True);    -- Flag8
+
+   procedure Set_Name
+     (N : Node_Id; Val : Node_Id);            -- Node2
+
+   procedure Set_Names
+     (N : Node_Id; Val : List_Id);            -- List2
+
+   procedure Set_Next_Entity
+     (N : Node_Id; Val : Node_Id);            -- Node2
+
+   procedure Set_Next_Named_Actual
+     (N : Node_Id; Val : Node_Id);            -- Node4
+
+   procedure Set_Next_Rep_Item
+     (N : Node_Id; Val : Node_Id);            -- Node4
+
+   procedure Set_Next_Use_Clause
+     (N : Node_Id; Val : Node_Id);            -- Node3
+
+   procedure Set_No_Ctrl_Actions
+     (N : Node_Id; Val : Boolean := True);    -- Flag7
+
+   procedure Set_No_Entities_Ref_In_Spec
+     (N : Node_Id; Val : Boolean := True);    -- Flag8
+
+   procedure Set_No_Initialization
+     (N : Node_Id; Val : Boolean := True);    -- Flag13
+
+   procedure Set_Null_Present
+     (N : Node_Id; Val : Boolean := True);    -- Flag13
+
+   procedure Set_Null_Record_Present
+     (N : Node_Id; Val : Boolean := True);    -- Flag17
+
+   procedure Set_Object_Definition
+     (N : Node_Id; Val : Node_Id);            -- Node4
+
+   procedure Set_OK_For_Stream
+     (N : Node_Id; Val : Boolean := True);    -- Flag4
+
+   procedure Set_Original_Discriminant
+     (N : Node_Id; Val : Node_Id);            -- Node2
+
+   procedure Set_Others_Discrete_Choices
+     (N : Node_Id; Val : List_Id);            -- List1
+
+   procedure Set_Out_Present
+     (N : Node_Id; Val : Boolean := True);    -- Flag17
+
+   procedure Set_Parameter_Associations
+     (N : Node_Id; Val : List_Id);            -- List3
+
+   procedure Set_Parameter_List_Truncated
+     (N : Node_Id; Val : Boolean := True);    -- Flag17
+
+   procedure Set_Parameter_Specifications
+     (N : Node_Id; Val : List_Id);            -- List3
+
+   procedure Set_Parameter_Type
+     (N : Node_Id; Val : Node_Id);            -- Node2
+
+   procedure Set_Parent_Spec
+     (N : Node_Id; Val : Node_Id);            -- Node4
+
+   procedure Set_Position
+     (N : Node_Id; Val : Node_Id);            -- Node2
+
+   procedure Set_Pragma_Argument_Associations
+     (N : Node_Id; Val : List_Id);            -- List2
+
+   procedure Set_Pragmas_After
+     (N : Node_Id; Val : List_Id);            -- List5
+
+   procedure Set_Pragmas_Before
+     (N : Node_Id; Val : List_Id);            -- List4
+
+   procedure Set_Prefix
+     (N : Node_Id; Val : Node_Id);            -- Node3
+
+   procedure Set_Present_Expr
+     (N : Node_Id; Val : Uint);               -- Uint3
+
+   procedure Set_Prev_Ids
+     (N : Node_Id; Val : Boolean := True);    -- Flag6
+
+   procedure Set_Print_In_Hex
+     (N : Node_Id; Val : Boolean := True);    -- Flag13
+
+   procedure Set_Private_Declarations
+     (N : Node_Id; Val : List_Id);            -- List3
+
+   procedure Set_Private_Present
+     (N : Node_Id; Val : Boolean := True);    -- Flag15
+
+   procedure Set_Procedure_To_Call
+     (N : Node_Id; Val : Node_Id);            -- Node4
+
+   procedure Set_Proper_Body
+     (N : Node_Id; Val : Node_Id);            -- Node1
+
+   procedure Set_Protected_Definition
+     (N : Node_Id; Val : Node_Id);            -- Node3
+
+   procedure Set_Protected_Present
+     (N : Node_Id; Val : Boolean := True);    -- Flag15
+
+   procedure Set_Raises_Constraint_Error
+     (N : Node_Id; Val : Boolean := True);    -- Flag7
+
+   procedure Set_Range_Constraint
+     (N : Node_Id; Val : Node_Id);            -- Node4
+
+   procedure Set_Range_Expression
+     (N : Node_Id; Val : Node_Id);            -- Node4
+
+   procedure Set_Real_Range_Specification
+     (N : Node_Id; Val : Node_Id);            -- Node4
+
+   procedure Set_Realval
+     (N : Node_Id; Val : Ureal);              -- Ureal3
+
+   procedure Set_Record_Extension_Part
+     (N : Node_Id; Val : Node_Id);            -- Node3
+
+   procedure Set_Redundant_Use
+     (N : Node_Id; Val : Boolean := True);    -- Flag13
+
+   procedure Set_Return_Type
+     (N : Node_Id; Val : Node_Id);            -- Node2
+
+   procedure Set_Reverse_Present
+     (N : Node_Id; Val : Boolean := True);    -- Flag15
+
+   procedure Set_Right_Opnd
+     (N : Node_Id; Val : Node_Id);            -- Node3
+
+   procedure Set_Rounded_Result
+     (N : Node_Id; Val : Boolean := True);    -- Flag18
+
+   procedure Set_Scope
+     (N : Node_Id; Val : Node_Id);            -- Node3
+
+   procedure Set_Select_Alternatives
+     (N : Node_Id; Val : List_Id);            -- List1
+
+   procedure Set_Selector_Name
+     (N : Node_Id; Val : Node_Id);            -- Node2
+
+   procedure Set_Selector_Names
+     (N : Node_Id; Val : List_Id);            -- List1
+
+   procedure Set_Shift_Count_OK
+     (N : Node_Id; Val : Boolean := True);    -- Flag4
+
+   procedure Set_Source_Type
+     (N : Node_Id; Val : Entity_Id);          -- Node1
+
+   procedure Set_Specification
+     (N : Node_Id; Val : Node_Id);            -- Node1
+
+   procedure Set_Statements
+     (N : Node_Id; Val : List_Id);            -- List3
+
+   procedure Set_Static_Processing_OK
+     (N : Node_Id; Val : Boolean);            -- Flag4
+
+   procedure Set_Storage_Pool
+     (N : Node_Id; Val : Node_Id);            -- Node1
+
+   procedure Set_Strval
+     (N : Node_Id; Val : String_Id);          -- Str3
+
+   procedure Set_Subtype_Indication
+     (N : Node_Id; Val : Node_Id);            -- Node5
+
+   procedure Set_Subtype_Mark
+     (N : Node_Id; Val : Node_Id);            -- Node4
+
+   procedure Set_Subtype_Marks
+     (N : Node_Id; Val : List_Id);            -- List2
+
+   procedure Set_Tagged_Present
+     (N : Node_Id; Val : Boolean := True);    -- Flag15
+
+   procedure Set_Target_Type
+     (N : Node_Id; Val : Entity_Id);          -- Node2
+
+   procedure Set_Task_Body_Procedure
+     (N : Node_Id; Val : Entity_Id);          -- Node2
+
+   procedure Set_Task_Definition
+     (N : Node_Id; Val : Node_Id);            -- Node3
+
+   procedure Set_Then_Actions
+     (N : Node_Id; Val : List_Id);            -- List2
+
+   procedure Set_Then_Statements
+     (N : Node_Id; Val : List_Id);            -- List2
+
+   procedure Set_Treat_Fixed_As_Integer
+     (N : Node_Id; Val : Boolean := True);    -- Flag14
+
+   procedure Set_Triggering_Alternative
+     (N : Node_Id; Val : Node_Id);            -- Node1
+
+   procedure Set_Triggering_Statement
+     (N : Node_Id; Val : Node_Id);            -- Node1
+
+   procedure Set_TSS_Elist
+     (N : Node_Id; Val : Elist_Id);           -- Elist3
+
+   procedure Set_Type_Definition
+     (N : Node_Id; Val : Node_Id);            -- Node3
+
+   procedure Set_Unit
+     (N : Node_Id; Val : Node_Id);            -- Node2
+
+   procedure Set_Unknown_Discriminants_Present
+     (N : Node_Id; Val : Boolean := True);    -- Flag13
+
+   procedure Set_Unreferenced_In_Spec
+     (N : Node_Id; Val : Boolean := True);    -- Flag7
+
+   procedure Set_Variant_Part
+     (N : Node_Id; Val : Node_Id);            -- Node4
+
+   procedure Set_Variants
+     (N : Node_Id; Val : List_Id);            -- List1
+
+   procedure Set_Visible_Declarations
+     (N : Node_Id; Val : List_Id);            -- List2
+
+   procedure Set_Was_Originally_Stub
+     (N : Node_Id; Val : Boolean := True);    -- Flag13
+
+   procedure Set_Zero_Cost_Handling
+     (N : Node_Id; Val : Boolean := True);    -- Flag5
+
+   -------------------------
+   -- Iterator Procedures --
+   -------------------------
+
+   --  The call to Next_xxx (N) is equivalent to N := Next_xxx (N)
+
+   procedure Next_Entity       (N : in out Node_Id);
+   procedure Next_Named_Actual (N : in out Node_Id);
+   procedure Next_Rep_Item     (N : in out Node_Id);
+   procedure Next_Use_Clause   (N : in out Node_Id);
+
+   --------------------------------------
+   -- Logical Access to End_Span Field --
+   --------------------------------------
+
+   function End_Location (N : Node_Id) return Source_Ptr;
+   --  N is an N_If_Statement or N_Case_Statement node, and this
+   --  function returns the location of the IF token in the END IF
+   --  sequence by translating the value of the End_Span field.
+
+   procedure Set_End_Location (N : Node_Id; S : Source_Ptr);
+   --  N is an N_If_Statement or N_Case_Statement node. This procedure
+   --  sets the End_Span field to correspond to the given value S. In
+   --  other words, End_Span is set to the difference between S and
+   --  Sloc (N), the starting location.
+
+   --------------------
+   -- Inline Pragmas --
+   --------------------
+
+   pragma Inline (ABE_Is_Certain);
+   pragma Inline (Abort_Present);
+   pragma Inline (Abortable_Part);
+   pragma Inline (Abstract_Present);
+   pragma Inline (Accept_Handler_Records);
+   pragma Inline (Accept_Statement);
+   pragma Inline (Access_Types_To_Process);
+   pragma Inline (Actions);
+   pragma Inline (Activation_Chain_Entity);
+   pragma Inline (Acts_As_Spec);
+   pragma Inline (Aggregate_Bounds);
+   pragma Inline (Aliased_Present);
+   pragma Inline (All_Others);
+   pragma Inline (All_Present);
+   pragma Inline (Alternatives);
+   pragma Inline (Ancestor_Part);
+   pragma Inline (Array_Aggregate);
+   pragma Inline (Assignment_OK);
+   pragma Inline (At_End_Proc);
+   pragma Inline (Attribute_Name);
+   pragma Inline (Aux_Decls_Node);
+   pragma Inline (Backwards_OK);
+   pragma Inline (Bad_Is_Detected);
+   pragma Inline (Body_To_Inline);
+   pragma Inline (Body_Required);
+   pragma Inline (By_Ref);
+   pragma Inline (Box_Present);
+   pragma Inline (Char_Literal_Value);
+   pragma Inline (Chars);
+   pragma Inline (Choice_Parameter);
+   pragma Inline (Choices);
+   pragma Inline (Compile_Time_Known_Aggregate);
+   pragma Inline (Component_Associations);
+   pragma Inline (Component_Clauses);
+   pragma Inline (Component_Items);
+   pragma Inline (Component_List);
+   pragma Inline (Component_Name);
+   pragma Inline (Condition);
+   pragma Inline (Condition_Actions);
+   pragma Inline (Constant_Present);
+   pragma Inline (Constraint);
+   pragma Inline (Constraints);
+   pragma Inline (Context_Installed);
+   pragma Inline (Context_Items);
+   pragma Inline (Controlling_Argument);
+   pragma Inline (Conversion_OK);
+   pragma Inline (Corresponding_Body);
+   pragma Inline (Corresponding_Generic_Association);
+   pragma Inline (Corresponding_Integer_Value);
+   pragma Inline (Corresponding_Spec);
+   pragma Inline (Corresponding_Stub);
+   pragma Inline (Dcheck_Function);
+   pragma Inline (Debug_Statement);
+   pragma Inline (Declarations);
+   pragma Inline (Default_Expression);
+   pragma Inline (Default_Name);
+   pragma Inline (Defining_Identifier);
+   pragma Inline (Defining_Unit_Name);
+   pragma Inline (Delay_Alternative);
+   pragma Inline (Delay_Finalize_Attach);
+   pragma Inline (Delay_Statement);
+   pragma Inline (Delta_Expression);
+   pragma Inline (Digits_Expression);
+   pragma Inline (Discr_Check_Funcs_Built);
+   pragma Inline (Discrete_Choices);
+   pragma Inline (Discrete_Range);
+   pragma Inline (Discrete_Subtype_Definition);
+   pragma Inline (Discrete_Subtype_Definitions);
+   pragma Inline (Discriminant_Specifications);
+   pragma Inline (Discriminant_Type);
+   pragma Inline (Do_Access_Check);
+   pragma Inline (Do_Accessibility_Check);
+   pragma Inline (Do_Discriminant_Check);
+   pragma Inline (Do_Length_Check);
+   pragma Inline (Do_Division_Check);
+   pragma Inline (Do_Overflow_Check);
+   pragma Inline (Do_Range_Check);
+   pragma Inline (Do_Storage_Check);
+   pragma Inline (Do_Tag_Check);
+   pragma Inline (Elaborate_Present);
+   pragma Inline (Elaborate_All_Present);
+   pragma Inline (Elaboration_Boolean);
+   pragma Inline (Else_Actions);
+   pragma Inline (Else_Statements);
+   pragma Inline (Elsif_Parts);
+   pragma Inline (Enclosing_Variant);
+   pragma Inline (End_Label);
+   pragma Inline (End_Span);
+   pragma Inline (Entity);
+   pragma Inline (Entry_Body_Formal_Part);
+   pragma Inline (Entry_Call_Alternative);
+   pragma Inline (Entry_Call_Statement);
+   pragma Inline (Entry_Direct_Name);
+   pragma Inline (Entry_Index);
+   pragma Inline (Entry_Index_Specification);
+   pragma Inline (Etype);
+   pragma Inline (Exception_Choices);
+   pragma Inline (Exception_Junk);
+   pragma Inline (Exception_Handlers);
+   pragma Inline (Expansion_Delayed);
+   pragma Inline (Explicit_Actual_Parameter);
+   pragma Inline (Explicit_Generic_Actual_Parameter);
+   pragma Inline (Expression);
+   pragma Inline (Expressions);
+   pragma Inline (First_Bit);
+   pragma Inline (First_Inlined_Subprogram);
+   pragma Inline (First_Name);
+   pragma Inline (First_Named_Actual);
+   pragma Inline (First_Real_Statement);
+   pragma Inline (First_Subtype_Link);
+   pragma Inline (Float_Truncate);
+   pragma Inline (Formal_Type_Definition);
+   pragma Inline (Forwards_OK);
+   pragma Inline (From_At_Mod);
+   pragma Inline (Generic_Associations);
+   pragma Inline (Generic_Formal_Declarations);
+   pragma Inline (Generic_Parent);
+   pragma Inline (Generic_Parent_Type);
+   pragma Inline (Handled_Statement_Sequence);
+   pragma Inline (Handler_List_Entry);
+   pragma Inline (Has_Created_Identifier);
+   pragma Inline (Has_Dynamic_Length_Check);
+   pragma Inline (Has_Dynamic_Range_Check);
+   pragma Inline (Has_No_Elaboration_Code);
+   pragma Inline (Has_Priority_Pragma);
+   pragma Inline (Has_Private_View);
+   pragma Inline (Has_Storage_Size_Pragma);
+   pragma Inline (Has_Task_Info_Pragma);
+   pragma Inline (Has_Task_Name_Pragma);
+   pragma Inline (Has_Wide_Character);
+   pragma Inline (Hidden_By_Use_Clause);
+   pragma Inline (High_Bound);
+   pragma Inline (Identifier);
+   pragma Inline (Implicit_With);
+   pragma Inline (Includes_Infinities);
+   pragma Inline (In_Present);
+   pragma Inline (Instance_Spec);
+   pragma Inline (Intval);
+   pragma Inline (Is_Asynchronous_Call_Block);
+   pragma Inline (Is_Component_Left_Opnd);
+   pragma Inline (Is_Component_Right_Opnd);
+   pragma Inline (Is_Controlling_Actual);
+   pragma Inline (Is_Machine_Number);
+   pragma Inline (Is_Overloaded);
+   pragma Inline (Is_Power_Of_2_For_Shift);
+   pragma Inline (Is_Protected_Subprogram_Body);
+   pragma Inline (Is_Static_Expression);
+   pragma Inline (Is_Subprogram_Descriptor);
+   pragma Inline (Is_Task_Allocation_Block);
+   pragma Inline (Is_Task_Master);
+   pragma Inline (Iteration_Scheme);
+   pragma Inline (Itype);
+   pragma Inline (Kill_Range_Check);
+   pragma Inline (Last_Bit);
+   pragma Inline (Last_Name);
+   pragma Inline (Library_Unit);
+   pragma Inline (Label_Construct);
+   pragma Inline (Left_Opnd);
+   pragma Inline (Limited_Present);
+   pragma Inline (Literals);
+   pragma Inline (Loop_Actions);
+   pragma Inline (Loop_Parameter_Specification);
+   pragma Inline (Low_Bound);
+   pragma Inline (Mod_Clause);
+   pragma Inline (More_Ids);
+   pragma Inline (Must_Not_Freeze);
+   pragma Inline (Name);
+   pragma Inline (Names);
+   pragma Inline (Next_Entity);
+   pragma Inline (Next_Named_Actual);
+   pragma Inline (Next_Rep_Item);
+   pragma Inline (Next_Use_Clause);
+   pragma Inline (No_Ctrl_Actions);
+   pragma Inline (No_Entities_Ref_In_Spec);
+   pragma Inline (No_Initialization);
+   pragma Inline (Null_Present);
+   pragma Inline (Null_Record_Present);
+   pragma Inline (Object_Definition);
+   pragma Inline (OK_For_Stream);
+   pragma Inline (Original_Discriminant);
+   pragma Inline (Others_Discrete_Choices);
+   pragma Inline (Out_Present);
+   pragma Inline (Parameter_Associations);
+   pragma Inline (Parameter_Specifications);
+   pragma Inline (Parameter_List_Truncated);
+   pragma Inline (Parameter_Type);
+   pragma Inline (Parent_Spec);
+   pragma Inline (Position);
+   pragma Inline (Pragma_Argument_Associations);
+   pragma Inline (Pragmas_After);
+   pragma Inline (Pragmas_Before);
+   pragma Inline (Prefix);
+   pragma Inline (Present_Expr);
+   pragma Inline (Prev_Ids);
+   pragma Inline (Print_In_Hex);
+   pragma Inline (Private_Declarations);
+   pragma Inline (Private_Present);
+   pragma Inline (Procedure_To_Call);
+   pragma Inline (Proper_Body);
+   pragma Inline (Protected_Definition);
+   pragma Inline (Protected_Present);
+   pragma Inline (Raises_Constraint_Error);
+   pragma Inline (Range_Constraint);
+   pragma Inline (Range_Expression);
+   pragma Inline (Realval);
+   pragma Inline (Real_Range_Specification);
+   pragma Inline (Record_Extension_Part);
+   pragma Inline (Redundant_Use);
+   pragma Inline (Return_Type);
+   pragma Inline (Reverse_Present);
+   pragma Inline (Right_Opnd);
+   pragma Inline (Rounded_Result);
+   pragma Inline (Scope);
+   pragma Inline (Select_Alternatives);
+   pragma Inline (Selector_Name);
+   pragma Inline (Selector_Names);
+   pragma Inline (Shift_Count_OK);
+   pragma Inline (Source_Type);
+   pragma Inline (Specification);
+   pragma Inline (Statements);
+   pragma Inline (Static_Processing_OK);
+   pragma Inline (Storage_Pool);
+   pragma Inline (Strval);
+   pragma Inline (Subtype_Indication);
+   pragma Inline (Subtype_Mark);
+   pragma Inline (Subtype_Marks);
+   pragma Inline (Tagged_Present);
+   pragma Inline (Target_Type);
+   pragma Inline (Task_Body_Procedure);
+   pragma Inline (Task_Definition);
+   pragma Inline (Then_Actions);
+   pragma Inline (Then_Statements);
+   pragma Inline (Triggering_Alternative);
+   pragma Inline (Triggering_Statement);
+   pragma Inline (Treat_Fixed_As_Integer);
+   pragma Inline (TSS_Elist);
+   pragma Inline (Type_Definition);
+   pragma Inline (Unit);
+   pragma Inline (Unknown_Discriminants_Present);
+   pragma Inline (Unreferenced_In_Spec);
+   pragma Inline (Variant_Part);
+   pragma Inline (Variants);
+   pragma Inline (Visible_Declarations);
+   pragma Inline (Was_Originally_Stub);
+   pragma Inline (Zero_Cost_Handling);
+
+   pragma Inline (Set_ABE_Is_Certain);
+   pragma Inline (Set_Abort_Present);
+   pragma Inline (Set_Abortable_Part);
+   pragma Inline (Set_Abstract_Present);
+   pragma Inline (Set_Accept_Handler_Records);
+   pragma Inline (Set_Accept_Statement);
+   pragma Inline (Set_Access_Types_To_Process);
+   pragma Inline (Set_Actions);
+   pragma Inline (Set_Activation_Chain_Entity);
+   pragma Inline (Set_Acts_As_Spec);
+   pragma Inline (Set_Aggregate_Bounds);
+   pragma Inline (Set_Aliased_Present);
+   pragma Inline (Set_All_Others);
+   pragma Inline (Set_All_Present);
+   pragma Inline (Set_Alternatives);
+   pragma Inline (Set_Ancestor_Part);
+   pragma Inline (Set_Array_Aggregate);
+   pragma Inline (Set_Assignment_OK);
+   pragma Inline (Set_At_End_Proc);
+   pragma Inline (Set_Attribute_Name);
+   pragma Inline (Set_Aux_Decls_Node);
+   pragma Inline (Set_Backwards_OK);
+   pragma Inline (Set_Bad_Is_Detected);
+   pragma Inline (Set_Body_To_Inline);
+   pragma Inline (Set_Body_Required);
+   pragma Inline (Set_By_Ref);
+   pragma Inline (Set_Box_Present);
+   pragma Inline (Set_Char_Literal_Value);
+   pragma Inline (Set_Chars);
+   pragma Inline (Set_Choice_Parameter);
+   pragma Inline (Set_Choices);
+   pragma Inline (Set_Compile_Time_Known_Aggregate);
+   pragma Inline (Set_Component_Associations);
+   pragma Inline (Set_Component_Clauses);
+   pragma Inline (Set_Component_Items);
+   pragma Inline (Set_Component_List);
+   pragma Inline (Set_Component_Name);
+   pragma Inline (Set_Condition);
+   pragma Inline (Set_Condition_Actions);
+   pragma Inline (Set_Constant_Present);
+   pragma Inline (Set_Constraint);
+   pragma Inline (Set_Constraints);
+   pragma Inline (Set_Context_Installed);
+   pragma Inline (Set_Context_Items);
+   pragma Inline (Set_Controlling_Argument);
+   pragma Inline (Set_Conversion_OK);
+   pragma Inline (Set_Corresponding_Body);
+   pragma Inline (Set_Corresponding_Generic_Association);
+   pragma Inline (Set_Corresponding_Integer_Value);
+   pragma Inline (Set_Corresponding_Spec);
+   pragma Inline (Set_Corresponding_Stub);
+   pragma Inline (Set_Dcheck_Function);
+   pragma Inline (Set_Debug_Statement);
+   pragma Inline (Set_Declarations);
+   pragma Inline (Set_Default_Expression);
+   pragma Inline (Set_Default_Name);
+   pragma Inline (Set_Defining_Identifier);
+   pragma Inline (Set_Defining_Unit_Name);
+   pragma Inline (Set_Delay_Alternative);
+   pragma Inline (Set_Delay_Finalize_Attach);
+   pragma Inline (Set_Delay_Statement);
+   pragma Inline (Set_Delta_Expression);
+   pragma Inline (Set_Digits_Expression);
+   pragma Inline (Set_Discr_Check_Funcs_Built);
+   pragma Inline (Set_Discrete_Choices);
+   pragma Inline (Set_Discrete_Range);
+   pragma Inline (Set_Discrete_Subtype_Definition);
+   pragma Inline (Set_Discrete_Subtype_Definitions);
+   pragma Inline (Set_Discriminant_Specifications);
+   pragma Inline (Set_Discriminant_Type);
+   pragma Inline (Set_Do_Access_Check);
+   pragma Inline (Set_Do_Accessibility_Check);
+   pragma Inline (Set_Do_Discriminant_Check);
+   pragma Inline (Set_Do_Length_Check);
+   pragma Inline (Set_Do_Division_Check);
+   pragma Inline (Set_Do_Overflow_Check);
+   pragma Inline (Set_Do_Range_Check);
+   pragma Inline (Set_Do_Storage_Check);
+   pragma Inline (Set_Do_Tag_Check);
+   pragma Inline (Set_Elaborate_Present);
+   pragma Inline (Set_Elaborate_All_Present);
+   pragma Inline (Set_Elaboration_Boolean);
+   pragma Inline (Set_Else_Actions);
+   pragma Inline (Set_Else_Statements);
+   pragma Inline (Set_Elsif_Parts);
+   pragma Inline (Set_Enclosing_Variant);
+   pragma Inline (Set_End_Label);
+   pragma Inline (Set_End_Span);
+   pragma Inline (Set_Entity);
+   pragma Inline (Set_Entry_Body_Formal_Part);
+   pragma Inline (Set_Entry_Call_Alternative);
+   pragma Inline (Set_Entry_Call_Statement);
+   pragma Inline (Set_Entry_Direct_Name);
+   pragma Inline (Set_Entry_Index);
+   pragma Inline (Set_Entry_Index_Specification);
+   pragma Inline (Set_Etype);
+   pragma Inline (Set_Exception_Choices);
+   pragma Inline (Set_Exception_Junk);
+   pragma Inline (Set_Exception_Handlers);
+   pragma Inline (Set_Expansion_Delayed);
+   pragma Inline (Set_Explicit_Actual_Parameter);
+   pragma Inline (Set_Explicit_Generic_Actual_Parameter);
+   pragma Inline (Set_Expression);
+   pragma Inline (Set_Expressions);
+   pragma Inline (Set_First_Bit);
+   pragma Inline (Set_First_Inlined_Subprogram);
+   pragma Inline (Set_First_Name);
+   pragma Inline (Set_First_Named_Actual);
+   pragma Inline (Set_First_Real_Statement);
+   pragma Inline (Set_First_Subtype_Link);
+   pragma Inline (Set_Float_Truncate);
+   pragma Inline (Set_Formal_Type_Definition);
+   pragma Inline (Set_Forwards_OK);
+   pragma Inline (Set_From_At_Mod);
+   pragma Inline (Set_Generic_Associations);
+   pragma Inline (Set_Generic_Formal_Declarations);
+   pragma Inline (Set_Generic_Parent);
+   pragma Inline (Set_Generic_Parent_Type);
+   pragma Inline (Set_Handled_Statement_Sequence);
+   pragma Inline (Set_Handler_List_Entry);
+   pragma Inline (Set_Has_Created_Identifier);
+   pragma Inline (Set_Has_Dynamic_Length_Check);
+   pragma Inline (Set_Has_Dynamic_Range_Check);
+   pragma Inline (Set_Has_No_Elaboration_Code);
+   pragma Inline (Set_Has_Priority_Pragma);
+   pragma Inline (Set_Has_Private_View);
+   pragma Inline (Set_Has_Storage_Size_Pragma);
+   pragma Inline (Set_Has_Task_Info_Pragma);
+   pragma Inline (Set_Has_Task_Name_Pragma);
+   pragma Inline (Set_Has_Wide_Character);
+   pragma Inline (Set_Hidden_By_Use_Clause);
+   pragma Inline (Set_High_Bound);
+   pragma Inline (Set_Identifier);
+   pragma Inline (Set_Implicit_With);
+   pragma Inline (Set_Includes_Infinities);
+   pragma Inline (Set_In_Present);
+   pragma Inline (Set_Instance_Spec);
+   pragma Inline (Set_Intval);
+   pragma Inline (Set_Is_Asynchronous_Call_Block);
+   pragma Inline (Set_Is_Component_Left_Opnd);
+   pragma Inline (Set_Is_Component_Right_Opnd);
+   pragma Inline (Set_Is_Controlling_Actual);
+   pragma Inline (Set_Is_Machine_Number);
+   pragma Inline (Set_Is_Overloaded);
+   pragma Inline (Set_Is_Power_Of_2_For_Shift);
+   pragma Inline (Set_Is_Protected_Subprogram_Body);
+   pragma Inline (Set_Is_Static_Expression);
+   pragma Inline (Set_Is_Subprogram_Descriptor);
+   pragma Inline (Set_Is_Task_Allocation_Block);
+   pragma Inline (Set_Is_Task_Master);
+   pragma Inline (Set_Iteration_Scheme);
+   pragma Inline (Set_Itype);
+   pragma Inline (Set_Kill_Range_Check);
+   pragma Inline (Set_Last_Bit);
+   pragma Inline (Set_Last_Name);
+   pragma Inline (Set_Library_Unit);
+   pragma Inline (Set_Label_Construct);
+   pragma Inline (Set_Left_Opnd);
+   pragma Inline (Set_Limited_Present);
+   pragma Inline (Set_Literals);
+   pragma Inline (Set_Loop_Actions);
+   pragma Inline (Set_Loop_Parameter_Specification);
+   pragma Inline (Set_Low_Bound);
+   pragma Inline (Set_Mod_Clause);
+   pragma Inline (Set_More_Ids);
+   pragma Inline (Set_Must_Not_Freeze);
+   pragma Inline (Set_Name);
+   pragma Inline (Set_Names);
+   pragma Inline (Set_Next_Entity);
+   pragma Inline (Set_Next_Named_Actual);
+   pragma Inline (Set_Next_Use_Clause);
+   pragma Inline (Set_No_Ctrl_Actions);
+   pragma Inline (Set_No_Entities_Ref_In_Spec);
+   pragma Inline (Set_No_Initialization);
+   pragma Inline (Set_Null_Present);
+   pragma Inline (Set_Null_Record_Present);
+   pragma Inline (Set_Object_Definition);
+   pragma Inline (Set_OK_For_Stream);
+   pragma Inline (Set_Original_Discriminant);
+   pragma Inline (Set_Others_Discrete_Choices);
+   pragma Inline (Set_Out_Present);
+   pragma Inline (Set_Parameter_Associations);
+   pragma Inline (Set_Parameter_Specifications);
+   pragma Inline (Set_Parameter_List_Truncated);
+   pragma Inline (Set_Parameter_Type);
+   pragma Inline (Set_Parent_Spec);
+   pragma Inline (Set_Position);
+   pragma Inline (Set_Pragma_Argument_Associations);
+   pragma Inline (Set_Pragmas_After);
+   pragma Inline (Set_Pragmas_Before);
+   pragma Inline (Set_Prefix);
+   pragma Inline (Set_Present_Expr);
+   pragma Inline (Set_Prev_Ids);
+   pragma Inline (Set_Print_In_Hex);
+   pragma Inline (Set_Private_Declarations);
+   pragma Inline (Set_Private_Present);
+   pragma Inline (Set_Procedure_To_Call);
+   pragma Inline (Set_Proper_Body);
+   pragma Inline (Set_Protected_Definition);
+   pragma Inline (Set_Protected_Present);
+   pragma Inline (Set_Raises_Constraint_Error);
+   pragma Inline (Set_Range_Constraint);
+   pragma Inline (Set_Range_Expression);
+   pragma Inline (Set_Realval);
+   pragma Inline (Set_Real_Range_Specification);
+   pragma Inline (Set_Record_Extension_Part);
+   pragma Inline (Set_Redundant_Use);
+   pragma Inline (Set_Return_Type);
+   pragma Inline (Set_Reverse_Present);
+   pragma Inline (Set_Right_Opnd);
+   pragma Inline (Set_Rounded_Result);
+   pragma Inline (Set_Scope);
+   pragma Inline (Set_Select_Alternatives);
+   pragma Inline (Set_Selector_Name);
+   pragma Inline (Set_Selector_Names);
+   pragma Inline (Set_Shift_Count_OK);
+   pragma Inline (Set_Source_Type);
+   pragma Inline (Set_Specification);
+   pragma Inline (Set_Statements);
+   pragma Inline (Set_Static_Processing_OK);
+   pragma Inline (Set_Storage_Pool);
+   pragma Inline (Set_Strval);
+   pragma Inline (Set_Subtype_Indication);
+   pragma Inline (Set_Subtype_Mark);
+   pragma Inline (Set_Subtype_Marks);
+   pragma Inline (Set_Tagged_Present);
+   pragma Inline (Set_Target_Type);
+   pragma Inline (Set_Task_Body_Procedure);
+   pragma Inline (Set_Task_Definition);
+   pragma Inline (Set_Then_Actions);
+   pragma Inline (Set_Then_Statements);
+   pragma Inline (Set_Triggering_Alternative);
+   pragma Inline (Set_Triggering_Statement);
+   pragma Inline (Set_Treat_Fixed_As_Integer);
+   pragma Inline (Set_TSS_Elist);
+   pragma Inline (Set_Type_Definition);
+   pragma Inline (Set_Unit);
+   pragma Inline (Set_Unknown_Discriminants_Present);
+   pragma Inline (Set_Unreferenced_In_Spec);
+   pragma Inline (Set_Variant_Part);
+   pragma Inline (Set_Variants);
+   pragma Inline (Set_Visible_Declarations);
+   pragma Inline (Set_Was_Originally_Stub);
+   pragma Inline (Set_Zero_Cost_Handling);
+
+end Sinfo;
diff --git a/gcc/ada/sinput-l.adb b/gcc/ada/sinput-l.adb
new file mode 100644 (file)
index 0000000..f00cbbd
--- /dev/null
@@ -0,0 +1,533 @@
+------------------------------------------------------------------------------
+--                                                                          --
+--                         GNAT COMPILER COMPONENTS                         --
+--                                                                          --
+--                             S I N P U T . L                              --
+--                                                                          --
+--                                 B o d y                                  --
+--                                                                          --
+--                            $Revision: 1.40 $
+--                                                                          --
+--          Copyright (C) 1992-2001 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- --
+-- ware  Foundation;  either version 2,  or (at your option) any later ver- --
+-- sion.  GNAT is distributed in the hope that it will be useful, but WITH- --
+-- OUT ANY WARRANTY;  without even the  implied warranty of MERCHANTABILITY --
+-- or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License --
+-- for  more details.  You should have  received  a copy of the GNU General --
+-- Public License  distributed with GNAT;  see file COPYING.  If not, write --
+-- to  the Free Software Foundation,  59 Temple Place - Suite 330,  Boston, --
+-- MA 02111-1307, USA.                                                      --
+--                                                                          --
+-- GNAT was originally developed  by the GNAT team at  New York University. --
+-- It is now maintained by Ada Core Technologies Inc (http://www.gnat.com). --
+--                                                                          --
+------------------------------------------------------------------------------
+
+with Alloc;
+with Atree;  use Atree;
+with Debug;  use Debug;
+with Einfo;  use Einfo;
+with Namet;  use Namet;
+with Opt;
+with Osint;  use Osint;
+with Output; use Output;
+with Scans;  use Scans;
+with Scn;    use Scn;
+with Sinfo;  use Sinfo;
+with System; use System;
+
+with Unchecked_Conversion;
+
+package body Sinput.L is
+
+   Dfile : Source_File_Index;
+   --  Index of currently active debug source file
+
+   -----------------
+   -- Subprograms --
+   -----------------
+
+   procedure Trim_Lines_Table (S : Source_File_Index);
+   --  Set lines table size for entry S in the source file table to
+   --  correspond to the current value of Num_Source_Lines, releasing
+   --  any unused storage.
+
+   function Load_File
+     (N    : File_Name_Type;
+      T    : File_Type)
+      return Source_File_Index;
+   --  Load a source file or a configuration pragma file.
+
+   -------------------------------
+   -- Adjust_Instantiation_Sloc --
+   -------------------------------
+
+   procedure Adjust_Instantiation_Sloc (N : Node_Id; A : Sloc_Adjustment) is
+      Loc : constant Source_Ptr := Sloc (N);
+
+   begin
+      --  We only do the adjustment if the value is between the appropriate
+      --  low and high values. It is not clear that this should ever not be
+      --  the case, but in practice there seem to be some nodes that get
+      --  copied twice, and this is a defence against that happening.
+
+      if A.Lo <= Loc and then Loc <= A.Hi then
+         Set_Sloc (N, Loc + A.Adjust);
+      end if;
+   end Adjust_Instantiation_Sloc;
+
+   ------------------------
+   -- Close_Debug_Source --
+   ------------------------
+
+   procedure Close_Debug_Source is
+      S    : Source_File_Record renames Source_File.Table (Dfile);
+      Src  : Source_Buffer_Ptr;
+
+   begin
+      Trim_Lines_Table (Dfile);
+      Close_Debug_File;
+
+      --  Now we need to read the file that we wrote and store it
+      --  in memory for subsequent access.
+
+      Read_Source_File
+        (S.Debug_Source_Name, S.Source_First, S.Source_Last, Src);
+      S.Source_Text := Src;
+   end Close_Debug_Source;
+
+   --------------------------------
+   -- Complete_Source_File_Entry --
+   --------------------------------
+
+   procedure Complete_Source_File_Entry is
+      CSF : constant Source_File_Index := Current_Source_File;
+
+   begin
+      Trim_Lines_Table (CSF);
+      Source_File.Table (CSF).Source_Checksum := Checksum;
+   end Complete_Source_File_Entry;
+
+   -------------------------
+   -- Create_Debug_Source --
+   -------------------------
+
+   procedure Create_Debug_Source
+     (Source : Source_File_Index;
+      Loc    : out Source_Ptr)
+   is
+   begin
+      Loc := Source_File.Table (Source_File.Last).Source_Last + 1;
+      Source_File.Increment_Last;
+      Dfile := Source_File.Last;
+
+      declare
+         S : Source_File_Record renames Source_File.Table (Dfile);
+
+      begin
+         S := Source_File.Table (Source);
+         S.Debug_Source_Name := Create_Debug_File (S.File_Name);
+         S.Source_First      := Loc;
+         S.Source_Last       := Loc;
+         S.Lines_Table       := null;
+         S.Last_Source_Line  := 1;
+
+         --  Allocate lines table, guess that it needs to be three times
+         --  bigger than the original source (in number of lines).
+
+         Alloc_Line_Tables
+           (S, Int (Source_File.Table (Source).Last_Source_Line * 3));
+         S.Lines_Table (1) := Loc;
+      end;
+
+      if Debug_Flag_GG then
+         Write_Str ("---> Create_Debug_Source (Source => ");
+         Write_Int (Int (Source));
+         Write_Str (", Loc => ");
+         Write_Int (Int (Loc));
+         Write_Str (");");
+         Write_Eol;
+      end if;
+
+   end Create_Debug_Source;
+
+   ---------------------------------
+   -- Create_Instantiation_Source --
+   ---------------------------------
+
+   procedure Create_Instantiation_Source
+     (Inst_Node   : Entity_Id;
+      Template_Id : Entity_Id;
+      A           : out Sloc_Adjustment)
+   is
+      Dnod : constant Node_Id := Declaration_Node (Template_Id);
+      Xold : Source_File_Index;
+      Xnew : Source_File_Index;
+
+   begin
+      Xold := Get_Source_File_Index (Sloc (Template_Id));
+      A.Lo := Source_File.Table (Xold).Source_First;
+      A.Hi := Source_File.Table (Xold).Source_Last;
+
+      Source_File.Increment_Last;
+      Xnew := Source_File.Last;
+
+      Source_File.Table (Xnew)               := Source_File.Table (Xold);
+      Source_File.Table (Xnew).Instantiation := Sloc (Inst_Node);
+      Source_File.Table (Xnew).Template      := Xold;
+
+      --  Now we need to compute the new values of Source_First, Source_Last
+      --  and adjust the source file pointer to have the correct virtual
+      --  origin for the new range of values.
+
+      Source_File.Table (Xnew).Source_First :=
+        Source_File.Table (Xnew - 1).Source_Last + 1;
+
+      A.Adjust := Source_File.Table (Xnew).Source_First - A.Lo;
+      Source_File.Table (Xnew).Source_Last := A.Hi + A.Adjust;
+
+      Source_File.Table (Xnew).Sloc_Adjust :=
+        Source_File.Table (Xold).Sloc_Adjust - A.Adjust;
+
+      if Debug_Flag_L then
+         Write_Eol;
+         Write_Str ("*** Create instantiation source for ");
+
+         if Nkind (Dnod) in N_Proper_Body
+           and then Was_Originally_Stub (Dnod)
+         then
+            Write_Str ("subunit ");
+
+         elsif Ekind (Template_Id) = E_Generic_Package then
+            if Nkind (Dnod) = N_Package_Body then
+               Write_Str ("body of package ");
+            else
+               Write_Str ("spec of package ");
+            end if;
+
+         elsif Ekind (Template_Id) = E_Function then
+            Write_Str ("body of function ");
+
+         elsif Ekind (Template_Id) = E_Procedure then
+            Write_Str ("body of procedure ");
+
+         elsif Ekind (Template_Id) = E_Generic_Function then
+            Write_Str ("spec of function ");
+
+         elsif Ekind (Template_Id) = E_Generic_Procedure then
+            Write_Str ("spec of procedure ");
+
+         elsif Ekind (Template_Id) = E_Package_Body then
+            Write_Str ("body of package ");
+
+         else pragma Assert (Ekind (Template_Id) = E_Subprogram_Body);
+
+            if Nkind (Dnod) = N_Procedure_Specification then
+               Write_Str ("body of procedure ");
+            else
+               Write_Str ("body of function ");
+            end if;
+         end if;
+
+         Write_Name (Chars (Template_Id));
+         Write_Eol;
+
+         Write_Str ("  new source index = ");
+         Write_Int (Int (Xnew));
+         Write_Eol;
+
+         Write_Str ("  copying from file name = ");
+         Write_Name (File_Name (Xold));
+         Write_Eol;
+
+         Write_Str ("  old source index = ");
+         Write_Int (Int (Xold));
+         Write_Eol;
+
+         Write_Str ("  old lo = ");
+         Write_Int (Int (A.Lo));
+         Write_Eol;
+
+         Write_Str ("  old hi = ");
+         Write_Int (Int (A.Hi));
+         Write_Eol;
+
+         Write_Str ("  new lo = ");
+         Write_Int (Int (Source_File.Table (Xnew).Source_First));
+         Write_Eol;
+
+         Write_Str ("  new hi = ");
+         Write_Int (Int (Source_File.Table (Xnew).Source_Last));
+         Write_Eol;
+
+         Write_Str ("  adjustment factor = ");
+         Write_Int (Int (A.Adjust));
+         Write_Eol;
+
+         Write_Str ("  instantiation location: ");
+         Write_Location (Sloc (Inst_Node));
+         Write_Eol;
+      end if;
+
+      --  For a given character in the source, a higher subscript will be
+      --  used to access the instantiation, which means that the virtual
+      --  origin must have a corresponding lower value. We compute this
+      --  new origin by taking the address of the appropriate adjusted
+      --  element in the old array. Since this adjusted element will be
+      --  at a negative subscript, we must suppress checks.
+
+      declare
+         pragma Suppress (All_Checks);
+
+         function To_Source_Buffer_Ptr is new
+           Unchecked_Conversion (Address, Source_Buffer_Ptr);
+
+      begin
+         Source_File.Table (Xnew).Source_Text :=
+           To_Source_Buffer_Ptr
+             (Source_File.Table (Xold).Source_Text (-A.Adjust)'Address);
+      end;
+
+   end Create_Instantiation_Source;
+
+   ----------------------
+   -- Load_Config_File --
+   ----------------------
+
+   function Load_Config_File
+     (N    : File_Name_Type)
+      return Source_File_Index
+   is
+   begin
+      return Load_File (N, Osint.Config);
+   end Load_Config_File;
+
+   ---------------
+   -- Load_File --
+   ---------------
+
+   function Load_File
+     (N :    File_Name_Type;
+      T :    File_Type)
+      return Source_File_Index
+   is
+      Src  : Source_Buffer_Ptr;
+      X    : Source_File_Index;
+      Lo   : Source_Ptr;
+      Hi   : Source_Ptr;
+
+   begin
+      for J in 1 .. Source_File.Last loop
+         if Source_File.Table (J).File_Name = N then
+            return J;
+         end if;
+      end loop;
+
+      --  Here we must build a new entry in the file table
+
+      Source_File.Increment_Last;
+      X := Source_File.Last;
+
+      if X = Source_File.First then
+         Lo := First_Source_Ptr;
+      else
+         Lo := Source_File.Table (X - 1).Source_Last + 1;
+      end if;
+
+      Read_Source_File (N, Lo, Hi, Src, T);
+
+      if Src = null then
+         Source_File.Decrement_Last;
+         return No_Source_File;
+
+      else
+         if Debug_Flag_L then
+            Write_Eol;
+            Write_Str ("*** Build source file table entry, Index = ");
+            Write_Int (Int (X));
+            Write_Str (", file name = ");
+            Write_Name (N);
+            Write_Eol;
+            Write_Str ("  lo = ");
+            Write_Int (Int (Lo));
+            Write_Eol;
+            Write_Str ("  hi = ");
+            Write_Int (Int (Hi));
+            Write_Eol;
+
+            Write_Str ("  first 10 chars -->");
+
+            declare
+               procedure Wchar (C : Character);
+               --  Writes character or ? for control character
+
+               procedure Wchar (C : Character) is
+               begin
+                  if C < ' ' or C in ASCII.DEL .. Character'Val (16#9F#) then
+                     Write_Char ('?');
+                  else
+                     Write_Char (C);
+                  end if;
+               end Wchar;
+
+            begin
+               for J in Lo .. Lo + 9 loop
+                  Wchar (Src (J));
+               end loop;
+
+               Write_Str ("<--");
+               Write_Eol;
+
+               Write_Str ("  last 10 chars  -->");
+
+               for J in Hi - 10 .. Hi - 1 loop
+                  Wchar (Src (J));
+               end loop;
+
+               Write_Str ("<--");
+               Write_Eol;
+
+               if Src (Hi) /= EOF then
+                  Write_Str ("  error: no EOF at end");
+                  Write_Eol;
+               end if;
+            end;
+         end if;
+
+         declare
+            S : Source_File_Record renames Source_File.Table (X);
+
+         begin
+            S := (Debug_Source_Name   => Full_Source_Name,
+                  File_Name           => N,
+                  First_Mapped_Line   => No_Line_Number,
+                  Full_File_Name      => Full_Source_Name,
+                  Full_Ref_Name       => Full_Source_Name,
+                  Identifier_Casing   => Unknown,
+                  Instantiation       => No_Location,
+                  Keyword_Casing      => Unknown,
+                  Last_Source_Line    => 1,
+                  License             => Unknown,
+                  Lines_Table         => null,
+                  Lines_Table_Max     => 1,
+                  Logical_Lines_Table => null,
+                  Num_SRef_Pragmas    => 0,
+                  Reference_Name      => N,
+                  Sloc_Adjust         => 0,
+                  Source_Checksum     => 0,
+                  Source_First        => Lo,
+                  Source_Last         => Hi,
+                  Source_Text         => Src,
+                  Template            => No_Source_File,
+                  Time_Stamp          => Current_Source_File_Stamp);
+
+            Alloc_Line_Tables (S, Opt.Table_Factor * Alloc.Lines_Initial);
+            S.Lines_Table (1) := Lo;
+         end;
+
+         return X;
+      end if;
+   end Load_File;
+
+   ----------------------
+   -- Load_Source_File --
+   ----------------------
+
+   function Load_Source_File
+     (N    : File_Name_Type)
+      return Source_File_Index
+   is
+   begin
+      return Load_File (N, Osint.Source);
+   end Load_Source_File;
+
+   ----------------------------
+   -- Source_File_Is_Subunit --
+   ----------------------------
+
+   function Source_File_Is_Subunit (X : Source_File_Index) return Boolean is
+   begin
+      Initialize_Scanner (No_Unit, X);
+
+      --  We scan past junk to the first interesting compilation unit
+      --  token, to see if it is SEPARATE. We ignore WITH keywords during
+      --  this and also PRIVATE. The reason for ignoring PRIVATE is that
+      --  it handles some error situations, and also it is possible that
+      --  a PRIVATE WITH feature might be approved some time in the future.
+
+      while Token = Tok_With
+        or else Token = Tok_Private
+        or else (Token not in Token_Class_Cunit and then Token /= Tok_EOF)
+      loop
+         Scan;
+      end loop;
+
+      return Token = Tok_Separate;
+   end Source_File_Is_Subunit;
+
+   ----------------------
+   -- Trim_Lines_Table --
+   ----------------------
+
+   procedure Trim_Lines_Table (S : Source_File_Index) is
+
+      function realloc
+        (P        : Lines_Table_Ptr;
+         New_Size : Int)
+         return     Lines_Table_Ptr;
+      pragma Import (C, realloc);
+
+      Max : constant Nat := Nat (Source_File.Table (S).Last_Source_Line);
+
+   begin
+      --  Release allocated storage that is no longer needed
+
+      Source_File.Table (S).Lines_Table :=
+        realloc
+          (Source_File.Table (S).Lines_Table,
+           Max * (Lines_Table_Type'Component_Size / System.Storage_Unit));
+      Source_File.Table (S).Lines_Table_Max := Physical_Line_Number (Max);
+   end Trim_Lines_Table;
+
+   ----------------------
+   -- Write_Debug_Line --
+   ----------------------
+
+   procedure Write_Debug_Line (Str : String; Loc : in out Source_Ptr) is
+      S : Source_File_Record renames Source_File.Table (Dfile);
+
+   begin
+      --  Ignore write request if null line at start of file
+
+      if Str'Length = 0 and then Loc = S.Source_First then
+         return;
+
+      --  Here we write the line, and update the source record entry
+
+      else
+         Write_Debug_Info (Str);
+         Add_Line_Tables_Entry (S, Loc);
+         Loc := Loc + Source_Ptr (Str'Length + Debug_File_Eol_Length);
+         S.Source_Last := Loc;
+
+         if Debug_Flag_GG then
+            declare
+               Lin : constant String := Str;
+
+            begin
+               Column := 1;
+               Write_Str ("---> Write_Debug_Line (Str => """);
+               Write_Str (Lin);
+               Write_Str (""", Loc => ");
+               Write_Int (Int (Loc));
+               Write_Str (");");
+               Write_Eol;
+            end;
+         end if;
+      end if;
+   end Write_Debug_Line;
+
+end Sinput.L;
diff --git a/gcc/ada/sinput-l.ads b/gcc/ada/sinput-l.ads
new file mode 100644 (file)
index 0000000..bba983f
--- /dev/null
@@ -0,0 +1,141 @@
+------------------------------------------------------------------------------
+--                                                                          --
+--                         GNAT COMPILER COMPONENTS                         --
+--                                                                          --
+--                             S I N P U T . L                              --
+--                                                                          --
+--                                 S p e c                                  --
+--                                                                          --
+--                            $Revision: 1.14 $                             --
+--                                                                          --
+--          Copyright (C) 1992-2001, 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- --
+-- ware  Foundation;  either version 2,  or (at your option) any later ver- --
+-- sion.  GNAT is distributed in the hope that it will be useful, but WITH- --
+-- OUT ANY WARRANTY;  without even the  implied warranty of MERCHANTABILITY --
+-- or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License --
+-- for  more details.  You should have  received  a copy of the GNU General --
+-- Public License  distributed with GNAT;  see file COPYING.  If not, write --
+-- to  the Free Software Foundation,  59 Temple Place - Suite 330,  Boston, --
+-- MA 02111-1307, USA.                                                      --
+--                                                                          --
+-- GNAT was originally developed  by the GNAT team at  New York University. --
+-- It is now maintained by Ada Core Technologies Inc (http://www.gnat.com). --
+--                                                                          --
+------------------------------------------------------------------------------
+
+--  This child package contains the routines used to actually load a source
+--  file and create entries in the source file table. It also contains the
+--  routines to create virtual entries for instantiations. This is separated
+--  off into a child package to avoid a dependence of Sinput on Osint which
+--  would cause trouble in the tree read/write routines.
+
+with Types; use Types;
+
+package Sinput.L is
+
+   -------------------------------------------
+   --  Subprograms for Loading Source Files --
+   -------------------------------------------
+
+   function Load_Source_File (N : File_Name_Type) return Source_File_Index;
+   --  Given a source file name, returns the index of the corresponding entry
+   --  in the source file table. If the file is not currently loaded, then
+   --  this is the call that causes the source file to be read and an entry
+   --  made in the table. A new entry in the table has the file name and time
+   --  stamp entries set and the Casing entries set to Unknown. Version is set
+   --  to all blanks, and the lines table is initialized but only the first
+   --  entry is set (and Last_Line is set to 1). If the given source file
+   --  cannot be opened, then the value returned is No_Source_File.
+
+   function Load_Config_File (N : File_Name_Type) return Source_File_Index;
+   --  Similar to Load_Source_File, except that the file name is always
+   --  interpreted in the context of the current working directory.
+
+   procedure Complete_Source_File_Entry;
+   --  Called on completing the parsing of a source file. This call completes
+   --  the source file table entry for the current source file.
+
+   function Source_File_Is_Subunit (X : Source_File_Index) return Boolean;
+   --  This function determines if a source file represents a subunit. It
+   --  works by scanning for the first compilation unit token, and returning
+   --  True if it is the token SEPARATE. It will return False otherwise,
+   --  meaning that the file cannot possibly be a legal subunit. This
+   --  function does NOT do a complete parse of the file, or build a
+   --  tree. It is used in the main driver in the check for bad bodies.
+
+   -------------------------------------------------
+   -- Subprograms for Dealing With Instantiations --
+   -------------------------------------------------
+
+   type Sloc_Adjustment is private;
+   --  Type returned by Create_Instantiation_Source for use in subsequent
+   --  calls to Adjust_Instantiation_Sloc.
+
+   procedure Create_Instantiation_Source
+     (Inst_Node   : Entity_Id;
+      Template_Id : Entity_Id;
+      A           : out Sloc_Adjustment);
+   --  This procedure creates the source table entry for an instantiation.
+   --  Inst_Node is the instantiation node, and Template_Id is the defining
+   --  identifier of the generic declaration or body unit as appropriate.
+   --  A is set to an adjustment factor to be used in subsequent calls to
+   --  Adjust_Instantiation_Sloc.
+
+   procedure Adjust_Instantiation_Sloc (N : Node_Id; A : Sloc_Adjustment);
+   --  The instantiation tree is created by copying the tree of the generic
+   --  template (including the original Sloc values), and then applying
+   --  Adjust_Instantiation_Sloc to each copied node to adjust the Sloc
+   --  to reference the source entry for the instantiation.
+
+   ------------------------------------------------
+   -- Subprograms for Writing Debug Source Files --
+   ------------------------------------------------
+
+   procedure Create_Debug_Source
+     (Source : Source_File_Index;
+      Loc    : out Source_Ptr);
+   --  Given a source file, creates a new source file table entry to be used
+   --  for the debug source file output (Debug_Generated_Code switch set).
+   --  Loc is set to the initial Sloc value for the first line. This call
+   --  also creates the debug source output file (using Create_Debug_File).
+
+   procedure Write_Debug_Line (Str : String; Loc : in out Source_Ptr);
+   --  This procedure is called to write a line to the debug source file
+   --  previously created by Create_Debug_Source using Write_Debug_Info.
+   --  Str is the source line to be written to the file (it does not include
+   --  an end of line character). On entry Loc is the Sloc value previously
+   --  returned by Create_Debug_Source or Write_Debug_Line, and on exit,
+   --  Sloc is updated to point to the start of the next line to be written,
+   --  taking into account the length of the ternminator that was written by
+   --  Write_Debug_Info.
+
+   procedure Close_Debug_Source;
+   --  This procedure completes the source table entry for the debug file
+   --  previously created by Create_Debug_Source, and written using the
+   --  Write_Debug_Line procedure. It then calls Close_Debug_File to
+   --  complete the writing of the file itself.
+
+private
+
+   type Sloc_Adjustment is record
+      Adjust : Source_Ptr;
+      --  Adjustment factor. To be added to source location values in the
+      --  source table entry for the template to get corresponding sloc
+      --  values for the instantiation image of the template. This is not
+      --  really a Source_Ptr value, but rather an offset, but it is more
+      --  convenient to represent it as a Source_Ptr value and this is a
+      --  private type anyway.
+
+      Lo, Hi : Source_Ptr;
+      --  Lo and hi values to which adjustment factor can legitimately
+      --  be applied, used to ensure that no incorrect adjustments are
+      --  made. Really it is a bug if anyone ever tries to adjust outside
+      --  this range, but since we are only doing this anyway for getting
+      --  better error messages, it is not critical
+
+   end record;
+
+end Sinput.L;
diff --git a/gcc/ada/sinput-p.adb b/gcc/ada/sinput-p.adb
new file mode 100644 (file)
index 0000000..10a20f4
--- /dev/null
@@ -0,0 +1,233 @@
+------------------------------------------------------------------------------
+--                                                                          --
+--                         GNAT COMPILER COMPONENTS                         --
+--                                                                          --
+--                             S I N P U T . P                              --
+--                                                                          --
+--                                 B o d y                                  --
+--                                                                          --
+--                            $Revision: 1.9 $
+--                                                                          --
+--          Copyright (C) 1992-2001 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- --
+-- ware  Foundation;  either version 2,  or (at your option) any later ver- --
+-- sion.  GNAT is distributed in the hope that it will be useful, but WITH- --
+-- OUT ANY WARRANTY;  without even the  implied warranty of MERCHANTABILITY --
+-- or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License --
+-- for  more details.  You should have  received  a copy of the GNU General --
+-- Public License  distributed with GNAT;  see file COPYING.  If not, write --
+-- to  the Free Software Foundation,  59 Temple Place - Suite 330,  Boston, --
+-- MA 02111-1307, USA.                                                      --
+--                                                                          --
+-- GNAT was originally developed  by the GNAT team at  New York University. --
+-- It is now maintained by Ada Core Technologies Inc (http://www.gnat.com). --
+--                                                                          --
+------------------------------------------------------------------------------
+
+with Ada.Unchecked_Conversion;
+
+with GNAT.OS_Lib; use GNAT.OS_Lib;
+with Namet;       use Namet;
+with Opt;         use Opt;
+with System;      use System;
+
+package body Sinput.P is
+
+   First : Boolean := True;
+   --  Flag used when Load_Project_File is called the first time,
+   --  to set Main_Source_File.
+   --  The flag is reset to False at the first call to Load_Project_File
+
+   -----------------------
+   -- Load_Project_File --
+   -----------------------
+
+   function Load_Project_File (Path : String) return Source_File_Index is
+      Src  : Source_Buffer_Ptr;
+      X    : Source_File_Index;
+      Lo   : Source_Ptr;
+      Hi   : Source_Ptr;
+
+      Source_File_FD : File_Descriptor;
+      --  The file descriptor for the current source file. A negative value
+      --  indicates failure to open the specified source file.
+
+      Len : Integer;
+      --  Length of file. Assume no more than 2 gigabytes of source!
+
+      Actual_Len : Integer;
+
+      Path_Id : Name_Id;
+      File_Id : Name_Id;
+
+   begin
+      if Path = "" then
+         return No_Source_File;
+      end if;
+
+      Source_File.Increment_Last;
+      X := Source_File.Last;
+
+      if First then
+         Main_Source_File := X;
+         First := False;
+      end if;
+
+      if X = Source_File.First then
+         Lo := First_Source_Ptr;
+      else
+         Lo := Source_File.Table (X - 1).Source_Last + 1;
+      end if;
+
+      Name_Len := Path'Length;
+      Name_Buffer (1 .. Name_Len) := Path;
+      Path_Id := Name_Find;
+      Name_Buffer (Name_Len + 1) := ASCII.NUL;
+
+      --  Open the source FD, note that we open in binary mode, because as
+      --  documented in the spec, the caller is expected to handle either
+      --  DOS or Unix mode files, and there is no point in wasting time on
+      --  text translation when it is not required.
+
+      Source_File_FD := Open_Read (Name_Buffer'Address, Binary);
+
+      if Source_File_FD = Invalid_FD then
+         Source_File.Decrement_Last;
+         return No_Source_File;
+
+      end if;
+
+      Len := Integer (File_Length (Source_File_FD));
+
+      --  Set Hi so that length is one more than the physical length,
+      --  allowing for the extra EOF character at the end of the buffer
+
+      Hi := Lo + Source_Ptr (Len);
+
+      --  Do the actual read operation
+
+      declare
+         subtype Actual_Source_Buffer is Source_Buffer (Lo .. Hi);
+         --  Physical buffer allocated
+
+         type Actual_Source_Ptr is access Actual_Source_Buffer;
+         --  This is the pointer type for the physical buffer allocated
+
+         Actual_Ptr : Actual_Source_Ptr := new Actual_Source_Buffer;
+         --  And this is the actual physical buffer
+
+      begin
+         --  Allocate source buffer, allowing extra character at end for EOF
+
+         --  Some systems (e.g. VMS) have file types that require one
+         --  read per line, so read until we get the Len bytes or until
+         --  there are no more characters.
+
+         Hi := Lo;
+         loop
+            Actual_Len := Read (Source_File_FD, Actual_Ptr (Hi)'Address, Len);
+            Hi := Hi + Source_Ptr (Actual_Len);
+            exit when Actual_Len = Len or Actual_Len <= 0;
+         end loop;
+
+         Actual_Ptr (Hi) := EOF;
+
+         --  Now we need to work out the proper virtual origin pointer to
+         --  return. This is exactly Actual_Ptr (0)'Address, but we have
+         --  to be careful to suppress checks to compute this address.
+
+         declare
+            pragma Suppress (All_Checks);
+
+            function To_Source_Buffer_Ptr is new
+              Ada.Unchecked_Conversion (Address, Source_Buffer_Ptr);
+
+         begin
+            Src := To_Source_Buffer_Ptr (Actual_Ptr (0)'Address);
+         end;
+      end;
+
+      --  Read is complete, get time stamp and close file and we are done
+
+      Close (Source_File_FD);
+
+      --  Get the file name, without path information
+
+      declare
+         Index : Positive := Path'Last;
+
+      begin
+         while Index > Path'First loop
+            exit when Path (Index - 1) = '/';
+            exit when Path (Index - 1) = Directory_Separator;
+            Index := Index - 1;
+         end loop;
+
+         Name_Len := Path'Last - Index + 1;
+         Name_Buffer (1 .. Name_Len) := Path (Index .. Path'Last);
+         File_Id := Name_Find;
+      end;
+
+      declare
+         S : Source_File_Record renames Source_File.Table (X);
+
+      begin
+         S := (Debug_Source_Name   => Path_Id,
+               File_Name           => File_Id,
+               First_Mapped_Line   => No_Line_Number,
+               Full_File_Name      => Path_Id,
+               Full_Ref_Name       => Path_Id,
+               Identifier_Casing   => Unknown,
+               Instantiation       => No_Location,
+               Keyword_Casing      => Unknown,
+               Last_Source_Line    => 1,
+               License             => Unknown,
+               Lines_Table         => null,
+               Lines_Table_Max     => 1,
+               Logical_Lines_Table => null,
+               Num_SRef_Pragmas    => 0,
+               Reference_Name      => File_Id,
+               Sloc_Adjust         => 0,
+               Source_Checksum     => 0,
+               Source_First        => Lo,
+               Source_Last         => Hi,
+               Source_Text         => Src,
+               Template            => No_Source_File,
+               Time_Stamp          => Empty_Time_Stamp);
+
+         Alloc_Line_Tables (S, Opt.Table_Factor * Alloc.Lines_Initial);
+         S.Lines_Table (1) := Lo;
+      end;
+
+      return X;
+   end Load_Project_File;
+
+   --------------------------------
+   -- Restore_Project_Scan_State --
+   --------------------------------
+
+   procedure Restore_Project_Scan_State
+     (Saved_State : in Saved_Project_Scan_State)
+   is
+   begin
+      Restore_Scan_State (Saved_State.Scan_State);
+      Source              := Saved_State.Source;
+      Current_Source_File := Saved_State.Current_Source_File;
+   end Restore_Project_Scan_State;
+
+   -----------------------------
+   -- Save_Project_Scan_State --
+   -----------------------------
+
+   procedure Save_Project_Scan_State
+     (Saved_State : out Saved_Project_Scan_State)
+   is
+   begin
+      Save_Scan_State (Saved_State.Scan_State);
+      Saved_State.Source              := Source;
+      Saved_State.Current_Source_File := Current_Source_File;
+   end Save_Project_Scan_State;
+
+end Sinput.P;
diff --git a/gcc/ada/sinput-p.ads b/gcc/ada/sinput-p.ads
new file mode 100644 (file)
index 0000000..9292eab
--- /dev/null
@@ -0,0 +1,65 @@
+------------------------------------------------------------------------------
+--                                                                          --
+--                         GNAT COMPILER COMPONENTS                         --
+--                                                                          --
+--                             S I N P U T . P                              --
+--                                                                          --
+--                                 S p e c                                  --
+--                                                                          --
+--                            $Revision: 1.3 $
+--                                                                          --
+--          Copyright (C) 1992-2001, 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- --
+-- ware  Foundation;  either version 2,  or (at your option) any later ver- --
+-- sion.  GNAT is distributed in the hope that it will be useful, but WITH- --
+-- OUT ANY WARRANTY;  without even the  implied warranty of MERCHANTABILITY --
+-- or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License --
+-- for  more details.  You should have  received  a copy of the GNU General --
+-- Public License  distributed with GNAT;  see file COPYING.  If not, write --
+-- to  the Free Software Foundation,  59 Temple Place - Suite 330,  Boston, --
+-- MA 02111-1307, USA.                                                      --
+--                                                                          --
+-- GNAT was originally developed  by the GNAT team at  New York University. --
+-- It is now maintained by Ada Core Technologies Inc (http://www.gnat.com). --
+--                                                                          --
+------------------------------------------------------------------------------
+
+--  This child package contains the routines used to actually load a project
+--  file and create entries in the source file table. It also contains two
+--  routines to save and restore a project scan context.
+
+with Scans; use Scans;
+with Types; use Types;
+
+package Sinput.P is
+
+   function Load_Project_File (Path : String) return Source_File_Index;
+   --  Load into memory the source of a project source file.
+   --  Initialize the Scans state.
+
+   type Saved_Project_Scan_State is limited private;
+   --  Used to save project scan state in following two routines
+
+   procedure Save_Project_Scan_State
+     (Saved_State : out Saved_Project_Scan_State);
+   pragma Inline (Save_Project_Scan_State);
+   --  Save the Scans state, as well as the values of
+   --  Source and Current_Source_File.
+
+   procedure Restore_Project_Scan_State
+     (Saved_State : Saved_Project_Scan_State);
+   pragma Inline (Restore_Project_Scan_State);
+   --  Restore the Scans state and the values of
+   --  Source and Current_Source_File.
+
+private
+
+   type Saved_Project_Scan_State is record
+      Scan_State          : Saved_Scan_State;
+      Source              : Source_Buffer_Ptr;
+      Current_Source_File : Source_File_Index;
+   end record;
+
+end Sinput.P;
diff --git a/gcc/ada/sinput.adb b/gcc/ada/sinput.adb
new file mode 100644 (file)
index 0000000..b861288
--- /dev/null
@@ -0,0 +1,1132 @@
+------------------------------------------------------------------------------
+--                                                                          --
+--                         GNAT COMPILER COMPONENTS                         --
+--                                                                          --
+--                               S I N P U T                                --
+--                                                                          --
+--                                 B o d y                                  --
+--                                                                          --
+--                            $Revision: 1.99 $
+--                                                                          --
+--          Copyright (C) 1992-2001 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- --
+-- ware  Foundation;  either version 2,  or (at your option) any later ver- --
+-- sion.  GNAT is distributed in the hope that it will be useful, but WITH- --
+-- OUT ANY WARRANTY;  without even the  implied warranty of MERCHANTABILITY --
+-- or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License --
+-- for  more details.  You should have  received  a copy of the GNU General --
+-- Public License  distributed with GNAT;  see file COPYING.  If not, write --
+-- to  the Free Software Foundation,  59 Temple Place - Suite 330,  Boston, --
+-- MA 02111-1307, USA.                                                      --
+--                                                                          --
+-- As a special exception,  if other files  instantiate  generics from this --
+-- unit, or you link  this unit with other files  to produce an executable, --
+-- this  unit  does not  by itself cause  the resulting  executable  to  be --
+-- covered  by the  GNU  General  Public  License.  This exception does not --
+-- however invalidate  any other reasons why  the executable file  might be --
+-- covered by the  GNU Public License.                                      --
+--                                                                          --
+-- GNAT was originally developed  by the GNAT team at  New York University. --
+-- It is now maintained by Ada Core Technologies Inc (http://www.gnat.com). --
+--                                                                          --
+------------------------------------------------------------------------------
+
+pragma Style_Checks (All_Checks);
+--  Subprograms not all in alpha order
+
+with Debug;   use Debug;
+with Namet;   use Namet;
+with Opt;     use Opt;
+with Output;  use Output;
+with Tree_IO; use Tree_IO;
+with System;  use System;
+
+with Unchecked_Conversion;
+with Unchecked_Deallocation;
+
+package body Sinput is
+
+   use ASCII;
+   --  Make control characters visible
+
+   First_Time_Around : Boolean := True;
+
+   ---------------------------
+   -- Add_Line_Tables_Entry --
+   ---------------------------
+
+   procedure Add_Line_Tables_Entry
+     (S : in out Source_File_Record;
+      P : Source_Ptr)
+   is
+      LL : Physical_Line_Number;
+
+   begin
+      --  Reallocate the lines tables if necessary.
+
+      --  Note: the reason we do not use the normal Table package
+      --  mechanism is that we have several of these tables. We could
+      --  use the new GNAT.Dynamic_Tables package and that would probably
+      --  be a good idea ???
+
+      if S.Last_Source_Line = S.Lines_Table_Max then
+         Alloc_Line_Tables
+           (S,
+            Int (S.Last_Source_Line) *
+              ((100 + Alloc.Lines_Increment) / 100));
+
+         if Debug_Flag_D then
+            Write_Str ("--> Reallocating lines table, size = ");
+            Write_Int (Int (S.Lines_Table_Max));
+            Write_Eol;
+         end if;
+      end if;
+
+      S.Last_Source_Line := S.Last_Source_Line + 1;
+      LL := S.Last_Source_Line;
+
+      S.Lines_Table (LL) := P;
+
+      --  Deal with setting new entry in logical lines table if one is
+      --  present. Note that there is always space (because the call to
+      --  Alloc_Line_Tables makes sure both tables are the same length),
+
+      if S.Logical_Lines_Table /= null then
+
+         --  We can always set the entry from the previous one, because
+         --  the processing for a Source_Reference pragma ensures that
+         --  at least one entry following the pragma is set up correctly.
+
+         S.Logical_Lines_Table (LL) := S.Logical_Lines_Table (LL - 1) + 1;
+      end if;
+   end Add_Line_Tables_Entry;
+
+   -----------------------
+   -- Alloc_Line_Tables --
+   -----------------------
+
+   procedure Alloc_Line_Tables
+     (S       : in out Source_File_Record;
+      New_Max : Nat)
+   is
+      function realloc
+        (memblock : Lines_Table_Ptr;
+         size     : size_t)
+         return     Lines_Table_Ptr;
+      pragma Import (C, realloc, "realloc");
+
+      function reallocl
+        (memblock : Logical_Lines_Table_Ptr;
+         size     : size_t)
+         return     Logical_Lines_Table_Ptr;
+      pragma Import (C, reallocl, "realloc");
+
+      function malloc
+        (size   : size_t)
+         return Lines_Table_Ptr;
+      pragma Import (C, malloc, "malloc");
+
+      function mallocl
+        (size   : size_t)
+         return Logical_Lines_Table_Ptr;
+      pragma Import (C, mallocl, "malloc");
+
+      New_Table : Lines_Table_Ptr;
+
+      New_Logical_Table : Logical_Lines_Table_Ptr;
+
+      New_Size : constant size_t :=
+                   size_t (New_Max * Lines_Table_Type'Component_Size /
+                                                             Storage_Unit);
+
+   begin
+      if S.Lines_Table = null then
+         New_Table := malloc (New_Size);
+
+      else
+         New_Table :=
+           realloc (memblock => S.Lines_Table, size => New_Size);
+      end if;
+
+      if New_Table = null then
+         raise Storage_Error;
+      else
+         S.Lines_Table     := New_Table;
+         S.Lines_Table_Max := Physical_Line_Number (New_Max);
+      end if;
+
+      if S.Num_SRef_Pragmas /= 0 then
+         if S.Logical_Lines_Table = null then
+            New_Logical_Table := mallocl (New_Size);
+         else
+            New_Logical_Table :=
+              reallocl (memblock => S.Logical_Lines_Table, size => New_Size);
+         end if;
+
+         if New_Logical_Table = null then
+            raise Storage_Error;
+         else
+            S.Logical_Lines_Table := New_Logical_Table;
+         end if;
+      end if;
+   end Alloc_Line_Tables;
+
+   -----------------
+   -- Backup_Line --
+   -----------------
+
+   procedure Backup_Line (P : in out Source_Ptr) is
+      Sindex : constant Source_File_Index := Get_Source_File_Index (P);
+      Src    : constant Source_Buffer_Ptr :=
+                 Source_File.Table (Sindex).Source_Text;
+      Sfirst : constant Source_Ptr :=
+                 Source_File.Table (Sindex).Source_First;
+
+   begin
+      P := P - 1;
+
+      if P = Sfirst then
+         return;
+      end if;
+
+      if Src (P) = CR then
+         if Src (P - 1) = LF then
+            P := P - 1;
+         end if;
+
+      else -- Src (P) = LF
+         if Src (P - 1) = CR then
+            P := P - 1;
+         end if;
+      end if;
+
+      --  Now find first character of the previous line
+
+      while P > Sfirst
+        and then Src (P - 1) /= LF
+        and then Src (P - 1) /= CR
+      loop
+         P := P - 1;
+      end loop;
+   end Backup_Line;
+
+   ---------------------------
+   -- Build_Location_String --
+   ---------------------------
+
+   procedure Build_Location_String (Loc : Source_Ptr) is
+      Ptr : Source_Ptr;
+
+   begin
+      Name_Len := 0;
+
+      --  Loop through instantiations
+
+      Ptr := Loc;
+      loop
+         Get_Name_String_And_Append
+           (Reference_Name (Get_Source_File_Index (Ptr)));
+         Add_Char_To_Name_Buffer (':');
+         Add_Nat_To_Name_Buffer
+           (Nat (Get_Logical_Line_Number (Ptr)));
+
+         Ptr := Instantiation_Location (Ptr);
+         exit when Ptr = No_Location;
+         Add_Str_To_Name_Buffer (" instantiated at ");
+      end loop;
+
+      Name_Buffer (Name_Len + 1) := NUL;
+      return;
+   end Build_Location_String;
+
+   -----------------------
+   -- Get_Column_Number --
+   -----------------------
+
+   function Get_Column_Number (P : Source_Ptr) return Column_Number is
+      S      : Source_Ptr;
+      C      : Column_Number;
+      Sindex : Source_File_Index;
+      Src    : Source_Buffer_Ptr;
+
+   begin
+      --  If the input source pointer is not a meaningful value then return
+      --  at once with column number 1. This can happen for a file not found
+      --  condition for a file loaded indirectly by RTE, and also perhaps on
+      --  some unknown internal error conditions. In either case we certainly
+      --  don't want to blow up.
+
+      if P < 1 then
+         return 1;
+
+      else
+         Sindex := Get_Source_File_Index (P);
+         Src := Source_File.Table (Sindex).Source_Text;
+         S := Line_Start (P);
+         C := 1;
+
+         while S < P loop
+            if Src (S) = HT then
+               C := (C - 1) / 8 * 8 + (8 + 1);
+            else
+               C := C + 1;
+            end if;
+
+            S := S + 1;
+         end loop;
+
+         return C;
+      end if;
+   end Get_Column_Number;
+
+   -----------------------------
+   -- Get_Logical_Line_Number --
+   -----------------------------
+
+   function Get_Logical_Line_Number
+     (P    : Source_Ptr)
+      return Logical_Line_Number
+   is
+      SFR : Source_File_Record
+              renames Source_File.Table (Get_Source_File_Index (P));
+
+      L : constant Physical_Line_Number := Get_Physical_Line_Number (P);
+
+   begin
+      if SFR.Num_SRef_Pragmas = 0 then
+         return Logical_Line_Number (L);
+      else
+         return SFR.Logical_Lines_Table (L);
+      end if;
+   end Get_Logical_Line_Number;
+
+   ------------------------------
+   -- Get_Physical_Line_Number --
+   ------------------------------
+
+   function Get_Physical_Line_Number
+     (P    : Source_Ptr)
+      return Physical_Line_Number
+   is
+      Sfile : Source_File_Index;
+      Table : Lines_Table_Ptr;
+      Lo    : Physical_Line_Number;
+      Hi    : Physical_Line_Number;
+      Mid   : Physical_Line_Number;
+      Loc   : Source_Ptr;
+
+   begin
+      --  If the input source pointer is not a meaningful value then return
+      --  at once with line number 1. This can happen for a file not found
+      --  condition for a file loaded indirectly by RTE, and also perhaps on
+      --  some unknown internal error conditions. In either case we certainly
+      --  don't want to blow up.
+
+      if P < 1 then
+         return 1;
+
+      --  Otherwise we can do the binary search
+
+      else
+         Sfile := Get_Source_File_Index (P);
+         Loc   := P + Source_File.Table (Sfile).Sloc_Adjust;
+         Table := Source_File.Table (Sfile).Lines_Table;
+         Lo    := 1;
+         Hi    := Source_File.Table (Sfile).Last_Source_Line;
+
+         loop
+            Mid := (Lo + Hi) / 2;
+
+            if Loc < Table (Mid) then
+               Hi := Mid - 1;
+
+            else -- Loc >= Table (Mid)
+
+               if Mid = Hi or else
+                  Loc < Table (Mid + 1)
+               then
+                  return Mid;
+               else
+                  Lo := Mid + 1;
+               end if;
+
+            end if;
+
+         end loop;
+      end if;
+   end Get_Physical_Line_Number;
+
+   ---------------------------
+   -- Get_Source_File_Index --
+   ---------------------------
+
+   Source_Cache_First : Source_Ptr := 1;
+   Source_Cache_Last  : Source_Ptr := 0;
+   --  Records the First and Last subscript values for the most recently
+   --  referenced entry in the source table, to optimize the common case
+   --  of repeated references to the same entry. The initial values force
+   --  an initial search to set the cache value.
+
+   Source_Cache_Index : Source_File_Index := No_Source_File;
+   --  Contains the index of the entry corresponding to Source_Cache
+
+   function Get_Source_File_Index
+     (S    : Source_Ptr)
+      return Source_File_Index
+   is
+   begin
+      if S in Source_Cache_First .. Source_Cache_Last then
+         return Source_Cache_Index;
+
+      else
+         for J in 1 .. Source_File.Last loop
+            if S in Source_File.Table (J).Source_First ..
+                    Source_File.Table (J).Source_Last
+            then
+               Source_Cache_Index := J;
+               Source_Cache_First :=
+                 Source_File.Table (Source_Cache_Index).Source_First;
+               Source_Cache_Last :=
+                 Source_File.Table (Source_Cache_Index).Source_Last;
+               return Source_Cache_Index;
+            end if;
+         end loop;
+      end if;
+
+      --  We must find a matching entry in the above loop!
+
+      raise Program_Error;
+   end Get_Source_File_Index;
+
+   ----------------
+   -- Initialize --
+   ----------------
+
+   procedure Initialize is
+   begin
+      Source_File.Init;
+   end Initialize;
+
+   -------------------------
+   -- Instantiation_Depth --
+   -------------------------
+
+   function Instantiation_Depth (S : Source_Ptr) return Nat is
+      Sind  : Source_File_Index;
+      Sval  : Source_Ptr;
+      Depth : Nat;
+
+   begin
+      Sval := S;
+      Depth := 0;
+
+      loop
+         Sind := Get_Source_File_Index (Sval);
+         Sval := Instantiation (Sind);
+         exit when Sval = No_Location;
+         Depth := Depth + 1;
+      end loop;
+
+      return Depth;
+   end Instantiation_Depth;
+
+   ----------------------------
+   -- Instantiation_Location --
+   ----------------------------
+
+   function Instantiation_Location (S : Source_Ptr) return Source_Ptr is
+   begin
+      return Instantiation (Get_Source_File_Index (S));
+   end Instantiation_Location;
+
+   ----------------------
+   -- Last_Source_File --
+   ----------------------
+
+   function Last_Source_File return Source_File_Index is
+   begin
+      return Source_File.Last;
+   end Last_Source_File;
+
+   ----------------
+   -- Line_Start --
+   ----------------
+
+   function Line_Start (P : Source_Ptr) return Source_Ptr is
+      Sindex : constant Source_File_Index := Get_Source_File_Index (P);
+      Src    : constant Source_Buffer_Ptr :=
+                 Source_File.Table (Sindex).Source_Text;
+      Sfirst : constant Source_Ptr :=
+                 Source_File.Table (Sindex).Source_First;
+      S      : Source_Ptr;
+
+   begin
+      S := P;
+
+      while S > Sfirst
+        and then Src (S - 1) /= CR
+        and then Src (S - 1) /= LF
+      loop
+         S := S - 1;
+      end loop;
+
+      return S;
+   end Line_Start;
+
+   function Line_Start
+     (L    : Physical_Line_Number;
+      S    : Source_File_Index)
+      return Source_Ptr
+   is
+   begin
+      return Source_File.Table (S).Lines_Table (L);
+   end Line_Start;
+
+   ----------
+   -- Lock --
+   ----------
+
+   procedure Lock is
+   begin
+      Source_File.Locked := True;
+      Source_File.Release;
+   end Lock;
+
+   ----------------------
+   -- Num_Source_Files --
+   ----------------------
+
+   function Num_Source_Files return Nat is
+   begin
+      return Int (Source_File.Last) - Int (Source_File.First) + 1;
+   end Num_Source_Files;
+
+   ----------------------
+   -- Num_Source_Lines --
+   ----------------------
+
+   function Num_Source_Lines (S : Source_File_Index) return Nat is
+   begin
+      return Nat (Source_File.Table (S).Last_Source_Line);
+   end Num_Source_Lines;
+
+   -----------------------
+   -- Original_Location --
+   -----------------------
+
+   function Original_Location (S : Source_Ptr) return Source_Ptr is
+      Sindex : Source_File_Index;
+      Tindex : Source_File_Index;
+
+   begin
+      if S <= No_Location then
+         return S;
+
+      else
+         Sindex := Get_Source_File_Index (S);
+
+         if Instantiation (Sindex) = No_Location then
+            return S;
+
+         else
+            Tindex := Template (Sindex);
+            while Instantiation (Tindex) /= No_Location loop
+               Tindex := Template (Tindex);
+            end loop;
+
+            return S - Source_First (Sindex) + Source_First (Tindex);
+         end if;
+      end if;
+   end Original_Location;
+
+   -------------------------
+   -- Physical_To_Logical --
+   -------------------------
+
+   function Physical_To_Logical
+     (Line : Physical_Line_Number;
+      S    : Source_File_Index)
+      return Logical_Line_Number
+   is
+      SFR : Source_File_Record renames Source_File.Table (S);
+
+   begin
+      if SFR.Num_SRef_Pragmas = 0 then
+         return Logical_Line_Number (Line);
+      else
+         return SFR.Logical_Lines_Table (Line);
+      end if;
+   end Physical_To_Logical;
+
+   --------------------------------
+   -- Register_Source_Ref_Pragma --
+   --------------------------------
+
+   procedure Register_Source_Ref_Pragma
+     (File_Name          : Name_Id;
+      Stripped_File_Name : Name_Id;
+      Mapped_Line        : Nat;
+      Line_After_Pragma  : Physical_Line_Number)
+   is
+      SFR : Source_File_Record renames Source_File.Table (Current_Source_File);
+
+      function malloc
+        (size     : size_t)
+         return     Logical_Lines_Table_Ptr;
+      pragma Import (C, malloc);
+
+      ML : Logical_Line_Number;
+
+   begin
+      if File_Name /= No_Name then
+         SFR.Full_Ref_Name := File_Name;
+
+         if not Debug_Generated_Code then
+            SFR.Debug_Source_Name := File_Name;
+         end if;
+
+         SFR.Reference_Name   := Stripped_File_Name;
+         SFR.Num_SRef_Pragmas := SFR.Num_SRef_Pragmas + 1;
+      end if;
+
+      if SFR.Num_SRef_Pragmas = 1 then
+         SFR.First_Mapped_Line := Logical_Line_Number (Mapped_Line);
+      end if;
+
+      if SFR.Logical_Lines_Table = null then
+         SFR.Logical_Lines_Table :=
+           malloc
+             (size_t (SFR.Lines_Table_Max *
+                        Logical_Lines_Table_Type'Component_Size /
+                                                        Storage_Unit));
+      end if;
+
+      SFR.Logical_Lines_Table (Line_After_Pragma - 1) := No_Line_Number;
+
+      ML := Logical_Line_Number (Mapped_Line);
+      for J in Line_After_Pragma .. SFR.Last_Source_Line loop
+         SFR.Logical_Lines_Table (J) := ML;
+         ML := ML + 1;
+      end loop;
+   end Register_Source_Ref_Pragma;
+
+   ---------------------------
+   -- Skip_Line_Terminators --
+   ---------------------------
+
+   --  There are two distinct concepts of line terminator in GNAT
+
+   --    A logical line terminator is what corresponds to the "end of a line"
+   --    as described in RM 2.2 (13). Any of the characters FF, LF, CR or VT
+   --    acts as an end of logical line in this sense, and it is essentially
+   --    irrelevant whether one or more appears in sequence (since if a
+   --    sequence of such characters is regarded as separate ends of line,
+   --    then the intervening logical lines are null in any case).
+
+   --    A physical line terminator is a sequence of format effectors that
+   --    is treated as ending a physical line. Physical lines have no Ada
+   --    semantic significance, but they are significant for error reporting
+   --    purposes, since errors are identified by line and column location.
+
+   --  In GNAT, a physical line is ended by any of the sequences LF, CR/LF,
+   --  CR or LF/CR. LF is used in typical Unix systems, CR/LF in DOS systems,
+   --  and CR alone in System 7. We don't know of any system using LF/CR, but
+   --  it seems reasonable to include this case for consistency. In addition,
+   --  we recognize any of these sequences in any of the operating systems,
+   --  for better behavior in treating foreign files (e.g. a Unix file with
+   --  LF terminators transferred to a DOS system).
+
+   procedure Skip_Line_Terminators
+     (P        : in out Source_Ptr;
+      Physical : out Boolean)
+   is
+   begin
+      pragma Assert (Source (P) in Line_Terminator);
+
+      if Source (P) = CR then
+         if Source (P + 1) = LF then
+            P := P + 2;
+         else
+            P := P + 1;
+         end if;
+
+      elsif Source (P) = LF then
+         if Source (P + 1) = CR then
+            P := P + 2;
+         else
+            P := P + 1;
+         end if;
+
+      else -- Source (P) = FF or else Source (P) = VT
+         P := P + 1;
+         Physical := False;
+         return;
+      end if;
+
+      --  Fall through in the physical line terminator case. First deal with
+      --  making a possible entry into the lines table if one is needed.
+
+      --  Note: we are dealing with a real source file here, this cannot be
+      --  the instantiation case, so we need not worry about Sloc adjustment.
+
+      declare
+         S : Source_File_Record
+               renames Source_File.Table (Current_Source_File);
+
+      begin
+         Physical := True;
+
+         --  Make entry in lines table if not already made (in some scan backup
+         --  cases, we will be rescanning previously scanned source, so the
+         --  entry may have already been made on the previous forward scan).
+
+         if Source (P) /= EOF
+           and then P > S.Lines_Table (S.Last_Source_Line)
+         then
+            Add_Line_Tables_Entry (S, P);
+         end if;
+      end;
+   end Skip_Line_Terminators;
+
+   -------------------
+   -- Source_Offset --
+   -------------------
+
+   function Source_Offset (S : Source_Ptr) return Nat is
+      Sindex : constant Source_File_Index := Get_Source_File_Index (S);
+      Sfirst : constant Source_Ptr :=
+                 Source_File.Table (Sindex).Source_First;
+
+   begin
+      return Nat (S - Sfirst);
+   end Source_Offset;
+
+   ------------------------
+   -- Top_Level_Location --
+   ------------------------
+
+   function Top_Level_Location (S : Source_Ptr) return Source_Ptr is
+      Oldloc : Source_Ptr;
+      Newloc : Source_Ptr;
+
+   begin
+      Newloc := S;
+      loop
+         Oldloc := Newloc;
+         Newloc := Instantiation_Location (Oldloc);
+         exit when Newloc = No_Location;
+      end loop;
+
+      return Oldloc;
+   end Top_Level_Location;
+
+   ---------------
+   -- Tree_Read --
+   ---------------
+
+   procedure Tree_Read is
+   begin
+      --  First we must free any old source buffer pointers
+
+      if not First_Time_Around then
+         for J in Source_File.First .. Source_File.Last loop
+            declare
+               S : Source_File_Record renames Source_File.Table (J);
+
+               procedure Free_Ptr is new Unchecked_Deallocation
+                 (Big_Source_Buffer, Source_Buffer_Ptr);
+
+               --  Note: we are using free here, because we used malloc
+               --  or realloc directly to allocate the tables. That is
+               --  because we were playing the big array trick.
+
+               procedure free (X : Lines_Table_Ptr);
+               pragma Import (C, free, "free");
+
+               procedure freel (X : Logical_Lines_Table_Ptr);
+               pragma Import (C, freel, "free");
+
+               function To_Source_Buffer_Ptr is new
+                 Unchecked_Conversion (Address, Source_Buffer_Ptr);
+
+               Tmp1 : Source_Buffer_Ptr;
+
+            begin
+               if S.Instantiation /= No_Location then
+                  null;
+
+               else
+                  --  We have to recreate a proper pointer to the actual array
+                  --  from the zero origin pointer stored in the source table.
+
+                  Tmp1 :=
+                    To_Source_Buffer_Ptr
+                      (S.Source_Text (S.Source_First)'Address);
+                  Free_Ptr (Tmp1);
+
+                  if S.Lines_Table /= null then
+                     free (S.Lines_Table);
+                     S.Lines_Table := null;
+                  end if;
+
+                  if S.Logical_Lines_Table /= null then
+                     freel (S.Logical_Lines_Table);
+                     S.Logical_Lines_Table := null;
+                  end if;
+               end if;
+            end;
+         end loop;
+      end if;
+
+      --  Reset source cache pointers to force new read
+
+      Source_Cache_First := 1;
+      Source_Cache_Last  := 0;
+
+      --  Read in source file table
+
+      Source_File.Tree_Read;
+
+      --  The pointers we read in there for the source buffer and lines
+      --  table pointers are junk. We now read in the actual data that
+      --  is referenced by these two fields.
+
+      for J in Source_File.First .. Source_File.Last loop
+         declare
+            S : Source_File_Record renames Source_File.Table (J);
+
+         begin
+            --  For the instantiation case, we do not read in any data. Instead
+            --  we share the data for the generic template entry. Since the
+            --  template always occurs first, we can safetly refer to its data.
+
+            if S.Instantiation /= No_Location then
+               declare
+                  ST : Source_File_Record renames
+                         Source_File.Table (S.Template);
+
+               begin
+                  --  The lines tables are copied from the template entry
+
+                  S.Lines_Table :=
+                    Source_File.Table (S.Template).Lines_Table;
+                  S.Logical_Lines_Table :=
+                    Source_File.Table (S.Template).Logical_Lines_Table;
+
+                  --  In the case of the source table pointer, we share the
+                  --  same data as the generic template, but the virtual origin
+                  --  is adjusted. For example, if the first subscript of the
+                  --  template is 100, and that of the instantiation is 200,
+                  --  then the instantiation pointer is obtained by subtracting
+                  --  100 from the template pointer.
+
+                  declare
+                     pragma Suppress (All_Checks);
+
+                     function To_Source_Buffer_Ptr is new
+                       Unchecked_Conversion (Address, Source_Buffer_Ptr);
+
+                  begin
+                     S.Source_Text :=
+                       To_Source_Buffer_Ptr
+                          (ST.Source_Text
+                            (ST.Source_First - S.Source_First)'Address);
+                  end;
+               end;
+
+            --  Normal case (non-instantiation)
+
+            else
+               First_Time_Around := False;
+               S.Lines_Table := null;
+               S.Logical_Lines_Table := null;
+               Alloc_Line_Tables (S, Int (S.Last_Source_Line));
+
+               for J in 1 .. S.Last_Source_Line loop
+                  Tree_Read_Int (Int (S.Lines_Table (J)));
+               end loop;
+
+               if S.Num_SRef_Pragmas /= 0 then
+                  for J in 1 .. S.Last_Source_Line loop
+                     Tree_Read_Int (Int (S.Logical_Lines_Table (J)));
+                  end loop;
+               end if;
+
+               --  Allocate source buffer and read in the data and then set the
+               --  virtual origin to point to the logical zero'th element. This
+               --  address must be computed with subscript checks turned off.
+
+               declare
+                  subtype B is Text_Buffer (S.Source_First .. S.Source_Last);
+                  type Text_Buffer_Ptr is access B;
+                  T : Text_Buffer_Ptr;
+
+                  pragma Suppress (All_Checks);
+
+                  function To_Source_Buffer_Ptr is new
+                    Unchecked_Conversion (Address, Source_Buffer_Ptr);
+
+               begin
+                  T := new B;
+
+                  Tree_Read_Data (T (S.Source_First)'Address,
+                     Int (S.Source_Last) - Int (S.Source_First) + 1);
+
+                  S.Source_Text := To_Source_Buffer_Ptr (T (0)'Address);
+               end;
+            end if;
+         end;
+      end loop;
+   end Tree_Read;
+
+   ----------------
+   -- Tree_Write --
+   ----------------
+
+   procedure Tree_Write is
+   begin
+      Source_File.Tree_Write;
+
+      --  The pointers we wrote out there for the source buffer and lines
+      --  table pointers are junk, we now write out the actual data that
+      --  is referenced by these two fields.
+
+      for J in Source_File.First .. Source_File.Last loop
+         declare
+            S : Source_File_Record renames Source_File.Table (J);
+
+         begin
+            --  For instantiations, there is nothing to do, since the data is
+            --  shared with the generic template. When the tree is read, the
+            --  pointers must be set, but no extra data needs to be written.
+
+            if S.Instantiation /= No_Location then
+               null;
+
+            --  For the normal case, write out the data of the tables
+
+            else
+               --  Lines table
+
+               for J in 1 .. S.Last_Source_Line loop
+                  Tree_Write_Int (Int (S.Lines_Table (J)));
+               end loop;
+
+               --  Logical lines table if present
+
+               if S.Num_SRef_Pragmas /= 0 then
+                  for J in 1 .. S.Last_Source_Line loop
+                     Tree_Write_Int (Int (S.Logical_Lines_Table (J)));
+                  end loop;
+               end if;
+
+               --  Source buffer
+
+               Tree_Write_Data
+                 (S.Source_Text (S.Source_First)'Address,
+                   Int (S.Source_Last) - Int (S.Source_First) + 1);
+            end if;
+         end;
+      end loop;
+   end Tree_Write;
+
+   --------------------
+   -- Write_Location --
+   --------------------
+
+   procedure Write_Location (P : Source_Ptr) is
+   begin
+      if P = No_Location then
+         Write_Str ("<no location>");
+
+      elsif P <= Standard_Location then
+         Write_Str ("<standard location>");
+
+      else
+         declare
+            SI : constant Source_File_Index := Get_Source_File_Index (P);
+
+         begin
+            Write_Name (Debug_Source_Name (SI));
+            Write_Char (':');
+            Write_Int (Int (Get_Logical_Line_Number (P)));
+            Write_Char (':');
+            Write_Int (Int (Get_Column_Number (P)));
+
+            if Instantiation (SI) /= No_Location then
+               Write_Str (" [");
+               Write_Location (Instantiation (SI));
+               Write_Char (']');
+            end if;
+         end;
+      end if;
+   end Write_Location;
+
+   ----------------------
+   -- Write_Time_Stamp --
+   ----------------------
+
+   procedure Write_Time_Stamp (S : Source_File_Index) is
+      T : constant Time_Stamp_Type := Time_Stamp (S);
+      P : Natural;
+
+   begin
+      if T (1) = '9' then
+         Write_Str ("19");
+         P := 0;
+      else
+         Write_Char (T (1));
+         Write_Char (T (2));
+         P := 2;
+      end if;
+
+      Write_Char (T (P + 1));
+      Write_Char (T (P + 2));
+      Write_Char ('-');
+
+      Write_Char (T (P + 3));
+      Write_Char (T (P + 4));
+      Write_Char ('-');
+
+      Write_Char (T (P + 5));
+      Write_Char (T (P + 6));
+      Write_Char (' ');
+
+      Write_Char (T (P + 7));
+      Write_Char (T (P + 8));
+      Write_Char (':');
+
+      Write_Char (T (P + 9));
+      Write_Char (T (P + 10));
+      Write_Char (':');
+
+      Write_Char (T (P + 11));
+      Write_Char (T (P + 12));
+   end Write_Time_Stamp;
+
+   ----------------------------------------------
+   -- Access Subprograms for Source File Table --
+   ----------------------------------------------
+
+   function Debug_Source_Name (S : SFI) return File_Name_Type is
+   begin
+      return Source_File.Table (S).Debug_Source_Name;
+   end Debug_Source_Name;
+
+   function File_Name (S : SFI) return File_Name_Type is
+   begin
+      return Source_File.Table (S).File_Name;
+   end File_Name;
+
+   function First_Mapped_Line (S : SFI) return Logical_Line_Number is
+   begin
+      return Source_File.Table (S).First_Mapped_Line;
+   end First_Mapped_Line;
+
+   function Full_File_Name (S : SFI) return File_Name_Type is
+   begin
+      return Source_File.Table (S).Full_File_Name;
+   end Full_File_Name;
+
+   function Full_Ref_Name (S : SFI) return File_Name_Type is
+   begin
+      return Source_File.Table (S).Full_Ref_Name;
+   end Full_Ref_Name;
+
+   function Identifier_Casing (S : SFI) return Casing_Type is
+   begin
+      return Source_File.Table (S).Identifier_Casing;
+   end Identifier_Casing;
+
+   function Instantiation (S : SFI) return Source_Ptr is
+   begin
+      return Source_File.Table (S).Instantiation;
+   end Instantiation;
+
+   function Keyword_Casing (S : SFI) return Casing_Type is
+   begin
+      return Source_File.Table (S).Keyword_Casing;
+   end Keyword_Casing;
+
+   function Last_Source_Line (S : SFI) return Physical_Line_Number is
+   begin
+      return Source_File.Table (S).Last_Source_Line;
+   end Last_Source_Line;
+
+   function License (S : SFI) return License_Type is
+   begin
+      return Source_File.Table (S).License;
+   end License;
+
+   function Num_SRef_Pragmas (S : SFI) return Nat is
+   begin
+      return Source_File.Table (S).Num_SRef_Pragmas;
+   end Num_SRef_Pragmas;
+
+   function Reference_Name (S : SFI) return File_Name_Type is
+   begin
+      return Source_File.Table (S).Reference_Name;
+   end Reference_Name;
+
+   function Source_Checksum (S : SFI) return Word is
+   begin
+      return Source_File.Table (S).Source_Checksum;
+   end Source_Checksum;
+
+   function Source_First (S : SFI) return Source_Ptr is
+   begin
+      return Source_File.Table (S).Source_First;
+   end Source_First;
+
+   function Source_Last (S : SFI) return Source_Ptr is
+   begin
+      return Source_File.Table (S).Source_Last;
+   end Source_Last;
+
+   function Source_Text (S : SFI) return Source_Buffer_Ptr is
+   begin
+      return Source_File.Table (S).Source_Text;
+   end Source_Text;
+
+   function Template (S : SFI) return SFI is
+   begin
+      return Source_File.Table (S).Template;
+   end Template;
+
+   function Time_Stamp (S : SFI) return Time_Stamp_Type is
+   begin
+      return Source_File.Table (S).Time_Stamp;
+   end Time_Stamp;
+
+   ------------------------------------------
+   -- Set Procedures for Source File Table --
+   ------------------------------------------
+
+   procedure Set_Identifier_Casing (S : SFI; C : Casing_Type) is
+   begin
+      Source_File.Table (S).Identifier_Casing := C;
+   end Set_Identifier_Casing;
+
+   procedure Set_Keyword_Casing (S : SFI; C : Casing_Type) is
+   begin
+      Source_File.Table (S).Keyword_Casing := C;
+   end Set_Keyword_Casing;
+
+   procedure Set_License (S : SFI; L : License_Type) is
+   begin
+      Source_File.Table (S).License := L;
+   end Set_License;
+
+   --------
+   -- wl --
+   --------
+
+   procedure wl (P : Source_Ptr) is
+   begin
+      Write_Location (P);
+      Write_Eol;
+   end wl;
+
+end Sinput;
diff --git a/gcc/ada/sinput.ads b/gcc/ada/sinput.ads
new file mode 100644 (file)
index 0000000..585a8b9
--- /dev/null
@@ -0,0 +1,650 @@
+------------------------------------------------------------------------------
+--                                                                          --
+--                         GNAT COMPILER COMPONENTS                         --
+--                                                                          --
+--                               S I N P U T                                --
+--                                                                          --
+--                                 S p e c                                  --
+--                                                                          --
+--                            $Revision: 1.69 $
+--                                                                          --
+--          Copyright (C) 1992-2001 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- --
+-- ware  Foundation;  either version 2,  or (at your option) any later ver- --
+-- sion.  GNAT is distributed in the hope that it will be useful, but WITH- --
+-- OUT ANY WARRANTY;  without even the  implied warranty of MERCHANTABILITY --
+-- or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License --
+-- for  more details.  You should have  received  a copy of the GNU General --
+-- Public License  distributed with GNAT;  see file COPYING.  If not, write --
+-- to  the Free Software Foundation,  59 Temple Place - Suite 330,  Boston, --
+-- MA 02111-1307, USA.                                                      --
+--                                                                          --
+-- As a special exception,  if other files  instantiate  generics from this --
+-- unit, or you link  this unit with other files  to produce an executable, --
+-- this  unit  does not  by itself cause  the resulting  executable  to  be --
+-- covered  by the  GNU  General  Public  License.  This exception does not --
+-- however invalidate  any other reasons why  the executable file  might be --
+-- covered by the  GNU Public License.                                      --
+--                                                                          --
+-- GNAT was originally developed  by the GNAT team at  New York University. --
+-- It is now maintained by Ada Core Technologies Inc (http://www.gnat.com). --
+--                                                                          --
+------------------------------------------------------------------------------
+
+--  This package contains the input routines used for reading the
+--  input source file. The actual I/O routines are in OS_Interface,
+--  with this module containing only the system independent processing.
+
+--  General Note: throughout the compiler, we use the term line or source
+--  line to refer to a physical line in the source, terminated by the end of
+--  physical line sequence. See Skip_Line_Terminators procedure for a full
+--  description of the difference between logical and physical lines.
+
+with Alloc;
+with Casing; use Casing;
+with Table;
+with Types;  use Types;
+
+package Sinput is
+
+   ----------------------------
+   -- Source License Control --
+   ----------------------------
+
+   --  The following type indicates the license state of a source if it
+   --  is known.
+
+   type License_Type is
+     (Unknown,
+      --  Licensing status of this source unit is unknown
+
+      Restricted,
+      --  This is a non-GPL'ed unit that is restricted from depending
+      --  on GPL'ed units (e.g. proprietary code is in this category)
+
+      GPL,
+      --  This file is licensed under the unmodified GPL. It is not allowed
+      --  to depend on Non_GPL units, and Non_GPL units may not depend on
+      --  this source unit.
+
+      Modified_GPL,
+      --  This file is licensed under the GNAT modified GPL (see header of
+      --  This file for wording of the modification). It may depend on other
+      --  Modified_GPL units or on unrestricted units.
+
+      Unrestricted);
+      --  The license on this file is permitted to depend on any other
+      --  units, or have other units depend on it, without violating the
+      --  license of this unit. Examples are public domain units, and
+      --  units defined in the RM).
+
+   --  The above license status is checked when the appropriate check is
+   --  activated and one source depends on another, and the licensing state
+   --  of both files is known:
+
+   --  The prohibited combinations are:
+
+   --    Restricted file may not depend on GPL file
+
+   --    GPL file may not depend on Restricted file
+
+   --    Modified GPL file may not depend on Restricted file
+   --    Modified_GPL file may not depend on GPL file
+
+   --  The reason for the last restriction here is that a client depending
+   --  on a modified GPL file must be sure that the license condition is
+   --  correct considered transitively.
+
+   --  The licensing status is determined either by the presence of a
+   --  specific pragma License, or by scanning the header for a predefined
+   --  file, or any file if compiling in -gnatg mode.
+
+   -----------------------
+   -- Source File Table --
+   -----------------------
+
+   --  The source file table has an entry for each source file read in for
+   --  this run of the compiler. This table is (default) initialized when
+   --  the compiler is loaded, and simply accumulates entries as compilation
+   --  proceeds and the Sinput.L.Load_Source_File procedure is called to load
+   --  required source files.
+
+   --  Virtual entries are also created for generic templates when they are
+   --  instantiated, as described in a separate section later on.
+
+   --  In the case where there are multiple main units (e.g. in the case of
+   --  the cross-reference tool), this table is not reset between these units,
+   --  so that a given source file is only read once if it is used by two
+   --  separate main units.
+
+   --  The entries in the table are accessed using a Source_File_Index that
+   --  ranges from 1 to Last_Source_File. Each entry has the following fields
+
+   --  Note that entry 1 is always for system.ads (see Targparm for details
+   --  of why we always read this source file first), and we have defined a
+   --  constant Types.System_Source_File_Index as 1 to reflect this fact.
+
+   --  File_Name : File_Name_Type
+   --    Name of the source file (simple name with no directory information).
+   --    Set by Sinput.L.Load_Source_File and cannot be subequently changed.
+
+   --  Full_File_Name : File_Name_Type
+   --    Full file name (full name with directory info), used for generation
+   --    of error messages, etc. Set by Sinput.L.Load_Source_File and cannot
+   --    be subsequently changed.
+
+   --  Reference_Name : File_Name_Type
+   --    Name to be used for source file references in error messages where
+   --    only the simple name of the file is required. Identical to File_Name
+   --    unless pragma Source_Reference is used to change it. Only processing
+   --    for the Source_Reference pragma circuit may set this field.
+
+   --  Full_Ref_Name : File_Name_Type
+   --    Name to be used for source file references in error messages where
+   --    the full name of the file is required. Identical to Full_File_Name
+   --    unless pragma Source_Reference is used to change it. Only processing
+   --    for the Source_Reference pragma may set this field.
+
+   --  Debug_Source_Name : File_Name_Type
+   --    Name to be used for source file references in debugging information
+   --    where only the simple name of the file is required. Identical to
+   --    Full_Ref_Name unless the -gnatD (debug source file) switch is used.
+   --    Only processing in Sprint that generates this file is permitted to
+   --    set this field.
+
+   --  License : License_Type;
+   --    License status of source file
+
+   --  Num_SRef_Pragmas : Nat;
+   --    Number of source reference pragmas present in source file
+
+   --  First_Mapped_Line : Logical_Line_Number;
+   --    This field stores logical line number of the first line in the
+   --    file that is not a Source_Reference pragma. If no source reference
+   --    pragmas are used, then the value is set to No_Line_Number.
+
+   --  Source_Text : Source_Buffer_Ptr
+   --    Text of source file. Note that every source file has a distinct set
+   --    of non-overlapping logical bounds, so it is possible to determine
+   --    which file is referenced from a given subscript (Source_Ptr) value.
+   --    Set by Sinput.L.Load_Source_File and cannot be subsequently changed.
+
+   --  Source_First : Source_Ptr;
+   --    Subscript of first character in Source_Text. Note that this cannot
+   --    be obtained as Source_Text'First, because we use virtual origin
+   --    addressing. Set by Sinput.L procedures when the entry is first
+   --    created and never subsequently changed.
+
+   --  Source_Last : Source_Ptr;
+   --    Subscript of last character in Source_Text. Note that this cannot
+   --    be obtained as Source_Text'Last, because we use virtual origin
+   --    addressing, so this value is always Source_Ptr'Last. Set by
+   --    Sinput.L procedures when the entry is first created and never
+   --    subsequently changed.
+
+   --  Time_Stamp : Time_Stamp_Type;
+   --    Time stamp of the source file. Set by Sinput.L.Load_Source_File,
+   --    and cannot be subsequently changed.
+
+   --  Source_Checksum : Word;
+   --    Computed checksum for contents of source file. See separate section
+   --    later on in this spec for a description of the checksum algorithm.
+
+   --  Last_Source_Line : Physical_Line_Number;
+   --    Physical line number of last source line. Whlie a file is being
+   --    read, this refers to the last line scanned. Once a file has been
+   --    completely scanned, it is the number of the last line in the file,
+   --    and hence also gives the number of source lines in the file.
+
+   --  Keyword_Casing : Casing_Type;
+   --    Casing style used in file for keyword casing. This is initialized
+   --    to Unknown, and then set from the first occurrence of a keyword.
+   --    This value is used only for formatting of error messages.
+
+   --  Identifier_Casing : Casing_Type;
+   --    Casing style used in file for identifier casing. This is initialized
+   --    to Unknown, and then set from an identifier in the program as soon as
+   --    one is found whose casing is sufficiently clear to make a decision.
+   --    This value is used for formatting of error messages, and also is used
+   --    in the detection of keywords misused as identifiers.
+
+   --  Instantiation : Source_Ptr;
+   --    Source file location of the instantiation if this source file entry
+   --    represents a generic instantiation. Set to No_Location for the case
+   --    of a normal non-instantiation entry. See section below for details.
+   --    This field is read-only for clients.
+
+   --  Template : Source_File_Index;
+   --    Source file index of the source file containing the template if this
+   --    is a generic instantiation. Set to No_Source_File for the normal case
+   --    of a non-instantiation entry. See Sinput-L for details. This field is
+   --    read-only for clients.
+
+   --  The source file table is accessed by clients using the following
+   --  subprogram interface:
+
+   subtype SFI is Source_File_Index;
+
+   function Debug_Source_Name (S : SFI) return File_Name_Type;
+   function File_Name         (S : SFI) return File_Name_Type;
+   function First_Mapped_Line (S : SFI) return Logical_Line_Number;
+   function Full_File_Name    (S : SFI) return File_Name_Type;
+   function Full_Ref_Name     (S : SFI) return File_Name_Type;
+   function Identifier_Casing (S : SFI) return Casing_Type;
+   function Instantiation     (S : SFI) return Source_Ptr;
+   function Keyword_Casing    (S : SFI) return Casing_Type;
+   function Last_Source_Line  (S : SFI) return Physical_Line_Number;
+   function License           (S : SFI) return License_Type;
+   function Num_SRef_Pragmas  (S : SFI) return Nat;
+   function Reference_Name    (S : SFI) return File_Name_Type;
+   function Source_Checksum   (S : SFI) return Word;
+   function Source_First      (S : SFI) return Source_Ptr;
+   function Source_Last       (S : SFI) return Source_Ptr;
+   function Source_Text       (S : SFI) return Source_Buffer_Ptr;
+   function Template          (S : SFI) return Source_File_Index;
+   function Time_Stamp        (S : SFI) return Time_Stamp_Type;
+
+   procedure Set_Keyword_Casing    (S : SFI; C : Casing_Type);
+   procedure Set_Identifier_Casing (S : SFI; C : Casing_Type);
+   procedure Set_License           (S : SFI; L : License_Type);
+
+   function Last_Source_File return Source_File_Index;
+   --  Index of last source file table entry
+
+   function Num_Source_Files return Nat;
+   --  Number of source file table entries
+
+   procedure Initialize;
+   --  Initialize internal tables
+
+   procedure Lock;
+   --  Lock internal tables
+
+   Main_Source_File : Source_File_Index;
+   --  This is set to the source file index of the main unit
+
+   -----------------------
+   -- Checksum Handling --
+   -----------------------
+
+   --  As a source file is scanned, a checksum is computed by taking all the
+   --  non-blank characters in the file, excluding comment characters, the
+   --  minus-minus sequence starting a comment, and all control characters
+   --  except ESC.
+
+   --  These characters are used to compute a 31-bit checksum which is stored
+   --  in the variable Scans.Checksum, as follows:
+
+   --    If a character, C, is not part of a wide character sequence, then
+   --    either the character itself, or its lower case equivalent if it
+   --    is a letter outside a string literal is used in the computation:
+
+   --      Checksum := Checksum + Checksum + Character'Pos (C);
+   --      if Checksum > 16#8000_0000# then
+   --         Checksum := (Checksum + 1) and 16#7FFF_FFFF#;
+   --      end if;
+
+   --    For a wide character sequence, the checksum is computed using the
+   --    corresponding character code value C, as follows:
+
+   --      Checksum := Checksum + Checksum + Char_Code'Pos (C);
+   --      if Checksum > 16#8000_0000# then
+   --         Checksum := (Checksum + 1) and 16#7FFF_FFFF#;
+   --      end if;
+
+   --  This algorithm ensures that the checksum includes all semantically
+   --  significant aspects of the program represented by the source file,
+   --  but is insensitive to layout, presence or contents of comments, wide
+   --  character representation method, or casing conventions outside strings.
+
+   --  Scans.Checksum is initialized to zero at the start of scanning a file,
+   --  and copied into the Source_Checksum field of the file table entry when
+   --  the end of file is encountered.
+
+   -------------------------------------
+   -- Handling Generic Instantiations --
+   -------------------------------------
+
+   --  As described in Sem_Ch12, a generic instantiation involves making a
+   --  copy of the tree of the generic template. The source locations in
+   --  this tree directly reference the source of the template. However it
+   --  is also possible to find the location of the instantiation.
+
+   --  This is achieved as follows. When an instantiation occurs, a new entry
+   --  is made in the source file table. This entry points to the same source
+   --  text, i.e. the file that contains the instantiation, but has a distinct
+   --  set of Source_Ptr index values. The separate range of Sloc values avoids
+   --  confusion, and means that the Sloc values can still be used to uniquely
+   --  identify the source file table entry. It is possible for both entries
+   --  to point to the same text, because of the virtual origin pointers used
+   --  in the source table.
+
+   --  The Instantiation field of this source file index entry, usually set
+   --  to No_Source_File, instead contains the Sloc of the instantiation. In
+   --  the case of nested instantiations, this Sloc may itself refer to an
+   --  instantiation, so the complete chain can be traced.
+
+   --  Two routines are used to build these special entries in the source
+   --  file table. Create_Instantiation_Source is first called to build
+   --  the virtual source table entry for the instantiation, and then the
+   --  Sloc values in the copy are adjusted using Adjust_Instantiation_Sloc.
+   --  See child unit Sinput.L for details on these two routines.
+
+   -----------------
+   -- Global Data --
+   -----------------
+
+   Current_Source_File : Source_File_Index;
+   --  Source_File table index of source file currently being scanned
+
+   Current_Source_Unit : Unit_Number_Type;
+   --  Unit number of source file currently being scanned. The special value
+   --  of No_Unit indicates that the configuration pragma file is currently
+   --  being scanned (this has no entry in the unit table).
+
+   Source_gnat_adc : Source_File_Index := No_Source_File;
+   --  This is set if a gnat.adc file is present to reference this file
+
+   Source : Source_Buffer_Ptr;
+   --  Current source (copy of Source_File.Table (Current_Source_Unit).Source)
+
+   Internal_Source : aliased Source_Buffer (1 .. 81);
+   --  This buffer is used internally in the compiler when the lexical analyzer
+   --  is used to scan a string from within the compiler. The procedure is to
+   --  establish Internal_Source_Ptr as the value of Source, set the string to
+   --  be scanned, appropriately terminated, in this buffer, and set Scan_Ptr
+   --  to point to the start of the buffer. It is a fatal error if the scanner
+   --  signals an error while scanning a token in this internal buffer.
+
+   Internal_Source_Ptr : constant Source_Buffer_Ptr :=
+                           Internal_Source'Unrestricted_Access;
+   --  Pointer to internal source buffer
+
+   -----------------
+   -- Subprograms --
+   -----------------
+
+   procedure Backup_Line (P : in out Source_Ptr);
+   --  Back up the argument pointer to the start of the previous line. On
+   --  entry, P points to the start of a physical line in the source buffer.
+   --  On return, P is updated to point to the start of the previous line.
+   --  The caller has checked that a Line_Terminator character precedes P so
+   --  that there definitely is a previous line in the source buffer.
+
+   procedure Build_Location_String (Loc : Source_Ptr);
+   --  This function builds a string literal of the form "name:line",
+   --  where name is the file name corresponding to Loc, and line is
+   --  the line number. In the event that instantiations are involved,
+   --  additional suffixes of the same form are appended after the
+   --  separating string " instantiated at ". The returned string is
+   --  stored in Name_Buffer, terminated by ASCII.Nul, with Name_Length
+   --  indicating the length not including the terminating Nul.
+
+   function Get_Column_Number (P : Source_Ptr) return Column_Number;
+   --  The ones-origin column number of the specified Source_Ptr value is
+   --  determined and returned. Tab characters if present are assumed to
+   --  represent the standard 1,9,17.. spacing pattern.
+
+   function Get_Logical_Line_Number
+     (P    : Source_Ptr)
+      return Logical_Line_Number;
+   --  The line number of the specified source position is obtained by
+   --  doing a binary search on the source positions in the lines table
+   --  for the unit containing the given source position. The returned
+   --  value is the logical line number, already adjusted for the effect
+   --  of source reference pragmas. If P refers to the line of a source
+   --  reference pragma itself, then No_Line is returned. If no source
+   --  reference pragmas have been encountered, the value returned is
+   --  the same as the physical line number.
+
+   function Get_Physical_Line_Number
+     (P    : Source_Ptr)
+      return Physical_Line_Number;
+   --  The line number of the specified source position is obtained by
+   --  doing a binary search on the source positions in the lines table
+   --  for the unit containing the given source position. The returned
+   --  value is the physical line number in the source being compiled.
+
+   function Get_Source_File_Index (S : Source_Ptr) return Source_File_Index;
+   --  Return file table index of file identified by given source pointer
+   --  value. This call must always succeed, since any valid source pointer
+   --  value belongs to some previously loaded source file.
+
+   function Instantiation_Depth (S : Source_Ptr) return Nat;
+   --  Determine instantiation depth for given Sloc value. A value of
+   --  zero means that the given Sloc is not in an instantiation.
+
+   function Line_Start (P : Source_Ptr) return Source_Ptr;
+   --  Finds the source position of the start of the line containing the
+   --  given source location.
+
+   function Line_Start
+     (L    : Physical_Line_Number;
+      S    : Source_File_Index)
+      return Source_Ptr;
+   --  Finds the source position of the start of the given line in the
+   --  given source file, using a physical line number to identify the line.
+
+   function Num_Source_Lines (S : Source_File_Index) return Nat;
+   --  Returns the number of source lines (this is equivalent to reading
+   --  the value of Last_Source_Line, but returns Nat rathern than a
+   --  physical line number.
+
+   procedure Register_Source_Ref_Pragma
+     (File_Name          : Name_Id;
+      Stripped_File_Name : Name_Id;
+      Mapped_Line        : Nat;
+      Line_After_Pragma  : Physical_Line_Number);
+   --  Register a source reference pragma, the parameter File_Name is the
+   --  file name from the pragma, and Stripped_File_Name is this name with
+   --  the directory information stripped. Both these parameters are set
+   --  to No_Name if no file name parameter was given in the pragma.
+   --  (which can only happen for the second and subsequent pragmas).
+   --  Mapped_Line is the line number parameter from the pragma, and
+   --  Line_After_Pragma is the physical line number of the line that
+   --  follows the line containing the Source_Reference pragma.
+
+   function Original_Location (S : Source_Ptr) return Source_Ptr;
+   --  Given a source pointer S, returns the corresponding source pointer
+   --  value ignoring instantiation copies. For locations that do not
+   --  correspond to instantiation copies of templates, the argument is
+   --  returned unchanged. For locations that do correspond to copies of
+   --  templates from instantiations, the location within the original
+   --  template is returned. This is useful in canonicalizing locations.
+
+   function Instantiation_Location (S : Source_Ptr) return Source_Ptr;
+   pragma Inline (Instantiation_Location);
+   --  Given a source pointer S, returns the corresponding source pointer
+   --  value of the instantiation if this location is within an instance.
+   --  If S is not within an instance, then this returns No_Location.
+
+   function Top_Level_Location (S : Source_Ptr) return Source_Ptr;
+   --  Given a source pointer S, returns the argument unchanged if it is
+   --  not in an instantiation. If S is in an instantiation, then it returns
+   --  the location of the top level instantiation, i.e. the outer level
+   --  instantiation in the nested case.
+
+   function Physical_To_Logical
+     (Line : Physical_Line_Number;
+      S    : Source_File_Index)
+      return Logical_Line_Number;
+   --  Given a physical line number in source file whose source index is S,
+   --  return the corresponding logical line number. If the physical line
+   --  number is one containing a Source_Reference pragma, the result will
+   --  be No_Line_Number.
+
+   procedure Skip_Line_Terminators
+     (P        : in out Source_Ptr;
+      Physical : out Boolean);
+   --  On entry, Source (P) points to the line terminator character that
+   --  terminates a line. The result set in P is the location of the first
+   --  character of the following line (after skipping the sequence of line
+   --  terminator characters terminating the current line). In addition, if
+   --  the terminator sequence ends a physical line (the definition of what
+   --  constitutes a physical line is embodied in the implementation of this
+   --  function), and it is the first time this sequence is encountered, then
+   --  an entry is made in the lines table to record the location for further
+   --  use by functions such as Get_Line_Number. Physical is set to True if
+   --  the line terminator was the end of a physical line.
+
+   function Source_Offset (S : Source_Ptr) return Nat;
+   --  Returns the zero-origin offset of the given source location from the
+   --  start of its corresponding unit. This is used for creating canonical
+   --  names in some situations.
+
+   procedure Write_Location (P : Source_Ptr);
+   --  Writes out a string of the form fff:nn:cc, where fff, nn, cc are the
+   --  file name, line number and column corresponding to the given source
+   --  location. No_Location and Standard_Location appear as the strings
+   --  <no location> and <standard location>. If the location is within an
+   --  instantiation, then the instance location is appended, enclosed in
+   --  square brackets (which can nest if necessary). Note that this routine
+   --  is used only for internal compiler debugging output purposes (which
+   --  is why the somewhat cryptic use of brackets is acceptable).
+
+   procedure wl (P : Source_Ptr);
+   --  Equivalent to Write_Location (P); Write_Eol; for calls from GDB
+
+   procedure Write_Time_Stamp (S : Source_File_Index);
+   --  Writes time stamp of specified file in YY-MM-DD HH:MM.SS format
+
+   procedure Tree_Write;
+   --  Writes out internal tables to current tree file using Tree_Write
+
+   procedure Tree_Read;
+   --  Initializes internal tables from current tree file using Tree_Read
+
+private
+   pragma Inline (File_Name);
+   pragma Inline (First_Mapped_Line);
+   pragma Inline (Full_File_Name);
+   pragma Inline (Identifier_Casing);
+   pragma Inline (Instantiation);
+   pragma Inline (Keyword_Casing);
+   pragma Inline (Last_Source_Line);
+   pragma Inline (Last_Source_File);
+   pragma Inline (License);
+   pragma Inline (Num_SRef_Pragmas);
+   pragma Inline (Num_Source_Files);
+   pragma Inline (Num_Source_Lines);
+   pragma Inline (Reference_Name);
+   pragma Inline (Set_Keyword_Casing);
+   pragma Inline (Set_Identifier_Casing);
+   pragma Inline (Source_First);
+   pragma Inline (Source_Last);
+   pragma Inline (Source_Text);
+   pragma Inline (Template);
+   pragma Inline (Time_Stamp);
+
+   -------------------------
+   -- Source_Lines Tables --
+   -------------------------
+
+   type Lines_Table_Type is
+     array (Physical_Line_Number) of Source_Ptr;
+   --  Type used for lines table. The entries are indexed by physical line
+   --  numbers. The values are the starting Source_Ptr values for the start
+   --  of the corresponding physical line. Note that we make this a bogus
+   --  big array, sized as required, so that we avoid the use of fat pointers.
+
+   type Lines_Table_Ptr is access all Lines_Table_Type;
+   --  Type used for pointers to line tables
+
+   type Logical_Lines_Table_Type is
+     array (Physical_Line_Number) of Logical_Line_Number;
+   --  Type used for logical lines table. This table is used if a source
+   --  reference pragma is present. It is indexed by physical line numbers,
+   --  and contains the corresponding logical line numbers. An entry that
+   --  corresponds to a source reference pragma is set to No_Line_Number.
+   --  Note that we make this a bogus big array, sized as required, so that
+   --  we avoid the use of fat pointers.
+
+   type Logical_Lines_Table_Ptr is access all Logical_Lines_Table_Type;
+   --  Type used for pointers to logical line tables.
+
+   -----------------------
+   -- Source_File Table --
+   -----------------------
+
+   --  See earlier descriptions for meanings of public fields
+
+   type Source_File_Record is record
+
+      File_Name         : File_Name_Type;
+      Reference_Name    : File_Name_Type;
+      Debug_Source_Name : File_Name_Type;
+      Full_File_Name    : File_Name_Type;
+      Full_Ref_Name     : File_Name_Type;
+      License           : License_Type;
+      Num_SRef_Pragmas  : Nat;
+      First_Mapped_Line : Logical_Line_Number;
+      Source_Text       : Source_Buffer_Ptr;
+      Source_First      : Source_Ptr;
+      Source_Last       : Source_Ptr;
+      Time_Stamp        : Time_Stamp_Type;
+      Source_Checksum   : Word;
+      Last_Source_Line  : Physical_Line_Number;
+      Keyword_Casing    : Casing_Type;
+      Identifier_Casing : Casing_Type;
+      Instantiation     : Source_Ptr;
+      Template          : Source_File_Index;
+
+      --  The following fields are for internal use only (i.e. only in the
+      --  body of Sinput or its children, with no direct access by clients).
+
+      Sloc_Adjust : Source_Ptr;
+      --  A value to be added to Sloc values for this file to reference the
+      --  corresponding lines table. This is zero for the non-instantiation
+      --  case, and set so that the adition references the ultimate template
+      --  for the instantiation case. See Sinput-L for further details.
+
+      Lines_Table : Lines_Table_Ptr;
+      --  Pointer to lines table for this source. Updated as additional
+      --  lines are accessed using the Skip_Line_Terminators procedure.
+      --  Note: the lines table for an instantiation entry refers to the
+      --  original line numbers of the template see Sinput-L for details.
+
+      Logical_Lines_Table : Logical_Lines_Table_Ptr;
+      --  Pointer to logical lines table for this source. Non-null only if
+      --  a source reference pragma has been processed. Updated as lines
+      --  are accessed using the Skip_Line_Terminators procedure.
+
+      Lines_Table_Max : Physical_Line_Number;
+      --  Maximum subscript values for currently allocated Lines_Table
+      --  and (if present) the allocated Logical_Lines_Table. The value
+      --  Max_Source_Line gives the maximum used value, this gives the
+      --  maximum allocated value.
+
+   end record;
+
+   package Source_File is new Table.Table (
+     Table_Component_Type => Source_File_Record,
+     Table_Index_Type     => Source_File_Index,
+     Table_Low_Bound      => 1,
+     Table_Initial        => Alloc.Source_File_Initial,
+     Table_Increment      => Alloc.Source_File_Increment,
+     Table_Name           => "Source_File");
+
+   -----------------
+   -- Subprograms --
+   -----------------
+
+   procedure Alloc_Line_Tables
+     (S       : in out Source_File_Record;
+      New_Max : Nat);
+   --  Allocate or reallocate the lines table for the given source file so
+   --  that it can accomodate at least New_Max lines. Also allocates or
+   --  reallocates logical lines table if source ref pragmas are present.
+
+   procedure Add_Line_Tables_Entry
+     (S : in out Source_File_Record;
+      P : Source_Ptr);
+   --  Increment line table size by one (reallocating the lines table if
+   --  needed) and set the new entry to contain the value P. Also bumps
+   --  the Source_Line_Count field. If source reference pragmas are
+   --  present, also increments logical lines table size by one, and
+   --  sets new entry.
+
+end Sinput;
diff --git a/gcc/ada/snames.adb b/gcc/ada/snames.adb
new file mode 100644 (file)
index 0000000..acda714
--- /dev/null
@@ -0,0 +1,883 @@
+------------------------------------------------------------------------------
+--                                                                          --
+--                         GNAT COMPILER COMPONENTS                         --
+--                                                                          --
+--                               S N A M E S                                --
+--                                                                          --
+--                                 B o d y                                  --
+--                                                                          --
+--                            $Revision: 1.205 $                            --
+--                                                                          --
+--          Copyright (C) 1992-2001, 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- --
+-- ware  Foundation;  either version 2,  or (at your option) any later ver- --
+-- sion.  GNAT is distributed in the hope that it will be useful, but WITH- --
+-- OUT ANY WARRANTY;  without even the  implied warranty of MERCHANTABILITY --
+-- or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License --
+-- for  more details.  You should have  received  a copy of the GNU General --
+-- Public License  distributed with GNAT;  see file COPYING.  If not, write --
+-- to  the Free Software Foundation,  59 Temple Place - Suite 330,  Boston, --
+-- MA 02111-1307, USA.                                                      --
+--                                                                          --
+-- As a special exception,  if other files  instantiate  generics from this --
+-- unit, or you link  this unit with other files  to produce an executable, --
+-- this  unit  does not  by itself cause  the resulting  executable  to  be --
+-- covered  by the  GNU  General  Public  License.  This exception does not --
+-- however invalidate  any other reasons why  the executable file  might be --
+-- covered by the  GNU Public License.                                      --
+--                                                                          --
+-- GNAT was originally developed  by the GNAT team at  New York University. --
+-- It is now maintained by Ada Core Technologies Inc (http://www.gnat.com). --
+--                                                                          --
+------------------------------------------------------------------------------
+
+with Namet; use Namet;
+
+package body Snames is
+
+   --  Table of names to be set by Initialize. Each name is terminated by a
+   --  single #, and the end of the list is marked by a null entry, i.e. by
+   --  two # marks in succession. Note that the table does not include the
+   --  entries for a-z, since these are initialized by Namet itself.
+
+   Preset_Names : constant String :=
+     "_parent#" &
+     "_tag#" &
+     "off#" &
+     "space#" &
+     "time#" &
+     "_init_proc#" &
+     "_size#" &
+     "_abort_signal#" &
+     "_address_resolver#" &
+     "_assign#" &
+     "_chain#" &
+     "_clean#" &
+     "_controller#" &
+     "_entry_bodies#" &
+     "_expunge#" &
+     "_final_list#" &
+     "_idepth#" &
+     "_init#" &
+     "_local_final_list#" &
+     "_master#" &
+     "_object#" &
+     "_priority#" &
+     "_service#" &
+     "_tags#" &
+     "_task#" &
+     "_task_id#" &
+     "_task_info#" &
+     "_task_name#" &
+     "_trace_sp#" &
+     "initialize#" &
+     "adjust#" &
+     "finalize#" &
+     "next#" &
+     "prev#" &
+     "_deep_adjust#" &
+     "_equality#" &
+     "_deep_finalize#" &
+     "_deep_initialize#" &
+     "_input#" &
+     "_output#" &
+     "_ras_access#" &
+     "_ras_dereference#" &
+     "_read#" &
+     "_rep_to_pos#" &
+     "_write#" &
+     "allocate#" &
+     "deallocate#" &
+     "dereference#" &
+     "decimal_io#" &
+     "enumeration_io#" &
+     "fixed_io#" &
+     "float_io#" &
+     "integer_io#" &
+     "modular_io#" &
+     "a_textio#" &
+     "a_witeio#" &
+     "const#" &
+     "<error>#" &
+     "go#" &
+     "put#" &
+     "put_line#" &
+     "to#" &
+     "finalization#" &
+     "finalization_root#" &
+     "interfaces#" &
+     "standard#" &
+     "system#" &
+     "text_io#" &
+     "wide_text_io#" &
+     "addr#" &
+     "async#" &
+     "get_active_partition_id#" &
+     "get_rci_package_receiver#" &
+     "origin#" &
+     "params#" &
+     "partition#" &
+     "partition_interface#" &
+     "ras#" &
+     "rci_name#" &
+     "receiver#" &
+     "result#" &
+     "rpc#" &
+     "subp_id#" &
+     "Oabs#" &
+     "Oand#" &
+     "Omod#" &
+     "Onot#" &
+     "Oor#" &
+     "Orem#" &
+     "Oxor#" &
+     "Oeq#" &
+     "One#" &
+     "Olt#" &
+     "Ole#" &
+     "Ogt#" &
+     "Oge#" &
+     "Oadd#" &
+     "Osubtract#" &
+     "Oconcat#" &
+     "Omultiply#" &
+     "Odivide#" &
+     "Oexpon#" &
+     "ada_83#" &
+     "ada_95#" &
+     "c_pass_by_copy#" &
+     "component_alignment#" &
+     "discard_names#" &
+     "elaboration_checks#" &
+     "eliminate#" &
+     "extend_system#" &
+     "extensions_allowed#" &
+     "external_name_casing#" &
+     "float_representation#" &
+     "initialize_scalars#" &
+     "license#" &
+     "locking_policy#" &
+     "long_float#" &
+     "no_run_time#" &
+     "normalize_scalars#" &
+     "polling#" &
+     "propagate_exceptions#" &
+     "queuing_policy#" &
+     "ravenscar#" &
+     "restricted_run_time#" &
+     "restrictions#" &
+     "reviewable#" &
+     "source_file_name#" &
+     "style_checks#" &
+     "suppress#" &
+     "task_dispatching_policy#" &
+     "unsuppress#" &
+     "use_vads_size#" &
+     "warnings#" &
+     "validity_checks#" &
+     "abort_defer#" &
+     "all_calls_remote#" &
+     "annotate#" &
+     "assert#" &
+     "asynchronous#" &
+     "atomic#" &
+     "atomic_components#" &
+     "attach_handler#" &
+     "comment#" &
+     "common_object#" &
+     "complex_representation#" &
+     "controlled#" &
+     "convention#" &
+     "cpp_class#" &
+     "cpp_constructor#" &
+     "cpp_virtual#" &
+     "cpp_vtable#" &
+     "debug#" &
+     "elaborate#" &
+     "elaborate_all#" &
+     "elaborate_body#" &
+     "export#" &
+     "export_exception#" &
+     "export_function#" &
+     "export_object#" &
+     "export_procedure#" &
+     "export_valued_procedure#" &
+     "finalize_storage_only#" &
+     "ident#" &
+     "import#" &
+     "import_exception#" &
+     "import_function#" &
+     "import_object#" &
+     "import_procedure#" &
+     "import_valued_procedure#" &
+     "inline#" &
+     "inline_always#" &
+     "inline_generic#" &
+     "inspection_point#" &
+     "interface#" &
+     "interface_name#" &
+     "interrupt_handler#" &
+     "interrupt_priority#" &
+     "java_constructor#" &
+     "java_interface#" &
+     "link_with#" &
+     "linker_alias#" &
+     "linker_options#" &
+     "linker_section#" &
+     "list#" &
+     "machine_attribute#" &
+     "main#" &
+     "main_storage#" &
+     "memory_size#" &
+     "no_return#" &
+     "optimize#" &
+     "pack#" &
+     "page#" &
+     "passive#" &
+     "preelaborate#" &
+     "priority#" &
+     "psect_object#" &
+     "pure#" &
+     "pure_function#" &
+     "remote_call_interface#" &
+     "remote_types#" &
+     "share_generic#" &
+     "shared#" &
+     "shared_passive#" &
+     "source_reference#" &
+     "stream_convert#" &
+     "subtitle#" &
+     "suppress_all#" &
+     "suppress_debug_info#" &
+     "suppress_initialization#" &
+     "system_name#" &
+     "task_info#" &
+     "task_name#" &
+     "task_storage#" &
+     "time_slice#" &
+     "title#" &
+     "unchecked_union#" &
+     "unimplemented_unit#" &
+     "unreserve_all_interrupts#" &
+     "volatile#" &
+     "volatile_components#" &
+     "weak_external#" &
+     "ada#" &
+     "asm#" &
+     "assembler#" &
+     "cobol#" &
+     "cpp#" &
+     "dll#" &
+     "fortran#" &
+     "intrinsic#" &
+     "java#" &
+     "stdcall#" &
+     "stubbed#" &
+     "win32#" &
+     "as_is#" &
+     "body_file_name#" &
+     "casing#" &
+     "code#" &
+     "component#" &
+     "component_size_4#" &
+     "copy#" &
+     "d_float#" &
+     "descriptor#" &
+     "default#" &
+     "dot_replacement#" &
+     "dynamic#" &
+     "entity#" &
+     "external#" &
+     "external_name#" &
+     "first_optional_parameter#" &
+     "form#" &
+     "g_float#" &
+     "gcc#" &
+     "gnat#" &
+     "gpl#" &
+     "ieee_float#" &
+     "internal#" &
+     "link_name#" &
+     "lowercase#" &
+     "max_size#" &
+     "mechanism#" &
+     "mixedcase#" &
+     "modified_gpl#" &
+     "name#" &
+     "nca#" &
+     "no#" &
+     "on#" &
+     "parameter_types#" &
+     "reference#" &
+     "restricted#" &
+     "result_mechanism#" &
+     "result_type#" &
+     "sb#" &
+     "section#" &
+     "semaphore#" &
+     "spec_file_name#" &
+     "static#" &
+     "stack_size#" &
+     "subunit_file_name#" &
+     "task_stack_size_default#" &
+     "task_type#" &
+     "time_slicing_enabled#" &
+     "top_guard#" &
+     "uba#" &
+     "ubs#" &
+     "ubsb#" &
+     "unit_name#" &
+     "unknown#" &
+     "unrestricted#" &
+     "uppercase#" &
+     "vax_float#" &
+     "vms#" &
+     "working_storage#" &
+     "abort_signal#" &
+     "access#" &
+     "address#" &
+     "address_size#" &
+     "aft#" &
+     "alignment#" &
+     "asm_input#" &
+     "asm_output#" &
+     "ast_entry#" &
+     "bit#" &
+     "bit_order#" &
+     "bit_position#" &
+     "body_version#" &
+     "callable#" &
+     "caller#" &
+     "code_address#" &
+     "component_size#" &
+     "compose#" &
+     "constrained#" &
+     "count#" &
+     "default_bit_order#" &
+     "definite#" &
+     "delta#" &
+     "denorm#" &
+     "digits#" &
+     "elaborated#" &
+     "emax#" &
+     "enum_rep#" &
+     "epsilon#" &
+     "exponent#" &
+     "external_tag#" &
+     "first#" &
+     "first_bit#" &
+     "fixed_value#" &
+     "fore#" &
+     "has_discriminants#" &
+     "identity#" &
+     "img#" &
+     "integer_value#" &
+     "large#" &
+     "last#" &
+     "last_bit#" &
+     "leading_part#" &
+     "length#" &
+     "machine_emax#" &
+     "machine_emin#" &
+     "machine_mantissa#" &
+     "machine_overflows#" &
+     "machine_radix#" &
+     "machine_rounds#" &
+     "machine_size#" &
+     "mantissa#" &
+     "max_interrupt_priority#" &
+     "max_priority#" &
+     "max_size_in_storage_elements#" &
+     "maximum_alignment#" &
+     "mechanism_code#" &
+     "model_emin#" &
+     "model_epsilon#" &
+     "model_mantissa#" &
+     "model_small#" &
+     "modulus#" &
+     "null_parameter#" &
+     "object_size#" &
+     "partition_id#" &
+     "passed_by_reference#" &
+     "pos#" &
+     "position#" &
+     "range#" &
+     "range_length#" &
+     "round#" &
+     "safe_emax#" &
+     "safe_first#" &
+     "safe_large#" &
+     "safe_last#" &
+     "safe_small#" &
+     "scale#" &
+     "scaling#" &
+     "signed_zeros#" &
+     "size#" &
+     "small#" &
+     "storage_size#" &
+     "storage_unit#" &
+     "tag#" &
+     "terminated#" &
+     "tick#" &
+     "to_address#" &
+     "type_class#" &
+     "uet_address#" &
+     "unbiased_rounding#" &
+     "unchecked_access#" &
+     "universal_literal_string#" &
+     "unrestricted_access#" &
+     "vads_size#" &
+     "val#" &
+     "valid#" &
+     "value_size#" &
+     "version#" &
+     "wchar_t_size#" &
+     "wide_width#" &
+     "width#" &
+     "word_size#" &
+     "adjacent#" &
+     "ceiling#" &
+     "copy_sign#" &
+     "floor#" &
+     "fraction#" &
+     "image#" &
+     "input#" &
+     "machine#" &
+     "max#" &
+     "min#" &
+     "model#" &
+     "pred#" &
+     "remainder#" &
+     "rounding#" &
+     "succ#" &
+     "truncation#" &
+     "value#" &
+     "wide_image#" &
+     "wide_value#" &
+     "output#" &
+     "read#" &
+     "write#" &
+     "elab_body#" &
+     "elab_spec#" &
+     "storage_pool#" &
+     "base#" &
+     "class#" &
+     "ceiling_locking#" &
+     "inheritance_locking#" &
+     "fifo_queuing#" &
+     "priority_queuing#" &
+     "fifo_within_priorities#" &
+     "access_check#" &
+     "accessibility_check#" &
+     "discriminant_check#" &
+     "division_check#" &
+     "elaboration_check#" &
+     "index_check#" &
+     "length_check#" &
+     "overflow_check#" &
+     "range_check#" &
+     "storage_check#" &
+     "tag_check#" &
+     "all_checks#" &
+     "abort#" &
+     "abs#" &
+     "accept#" &
+     "and#" &
+     "all#" &
+     "array#" &
+     "at#" &
+     "begin#" &
+     "body#" &
+     "case#" &
+     "constant#" &
+     "declare#" &
+     "delay#" &
+     "do#" &
+     "else#" &
+     "elsif#" &
+     "end#" &
+     "entry#" &
+     "exception#" &
+     "exit#" &
+     "for#" &
+     "function#" &
+     "generic#" &
+     "goto#" &
+     "if#" &
+     "in#" &
+     "is#" &
+     "limited#" &
+     "loop#" &
+     "mod#" &
+     "new#" &
+     "not#" &
+     "null#" &
+     "of#" &
+     "or#" &
+     "others#" &
+     "out#" &
+     "package#" &
+     "pragma#" &
+     "private#" &
+     "procedure#" &
+     "raise#" &
+     "record#" &
+     "rem#" &
+     "renames#" &
+     "return#" &
+     "reverse#" &
+     "select#" &
+     "separate#" &
+     "subtype#" &
+     "task#" &
+     "terminate#" &
+     "then#" &
+     "type#" &
+     "use#" &
+     "when#" &
+     "while#" &
+     "with#" &
+     "xor#" &
+     "divide#" &
+     "enclosing_entity#" &
+     "exception_information#" &
+     "exception_message#" &
+     "exception_name#" &
+     "file#" &
+     "import_address#" &
+     "import_largest_value#" &
+     "import_value#" &
+     "is_negative#" &
+     "line#" &
+     "rotate_left#" &
+     "rotate_right#" &
+     "shift_left#" &
+     "shift_right#" &
+     "shift_right_arithmetic#" &
+     "source_location#" &
+     "unchecked_conversion#" &
+     "unchecked_deallocation#" &
+     "abstract#" &
+     "aliased#" &
+     "protected#" &
+     "until#" &
+     "requeue#" &
+     "tagged#" &
+     "raise_exception#" &
+     "project#" &
+     "modifying#" &
+     "naming#" &
+     "object_dir#" &
+     "source_dirs#" &
+     "specification#" &
+     "body_part#" &
+     "specification_append#" &
+     "body_append#" &
+     "separate_append#" &
+     "source_files#" &
+     "source_list_file#" &
+     "switches#" &
+     "library_dir#" &
+     "library_name#" &
+     "library_kind#" &
+     "library_version#" &
+     "library_elaboration#" &
+     "gnatmake#" &
+     "gnatls#" &
+     "gnatxref#" &
+     "gnatfind#" &
+     "gnatbind#" &
+     "gnatlink#" &
+     "compiler#" &
+     "binder#" &
+     "linker#" &
+      "#";
+
+   ---------------------
+   -- Generated Names --
+   ---------------------
+
+   --  This section lists the various cases of generated names which are
+   --  built from existing names by adding unique leading and/or trailing
+   --  upper case letters. In some cases these names are built recursively,
+   --  in particular names built from types may be built from types which
+   --  themselves have generated names. In this list, xxx represents an
+   --  existing name to which identifying letters are prepended or appended,
+   --  and a trailing n represents a serial number in an external name that
+   --  has some semantic significance (e.g. the n'th index type of an array).
+
+   --    xxxA    access type for formal xxx in entry param record   (Exp_Ch9)
+   --    xxxB    tag table for tagged type xxx                      (Exp_Ch3)
+   --    xxxB    task body procedure for task xxx                   (Exp_Ch9)
+   --    xxxD    dispatch table for tagged type xxx                 (Exp_Ch3)
+   --    xxxD    discriminal for discriminant xxx                   (Sem_Ch3)
+   --    xxxDn   n'th discr check function for rec type xxx         (Exp_Ch3)
+   --    xxxE    elaboration boolean flag for task xxx              (Exp_Ch9)
+   --    xxxE    dispatch table pointer type for tagged type xxx    (Exp_Ch3)
+   --    xxxE    parameters for accept body for entry xxx           (Exp_Ch9)
+   --    xxxFn   n'th primitive of a tagged type (named xxx)        (Exp_Ch3)
+   --    xxxI    initialization procedure for type xxx              (Exp_Ch3)
+   --    xxxJ    tag table type index for tagged type xxx           (Exp_Ch3)
+   --    xxxM    master Id value for access type xxx                (Exp_Ch3)
+   --    xxxP    tag table pointer type for tagged type xxx         (Exp_Ch3)
+   --    xxxP    parameter record type for entry xxx                (Exp_Ch9)
+   --    xxxPA   access to parameter record type for entry xxx      (Exp_Ch9)
+   --    xxxPn   pointer type for n'th primitive of tagged type xxx (Exp_Ch3)
+   --    xxxR    dispatch table pointer for tagged type xxx         (Exp_Ch3)
+   --    xxxT    tag table type for tagged type xxx                 (Exp_Ch3)
+   --    xxxT    literal table for enumeration type xxx             (Sem_Ch3)
+   --    xxxV    type for task value record for task xxx            (Exp_Ch9)
+   --    xxxX    entry index constant                               (Exp_Ch9)
+   --    xxxY    dispatch table type for tagged type xxx            (Exp_Ch3)
+   --    xxxZ    size variable for task xxx                         (Exp_Ch9)
+
+   --  Implicit type names
+
+   --    TxxxT   type of literal table for enumeration type xxx     (Sem_Ch3)
+
+   --  (list not yet complete ???)
+
+   ----------------------
+   -- Get_Attribute_Id --
+   ----------------------
+
+   function Get_Attribute_Id (N : Name_Id) return Attribute_Id is
+   begin
+      return Attribute_Id'Val (N - First_Attribute_Name);
+   end Get_Attribute_Id;
+
+   ------------------
+   -- Get_Check_Id --
+   ------------------
+
+   function Get_Check_Id (N : Name_Id) return Check_Id is
+   begin
+      return Check_Id'Val (N - First_Check_Name);
+   end Get_Check_Id;
+
+   -----------------------
+   -- Get_Convention_Id --
+   -----------------------
+
+   function Get_Convention_Id (N : Name_Id) return Convention_Id is
+   begin
+      case N is
+         when Name_Ada        => return Convention_Ada;
+         when Name_Asm        => return Convention_Assembler;
+         when Name_Assembler  => return Convention_Assembler;
+         when Name_C          => return Convention_C;
+         when Name_COBOL      => return Convention_COBOL;
+         when Name_CPP        => return Convention_CPP;
+         when Name_DLL        => return Convention_Stdcall;
+         when Name_Fortran    => return Convention_Fortran;
+         when Name_Intrinsic  => return Convention_Intrinsic;
+         when Name_Java       => return Convention_Java;
+         when Name_Stdcall    => return Convention_Stdcall;
+         when Name_Stubbed    => return Convention_Stubbed;
+         when Name_Win32      => return Convention_Stdcall;
+         when others          =>
+            raise Program_Error;
+      end case;
+   end Get_Convention_Id;
+
+   ---------------------------
+   -- Get_Locking_Policy_Id --
+   ---------------------------
+
+   function Get_Locking_Policy_Id (N : Name_Id) return Locking_Policy_Id is
+   begin
+      return Locking_Policy_Id'Val (N - First_Locking_Policy_Name);
+   end Get_Locking_Policy_Id;
+
+   -------------------
+   -- Get_Pragma_Id --
+   -------------------
+
+   function Get_Pragma_Id (N : Name_Id) return Pragma_Id is
+   begin
+      if N = Name_AST_Entry then
+         return Pragma_AST_Entry;
+      elsif N = Name_Storage_Size then
+         return Pragma_Storage_Size;
+      elsif N = Name_Storage_Unit then
+         return Pragma_Storage_Unit;
+      else
+         return Pragma_Id'Val (N - First_Pragma_Name);
+      end if;
+   end Get_Pragma_Id;
+
+   ---------------------------
+   -- Get_Queuing_Policy_Id --
+   ---------------------------
+
+   function Get_Queuing_Policy_Id (N : Name_Id) return Queuing_Policy_Id is
+   begin
+      return Queuing_Policy_Id'Val (N - First_Queuing_Policy_Name);
+   end Get_Queuing_Policy_Id;
+
+   ------------------------------------
+   -- Get_Task_Dispatching_Policy_Id --
+   ------------------------------------
+
+   function Get_Task_Dispatching_Policy_Id (N : Name_Id)
+     return Task_Dispatching_Policy_Id is
+   begin
+      return Task_Dispatching_Policy_Id'Val
+        (N - First_Task_Dispatching_Policy_Name);
+   end Get_Task_Dispatching_Policy_Id;
+
+   ----------------
+   -- Initialize --
+   ----------------
+
+   procedure Initialize is
+      P_Index      : Natural;
+      Discard_Name : Name_Id;
+
+   begin
+      P_Index := Preset_Names'First;
+
+      loop
+         Name_Len := 0;
+
+         while Preset_Names (P_Index) /= '#' loop
+            Name_Len := Name_Len + 1;
+            Name_Buffer (Name_Len) := Preset_Names (P_Index);
+            P_Index := P_Index + 1;
+         end loop;
+
+         --  We do the Name_Find call to enter the name into the table, but
+         --  we don't need to do anything with the result, since we already
+         --  initialized all the preset names to have the right value (we
+         --  are depending on the order of the names and Preset_Names).
+
+         Discard_Name := Name_Find;
+         P_Index := P_Index + 1;
+         exit when Preset_Names (P_Index) = '#';
+      end loop;
+
+      --  Make sure that number of names in standard table is correct. If
+      --  this check fails, run utility program XSNAMES to construct a new
+      --  properly matching version of the body.
+
+      pragma Assert (Discard_Name = Last_Predefined_Name);
+   end Initialize;
+
+   -----------------------
+   -- Is_Attribute_Name --
+   -----------------------
+
+   function Is_Attribute_Name (N : Name_Id) return Boolean is
+   begin
+      return N in First_Attribute_Name .. Last_Attribute_Name;
+   end Is_Attribute_Name;
+
+   -------------------
+   -- Is_Check_Name --
+   -------------------
+
+   function Is_Check_Name (N : Name_Id) return Boolean is
+   begin
+      return N in First_Check_Name .. Last_Check_Name;
+   end Is_Check_Name;
+
+   ------------------------
+   -- Is_Convention_Name --
+   ------------------------
+
+   function Is_Convention_Name (N : Name_Id) return Boolean is
+   begin
+      return N in First_Convention_Name .. Last_Convention_Name
+        or else N = Name_C;
+   end Is_Convention_Name;
+
+   ------------------------------
+   -- Is_Entity_Attribute_Name --
+   ------------------------------
+
+   function Is_Entity_Attribute_Name (N : Name_Id) return Boolean is
+   begin
+      return N in First_Entity_Attribute_Name .. Last_Entity_Attribute_Name;
+   end Is_Entity_Attribute_Name;
+
+   --------------------------------
+   -- Is_Function_Attribute_Name --
+   --------------------------------
+
+   function Is_Function_Attribute_Name (N : Name_Id) return Boolean is
+   begin
+      return N in
+        First_Renamable_Function_Attribute ..
+          Last_Renamable_Function_Attribute;
+   end Is_Function_Attribute_Name;
+
+   ----------------------------
+   -- Is_Locking_Policy_Name --
+   ----------------------------
+
+   function Is_Locking_Policy_Name (N : Name_Id) return Boolean is
+   begin
+      return N in First_Locking_Policy_Name .. Last_Locking_Policy_Name;
+   end Is_Locking_Policy_Name;
+
+   -----------------------------
+   -- Is_Operator_Symbol_Name --
+   -----------------------------
+
+   function Is_Operator_Symbol_Name (N : Name_Id) return Boolean is
+   begin
+      return N in First_Operator_Name .. Last_Operator_Name;
+   end Is_Operator_Symbol_Name;
+
+   --------------------
+   -- Is_Pragma_Name --
+   --------------------
+
+   function Is_Pragma_Name (N : Name_Id) return Boolean is
+   begin
+      return N in First_Pragma_Name .. Last_Pragma_Name
+        or else N = Name_AST_Entry
+        or else N = Name_Storage_Size
+        or else N = Name_Storage_Unit;
+   end Is_Pragma_Name;
+
+   ---------------------------------
+   -- Is_Procedure_Attribute_Name --
+   ---------------------------------
+
+   function Is_Procedure_Attribute_Name (N : Name_Id) return Boolean is
+   begin
+      return N in First_Procedure_Attribute .. Last_Procedure_Attribute;
+   end Is_Procedure_Attribute_Name;
+
+   ----------------------------
+   -- Is_Queuing_Policy_Name --
+   ----------------------------
+
+   function Is_Queuing_Policy_Name (N : Name_Id) return Boolean is
+   begin
+      return N in First_Queuing_Policy_Name .. Last_Queuing_Policy_Name;
+   end Is_Queuing_Policy_Name;
+
+   -------------------------------------
+   -- Is_Task_Dispatching_Policy_Name --
+   -------------------------------------
+
+   function Is_Task_Dispatching_Policy_Name (N : Name_Id) return Boolean is
+   begin
+      return N in First_Task_Dispatching_Policy_Name ..
+                  Last_Task_Dispatching_Policy_Name;
+   end Is_Task_Dispatching_Policy_Name;
+
+   ----------------------------
+   -- Is_Type_Attribute_Name --
+   ----------------------------
+
+   function Is_Type_Attribute_Name (N : Name_Id) return Boolean is
+   begin
+      return N in First_Type_Attribute_Name .. Last_Type_Attribute_Name;
+   end Is_Type_Attribute_Name;
+
+end Snames;
diff --git a/gcc/ada/snames.ads b/gcc/ada/snames.ads
new file mode 100644 (file)
index 0000000..4c365b8
--- /dev/null
@@ -0,0 +1,1373 @@
+------------------------------------------------------------------------------
+--                                                                          --
+--                         GNAT COMPILER COMPONENTS                         --
+--                                                                          --
+--                               S N A M E S                                --
+--                                                                          --
+--                                 S p e c                                  --
+--                                                                          --
+--                            $Revision: 1.209 $
+--                                                                          --
+--          Copyright (C) 1992-2001, 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- --
+-- ware  Foundation;  either version 2,  or (at your option) any later ver- --
+-- sion.  GNAT is distributed in the hope that it will be useful, but WITH- --
+-- OUT ANY WARRANTY;  without even the  implied warranty of MERCHANTABILITY --
+-- or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License --
+-- for  more details.  You should have  received  a copy of the GNU General --
+-- Public License  distributed with GNAT;  see file COPYING.  If not, write --
+-- to  the Free Software Foundation,  59 Temple Place - Suite 330,  Boston, --
+-- MA 02111-1307, USA.                                                      --
+--                                                                          --
+-- As a special exception,  if other files  instantiate  generics from this --
+-- unit, or you link  this unit with other files  to produce an executable, --
+-- this  unit  does not  by itself cause  the resulting  executable  to  be --
+-- covered  by the  GNU  General  Public  License.  This exception does not --
+-- however invalidate  any other reasons why  the executable file  might be --
+-- covered by the  GNU Public License.                                      --
+--                                                                          --
+-- GNAT was originally developed  by the GNAT team at  New York University. --
+-- It is now maintained by Ada Core Technologies Inc (http://www.gnat.com). --
+--                                                                          --
+------------------------------------------------------------------------------
+
+with Types; use Types;
+
+package Snames is
+
+--  This package contains definitions of standard names (i.e. entries in the
+--  Names table) that are used throughout the GNAT compiler). It also contains
+--  the definitions of some enumeration types whose definitions are tied to
+--  the order of these preset names.
+
+--  WARNING: There is a C file, a-snames-h which duplicates some of the
+--  definitions in this file and must be kept properly synchronized.
+
+   ------------------
+   -- Preset Names --
+   ------------------
+
+   --  The following are preset entries in the names table, which are
+   --  entered at the start of every compilation for easy access. Note
+   --  that the order of initialization of these names in the body must
+   --  be coordinated with the order of names in this table.
+
+   --  Note: a name may not appear more than once in the following list.
+   --  If additional pragmas or attributes are introduced which might
+   --  otherwise cause a duplicate, then list it only once in this table,
+   --  and adjust the definition of the functions for testing for pragma
+   --  names and attribute names, and returning their ID values. Of course
+   --  everything is simpler if no such duplications occur!
+
+   --  First we have the one character names used to optimize the lookup
+   --  process for one character identifiers (avoid the hashing in this case)
+   --  There are a full 256 of these, but only the entries for lower case
+   --  and upper case letters have identifiers
+
+   --  The lower case letter entries are used for one character identifiers
+   --  appearing in the source, for example in pragma Interface (C).
+
+   Name_A         : constant Name_Id := First_Name_Id + Character'Pos ('a');
+   Name_B         : constant Name_Id := First_Name_Id + Character'Pos ('b');
+   Name_C         : constant Name_Id := First_Name_Id + Character'Pos ('c');
+   Name_D         : constant Name_Id := First_Name_Id + Character'Pos ('d');
+   Name_E         : constant Name_Id := First_Name_Id + Character'Pos ('e');
+   Name_F         : constant Name_Id := First_Name_Id + Character'Pos ('f');
+   Name_G         : constant Name_Id := First_Name_Id + Character'Pos ('g');
+   Name_H         : constant Name_Id := First_Name_Id + Character'Pos ('h');
+   Name_I         : constant Name_Id := First_Name_Id + Character'Pos ('i');
+   Name_J         : constant Name_Id := First_Name_Id + Character'Pos ('j');
+   Name_K         : constant Name_Id := First_Name_Id + Character'Pos ('k');
+   Name_L         : constant Name_Id := First_Name_Id + Character'Pos ('l');
+   Name_M         : constant Name_Id := First_Name_Id + Character'Pos ('m');
+   Name_N         : constant Name_Id := First_Name_Id + Character'Pos ('n');
+   Name_O         : constant Name_Id := First_Name_Id + Character'Pos ('o');
+   Name_P         : constant Name_Id := First_Name_Id + Character'Pos ('p');
+   Name_Q         : constant Name_Id := First_Name_Id + Character'Pos ('q');
+   Name_R         : constant Name_Id := First_Name_Id + Character'Pos ('r');
+   Name_S         : constant Name_Id := First_Name_Id + Character'Pos ('s');
+   Name_T         : constant Name_Id := First_Name_Id + Character'Pos ('t');
+   Name_U         : constant Name_Id := First_Name_Id + Character'Pos ('u');
+   Name_V         : constant Name_Id := First_Name_Id + Character'Pos ('v');
+   Name_W         : constant Name_Id := First_Name_Id + Character'Pos ('w');
+   Name_X         : constant Name_Id := First_Name_Id + Character'Pos ('x');
+   Name_Y         : constant Name_Id := First_Name_Id + Character'Pos ('y');
+   Name_Z         : constant Name_Id := First_Name_Id + Character'Pos ('z');
+
+   --  The upper case letter entries are used by expander code for local
+   --  variables that do not require unique names (e.g. formal parameter
+   --  names in constructed procedures)
+
+   Name_uA        : constant Name_Id := First_Name_Id + Character'Pos ('A');
+   Name_uB        : constant Name_Id := First_Name_Id + Character'Pos ('B');
+   Name_uC        : constant Name_Id := First_Name_Id + Character'Pos ('C');
+   Name_uD        : constant Name_Id := First_Name_Id + Character'Pos ('D');
+   Name_uE        : constant Name_Id := First_Name_Id + Character'Pos ('E');
+   Name_uF        : constant Name_Id := First_Name_Id + Character'Pos ('F');
+   Name_uG        : constant Name_Id := First_Name_Id + Character'Pos ('G');
+   Name_uH        : constant Name_Id := First_Name_Id + Character'Pos ('H');
+   Name_uI        : constant Name_Id := First_Name_Id + Character'Pos ('I');
+   Name_uJ        : constant Name_Id := First_Name_Id + Character'Pos ('J');
+   Name_uK        : constant Name_Id := First_Name_Id + Character'Pos ('K');
+   Name_uL        : constant Name_Id := First_Name_Id + Character'Pos ('L');
+   Name_uM        : constant Name_Id := First_Name_Id + Character'Pos ('M');
+   Name_uN        : constant Name_Id := First_Name_Id + Character'Pos ('N');
+   Name_uO        : constant Name_Id := First_Name_Id + Character'Pos ('O');
+   Name_uP        : constant Name_Id := First_Name_Id + Character'Pos ('P');
+   Name_uQ        : constant Name_Id := First_Name_Id + Character'Pos ('Q');
+   Name_uR        : constant Name_Id := First_Name_Id + Character'Pos ('R');
+   Name_uS        : constant Name_Id := First_Name_Id + Character'Pos ('S');
+   Name_uT        : constant Name_Id := First_Name_Id + Character'Pos ('T');
+   Name_uU        : constant Name_Id := First_Name_Id + Character'Pos ('U');
+   Name_uV        : constant Name_Id := First_Name_Id + Character'Pos ('V');
+   Name_uW        : constant Name_Id := First_Name_Id + Character'Pos ('W');
+   Name_uX        : constant Name_Id := First_Name_Id + Character'Pos ('X');
+   Name_uY        : constant Name_Id := First_Name_Id + Character'Pos ('Y');
+   Name_uZ        : constant Name_Id := First_Name_Id + Character'Pos ('Z');
+
+   --  Note: the following table is read by the utility program XSNAMES and
+   --  its format should not be changed without coordinating with this program.
+
+   N : constant Name_Id := First_Name_Id + 256;
+   --  Synonym used in standard name definitions
+
+   --  Some names that are used by gigi, and whose definitions are reflected
+   --  in the C header file a-snames.h. They are placed at the start so that
+   --  the need to modify a-snames.h is minimized.
+
+   Name_uParent                        : constant Name_Id := N + 000;
+   Name_uTag                           : constant Name_Id := N + 001;
+   Name_Off                            : constant Name_Id := N + 002;
+   Name_Space                          : constant Name_Id := N + 003;
+   Name_Time                           : constant Name_Id := N + 004;
+   Name_uInit_Proc                     : constant Name_Id := N + 005;
+   Name_uSize                          : constant Name_Id := N + 006;
+
+   --  Some special names used by the expander. Note that the lower case u's
+   --  at the start of these names get translated to extra underscores. These
+   --  names are only referenced internally by expander generated code.
+
+   Name_uAbort_Signal                  : constant Name_Id := N + 007;
+   Name_uAddress_Resolver              : constant Name_Id := N + 008;
+   Name_uAssign                        : constant Name_Id := N + 009;
+   Name_uChain                         : constant Name_Id := N + 010;
+   Name_uClean                         : constant Name_Id := N + 011;
+   Name_uController                    : constant Name_Id := N + 012;
+   Name_uEntry_Bodies                  : constant Name_Id := N + 013;
+   Name_uExpunge                       : constant Name_Id := N + 014;
+   Name_uFinal_List                    : constant Name_Id := N + 015;
+   Name_uIdepth                        : constant Name_Id := N + 016;
+   Name_uInit                          : constant Name_Id := N + 017;
+   Name_uLocal_Final_List              : constant Name_Id := N + 018;
+   Name_uMaster                        : constant Name_Id := N + 019;
+   Name_uObject                        : constant Name_Id := N + 020;
+   Name_uPriority                      : constant Name_Id := N + 021;
+   Name_uService                       : constant Name_Id := N + 022;
+   Name_uTags                          : constant Name_Id := N + 023;
+   Name_uTask                          : constant Name_Id := N + 024;
+   Name_uTask_Id                       : constant Name_Id := N + 025;
+   Name_uTask_Info                     : constant Name_Id := N + 026;
+   Name_uTask_Name                     : constant Name_Id := N + 027;
+   Name_uTrace_Sp                      : constant Name_Id := N + 028;
+
+   --  Names of routines in Ada.Finalization, needed by expander
+
+   Name_Initialize                     : constant Name_Id := N + 029;
+   Name_Adjust                         : constant Name_Id := N + 030;
+   Name_Finalize                       : constant Name_Id := N + 031;
+
+   --  Names of fields declared in System.Finalization_Implementation,
+   --  needed by the expander when generating code for finalization.
+
+   Name_Next                           : constant Name_Id := N + 032;
+   Name_Prev                           : constant Name_Id := N + 033;
+
+   --  Names of TSS routines (see Exp_TSS); Name_uInit_Proc above is also
+   --  one of these.
+
+   Name_uDeep_Adjust                   : constant Name_Id := N + 034;
+   Name_uEquality                      : constant Name_Id := N + 035;
+   Name_uDeep_Finalize                 : constant Name_Id := N + 036;
+   Name_uDeep_Initialize               : constant Name_Id := N + 037;
+   Name_uInput                         : constant Name_Id := N + 038;
+   Name_uOutput                        : constant Name_Id := N + 039;
+   Name_uRAS_Access                    : constant Name_Id := N + 040;
+   Name_uRAS_Dereference               : constant Name_Id := N + 041;
+   Name_uRead                          : constant Name_Id := N + 042;
+   Name_uRep_To_Pos                    : constant Name_Id := N + 043;
+   Name_uWrite                         : constant Name_Id := N + 044;
+
+   --  Names of allocation routines, also needed by expander
+
+   Name_Allocate                       : constant Name_Id := N + 045;
+   Name_Deallocate                     : constant Name_Id := N + 046;
+   Name_Dereference                    : constant Name_Id := N + 047;
+
+   --  Names of Text_IO generic subpackages (see Rtsfind.Text_IO_Kludge)
+
+   First_Text_IO_Package               : constant Name_Id := N + 048;
+   Name_Decimal_IO                     : constant Name_Id := N + 048;
+   Name_Enumeration_IO                 : constant Name_Id := N + 049;
+   Name_Fixed_IO                       : constant Name_Id := N + 050;
+   Name_Float_IO                       : constant Name_Id := N + 051;
+   Name_Integer_IO                     : constant Name_Id := N + 052;
+   Name_Modular_IO                     : constant Name_Id := N + 053;
+   Last_Text_IO_Package                : constant Name_Id := N + 053;
+
+   subtype Text_IO_Package_Name is Name_Id
+     range First_Text_IO_Package .. Last_Text_IO_Package;
+
+   --  Names of files in library for Ada.Text_IO and Ada.Wide_Text_IO
+
+   Name_a_textio                       : constant Name_Id := N + 054;
+   Name_a_witeio                       : constant Name_Id := N + 055;
+
+   --  Some miscellaneous names used for error detection/recovery
+
+   Name_Const                          : constant Name_Id := N + 056;
+   Name_Error                          : constant Name_Id := N + 057;
+   Name_Go                             : constant Name_Id := N + 058;
+   Name_Put                            : constant Name_Id := N + 059;
+   Name_Put_Line                       : constant Name_Id := N + 060;
+   Name_To                             : constant Name_Id := N + 061;
+
+   --  Names for packages that are treated specially by the compiler
+
+   Name_Finalization                   : constant Name_Id := N + 062;
+   Name_Finalization_Root              : constant Name_Id := N + 063;
+   Name_Interfaces                     : constant Name_Id := N + 064;
+   Name_Standard                       : constant Name_Id := N + 065;
+   Name_System                         : constant Name_Id := N + 066;
+   Name_Text_IO                        : constant Name_Id := N + 067;
+   Name_Wide_Text_IO                   : constant Name_Id := N + 068;
+
+   --  Names of identifiers used in expanding distribution stubs
+
+   Name_Addr                           : constant Name_Id := N + 069;
+   Name_Async                          : constant Name_Id := N + 070;
+   Name_Get_Active_Partition_ID        : constant Name_Id := N + 071;
+   Name_Get_RCI_Package_Receiver       : constant Name_Id := N + 072;
+   Name_Origin                         : constant Name_Id := N + 073;
+   Name_Params                         : constant Name_Id := N + 074;
+   Name_Partition                      : constant Name_Id := N + 075;
+   Name_Partition_Interface            : constant Name_Id := N + 076;
+   Name_Ras                            : constant Name_Id := N + 077;
+   Name_RCI_Name                       : constant Name_Id := N + 078;
+   Name_Receiver                       : constant Name_Id := N + 079;
+   Name_Result                         : constant Name_Id := N + 080;
+   Name_Rpc                            : constant Name_Id := N + 081;
+   Name_Subp_Id                        : constant Name_Id := N + 082;
+
+   --  Operator Symbol entries. The actual names have an upper case O at
+   --  the start in place of the Op_ prefix (e.g. the actual name that
+   --  corresponds to Name_Op_Abs is "Oabs".
+
+   First_Operator_Name                 : constant Name_Id := N + 083;
+   Name_Op_Abs                         : constant Name_Id := N + 083; -- "abs"
+   Name_Op_And                         : constant Name_Id := N + 084; -- "and"
+   Name_Op_Mod                         : constant Name_Id := N + 085; -- "mod"
+   Name_Op_Not                         : constant Name_Id := N + 086; -- "not"
+   Name_Op_Or                          : constant Name_Id := N + 087; -- "or"
+   Name_Op_Rem                         : constant Name_Id := N + 088; -- "rem"
+   Name_Op_Xor                         : constant Name_Id := N + 089; -- "xor"
+   Name_Op_Eq                          : constant Name_Id := N + 090; -- "="
+   Name_Op_Ne                          : constant Name_Id := N + 091; -- "/="
+   Name_Op_Lt                          : constant Name_Id := N + 092; -- "<"
+   Name_Op_Le                          : constant Name_Id := N + 093; -- "<="
+   Name_Op_Gt                          : constant Name_Id := N + 094; -- ">"
+   Name_Op_Ge                          : constant Name_Id := N + 095; -- ">="
+   Name_Op_Add                         : constant Name_Id := N + 096; -- "+"
+   Name_Op_Subtract                    : constant Name_Id := N + 097; -- "-"
+   Name_Op_Concat                      : constant Name_Id := N + 098; -- "&"
+   Name_Op_Multiply                    : constant Name_Id := N + 099; -- "*"
+   Name_Op_Divide                      : constant Name_Id := N + 100; -- "/"
+   Name_Op_Expon                       : constant Name_Id := N + 101; -- "**"
+   Last_Operator_Name                  : constant Name_Id := N + 101;
+
+   --  Names for all pragmas recognized by GNAT. The entries with the comment
+   --  "Ada 83" are pragmas that are defined in Ada 83, but not in Ada 95.
+   --  These pragmas are fully implemented in both Ada 83 and Ada 95 modes
+   --  in GNAT.
+
+   --  The entries marked GNAT are pragmas that are defined by GNAT
+   --  and implemented in both Ada 83 and Ada 95 modes. Full descriptions
+   --  of these implementation dependent pragmas may be found in the
+   --  appropriate section in unit Sem_Prag in file sem-prag.adb.
+
+   --  The entries marked VMS are VMS specific pragmas that are recognized
+   --  only in OpenVMS versions of GNAT. They are ignored in other versions
+   --  with an appropriate warning.
+
+   First_Pragma_Name                   : constant Name_Id := N + 102;
+
+   --  Configuration pragmas are grouped at start
+
+   Name_Ada_83                         : constant Name_Id := N + 102; -- GNAT
+   Name_Ada_95                         : constant Name_Id := N + 103; -- GNAT
+   Name_C_Pass_By_Copy                 : constant Name_Id := N + 104; -- GNAT
+   Name_Component_Alignment            : constant Name_Id := N + 105; -- GNAT
+   Name_Discard_Names                  : constant Name_Id := N + 106;
+   Name_Elaboration_Checks             : constant Name_Id := N + 107; -- GNAT
+   Name_Eliminate                      : constant Name_Id := N + 108; -- GNAT
+   Name_Extend_System                  : constant Name_Id := N + 109; -- GNAT
+   Name_Extensions_Allowed             : constant Name_Id := N + 110; -- GNAT
+   Name_External_Name_Casing           : constant Name_Id := N + 111; -- GNAT
+   Name_Float_Representation           : constant Name_Id := N + 112; -- GNAT
+   Name_Initialize_Scalars             : constant Name_Id := N + 113; -- GNAT
+   Name_License                        : constant Name_Id := N + 114; -- GNAT
+   Name_Locking_Policy                 : constant Name_Id := N + 115;
+   Name_Long_Float                     : constant Name_Id := N + 116; -- VMS
+   Name_No_Run_Time                    : constant Name_Id := N + 117; -- GNAT
+   Name_Normalize_Scalars              : constant Name_Id := N + 118;
+   Name_Polling                        : constant Name_Id := N + 119; -- GNAT
+   Name_Propagate_Exceptions           : constant Name_Id := N + 120; -- GNAT
+   Name_Queuing_Policy                 : constant Name_Id := N + 121;
+   Name_Ravenscar                      : constant Name_Id := N + 122;
+   Name_Restricted_Run_Time            : constant Name_Id := N + 123;
+   Name_Restrictions                   : constant Name_Id := N + 124;
+   Name_Reviewable                     : constant Name_Id := N + 125;
+   Name_Source_File_Name               : constant Name_Id := N + 126; -- GNAT
+   Name_Style_Checks                   : constant Name_Id := N + 127; -- GNAT
+   Name_Suppress                       : constant Name_Id := N + 128;
+   Name_Task_Dispatching_Policy        : constant Name_Id := N + 129;
+   Name_Unsuppress                     : constant Name_Id := N + 130; -- GNAT
+   Name_Use_VADS_Size                  : constant Name_Id := N + 131; -- GNAT
+   Name_Warnings                       : constant Name_Id := N + 132; -- GNAT
+   Name_Validity_Checks                : constant Name_Id := N + 133; -- GNAT
+   Last_Configuration_Pragma_Name      : constant Name_Id := N + 133;
+
+   --  Remaining pragma names
+
+   Name_Abort_Defer                    : constant Name_Id := N + 134; -- GNAT
+   Name_All_Calls_Remote               : constant Name_Id := N + 135;
+   Name_Annotate                       : constant Name_Id := N + 136; -- GNAT
+
+   --  Note: AST_Entry is not in this list because its name matches the
+   --  name of the corresponding attribute. However, it is included in the
+   --  definition of the type Attribute_Id, and the functions Get_Pragma_Id
+   --  and Check_Pragma_Id correctly recognize and process Name_AST_Entry.
+   --  AST_Entry is a VMS specific pragma.
+
+   Name_Assert                         : constant Name_Id := N + 137; -- GNAT
+   Name_Asynchronous                   : constant Name_Id := N + 138;
+   Name_Atomic                         : constant Name_Id := N + 139;
+   Name_Atomic_Components              : constant Name_Id := N + 140;
+   Name_Attach_Handler                 : constant Name_Id := N + 141;
+   Name_Comment                        : constant Name_Id := N + 142; -- GNAT
+   Name_Common_Object                  : constant Name_Id := N + 143; -- GNAT
+   Name_Complex_Representation         : constant Name_Id := N + 144; -- GNAT
+   Name_Controlled                     : constant Name_Id := N + 145;
+   Name_Convention                     : constant Name_Id := N + 146;
+   Name_CPP_Class                      : constant Name_Id := N + 147; -- GNAT
+   Name_CPP_Constructor                : constant Name_Id := N + 148; -- GNAT
+   Name_CPP_Virtual                    : constant Name_Id := N + 149; -- GNAT
+   Name_CPP_Vtable                     : constant Name_Id := N + 150; -- GNAT
+   Name_Debug                          : constant Name_Id := N + 151; -- GNAT
+   Name_Elaborate                      : constant Name_Id := N + 152; -- Ada 83
+   Name_Elaborate_All                  : constant Name_Id := N + 153;
+   Name_Elaborate_Body                 : constant Name_Id := N + 154;
+   Name_Export                         : constant Name_Id := N + 155;
+   Name_Export_Exception               : constant Name_Id := N + 156; -- VMS
+   Name_Export_Function                : constant Name_Id := N + 157; -- GNAT
+   Name_Export_Object                  : constant Name_Id := N + 158; -- GNAT
+   Name_Export_Procedure               : constant Name_Id := N + 159; -- GNAT
+   Name_Export_Valued_Procedure        : constant Name_Id := N + 160; -- GNAT
+   Name_Finalize_Storage_Only          : constant Name_Id := N + 161; -- GNAT
+   Name_Ident                          : constant Name_Id := N + 162; -- VMS
+   Name_Import                         : constant Name_Id := N + 163;
+   Name_Import_Exception               : constant Name_Id := N + 164; -- VMS
+   Name_Import_Function                : constant Name_Id := N + 165; -- GNAT
+   Name_Import_Object                  : constant Name_Id := N + 166; -- GNAT
+   Name_Import_Procedure               : constant Name_Id := N + 167; -- GNAT
+   Name_Import_Valued_Procedure        : constant Name_Id := N + 168; -- GNAT
+   Name_Inline                         : constant Name_Id := N + 169;
+   Name_Inline_Always                  : constant Name_Id := N + 170; -- GNAT
+   Name_Inline_Generic                 : constant Name_Id := N + 171; -- GNAT
+   Name_Inspection_Point               : constant Name_Id := N + 172;
+   Name_Interface                      : constant Name_Id := N + 173; -- Ada 83
+   Name_Interface_Name                 : constant Name_Id := N + 174; -- GNAT
+   Name_Interrupt_Handler              : constant Name_Id := N + 175;
+   Name_Interrupt_Priority             : constant Name_Id := N + 176;
+   Name_Java_Constructor               : constant Name_Id := N + 177; -- GNAT
+   Name_Java_Interface                 : constant Name_Id := N + 178; -- GNAT
+   Name_Link_With                      : constant Name_Id := N + 179; -- GNAT
+   Name_Linker_Alias                   : constant Name_Id := N + 180; -- GNAT
+   Name_Linker_Options                 : constant Name_Id := N + 181;
+   Name_Linker_Section                 : constant Name_Id := N + 182; -- GNAT
+   Name_List                           : constant Name_Id := N + 183;
+   Name_Machine_Attribute              : constant Name_Id := N + 184; -- GNAT
+   Name_Main                           : constant Name_Id := N + 185; -- GNAT
+   Name_Main_Storage                   : constant Name_Id := N + 186; -- GNAT
+   Name_Memory_Size                    : constant Name_Id := N + 187; -- Ada 83
+   Name_No_Return                      : constant Name_Id := N + 188; -- GNAT
+   Name_Optimize                       : constant Name_Id := N + 189;
+   Name_Pack                           : constant Name_Id := N + 190;
+   Name_Page                           : constant Name_Id := N + 191;
+   Name_Passive                        : constant Name_Id := N + 192; -- GNAT
+   Name_Preelaborate                   : constant Name_Id := N + 193;
+   Name_Priority                       : constant Name_Id := N + 194;
+   Name_Psect_Object                   : constant Name_Id := N + 195; -- VMS
+   Name_Pure                           : constant Name_Id := N + 196;
+   Name_Pure_Function                  : constant Name_Id := N + 197; -- GNAT
+   Name_Remote_Call_Interface          : constant Name_Id := N + 198;
+   Name_Remote_Types                   : constant Name_Id := N + 199;
+   Name_Share_Generic                  : constant Name_Id := N + 200; -- GNAT
+   Name_Shared                         : constant Name_Id := N + 201; -- Ada 83
+   Name_Shared_Passive                 : constant Name_Id := N + 202;
+
+   --  Note: Storage_Size is not in this list because its name matches the
+   --  name of the corresponding attribute. However, it is included in the
+   --  definition of the type Attribute_Id, and the functions Get_Pragma_Id
+   --  and Check_Pragma_Id correctly recognize and process Name_Storage_Size.
+
+   --  Note: Storage_Unit is also omitted from the list because of a clash
+   --  with an attribute name, and is treated similarly.
+
+   Name_Source_Reference               : constant Name_Id := N + 203; -- GNAT
+   Name_Stream_Convert                 : constant Name_Id := N + 204; -- GNAT
+   Name_Subtitle                       : constant Name_Id := N + 205; -- GNAT
+   Name_Suppress_All                   : constant Name_Id := N + 206; -- GNAT
+   Name_Suppress_Debug_Info            : constant Name_Id := N + 207; -- GNAT
+   Name_Suppress_Initialization        : constant Name_Id := N + 208; -- GNAT
+   Name_System_Name                    : constant Name_Id := N + 209; -- Ada 83
+   Name_Task_Info                      : constant Name_Id := N + 210; -- GNAT
+   Name_Task_Name                      : constant Name_Id := N + 211; -- GNAT
+   Name_Task_Storage                   : constant Name_Id := N + 212; -- VMS
+   Name_Time_Slice                     : constant Name_Id := N + 213; -- GNAT
+   Name_Title                          : constant Name_Id := N + 214; -- GNAT
+   Name_Unchecked_Union                : constant Name_Id := N + 215; -- GNAT
+   Name_Unimplemented_Unit             : constant Name_Id := N + 216; -- GNAT
+   Name_Unreserve_All_Interrupts       : constant Name_Id := N + 217; -- GNAT
+   Name_Volatile                       : constant Name_Id := N + 218;
+   Name_Volatile_Components            : constant Name_Id := N + 219;
+   Name_Weak_External                  : constant Name_Id := N + 220; -- GNAT
+   Last_Pragma_Name                    : constant Name_Id := N + 220;
+
+   --  Language convention names for pragma Convention/Export/Import/Interface
+   --  Note that Name_C is not included in this list, since it was already
+   --  declared earlier in the context of one-character identifier names
+   --  (where the order is critical to the fast look up process).
+
+   --  Note: there are no convention names corresponding to the conventions
+   --  Entry and Protected, this is because these conventions cannot be
+   --  specified by a pragma.
+
+   --  Note: The convention name C_Pass_By_Copy is treated as entirely
+   --  equivalent to C except when it is specified on a record type. In
+   --  this case the convention of the record type is set to C, but in
+   --  addition the flag C_Pass_By_Copy is set on the record type.
+
+   First_Convention_Name               : constant Name_Id := N + 221;
+   Name_Ada                            : constant Name_Id := N + 221;
+   Name_Asm                            : constant Name_Id := N + 222;
+   Name_Assembler                      : constant Name_Id := N + 223;
+   Name_COBOL                          : constant Name_Id := N + 224;
+   Name_CPP                            : constant Name_Id := N + 225;
+   Name_DLL                            : constant Name_Id := N + 226;
+   Name_Fortran                        : constant Name_Id := N + 227;
+   Name_Intrinsic                      : constant Name_Id := N + 228;
+   Name_Java                           : constant Name_Id := N + 229;
+   Name_Stdcall                        : constant Name_Id := N + 230;
+   Name_Stubbed                        : constant Name_Id := N + 231;
+   Name_Win32                          : constant Name_Id := N + 232;
+   Last_Convention_Name                : constant Name_Id := N + 232;
+
+   --  Other special names used in processing pragma arguments
+
+   Name_As_Is                          : constant Name_Id := N + 233;
+   Name_Body_File_Name                 : constant Name_Id := N + 234;
+   Name_Casing                         : constant Name_Id := N + 235;
+   Name_Code                           : constant Name_Id := N + 236;
+   Name_Component                      : constant Name_Id := N + 237;
+   Name_Component_Size_4               : constant Name_Id := N + 238;
+   Name_Copy                           : constant Name_Id := N + 239;
+   Name_D_Float                        : constant Name_Id := N + 240;
+   Name_Descriptor                     : constant Name_Id := N + 241;
+   Name_Default                        : constant Name_Id := N + 242;
+   Name_Dot_Replacement                : constant Name_Id := N + 243;
+   Name_Dynamic                        : constant Name_Id := N + 244;
+   Name_Entity                         : constant Name_Id := N + 245;
+   Name_External                       : constant Name_Id := N + 246;
+   Name_External_Name                  : constant Name_Id := N + 247;
+   Name_First_Optional_Parameter       : constant Name_Id := N + 248;
+   Name_Form                           : constant Name_Id := N + 249;
+   Name_G_Float                        : constant Name_Id := N + 250;
+   Name_Gcc                            : constant Name_Id := N + 251;
+   Name_Gnat                           : constant Name_Id := N + 252;
+   Name_GPL                            : constant Name_Id := N + 253;
+   Name_IEEE_Float                     : constant Name_Id := N + 254;
+   Name_Internal                       : constant Name_Id := N + 255;
+   Name_Link_Name                      : constant Name_Id := N + 256;
+   Name_Lowercase                      : constant Name_Id := N + 257;
+   Name_Max_Size                       : constant Name_Id := N + 258;
+   Name_Mechanism                      : constant Name_Id := N + 259;
+   Name_Mixedcase                      : constant Name_Id := N + 260;
+   Name_Modified_GPL                   : constant Name_Id := N + 261;
+   Name_Name                           : constant Name_Id := N + 262;
+   Name_NCA                            : constant Name_Id := N + 263;
+   Name_No                             : constant Name_Id := N + 264;
+   Name_On                             : constant Name_Id := N + 265;
+   Name_Parameter_Types                : constant Name_Id := N + 266;
+   Name_Reference                      : constant Name_Id := N + 267;
+   Name_Restricted                     : constant Name_Id := N + 268;
+   Name_Result_Mechanism               : constant Name_Id := N + 269;
+   Name_Result_Type                    : constant Name_Id := N + 270;
+   Name_SB                             : constant Name_Id := N + 271;
+   Name_Section                        : constant Name_Id := N + 272;
+   Name_Semaphore                      : constant Name_Id := N + 273;
+   Name_Spec_File_Name                 : constant Name_Id := N + 274;
+   Name_Static                         : constant Name_Id := N + 275;
+   Name_Stack_Size                     : constant Name_Id := N + 276;
+   Name_Subunit_File_Name              : constant Name_Id := N + 277;
+   Name_Task_Stack_Size_Default        : constant Name_Id := N + 278;
+   Name_Task_Type                      : constant Name_Id := N + 279;
+   Name_Time_Slicing_Enabled           : constant Name_Id := N + 280;
+   Name_Top_Guard                      : constant Name_Id := N + 281;
+   Name_UBA                            : constant Name_Id := N + 282;
+   Name_UBS                            : constant Name_Id := N + 283;
+   Name_UBSB                           : constant Name_Id := N + 284;
+   Name_Unit_Name                      : constant Name_Id := N + 285;
+   Name_Unknown                        : constant Name_Id := N + 286;
+   Name_Unrestricted                   : constant Name_Id := N + 287;
+   Name_Uppercase                      : constant Name_Id := N + 288;
+   Name_VAX_Float                      : constant Name_Id := N + 289;
+   Name_VMS                            : constant Name_Id := N + 290;
+   Name_Working_Storage                : constant Name_Id := N + 291;
+
+   --  Names of recognized attributes. The entries with the comment "Ada 83"
+   --  are attributes that are defined in Ada 83, but not in Ada 95. These
+   --  attributes are implemented in both Ada 83 and Ada 95 modes in GNAT.
+
+   --  The entries marked GNAT are attributes that are defined by GNAT
+   --  and implemented in both Ada 83 and Ada 95 modes. Full descriptions
+   --  of these implementation dependent attributes may be found in the
+   --  appropriate section in package Sem_Attr in file sem-attr.ads.
+
+   --  The entries marked VMS are recognized only in OpenVMS implementations
+   --  of GNAT, and are treated as illegal in all other contexts.
+
+   First_Attribute_Name                : constant Name_Id := N + 292;
+   Name_Abort_Signal                   : constant Name_Id := N + 292;  -- GNAT
+   Name_Access                         : constant Name_Id := N + 293;
+   Name_Address                        : constant Name_Id := N + 294;
+   Name_Address_Size                   : constant Name_Id := N + 295;  -- GNAT
+   Name_Aft                            : constant Name_Id := N + 296;
+   Name_Alignment                      : constant Name_Id := N + 297;
+   Name_Asm_Input                      : constant Name_Id := N + 298;  -- GNAT
+   Name_Asm_Output                     : constant Name_Id := N + 299;  -- GNAT
+   Name_AST_Entry                      : constant Name_Id := N + 300;  -- VMS
+   Name_Bit                            : constant Name_Id := N + 301;  -- GNAT
+   Name_Bit_Order                      : constant Name_Id := N + 302;
+   Name_Bit_Position                   : constant Name_Id := N + 303;  -- GNAT
+   Name_Body_Version                   : constant Name_Id := N + 304;
+   Name_Callable                       : constant Name_Id := N + 305;
+   Name_Caller                         : constant Name_Id := N + 306;
+   Name_Code_Address                   : constant Name_Id := N + 307;  -- GNAT
+   Name_Component_Size                 : constant Name_Id := N + 308;
+   Name_Compose                        : constant Name_Id := N + 309;
+   Name_Constrained                    : constant Name_Id := N + 310;
+   Name_Count                          : constant Name_Id := N + 311;
+   Name_Default_Bit_Order              : constant Name_Id := N + 312; -- GNAT
+   Name_Definite                       : constant Name_Id := N + 313;
+   Name_Delta                          : constant Name_Id := N + 314;
+   Name_Denorm                         : constant Name_Id := N + 315;
+   Name_Digits                         : constant Name_Id := N + 316;
+   Name_Elaborated                     : constant Name_Id := N + 317; -- GNAT
+   Name_Emax                           : constant Name_Id := N + 318; -- Ada 83
+   Name_Enum_Rep                       : constant Name_Id := N + 319; -- GNAT
+   Name_Epsilon                        : constant Name_Id := N + 320; -- Ada 83
+   Name_Exponent                       : constant Name_Id := N + 321;
+   Name_External_Tag                   : constant Name_Id := N + 322;
+   Name_First                          : constant Name_Id := N + 323;
+   Name_First_Bit                      : constant Name_Id := N + 324;
+   Name_Fixed_Value                    : constant Name_Id := N + 325; -- GNAT
+   Name_Fore                           : constant Name_Id := N + 326;
+   Name_Has_Discriminants              : constant Name_Id := N + 327; -- GNAT
+   Name_Identity                       : constant Name_Id := N + 328;
+   Name_Img                            : constant Name_Id := N + 329; -- GNAT
+   Name_Integer_Value                  : constant Name_Id := N + 330; -- GNAT
+   Name_Large                          : constant Name_Id := N + 331; -- Ada 83
+   Name_Last                           : constant Name_Id := N + 332;
+   Name_Last_Bit                       : constant Name_Id := N + 333;
+   Name_Leading_Part                   : constant Name_Id := N + 334;
+   Name_Length                         : constant Name_Id := N + 335;
+   Name_Machine_Emax                   : constant Name_Id := N + 336;
+   Name_Machine_Emin                   : constant Name_Id := N + 337;
+   Name_Machine_Mantissa               : constant Name_Id := N + 338;
+   Name_Machine_Overflows              : constant Name_Id := N + 339;
+   Name_Machine_Radix                  : constant Name_Id := N + 340;
+   Name_Machine_Rounds                 : constant Name_Id := N + 341;
+   Name_Machine_Size                   : constant Name_Id := N + 342; -- GNAT
+   Name_Mantissa                       : constant Name_Id := N + 343; -- Ada 83
+   Name_Max_Interrupt_Priority         : constant Name_Id := N + 344; -- GNAT
+   Name_Max_Priority                   : constant Name_Id := N + 345; -- GNAT
+   Name_Max_Size_In_Storage_Elements   : constant Name_Id := N + 346;
+   Name_Maximum_Alignment              : constant Name_Id := N + 347; -- GNAT
+   Name_Mechanism_Code                 : constant Name_Id := N + 348; -- GNAT
+   Name_Model_Emin                     : constant Name_Id := N + 349;
+   Name_Model_Epsilon                  : constant Name_Id := N + 350;
+   Name_Model_Mantissa                 : constant Name_Id := N + 351;
+   Name_Model_Small                    : constant Name_Id := N + 352;
+   Name_Modulus                        : constant Name_Id := N + 353;
+   Name_Null_Parameter                 : constant Name_Id := N + 354; -- GNAT
+   Name_Object_Size                    : constant Name_Id := N + 355; -- GNAT
+   Name_Partition_ID                   : constant Name_Id := N + 356;
+   Name_Passed_By_Reference            : constant Name_Id := N + 357; -- GNAT
+   Name_Pos                            : constant Name_Id := N + 358;
+   Name_Position                       : constant Name_Id := N + 359;
+   Name_Range                          : constant Name_Id := N + 360;
+   Name_Range_Length                   : constant Name_Id := N + 361; -- GNAT
+   Name_Round                          : constant Name_Id := N + 362;
+   Name_Safe_Emax                      : constant Name_Id := N + 363; -- Ada 83
+   Name_Safe_First                     : constant Name_Id := N + 364;
+   Name_Safe_Large                     : constant Name_Id := N + 365; -- Ada 83
+   Name_Safe_Last                      : constant Name_Id := N + 366;
+   Name_Safe_Small                     : constant Name_Id := N + 367; -- Ada 83
+   Name_Scale                          : constant Name_Id := N + 368;
+   Name_Scaling                        : constant Name_Id := N + 369;
+   Name_Signed_Zeros                   : constant Name_Id := N + 370;
+   Name_Size                           : constant Name_Id := N + 371;
+   Name_Small                          : constant Name_Id := N + 372;
+   Name_Storage_Size                   : constant Name_Id := N + 373;
+   Name_Storage_Unit                   : constant Name_Id := N + 374; -- GNAT
+   Name_Tag                            : constant Name_Id := N + 375;
+   Name_Terminated                     : constant Name_Id := N + 376;
+   Name_Tick                           : constant Name_Id := N + 377; -- GNAT
+   Name_To_Address                     : constant Name_Id := N + 378; -- GNAT
+   Name_Type_Class                     : constant Name_Id := N + 379; -- GNAT
+   Name_UET_Address                    : constant Name_Id := N + 380; -- GNAT
+   Name_Unbiased_Rounding              : constant Name_Id := N + 381;
+   Name_Unchecked_Access               : constant Name_Id := N + 382;
+   Name_Universal_Literal_String       : constant Name_Id := N + 383; -- GNAT
+   Name_Unrestricted_Access            : constant Name_Id := N + 384; -- GNAT
+   Name_VADS_Size                      : constant Name_Id := N + 385; -- GNAT
+   Name_Val                            : constant Name_Id := N + 386;
+   Name_Valid                          : constant Name_Id := N + 387;
+   Name_Value_Size                     : constant Name_Id := N + 388; -- GNAT
+   Name_Version                        : constant Name_Id := N + 389;
+   Name_Wchar_T_Size                   : constant Name_Id := N + 390; -- GNAT
+   Name_Wide_Width                     : constant Name_Id := N + 391;
+   Name_Width                          : constant Name_Id := N + 392;
+   Name_Word_Size                      : constant Name_Id := N + 393; -- GNAT
+
+   --  Attributes that designate attributes returning renamable functions,
+   --  i.e. functions that return other than a universal value.
+
+   First_Renamable_Function_Attribute  : constant Name_Id := N + 394;
+   Name_Adjacent                       : constant Name_Id := N + 394;
+   Name_Ceiling                        : constant Name_Id := N + 395;
+   Name_Copy_Sign                      : constant Name_Id := N + 396;
+   Name_Floor                          : constant Name_Id := N + 397;
+   Name_Fraction                       : constant Name_Id := N + 398;
+   Name_Image                          : constant Name_Id := N + 399;
+   Name_Input                          : constant Name_Id := N + 400;
+   Name_Machine                        : constant Name_Id := N + 401;
+   Name_Max                            : constant Name_Id := N + 402;
+   Name_Min                            : constant Name_Id := N + 403;
+   Name_Model                          : constant Name_Id := N + 404;
+   Name_Pred                           : constant Name_Id := N + 405;
+   Name_Remainder                      : constant Name_Id := N + 406;
+   Name_Rounding                       : constant Name_Id := N + 407;
+   Name_Succ                           : constant Name_Id := N + 408;
+   Name_Truncation                     : constant Name_Id := N + 409;
+   Name_Value                          : constant Name_Id := N + 410;
+   Name_Wide_Image                     : constant Name_Id := N + 411;
+   Name_Wide_Value                     : constant Name_Id := N + 412;
+   Last_Renamable_Function_Attribute   : constant Name_Id := N + 412;
+
+   --  Attributes that designate procedures
+
+   First_Procedure_Attribute           : constant Name_Id := N + 413;
+   Name_Output                         : constant Name_Id := N + 413;
+   Name_Read                           : constant Name_Id := N + 414;
+   Name_Write                          : constant Name_Id := N + 415;
+   Last_Procedure_Attribute            : constant Name_Id := N + 415;
+
+   --  Remaining attributes are ones that return entities
+
+   First_Entity_Attribute_Name         : constant Name_Id := N + 416;
+   Name_Elab_Body                      : constant Name_Id := N + 416; -- GNAT
+   Name_Elab_Spec                      : constant Name_Id := N + 417; -- GNAT
+   Name_Storage_Pool                   : constant Name_Id := N + 418;
+
+   --  These attributes are the ones that return types
+
+   First_Type_Attribute_Name           : constant Name_Id := N + 419;
+   Name_Base                           : constant Name_Id := N + 419;
+   Name_Class                          : constant Name_Id := N + 420;
+   Last_Type_Attribute_Name            : constant Name_Id := N + 420;
+   Last_Entity_Attribute_Name          : constant Name_Id := N + 420;
+   Last_Attribute_Name                 : constant Name_Id := N + 420;
+
+   --  Names of recognized locking policy identifiers
+
+   --  Note: policies are identified by the first character of the
+   --  name (e.g. C for Ceiling_Locking). If new policy names are added,
+   --  the first character must be distinct.
+
+   First_Locking_Policy_Name           : constant Name_Id := N + 421;
+   Name_Ceiling_Locking                : constant Name_Id := N + 421;
+   Name_Inheritance_Locking            : constant Name_Id := N + 422;
+   Last_Locking_Policy_Name            : constant Name_Id := N + 422;
+
+   --  Names of recognized queuing policy identifiers.
+
+   --  Note: policies are identified by the first character of the
+   --  name (e.g. F for FIFO_Queuing). If new policy names are added,
+   --  the first character must be distinct.
+
+   First_Queuing_Policy_Name           : constant Name_Id := N + 423;
+   Name_FIFO_Queuing                   : constant Name_Id := N + 423;
+   Name_Priority_Queuing               : constant Name_Id := N + 424;
+   Last_Queuing_Policy_Name            : constant Name_Id := N + 424;
+
+   --  Names of recognized task dispatching policy identifiers
+
+   --  Note: policies are identified by the first character of the
+   --  name (e.g. F for FIFO_WIthinn_Priorities). If new policy names
+   --  are added, the first character must be distinct.
+
+   First_Task_Dispatching_Policy_Name  : constant Name_Id := N + 425;
+   Name_Fifo_Within_Priorities         : constant Name_Id := N + 425;
+   Last_Task_Dispatching_Policy_Name   : constant Name_Id := N + 425;
+
+   --  Names of recognized checks for pragma Suppress
+
+   First_Check_Name                    : constant Name_Id := N + 426;
+   Name_Access_Check                   : constant Name_Id := N + 426;
+   Name_Accessibility_Check            : constant Name_Id := N + 427;
+   Name_Discriminant_Check             : constant Name_Id := N + 428;
+   Name_Division_Check                 : constant Name_Id := N + 429;
+   Name_Elaboration_Check              : constant Name_Id := N + 430;
+   Name_Index_Check                    : constant Name_Id := N + 431;
+   Name_Length_Check                   : constant Name_Id := N + 432;
+   Name_Overflow_Check                 : constant Name_Id := N + 433;
+   Name_Range_Check                    : constant Name_Id := N + 434;
+   Name_Storage_Check                  : constant Name_Id := N + 435;
+   Name_Tag_Check                      : constant Name_Id := N + 436;
+   Name_All_Checks                     : constant Name_Id := N + 437;
+   Last_Check_Name                     : constant Name_Id := N + 437;
+
+   --  Names corresponding to reserved keywords, excluding those already
+   --  declared in the attribute list (Access, Delta, Digits, Range).
+
+   Name_Abort                          : constant Name_Id := N + 438;
+   Name_Abs                            : constant Name_Id := N + 439;
+   Name_Accept                         : constant Name_Id := N + 440;
+   Name_And                            : constant Name_Id := N + 441;
+   Name_All                            : constant Name_Id := N + 442;
+   Name_Array                          : constant Name_Id := N + 443;
+   Name_At                             : constant Name_Id := N + 444;
+   Name_Begin                          : constant Name_Id := N + 445;
+   Name_Body                           : constant Name_Id := N + 446;
+   Name_Case                           : constant Name_Id := N + 447;
+   Name_Constant                       : constant Name_Id := N + 448;
+   Name_Declare                        : constant Name_Id := N + 449;
+   Name_Delay                          : constant Name_Id := N + 450;
+   Name_Do                             : constant Name_Id := N + 451;
+   Name_Else                           : constant Name_Id := N + 452;
+   Name_Elsif                          : constant Name_Id := N + 453;
+   Name_End                            : constant Name_Id := N + 454;
+   Name_Entry                          : constant Name_Id := N + 455;
+   Name_Exception                      : constant Name_Id := N + 456;
+   Name_Exit                           : constant Name_Id := N + 457;
+   Name_For                            : constant Name_Id := N + 458;
+   Name_Function                       : constant Name_Id := N + 459;
+   Name_Generic                        : constant Name_Id := N + 460;
+   Name_Goto                           : constant Name_Id := N + 461;
+   Name_If                             : constant Name_Id := N + 462;
+   Name_In                             : constant Name_Id := N + 463;
+   Name_Is                             : constant Name_Id := N + 464;
+   Name_Limited                        : constant Name_Id := N + 465;
+   Name_Loop                           : constant Name_Id := N + 466;
+   Name_Mod                            : constant Name_Id := N + 467;
+   Name_New                            : constant Name_Id := N + 468;
+   Name_Not                            : constant Name_Id := N + 469;
+   Name_Null                           : constant Name_Id := N + 470;
+   Name_Of                             : constant Name_Id := N + 471;
+   Name_Or                             : constant Name_Id := N + 472;
+   Name_Others                         : constant Name_Id := N + 473;
+   Name_Out                            : constant Name_Id := N + 474;
+   Name_Package                        : constant Name_Id := N + 475;
+   Name_Pragma                         : constant Name_Id := N + 476;
+   Name_Private                        : constant Name_Id := N + 477;
+   Name_Procedure                      : constant Name_Id := N + 478;
+   Name_Raise                          : constant Name_Id := N + 479;
+   Name_Record                         : constant Name_Id := N + 480;
+   Name_Rem                            : constant Name_Id := N + 481;
+   Name_Renames                        : constant Name_Id := N + 482;
+   Name_Return                         : constant Name_Id := N + 483;
+   Name_Reverse                        : constant Name_Id := N + 484;
+   Name_Select                         : constant Name_Id := N + 485;
+   Name_Separate                       : constant Name_Id := N + 486;
+   Name_Subtype                        : constant Name_Id := N + 487;
+   Name_Task                           : constant Name_Id := N + 488;
+   Name_Terminate                      : constant Name_Id := N + 489;
+   Name_Then                           : constant Name_Id := N + 490;
+   Name_Type                           : constant Name_Id := N + 491;
+   Name_Use                            : constant Name_Id := N + 492;
+   Name_When                           : constant Name_Id := N + 493;
+   Name_While                          : constant Name_Id := N + 494;
+   Name_With                           : constant Name_Id := N + 495;
+   Name_Xor                            : constant Name_Id := N + 496;
+
+   --  Names of intrinsic subprograms
+
+   --  Note: Asm is missing from this list, since Asm is a legitimate
+   --  convention name.
+
+   First_Intrinsic_Name                : constant Name_Id := N + 497;
+   Name_Divide                         : constant Name_Id := N + 497;
+   Name_Enclosing_Entity               : constant Name_Id := N + 498;
+   Name_Exception_Information          : constant Name_Id := N + 499;
+   Name_Exception_Message              : constant Name_Id := N + 500;
+   Name_Exception_Name                 : constant Name_Id := N + 501;
+   Name_File                           : constant Name_Id := N + 502;
+   Name_Import_Address                 : constant Name_Id := N + 503;
+   Name_Import_Largest_Value           : constant Name_Id := N + 504;
+   Name_Import_Value                   : constant Name_Id := N + 505;
+   Name_Is_Negative                    : constant Name_Id := N + 506;
+   Name_Line                           : constant Name_Id := N + 507;
+   Name_Rotate_Left                    : constant Name_Id := N + 508;
+   Name_Rotate_Right                   : constant Name_Id := N + 509;
+   Name_Shift_Left                     : constant Name_Id := N + 510;
+   Name_Shift_Right                    : constant Name_Id := N + 511;
+   Name_Shift_Right_Arithmetic         : constant Name_Id := N + 512;
+   Name_Source_Location                : constant Name_Id := N + 513;
+   Name_Unchecked_Conversion           : constant Name_Id := N + 514;
+   Name_Unchecked_Deallocation         : constant Name_Id := N + 515;
+   Last_Intrinsic_Name                 : constant Name_Id := N + 515;
+
+   --  Reserved words used only in Ada 95
+
+   First_95_Reserved_Word              : constant Name_Id := N + 516;
+   Name_Abstract                       : constant Name_Id := N + 516;
+   Name_Aliased                        : constant Name_Id := N + 517;
+   Name_Protected                      : constant Name_Id := N + 518;
+   Name_Until                          : constant Name_Id := N + 519;
+   Name_Requeue                        : constant Name_Id := N + 520;
+   Name_Tagged                         : constant Name_Id := N + 521;
+   Last_95_Reserved_Word               : constant Name_Id := N + 521;
+
+   subtype Ada_95_Reserved_Words is
+     Name_Id range First_95_Reserved_Word .. Last_95_Reserved_Word;
+
+   --  Miscellaneous names used in semantic checking
+
+   Name_Raise_Exception                : constant Name_Id := N + 522;
+
+   --  Reserved words of GNAT Project Files
+
+   Name_Project                        : constant Name_Id := N + 523;
+   Name_Modifying                      : constant Name_Id := N + 524;
+   --  Name_External is already declared as N + 243
+
+   --  Names used in GNAT Project Files
+
+   Name_Naming                         : constant Name_Id := N + 525;
+   Name_Object_Dir                     : constant Name_Id := N + 526;
+   Name_Source_Dirs                    : constant Name_Id := N + 527;
+   Name_Specification                  : constant Name_Id := N + 528;
+   Name_Body_Part                      : constant Name_Id := N + 529;
+   Name_Specification_Append           : constant Name_Id := N + 530;
+   Name_Body_Append                    : constant Name_Id := N + 531;
+   Name_Separate_Append                : constant Name_Id := N + 532;
+   Name_Source_Files                   : constant Name_Id := N + 533;
+   Name_Source_List_File               : constant Name_Id := N + 534;
+   Name_Switches                       : constant Name_Id := N + 535;
+   Name_Library_Dir                    : constant Name_Id := N + 536;
+   Name_Library_Name                   : constant Name_Id := N + 537;
+   Name_Library_Kind                   : constant Name_Id := N + 538;
+   Name_Library_Version                : constant Name_Id := N + 539;
+   Name_Library_Elaboration            : constant Name_Id := N + 540;
+
+   Name_Gnatmake                       : constant Name_Id := N + 541;
+   Name_Gnatls                         : constant Name_Id := N + 542;
+   Name_Gnatxref                       : constant Name_Id := N + 543;
+   Name_Gnatfind                       : constant Name_Id := N + 544;
+   Name_Gnatbind                       : constant Name_Id := N + 545;
+   Name_Gnatlink                       : constant Name_Id := N + 546;
+   Name_Compiler                       : constant Name_Id := N + 547;
+   Name_Binder                         : constant Name_Id := N + 548;
+   Name_Linker                         : constant Name_Id := N + 549;
+
+   --  Mark last defined name for consistency check in Snames body
+
+   Last_Predefined_Name                : constant Name_Id := N + 549;
+
+   subtype Any_Operator_Name is Name_Id range
+     First_Operator_Name .. Last_Operator_Name;
+
+   ------------------------------
+   -- Attribute ID Definitions --
+   ------------------------------
+
+   type Attribute_Id is (
+      Attribute_Abort_Signal,
+      Attribute_Access,
+      Attribute_Address,
+      Attribute_Address_Size,
+      Attribute_Aft,
+      Attribute_Alignment,
+      Attribute_Asm_Input,
+      Attribute_Asm_Output,
+      Attribute_AST_Entry,
+      Attribute_Bit,
+      Attribute_Bit_Order,
+      Attribute_Bit_Position,
+      Attribute_Body_Version,
+      Attribute_Callable,
+      Attribute_Caller,
+      Attribute_Code_Address,
+      Attribute_Component_Size,
+      Attribute_Compose,
+      Attribute_Constrained,
+      Attribute_Count,
+      Attribute_Default_Bit_Order,
+      Attribute_Definite,
+      Attribute_Delta,
+      Attribute_Denorm,
+      Attribute_Digits,
+      Attribute_Elaborated,
+      Attribute_Emax,
+      Attribute_Enum_Rep,
+      Attribute_Epsilon,
+      Attribute_Exponent,
+      Attribute_External_Tag,
+      Attribute_First,
+      Attribute_First_Bit,
+      Attribute_Fixed_Value,
+      Attribute_Fore,
+      Attribute_Has_Discriminants,
+      Attribute_Identity,
+      Attribute_Img,
+      Attribute_Integer_Value,
+      Attribute_Large,
+      Attribute_Last,
+      Attribute_Last_Bit,
+      Attribute_Leading_Part,
+      Attribute_Length,
+      Attribute_Machine_Emax,
+      Attribute_Machine_Emin,
+      Attribute_Machine_Mantissa,
+      Attribute_Machine_Overflows,
+      Attribute_Machine_Radix,
+      Attribute_Machine_Rounds,
+      Attribute_Machine_Size,
+      Attribute_Mantissa,
+      Attribute_Max_Interrupt_Priority,
+      Attribute_Max_Priority,
+      Attribute_Max_Size_In_Storage_Elements,
+      Attribute_Maximum_Alignment,
+      Attribute_Mechanism_Code,
+      Attribute_Model_Emin,
+      Attribute_Model_Epsilon,
+      Attribute_Model_Mantissa,
+      Attribute_Model_Small,
+      Attribute_Modulus,
+      Attribute_Null_Parameter,
+      Attribute_Object_Size,
+      Attribute_Partition_ID,
+      Attribute_Passed_By_Reference,
+      Attribute_Pos,
+      Attribute_Position,
+      Attribute_Range,
+      Attribute_Range_Length,
+      Attribute_Round,
+      Attribute_Safe_Emax,
+      Attribute_Safe_First,
+      Attribute_Safe_Large,
+      Attribute_Safe_Last,
+      Attribute_Safe_Small,
+      Attribute_Scale,
+      Attribute_Scaling,
+      Attribute_Signed_Zeros,
+      Attribute_Size,
+      Attribute_Small,
+      Attribute_Storage_Size,
+      Attribute_Storage_Unit,
+      Attribute_Tag,
+      Attribute_Terminated,
+      Attribute_Tick,
+      Attribute_To_Address,
+      Attribute_Type_Class,
+      Attribute_UET_Address,
+      Attribute_Unbiased_Rounding,
+      Attribute_Unchecked_Access,
+      Attribute_Universal_Literal_String,
+      Attribute_Unrestricted_Access,
+      Attribute_VADS_Size,
+      Attribute_Val,
+      Attribute_Valid,
+      Attribute_Value_Size,
+      Attribute_Version,
+      Attribute_Wchar_T_Size,
+      Attribute_Wide_Width,
+      Attribute_Width,
+      Attribute_Word_Size,
+
+      --  Attributes designating renamable functions
+
+      Attribute_Adjacent,
+      Attribute_Ceiling,
+      Attribute_Copy_Sign,
+      Attribute_Floor,
+      Attribute_Fraction,
+      Attribute_Image,
+      Attribute_Input,
+      Attribute_Machine,
+      Attribute_Max,
+      Attribute_Min,
+      Attribute_Model,
+      Attribute_Pred,
+      Attribute_Remainder,
+      Attribute_Rounding,
+      Attribute_Succ,
+      Attribute_Truncation,
+      Attribute_Value,
+      Attribute_Wide_Image,
+      Attribute_Wide_Value,
+
+      --  Attributes designating procedures
+
+      Attribute_Output,
+      Attribute_Read,
+      Attribute_Write,
+
+      --  Entity attributes (includes type attributes)
+
+      Attribute_Elab_Body,
+      Attribute_Elab_Spec,
+      Attribute_Storage_Pool,
+
+      --  Type attributes
+
+      Attribute_Base,
+      Attribute_Class);
+
+   -------------------------------
+   -- Check Name ID Definitions --
+   -------------------------------
+
+   type Check_Id is (
+      Access_Check,
+      Accessibility_Check,
+      Discriminant_Check,
+      Division_Check,
+      Elaboration_Check,
+      Index_Check,
+      Length_Check,
+      Overflow_Check,
+      Range_Check,
+      Storage_Check,
+      Tag_Check,
+      All_Checks);
+
+   ------------------------------------
+   -- Convention Name ID Definitions --
+   ------------------------------------
+
+   type Convention_Id is (
+
+      --  The conventions that are defined by the RM come first
+
+      Convention_Ada,
+      Convention_Intrinsic,
+      Convention_Entry,
+      Convention_Protected,
+
+      --  The remaining conventions are foreign language conventions
+
+      Convention_Assembler,
+      Convention_C,
+      Convention_COBOL,
+      Convention_CPP,
+      Convention_Fortran,
+      Convention_Java,
+      Convention_Stdcall,
+      Convention_Stubbed);
+
+      --  Note: Conventions C_Pass_By_Copy, External, and Default are all
+      --  treated as synonyms for convention C (with an appropriate flag
+      --  being set in a record type in the case of C_Pass_By_Copy). See
+      --  processing in Sem_Prag for details.
+
+      --  Note: convention Win32 has the same effect as convention Stdcall
+      --  and as a special exception to normal rules is considered to be
+      --  conformant with convention Stdcall. Therefore if the convention
+      --  Win32 is encountered, it is translated into Convention_Stdcall.
+
+   for Convention_Id'Size use 8;
+   --  Plenty of space for expansion
+
+   subtype Foreign_Convention is
+     Convention_Id range Convention_Assembler .. Convention_Stdcall;
+
+   -----------------------------------
+   -- Locking Policy ID Definitions --
+   -----------------------------------
+
+   type Locking_Policy_Id is (
+      Locking_Policy_Inheritance_Locking,
+      Locking_Policy_Ceiling_Locking);
+
+   ---------------------------
+   -- Pragma ID Definitions --
+   ---------------------------
+
+   type Pragma_Id is (
+
+      --  Configuration pragmas
+
+      Pragma_Ada_83,
+      Pragma_Ada_95,
+      Pragma_C_Pass_By_Copy,
+      Pragma_Component_Alignment,
+      Pragma_Discard_Names,
+      Pragma_Elaboration_Checks,
+      Pragma_Eliminate,
+      Pragma_Extend_System,
+      Pragma_Extensions_Allowed,
+      Pragma_External_Name_Casing,
+      Pragma_Float_Representation,
+      Pragma_Initialize_Scalars,
+      Pragma_License,
+      Pragma_Locking_Policy,
+      Pragma_Long_Float,
+      Pragma_No_Run_Time,
+      Pragma_Normalize_Scalars,
+      Pragma_Polling,
+      Pragma_Propagate_Exceptions,
+      Pragma_Queuing_Policy,
+      Pragma_Ravenscar,
+      Pragma_Restricted_Run_Time,
+      Pragma_Restrictions,
+      Pragma_Reviewable,
+      Pragma_Source_File_Name,
+      Pragma_Style_Checks,
+      Pragma_Suppress,
+      Pragma_Task_Dispatching_Policy,
+      Pragma_Unsuppress,
+      Pragma_Use_VADS_Size,
+      Pragma_Warnings,
+      Pragma_Validity_Checks,
+
+      --  Remaining (non-configuration) pragmas
+
+      Pragma_Abort_Defer,
+      Pragma_All_Calls_Remote,
+      Pragma_Annotate,
+      Pragma_Assert,
+      Pragma_Asynchronous,
+      Pragma_Atomic,
+      Pragma_Atomic_Components,
+      Pragma_Attach_Handler,
+      Pragma_Comment,
+      Pragma_Common_Object,
+      Pragma_Complex_Representation,
+      Pragma_Controlled,
+      Pragma_Convention,
+      Pragma_CPP_Class,
+      Pragma_CPP_Constructor,
+      Pragma_CPP_Virtual,
+      Pragma_CPP_Vtable,
+      Pragma_Debug,
+      Pragma_Elaborate,
+      Pragma_Elaborate_All,
+      Pragma_Elaborate_Body,
+      Pragma_Export,
+      Pragma_Export_Exception,
+      Pragma_Export_Function,
+      Pragma_Export_Object,
+      Pragma_Export_Procedure,
+      Pragma_Export_Valued_Procedure,
+      Pragma_Finalize_Storage_Only,
+      Pragma_Ident,
+      Pragma_Import,
+      Pragma_Import_Exception,
+      Pragma_Import_Function,
+      Pragma_Import_Object,
+      Pragma_Import_Procedure,
+      Pragma_Import_Valued_Procedure,
+      Pragma_Inline,
+      Pragma_Inline_Always,
+      Pragma_Inline_Generic,
+      Pragma_Inspection_Point,
+      Pragma_Interface,
+      Pragma_Interface_Name,
+      Pragma_Interrupt_Handler,
+      Pragma_Interrupt_Priority,
+      Pragma_Java_Constructor,
+      Pragma_Java_Interface,
+      Pragma_Link_With,
+      Pragma_Linker_Alias,
+      Pragma_Linker_Options,
+      Pragma_Linker_Section,
+      Pragma_List,
+      Pragma_Machine_Attribute,
+      Pragma_Main,
+      Pragma_Main_Storage,
+      Pragma_Memory_Size,
+      Pragma_No_Return,
+      Pragma_Optimize,
+      Pragma_Pack,
+      Pragma_Page,
+      Pragma_Passive,
+      Pragma_Preelaborate,
+      Pragma_Priority,
+      Pragma_Psect_Object,
+      Pragma_Pure,
+      Pragma_Pure_Function,
+      Pragma_Remote_Call_Interface,
+      Pragma_Remote_Types,
+      Pragma_Share_Generic,
+      Pragma_Shared,
+      Pragma_Shared_Passive,
+      Pragma_Source_Reference,
+      Pragma_Stream_Convert,
+      Pragma_Subtitle,
+      Pragma_Suppress_All,
+      Pragma_Suppress_Debug_Info,
+      Pragma_Suppress_Initialization,
+      Pragma_System_Name,
+      Pragma_Task_Info,
+      Pragma_Task_Name,
+      Pragma_Task_Storage,
+      Pragma_Time_Slice,
+      Pragma_Title,
+      Pragma_Unchecked_Union,
+      Pragma_Unimplemented_Unit,
+      Pragma_Unreserve_All_Interrupts,
+      Pragma_Volatile,
+      Pragma_Volatile_Components,
+      Pragma_Weak_External,
+
+      --  The following pragmas are on their own, out of order, because of
+      --  the special processing required to deal with the fact that their
+      --  names match existing attribute names.
+
+      Pragma_AST_Entry,
+      Pragma_Storage_Size,
+      Pragma_Storage_Unit);
+
+   -----------------------------------
+   -- Queuing Policy ID definitions --
+   -----------------------------------
+
+   type Queuing_Policy_Id is (
+      Queuing_Policy_FIFO_Queuing,
+      Queuing_Policy_Priority_Queuing);
+
+   --------------------------------------------
+   -- Task Dispatching Policy ID definitions --
+   --------------------------------------------
+
+   type Task_Dispatching_Policy_Id is (
+      Task_Dispatching_FIFO_Within_Priorities);
+   --  Id values used to identify task dispatching policies
+
+   -----------------
+   -- Subprograms --
+   -----------------
+
+   procedure Initialize;
+   --  Called to initialize the preset names in the names table.
+
+   function Is_Attribute_Name (N : Name_Id) return Boolean;
+   --  Test to see if the name N is the name of a recognized attribute
+
+   function Is_Entity_Attribute_Name (N : Name_Id) return Boolean;
+   --  Test to see if the name N is the name of a recognized entity attribute,
+   --  i.e. an attribute reference that returns an entity.
+
+   function Is_Procedure_Attribute_Name (N : Name_Id) return Boolean;
+   --  Test to see if the name N is the name of a recognized attribute that
+   --  designates a procedure (and can therefore appear as a statement).
+
+   function Is_Function_Attribute_Name (N : Name_Id) return Boolean;
+   --  Test to see if the name N is the name of a recognized attribute
+   --  that designates a renameable function, and can therefore appear in
+   --  a renaming statement. Note that not all attributes designating
+   --  functions are renamable, in particular, thos returning a universal
+   --  value cannot be renamed.
+
+   function Is_Type_Attribute_Name (N : Name_Id) return Boolean;
+   --  Test to see if the name N is the name of a recognized type attribute,
+   --  i.e. an attribute reference that returns a type
+
+   function Is_Check_Name (N : Name_Id) return Boolean;
+   --  Test to see if the name N is the name of a recognized suppress check
+   --  as required by pragma Suppress.
+
+   function Is_Convention_Name (N : Name_Id) return Boolean;
+   --  Test to see if the name N is the name of one of the recognized language
+   --  conventions, as required by pragma Convention, Import, Export, Interface
+
+   function Is_Locking_Policy_Name (N : Name_Id) return Boolean;
+   --  Test to see if the name N is the name of a recognized locking policy
+
+   function Is_Operator_Symbol_Name (N : Name_Id) return Boolean;
+   --  Test to see if the name N is the name of an operator symbol
+
+   function Is_Pragma_Name (N : Name_Id) return Boolean;
+   --  Test to see if the name N is the name of a recognized pragma. Note
+   --  that pragmas AST_Entry, Storage_Size, and Storage_Unit are recognized
+   --  as pragmas by this function even though their names are separate from
+   --  the other pragma names.
+
+   function Is_Queuing_Policy_Name (N : Name_Id) return Boolean;
+   --  Test to see if the name N is the name of a recognized queuing policy
+
+   function Is_Task_Dispatching_Policy_Name (N : Name_Id) return Boolean;
+   --  Test to see if the name N is the name of a recognized
+   --  task dispatching policy
+
+   function Get_Attribute_Id (N : Name_Id) return Attribute_Id;
+   --  Returns Id of attribute corresponding to given name. It is an error to
+   --  call this function with a name that is not the name of a attribute.
+
+   function Get_Convention_Id (N : Name_Id) return Convention_Id;
+   --  Returns Id of language convention corresponding to given name. It is an
+   --  to call this function with a name that is not the name of a check.
+
+   function Get_Check_Id (N : Name_Id) return Check_Id;
+   --  Returns Id of suppress check corresponding to given name. It is an error
+   --  to call this function with a name that is not the name of a check.
+
+   function Get_Locking_Policy_Id (N : Name_Id) return Locking_Policy_Id;
+   --  Returns Id of locking policy corresponding to given name. It is an error
+   --  to call this function with a name that is not the name of a check.
+
+   function Get_Pragma_Id (N : Name_Id) return Pragma_Id;
+   --  Returns Id of pragma corresponding to given name. It is an error to
+   --  call this function with a name that is not the name of a pragma. Note
+   --  that the function also works correctly for names of pragmas that are
+   --  not in the main list of pragma Names (AST_Entry, Storage_Size, and
+   --  Storage_Unit (e.g. Name_Storage_Size returns Pragma_Storage_Size).
+
+   function Get_Queuing_Policy_Id (N : Name_Id) return Queuing_Policy_Id;
+   --  Returns Id of queuing policy corresponding to given name. It is an error
+   --  to call this function with a name that is not the name of a check.
+
+   function Get_Task_Dispatching_Policy_Id
+     (N    : Name_Id)
+      return Task_Dispatching_Policy_Id;
+   --  Returns Id of task dispatching policy corresponding to given name. It
+   --  is an error to call this function with a name that is not the name
+   --  of a check.
+
+private
+   pragma Inline (Is_Attribute_Name);
+   pragma Inline (Is_Entity_Attribute_Name);
+   pragma Inline (Is_Type_Attribute_Name);
+   pragma Inline (Is_Check_Name);
+   pragma Inline (Is_Convention_Name);
+   pragma Inline (Is_Locking_Policy_Name);
+   pragma Inline (Is_Operator_Symbol_Name);
+   pragma Inline (Is_Queuing_Policy_Name);
+   pragma Inline (Is_Pragma_Name);
+   pragma Inline (Is_Task_Dispatching_Policy_Name);
+
+end Snames;
diff --git a/gcc/ada/snames.h b/gcc/ada/snames.h
new file mode 100644 (file)
index 0000000..e0c9b50
--- /dev/null
@@ -0,0 +1,345 @@
+/****************************************************************************
+ *                                                                          *
+ *                         GNAT COMPILER COMPONENTS                         *
+ *                                                                          *
+ *                               S N A M E S                                *
+ *                                                                          *
+ *                              C Header File                               *
+ *                                                                          *
+ *                            $Revision: 1.2 $
+ *                                                                          *
+ *          Copyright (C) 1992-2001 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- *
+ * ware  Foundation;  either version 2,  or (at your option) any later ver- *
+ * sion.  GNAT is distributed in the hope that it will be useful, but WITH- *
+ * OUT ANY WARRANTY;  without even the  implied warranty of MERCHANTABILITY *
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License *
+ * for  more details.  You should have  received  a copy of the GNU General *
+ * Public License  distributed with GNAT;  see file COPYING.  If not, write *
+ * to  the Free Software Foundation,  59 Temple Place - Suite 330,  Boston, *
+ * MA 02111-1307, USA.                                                      *
+ *                                                                          *
+ * GNAT was originally developed  by the GNAT team at  New York University. *
+ * It is now maintained by Ada Core Technologies Inc (http://www.gnat.com). *
+ *                                                                          *
+ ****************************************************************************/
+
+/* This is the C file that corresponds to the Ada package specification
+   Snames. It was created manually from the file snames.ads. */
+
+/* Name_Id values */
+
+#define Name_uParent    (First_Name_Id + 256 + 0)
+#define Name_uTag       (First_Name_Id + 256 + 1)
+#define Name_Off        (First_Name_Id + 256 + 2)
+#define Name_Space             (First_Name_Id + 256 + 3)
+#define Name_Time       (First_Name_Id + 256 + 4)
+#define Name_uInit_Proc (First_Name_Id + 256 + 5)
+#define Name_uSize      (First_Name_Id + 256 + 6)
+
+/* Define the function to return one of the numeric values below. Note
+   that it actually returns a char since an enumeration value of less
+   than 256 entries is represented that way in Ada.  The operand is a Chars
+   field value.  */
+
+#define Get_Attribute_Id snames__get_attribute_id
+extern char Get_Attribute_Id PARAMS ((int));
+
+/* Define the numeric values for the attributes.  */
+
+#define  Attr_Abort_Signal                   0
+#define  Attr_Access                         1
+#define  Attr_Address                        2
+#define  Attr_Address_Size                   3
+#define  Attr_Aft                            4
+#define  Attr_Alignment                      5
+#define  Attr_Asm_Input                      6
+#define  Attr_Asm_Output                     7
+#define  Attr_AST_Entry                      8
+#define  Attr_Bit                            9
+#define  Attr_Bit_Order                     10
+#define  Attr_Bit_Position                  11
+#define  Attr_Body_Version                  12
+#define  Attr_Callable                      13
+#define  Attr_Caller                        14
+#define  Attr_Code_Address                  15
+#define  Attr_Component_Size                16
+#define  Attr_Compose                       17
+#define  Attr_Constrained                   18
+#define  Attr_Count                         19
+#define  Attr_Default_Bit_Order             20
+#define  Attr_Definite                      21
+#define  Attr_Delta                         22
+#define  Attr_Denorm                        23
+#define  Attr_Digits                        24
+#define  Attr_Elaborated                    25
+#define  Attr_Emax                          26
+#define  Attr_Enum_Rep                      27
+#define  Attr_Epsilon                       28
+#define  Attr_Exponent                      29
+#define  Attr_External_Tag                  30
+#define  Attr_First                         31
+#define  Attr_First_Bit                     32
+#define  Attr_Fixed_Value                   33
+#define  Attr_Fore                          34
+#define  Attr_Has_Discriminants             35
+#define  Attr_Identity                      36
+#define  Attr_Img                           37
+#define  Attr_Integer_Value                 38
+#define  Attr_Large                         39
+#define  Attr_Last                          40
+#define  Attr_Last_Bit                      41
+#define  Attr_Leading_Part                  42
+#define  Attr_Length                        43
+#define  Attr_Machine_Emax                  44
+#define  Attr_Machine_Emin                  45
+#define  Attr_Machine_Mantissa              46
+#define  Attr_Machine_Overflows             47
+#define  Attr_Machine_Radix                 48
+#define  Attr_Machine_Rounds                49
+#define  Attr_Machine_Size                  50
+#define  Attr_Mantissa                      51
+#define  Attr_Max_Interrupt_Priority        52
+#define  Attr_Max_Priority                  53
+#define  Attr_Max_Size_In_Storage_Elements  54
+#define  Attr_Maximum_Alignment             55
+#define  Attr_Mechanism_Code                56
+#define  Attr_Model_Emin                    57
+#define  Attr_Model_Epsilon                 58
+#define  Attr_Model_Mantissa                59
+#define  Attr_Model_Small                   60
+#define  Attr_Modulus                       61
+#define  Attr_Null_Parameter                62
+#define  Attr_Object_Size                   63
+#define  Attr_Partition_ID                  64
+#define  Attr_Passed_By_Reference           65
+#define  Attr_Pos                           66
+#define  Attr_Position                      67
+#define  Attr_Range                         68
+#define  Attr_Range_Length                  69
+#define  Attr_Round                         70
+#define  Attr_Safe_Emax                     71
+#define  Attr_Safe_First                    72
+#define  Attr_Safe_Large                    73
+#define  Attr_Safe_Last                     74
+#define  Attr_Safe_Small                    75
+#define  Attr_Scale                         76
+#define  Attr_Scaling                       77
+#define  Attr_Signed_Zeros                  78
+#define  Attr_Size                          79
+#define  Attr_Small                         80
+#define  Attr_Storage_Size                  81
+#define  Attr_Storage_Unit                  82
+#define  Attr_Tag                           83
+#define  Attr_Terminated                    84
+#define  Attr_Tick                          85
+#define  Attr_To_Address                    86
+#define  Attr_Type_Class                    87
+#define  Attr_UET_Address                   88
+#define  Attr_Unbiased_Rounding             89
+#define  Attr_Unchecked_Access              90
+#define  Attr_Universal_Literal_String      91
+#define  Attr_Unrestricted_Access           92
+#define  Attr_VADS_Size                     93
+#define  Attr_Val                           94
+#define  Attr_Valid                         95
+#define  Attr_Value_Size                    96
+#define  Attr_Version                       97
+#define  Attr_Wide_Character_Size           98
+#define  Attr_Wide_Width                    99
+#define  Attr_Width                        100
+#define  Attr_Word_Size                    101
+
+#define  Attr_Adjacent                     102
+#define  Attr_Ceiling                      103
+#define  Attr_Copy_Sign                    104
+#define  Attr_Floor                        105
+#define  Attr_Fraction                     106
+#define  Attr_Image                        107
+#define  Attr_Input                        108
+#define  Attr_Machine                      109
+#define  Attr_Max                          110
+#define  Attr_Min                          111
+#define  Attr_Model                        112
+#define  Attr_Pred                         113
+#define  Attr_Remainder                    114
+#define  Attr_Rounding                     115
+#define  Attr_Succ                         116
+#define  Attr_Truncation                   117
+#define  Attr_Value                        118
+#define  Attr_Wide_Image                   119
+#define  Attr_Wide_Value                   120
+
+#define  Attr_Output                       121
+#define  Attr_Read                         122
+#define  Attr_Write                        123
+
+#define  Attr_Elab_Body                    124
+#define  Attr_Elab_Spec                    125
+#define  Attr_Storage_Pool                 126
+
+#define  Attr_Base                         127
+#define  Attr_Class                        128
+
+/* Define the function to check if a Name_Id value is a valid pragma */
+
+#define Is_Pragma_Name snames__is_pragma_name
+extern Boolean Is_Pragma_Name PARAMS ((Name_Id));
+
+/* Define the function to return one of the numeric values below.  Note
+   that it actually returns a char since an enumeration value of less
+   than 256 entries is represented that way in Ada.  The operand is a Chars
+   field value.  */
+
+#define Get_Pragma_Id snames__get_pragma_id
+extern char Get_Pragma_Id PARAMS ((int));
+
+/* Define the numeric values for the pragmas. */
+
+/* Configuration pragmas first */
+
+#define  Pragma_Ada_83                       0
+#define  Pragma_Ada_95                       1
+#define  Pragma_C_Pass_By_Copy               2
+#define  Pragma_Component_Alignment          3
+#define  Pragma_Discard_Names                4
+#define  Pragma_Elaboration_Checking         5
+#define  Pragma_Eliminate                    6
+#define  Pragma_Extend_System                7
+#define  Pragma_Extensions_Allowed           8
+#define  Pragma_External_Name_Casing         9
+#define  Pragma_Float_Representation        10
+#define  Pragma_Initialize                  11
+#define  Pragma_License                     12
+#define  Pragma_Locking_Policy              13
+#define  Pragma_Long_Float                  14
+#define  Pragma_No_Run_Time                 15
+#define  Pragma_Normalize_Scalars           16
+#define  Pragma_Polling                     17
+#define  Pragma_Propagate_Exceptions        18
+#define  Pragma_Queuing_Policy              19
+#define  Pragma_Ravenscar                   20
+#define  Pragma_Restricted_Run_Time         21
+#define  Pragma_Restrictions                22
+#define  Pragma_Reviewable                  23
+#define  Pragma_Source_File_Name            24
+#define  Pragma_Style_Checks                25
+#define  Pragma_Suppress                    26
+#define  Pragma_Task_Dispatching_Policy     27
+#define  Pragma_Unsuppress                  28
+#define  Pragma_Use_VADS_Size               29
+#define  Pragma_Validity_Checks             30
+#define  Pragma_Warnings                    31
+
+/* Remaining pragmas */
+
+#define  Pragma_Abort_Defer                 32
+#define  Pragma_All_Calls_Remote            33
+#define  Pragma_Annotate                    34
+#define  Pragma_Assert                      35
+#define  Pragma_Asynchronous                36
+#define  Pragma_Atomic                      37
+#define  Pragma_Atomic_Components           38
+#define  Pragma_Attach_Handler              39
+#define  Pragma_Comment                     40
+#define  Pragma_Common_Object               41
+#define  Pragma_Complex_Representation      42
+#define  Pragma_Controlled                  43
+#define  Pragma_Convention                  44
+#define  Pragma_CPP_Class                   45
+#define  Pragma_CPP_Constructor             46
+#define  Pragma_CPP_Virtual                 47
+#define  Pragma_CPP_Vtable                  48
+#define  Pragma_Debug                       49
+#define  Pragma_Elaborate                   50
+#define  Pragma_Elaborate_All               51
+#define  Pragma_Elaborate_Body              52
+#define  Pragma_Export                      53
+#define  Pragma_Export_Exception            54
+#define  Pragma_Export_Function             55
+#define  Pragma_Export_Object               56
+#define  Pragma_Export_Procedure            57
+#define  Pragma_Export_Valued_Procedure     58
+#define  Pragma_Finalize_Storage_Only       59
+#define  Pragma_Ident                       60
+#define  Pragma_Import                      61
+#define  Pragma_Import_Exception            62
+#define  Pragma_Import_Function             63
+#define  Pragma_Import_Object               64
+#define  Pragma_Import_Procedure            65
+#define  Pragma_Import_Valued_Procedure     66
+#define  Pragma_Inline                      67
+#define  Pragma_Inline_Always               68
+#define  Pragma_Inline_Generic              69
+#define  Pragma_Inspection_Point            70
+#define  Pragma_Interface                   71
+#define  Pragma_Interface_Name              72
+#define  Pragma_Interrupt_Handler           73
+#define  Pragma_Interrupt_Priority          74
+#define  Pragma_Java_Constructor            75
+#define  Pragma_Java_Interface              76
+#define  Pragma_Link_With                   77
+#define  Pragma_Linker_Alias                78
+#define  Pragma_Linker_Options              79
+#define  Pragma_Linker_Section              80
+#define  Pragma_List                        81
+#define  Pragma_Machine_Attribute           82
+#define  Pragma_Main                        83
+#define  Pragma_Main_Storage                84
+#define  Pragma_Memory_Size                 85
+#define  Pragma_No_Return                   86
+#define  Pragma_Optimize                    87
+#define  Pragma_Pack                        88
+#define  Pragma_Page                        89
+#define  Pragma_Passive                     90
+#define  Pragma_Preelaborate                91
+#define  Pragma_Priority                    92
+#define  Pragma_Psect_Object                93
+#define  Pragma_Pure                        94
+#define  Pragma_Pure_Function               95
+#define  Pragma_Remote_Call_Interface       96
+#define  Pragma_Remote_Types                97
+#define  Pragma_Share_Generic               98
+#define  Pragma_Shared                      99
+#define  Pragma_Shared_Passive             100
+#define  Pragma_Source_Reference           101
+#define  Pragma_Stream_Convert             102
+#define  Pragma_Subtitle                   103
+#define  Pragma_Suppress_All               104
+#define  Pragma_Suppress_Debug_Info        105
+#define  Pragma_Suppress_Initialization    106
+#define  Pragma_System_Name                107
+#define  Pragma_Task_Info                  108
+#define  Pragma_Task_Name                  109
+#define  Pragma_Task_Storage               110
+#define  Pragma_Time_Slice                 111
+#define  Pragma_Title                      112
+#define  Pragma_Unchecked_Union            113
+#define  Pragma_Unimplemented_Unit         114
+#define  Pragma_Unreserve_All_Interrupts   115
+#define  Pragma_Volatile                   116
+#define  Pragma_Volatile_Components        117
+#define  Pragma_Weak_External              118
+
+/* The following are deliberately out of alphabetical order, see Snames */
+
+#define  Pragma_AST_Entry                  119
+#define  Pragma_Storage_Size               120
+#define  Pragma_Storage_Unit               121
+
+/* Define the numeric values for the conventions.  */
+
+#define  Convention_Ada                      0
+#define  Convention_Intrinsic                1
+#define  Convention_Entry                    2
+#define  Convention_Protected                3
+#define  Convention_Assembler                4
+#define  Convention_C                        5
+#define  Convention_COBOL                    6
+#define  Convention_CPP                      7
+#define  Convention_Fortran                  8
+#define  Convention_Java                     9
+#define  Convention_Stdcall                 10
+#define  Convention_Stubbed                 11
diff --git a/gcc/ada/sprint.adb b/gcc/ada/sprint.adb
new file mode 100644 (file)
index 0000000..8c58ca8
--- /dev/null
@@ -0,0 +1,3071 @@
+------------------------------------------------------------------------------
+--                                                                          --
+--                         GNAT COMPILER COMPONENTS                         --
+--                                                                          --
+--                               S P R I N T                                --
+--                                                                          --
+--                                 B o d y                                  --
+--                                                                          --
+--                            $Revision: 1.205 $
+--                                                                          --
+--          Copyright (C) 1992-2001, 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- --
+-- ware  Foundation;  either version 2,  or (at your option) any later ver- --
+-- sion.  GNAT is distributed in the hope that it will be useful, but WITH- --
+-- OUT ANY WARRANTY;  without even the  implied warranty of MERCHANTABILITY --
+-- or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License --
+-- for  more details.  You should have  received  a copy of the GNU General --
+-- Public License  distributed with GNAT;  see file COPYING.  If not, write --
+-- to  the Free Software Foundation,  59 Temple Place - Suite 330,  Boston, --
+-- MA 02111-1307, USA.                                                      --
+--                                                                          --
+-- GNAT was originally developed  by the GNAT team at  New York University. --
+-- It is now maintained by Ada Core Technologies Inc (http://www.gnat.com). --
+--                                                                          --
+------------------------------------------------------------------------------
+
+with Atree;    use Atree;
+with Casing;   use Casing;
+with Debug;    use Debug;
+with Einfo;    use Einfo;
+with Lib;      use Lib;
+with Namet;    use Namet;
+with Nlists;   use Nlists;
+with Opt;      use Opt;
+with Output;   use Output;
+with Rtsfind;  use Rtsfind;
+with Sinfo;    use Sinfo;
+with Sinput;   use Sinput;
+with Sinput.L; use Sinput.L;
+with Snames;   use Snames;
+with Stand;    use Stand;
+with Stringt;  use Stringt;
+with Uintp;    use Uintp;
+with Uname;    use Uname;
+with Urealp;   use Urealp;
+
+package body Sprint is
+
+   Debug_Node : Node_Id := Empty;
+   --  If we are in Debug_Generated_Code mode, then this location is set
+   --  to the current node requiring Sloc fixup, until Set_Debug_Sloc is
+   --  called to set the proper value. The call clears it back to Empty.
+
+   Debug_Sloc : Source_Ptr;
+   --  Sloc of first byte of line currently being written if we are
+   --  generating a source debug file.
+
+   Dump_Original_Only : Boolean;
+   --  Set True if the -gnatdo (dump original tree) flag is set
+
+   Dump_Generated_Only : Boolean;
+   --  Set True if the -gnatG (dump generated tree) debug flag is set
+   --  or for Print_Generated_Code (-gnatG) or Dump_Gnerated_Code (-gnatD).
+
+   Dump_Freeze_Null : Boolean;
+   --  Set True if freeze nodes and non-source null statements output
+
+   Indent : Int := 0;
+   --  Number of columns for current line output indentation
+
+   Indent_Annull_Flag : Boolean := False;
+   --  Set True if subsequent Write_Indent call to be ignored, gets reset
+   --  by this call, so it is only active to suppress a single indent call.
+
+   Line_Limit : constant := 72;
+   --  Limit value for chopping long lines
+
+   Freeze_Indent : Int := 0;
+   --  Keep track of freeze indent level (controls blank lines before
+   --  procedures within expression freeze actions)
+
+   -----------------------
+   -- Local Subprograms --
+   -----------------------
+
+   procedure Col_Check (N : Nat);
+   --  Check that at least N characters remain on current line, and if not,
+   --  then start an extra line with two characters extra indentation for
+   --  continuing text on the next line.
+
+   procedure Indent_Annull;
+   --  Causes following call to Write_Indent to be ignored. This is used when
+   --  a higher level node wants to stop a lower level node from starting a
+   --  new line, when it would otherwise be inclined to do so (e.g. the case
+   --  of an accept statement called from an accept alternative with a guard)
+
+   procedure Indent_Begin;
+   --  Increase indentation level
+
+   procedure Indent_End;
+   --  Decrease indentation level
+
+   procedure Print_Eol;
+   --  Terminate current line in line buffer
+
+   procedure Process_TFAI_RR_Flags (Nod : Node_Id);
+   --  Given a divide, multiplication or division node, check the flags
+   --  Treat_Fixed_As_Integer and Rounded_Flags, and if set, output the
+   --  appropriate special syntax characters (# and @).
+
+   procedure Set_Debug_Sloc;
+   --  If Debug_Node is non-empty, this routine sets the appropriate value
+   --  in its Sloc field, from the current location in the debug source file
+   --  that is currently being written. Note that Debug_Node is always empty
+   --  if a debug source file is not being written.
+
+   procedure Sprint_Bar_List (List : List_Id);
+   --  Print the given list with items separated by vertical bars
+
+   procedure Sprint_Node_Actual (Node : Node_Id);
+   --  This routine prints its node argument. It is a lower level routine than
+   --  Sprint_Node, in that it does not bother about rewritten trees.
+
+   procedure Sprint_Node_Sloc (Node : Node_Id);
+   --  Like Sprint_Node, but in addition, in Debug_Generated_Code mode,
+   --  sets the Sloc of the current debug node to be a copy of the Sloc
+   --  of the sprinted node Node. Note that this is done after printing
+   --  Node, so that the Sloc is the proper updated value for the debug file.
+
+   procedure Write_Char_Sloc (C : Character);
+   --  Like Write_Char, except that if C is non-blank, Set_Debug_Sloc is
+   --  called to ensure that the current node has a proper Sloc set.
+
+   procedure Write_Discr_Specs (N : Node_Id);
+   --  Ouput discriminant specification for node, which is any of the type
+   --  declarations that can have discriminants.
+
+   procedure Write_Ekind (E : Entity_Id);
+   --  Write the String corresponding to the Ekind without "E_".
+
+   procedure Write_Id (N : Node_Id);
+   --  N is a node with a Chars field. This procedure writes the name that
+   --  will be used in the generated code associated with the name. For a
+   --  node with no associated entity, this is simply the Chars field. For
+   --  the case where there is an entity associated with the node, we print
+   --  the name associated with the entity (since it may have been encoded).
+   --  One other special case is that an entity has an active external name
+   --  (i.e. an external name present with no address clause), then this
+   --  external name is output.
+
+   function Write_Identifiers (Node : Node_Id) return Boolean;
+   --  Handle node where the grammar has a list of defining identifiers, but
+   --  the tree has a separate declaration for each identifier. Handles the
+   --  printing of the defining identifier, and returns True if the type and
+   --  initialization information is to be printed, False if it is to be
+   --  skipped (the latter case happens when printing defining identifiers
+   --  other than the first in the original tree output case).
+
+   procedure Write_Implicit_Def (E : Entity_Id);
+   pragma Warnings (Off, Write_Implicit_Def);
+   --  Write the definition of the implicit type E according to its Ekind
+   --  For now a debugging procedure, but might be used in the future.
+
+   procedure Write_Indent;
+   --  Start a new line and write indentation spacing
+
+   function Write_Indent_Identifiers (Node : Node_Id) return Boolean;
+   --  Like Write_Identifiers except that each new printed declaration
+   --  is at the start of a new line.
+
+   function Write_Indent_Identifiers_Sloc (Node : Node_Id) return Boolean;
+   --  Like Write_Indent_Identifiers except that in Debug_Generated_Code
+   --  mode, the Sloc of the current debug node is set to point ot the
+   --  first output identifier.
+
+   procedure Write_Indent_Str (S : String);
+   --  Start a new line and write indent spacing followed by given string
+
+   procedure Write_Indent_Str_Sloc (S : String);
+   --  Like Write_Indent_Str, but in addition, in Debug_Generated_Code mode,
+   --  the Sloc of the current node is set to the first non-blank character
+   --  in the string S.
+
+   procedure Write_Name_With_Col_Check (N : Name_Id);
+   --  Write name (using Write_Name) with initial column check, and possible
+   --  initial Write_Indent (to get new line) if current line is too full.
+
+   procedure Write_Name_With_Col_Check_Sloc (N : Name_Id);
+   --  Like Write_Name_With_Col_Check but in addition, in Debug_Generated_Code
+   --  mode, sets Sloc of current debug node to first character of name.
+
+   procedure Write_Operator (N : Node_Id; S : String);
+   --  Like Write_Str_Sloc, used for operators, encloses the string in
+   --  characters {} if the Do_Overflow flag is set on the node N.
+
+   procedure Write_Param_Specs (N : Node_Id);
+   --  Output parameter specifications for node (which is either a function
+   --  or procedure specification with a Parameter_Specifications field)
+
+   procedure Write_Rewrite_Str (S : String);
+   --  Writes out a string (typically containing <<< or >>>}) for a node
+   --  created by rewriting the tree. Suppressed if we are outputting the
+   --  generated code only, since in this case we don't specially mark nodes
+   --  created by rewriting).
+
+   procedure Write_Str_Sloc (S : String);
+   --  Like Write_Str, but sets debug Sloc of current debug node to first
+   --  non-blank character if a current debug node is active.
+
+   procedure Write_Str_With_Col_Check (S : String);
+   --  Write string (using Write_Str) with initial column check, and possible
+   --  initial Write_Indent (to get new line) if current line is too full.
+
+   procedure Write_Str_With_Col_Check_Sloc (S : String);
+   --  Like Write_Str_WIth_Col_Check, but sets debug Sloc of current debug
+   --  node to first non-blank character if a current debug node is active.
+
+   procedure Write_Uint_With_Col_Check_Sloc (U : Uint; Format : UI_Format);
+   --  Write Uint (using UI_Write) with initial column check, and possible
+   --  initial Write_Indent (to get new line) if current line is too full.
+   --  The format parameter determines the output format (see UI_Write).
+   --  In addition, in Debug_Generated_Code mode, sets the current node
+   --  Sloc to the first character of the output value.
+
+   procedure Write_Ureal_With_Col_Check_Sloc (U : Ureal);
+   --  Write Ureal (using same output format as UR_Write) with column checks
+   --  and a possible initial Write_Indent (to get new line) if current line
+   --  is too full. In addition, in Debug_Generated_Code mode, sets the
+   --  current node Sloc to the first character of the output value.
+
+   ---------------
+   -- Col_Check --
+   ---------------
+
+   procedure Col_Check (N : Nat) is
+   begin
+      if N + Column > Line_Limit then
+         Write_Indent_Str ("  ");
+      end if;
+   end Col_Check;
+
+   -------------------
+   -- Indent_Annull --
+   -------------------
+
+   procedure Indent_Annull is
+   begin
+      Indent_Annull_Flag := True;
+   end Indent_Annull;
+
+   ------------------
+   -- Indent_Begin --
+   ------------------
+
+   procedure Indent_Begin is
+   begin
+      Indent := Indent + 3;
+   end Indent_Begin;
+
+   ----------------
+   -- Indent_End --
+   ----------------
+
+   procedure Indent_End is
+   begin
+      Indent := Indent - 3;
+   end Indent_End;
+
+   --------
+   -- PG --
+   --------
+
+   procedure PG (Node : Node_Id) is
+   begin
+      Dump_Generated_Only := True;
+      Dump_Original_Only := False;
+      Sprint_Node (Node);
+      Print_Eol;
+   end PG;
+
+   --------
+   -- PO --
+   --------
+
+   procedure PO (Node : Node_Id) is
+   begin
+      Dump_Generated_Only := False;
+      Dump_Original_Only := True;
+      Sprint_Node (Node);
+      Print_Eol;
+   end PO;
+
+   ---------------
+   -- Print_Eol --
+   ---------------
+
+   procedure Print_Eol is
+   begin
+      --  If we are writing a debug source file, then grab it from the
+      --  Output buffer, and reset the column counter (the routines in
+      --  Output never actually write any output for us in this mode,
+      --  they just build line images in Buffer).
+
+      if Debug_Generated_Code then
+         Write_Debug_Line (Buffer (1 .. Natural (Column) - 1), Debug_Sloc);
+         Column := 1;
+
+      --  In normal mode, we call Write_Eol to write the line normally
+
+      else
+         Write_Eol;
+      end if;
+   end Print_Eol;
+
+   ---------------------------
+   -- Process_TFAI_RR_Flags --
+   ---------------------------
+
+   procedure Process_TFAI_RR_Flags (Nod : Node_Id) is
+   begin
+      if Treat_Fixed_As_Integer (Nod) then
+         Write_Char ('#');
+      end if;
+
+      if Rounded_Result (Nod) then
+         Write_Char ('@');
+      end if;
+   end Process_TFAI_RR_Flags;
+
+   --------
+   -- PS --
+   --------
+
+   procedure PS (Node : Node_Id) is
+   begin
+      Dump_Generated_Only := False;
+      Dump_Original_Only := False;
+      Sprint_Node (Node);
+      Print_Eol;
+   end PS;
+
+   --------------------
+   -- Set_Debug_Sloc --
+   --------------------
+
+   procedure Set_Debug_Sloc is
+   begin
+      if Present (Debug_Node) then
+         Set_Sloc (Debug_Node, Debug_Sloc + Source_Ptr (Column - 1));
+         Debug_Node := Empty;
+      end if;
+   end Set_Debug_Sloc;
+
+   -----------------
+   -- Source_Dump --
+   -----------------
+
+   procedure Source_Dump is
+
+      procedure Underline;
+      --  Put underline under string we just printed
+
+      procedure Underline is
+         Col : constant Int := Column;
+
+      begin
+         Print_Eol;
+
+         while Col > Column loop
+            Write_Char ('-');
+         end loop;
+
+         Print_Eol;
+      end Underline;
+
+   --  Start of processing for Tree_Dump.
+
+   begin
+      Dump_Generated_Only := Debug_Flag_G or
+                             Print_Generated_Code or
+                             Debug_Generated_Code;
+      Dump_Original_Only  := Debug_Flag_O;
+      Dump_Freeze_Null    := Debug_Flag_S or Debug_Flag_G;
+
+      --  Note that we turn off the tree dump flags immediately, before
+      --  starting the dump. This avoids generating two copies of the dump
+      --  if an abort occurs after printing the dump, and more importantly,
+      --  avoids an infinite loop if an abort occurs during the dump.
+
+      if Debug_Flag_Z then
+         Debug_Flag_Z := False;
+         Print_Eol;
+         Print_Eol;
+         Write_Str ("Source recreated from tree of Standard (spec)");
+         Underline;
+         Sprint_Node (Standard_Package_Node);
+         Print_Eol;
+         Print_Eol;
+      end if;
+
+      if Debug_Flag_S or Dump_Generated_Only or Dump_Original_Only then
+         Debug_Flag_G := False;
+         Debug_Flag_O := False;
+         Debug_Flag_S := False;
+
+         --  Dump requested units
+
+         for U in Main_Unit .. Last_Unit loop
+
+            --  Dump all units if -gnatdf set, otherwise we dump only
+            --  the source files that are in the extended main source.
+
+            if Debug_Flag_F
+              or else In_Extended_Main_Source_Unit (Cunit_Entity (U))
+            then
+               --  If we are generating debug files, setup to write them
+
+               if Debug_Generated_Code then
+                  Create_Debug_Source (Source_Index (U), Debug_Sloc);
+                  Sprint_Node (Cunit (U));
+                  Print_Eol;
+                  Close_Debug_Source;
+
+               --  Normal output to standard output file
+
+               else
+                  Write_Str ("Source recreated from tree for ");
+                  Write_Unit_Name (Unit_Name (U));
+                  Underline;
+                  Sprint_Node (Cunit (U));
+                  Write_Eol;
+                  Write_Eol;
+               end if;
+            end if;
+         end loop;
+      end if;
+   end Source_Dump;
+
+   ---------------------
+   -- Sprint_Bar_List --
+   ---------------------
+
+   procedure Sprint_Bar_List (List : List_Id) is
+      Node : Node_Id;
+
+   begin
+      if Is_Non_Empty_List (List) then
+         Node := First (List);
+
+         loop
+            Sprint_Node (Node);
+            Next (Node);
+            exit when Node = Empty;
+            Write_Str (" | ");
+         end loop;
+      end if;
+   end Sprint_Bar_List;
+
+   -----------------------
+   -- Sprint_Comma_List --
+   -----------------------
+
+   procedure Sprint_Comma_List (List : List_Id) is
+      Node : Node_Id;
+
+   begin
+      if Is_Non_Empty_List (List) then
+         Node := First (List);
+
+         loop
+            Sprint_Node (Node);
+            Next (Node);
+            exit when Node = Empty;
+
+            if not Is_Rewrite_Insertion (Node)
+              or else not Dump_Original_Only
+            then
+               Write_Str (", ");
+            end if;
+
+         end loop;
+      end if;
+   end Sprint_Comma_List;
+
+   --------------------------
+   -- Sprint_Indented_List --
+   --------------------------
+
+   procedure Sprint_Indented_List (List : List_Id) is
+   begin
+      Indent_Begin;
+      Sprint_Node_List (List);
+      Indent_End;
+   end Sprint_Indented_List;
+
+   -----------------
+   -- Sprint_Node --
+   -----------------
+
+   procedure Sprint_Node (Node : Node_Id) is
+   begin
+      if Is_Rewrite_Insertion (Node) then
+         if not Dump_Original_Only then
+
+            --  For special cases of nodes that always output <<< >>>
+            --  do not duplicate the output at this point.
+
+            if Nkind (Node) = N_Freeze_Entity
+              or else Nkind (Node) = N_Implicit_Label_Declaration
+            then
+               Sprint_Node_Actual (Node);
+
+            --  Normal case where <<< >>> may be required
+
+            else
+               Write_Rewrite_Str ("<<<");
+               Sprint_Node_Actual (Node);
+               Write_Rewrite_Str (">>>");
+            end if;
+         end if;
+
+      elsif Is_Rewrite_Substitution (Node) then
+
+         --  Case of dump generated only
+
+         if Dump_Generated_Only then
+            Sprint_Node_Actual (Node);
+
+         --  Case of dump original only
+
+         elsif Dump_Original_Only then
+            Sprint_Node_Actual (Original_Node (Node));
+
+         --  Case of both being dumped
+
+         else
+            Sprint_Node_Actual (Original_Node (Node));
+            Write_Rewrite_Str ("<<<");
+            Sprint_Node_Actual (Node);
+            Write_Rewrite_Str (">>>");
+         end if;
+
+      else
+         Sprint_Node_Actual (Node);
+      end if;
+   end Sprint_Node;
+
+   ------------------------
+   -- Sprint_Node_Actual --
+   ------------------------
+
+   procedure Sprint_Node_Actual (Node : Node_Id) is
+      Save_Debug_Node : constant Node_Id := Debug_Node;
+
+   begin
+      if Node = Empty then
+         return;
+      end if;
+
+      for J in 1 .. Paren_Count (Node) loop
+         Write_Str_With_Col_Check ("(");
+      end loop;
+
+      --  Setup node for Sloc fixup if writing a debug source file. Note
+      --  that we take care of any previous node not yet properly set.
+
+      if Debug_Generated_Code then
+         Debug_Node := Node;
+      end if;
+
+      if Nkind (Node) in N_Subexpr
+        and then Do_Range_Check (Node)
+      then
+         Write_Str_With_Col_Check ("{");
+      end if;
+
+      --  Select print circuit based on node kind
+
+      case Nkind (Node) is
+
+         when N_Abort_Statement =>
+            Write_Indent_Str_Sloc ("abort ");
+            Sprint_Comma_List (Names (Node));
+            Write_Char (';');
+
+         when N_Abortable_Part =>
+            Set_Debug_Sloc;
+            Write_Str_Sloc ("abort ");
+            Sprint_Indented_List (Statements (Node));
+
+         when N_Abstract_Subprogram_Declaration =>
+            Write_Indent;
+            Sprint_Node (Specification (Node));
+            Write_Str_With_Col_Check (" is ");
+            Write_Str_Sloc ("abstract;");
+
+         when N_Accept_Alternative =>
+            Sprint_Node_List (Pragmas_Before (Node));
+
+            if Present (Condition (Node)) then
+               Write_Indent_Str ("when ");
+               Sprint_Node (Condition (Node));
+               Write_Str (" => ");
+               Indent_Annull;
+            end if;
+
+            Sprint_Node_Sloc (Accept_Statement (Node));
+            Sprint_Node_List (Statements (Node));
+
+         when N_Accept_Statement =>
+            Write_Indent_Str_Sloc ("accept ");
+            Write_Id (Entry_Direct_Name (Node));
+
+            if Present (Entry_Index (Node)) then
+               Write_Str_With_Col_Check (" (");
+               Sprint_Node (Entry_Index (Node));
+               Write_Char (')');
+            end if;
+
+            Write_Param_Specs (Node);
+
+            if Present (Handled_Statement_Sequence (Node)) then
+               Write_Str_With_Col_Check (" do");
+               Sprint_Node (Handled_Statement_Sequence (Node));
+               Write_Indent_Str ("end ");
+               Write_Id (Entry_Direct_Name (Node));
+            end if;
+
+            Write_Char (';');
+
+         when N_Access_Definition =>
+            Write_Str_With_Col_Check_Sloc ("access ");
+            Sprint_Node (Subtype_Mark (Node));
+
+         when N_Access_Function_Definition =>
+            Write_Str_With_Col_Check_Sloc ("access ");
+
+            if Protected_Present (Node) then
+               Write_Str_With_Col_Check ("protected ");
+            end if;
+
+            Write_Str_With_Col_Check ("function");
+            Write_Param_Specs (Node);
+            Write_Str_With_Col_Check (" return ");
+            Sprint_Node (Subtype_Mark (Node));
+
+         when N_Access_Procedure_Definition =>
+            Write_Str_With_Col_Check_Sloc ("access ");
+
+            if Protected_Present (Node) then
+               Write_Str_With_Col_Check ("protected ");
+            end if;
+
+            Write_Str_With_Col_Check ("procedure");
+            Write_Param_Specs (Node);
+
+         when N_Access_To_Object_Definition =>
+            Write_Str_With_Col_Check_Sloc ("access ");
+
+            if All_Present (Node) then
+               Write_Str_With_Col_Check ("all ");
+            elsif Constant_Present (Node) then
+               Write_Str_With_Col_Check ("constant ");
+            end if;
+
+            Sprint_Node (Subtype_Indication (Node));
+
+         when N_Aggregate =>
+            if Null_Record_Present (Node) then
+               Write_Str_With_Col_Check_Sloc ("(null record)");
+
+            else
+               Write_Str_With_Col_Check_Sloc ("(");
+
+               if Present (Expressions (Node)) then
+                  Sprint_Comma_List (Expressions (Node));
+
+                  if Present (Component_Associations (Node)) then
+                     Write_Str (", ");
+                  end if;
+               end if;
+
+               if Present (Component_Associations (Node)) then
+                  Indent_Begin;
+
+                  declare
+                     Nd : Node_Id;
+
+                  begin
+                     Nd := First (Component_Associations (Node));
+
+                     loop
+                        Write_Indent;
+                        Sprint_Node (Nd);
+                        Next (Nd);
+                        exit when No (Nd);
+
+                        if not Is_Rewrite_Insertion (Nd)
+                          or else not Dump_Original_Only
+                        then
+                           Write_Str (", ");
+                        end if;
+                     end loop;
+                  end;
+
+                  Indent_End;
+               end if;
+
+               Write_Char (')');
+            end if;
+
+         when N_Allocator =>
+            Write_Str_With_Col_Check_Sloc ("new ");
+            Sprint_Node (Expression (Node));
+
+            if Present (Storage_Pool (Node)) then
+               Write_Str_With_Col_Check ("[storage_pool = ");
+               Sprint_Node (Storage_Pool (Node));
+               Write_Char (']');
+            end if;
+
+         when N_And_Then =>
+            Sprint_Node (Left_Opnd (Node));
+            Write_Str_Sloc (" and then ");
+            Sprint_Node (Right_Opnd (Node));
+
+         when N_At_Clause =>
+            Write_Indent_Str_Sloc ("for ");
+            Write_Id (Identifier (Node));
+            Write_Str_With_Col_Check (" use at ");
+            Sprint_Node (Expression (Node));
+            Write_Char (';');
+
+         when N_Assignment_Statement =>
+            Write_Indent;
+            Sprint_Node (Name (Node));
+            Write_Str_Sloc (" := ");
+            Sprint_Node (Expression (Node));
+            Write_Char (';');
+
+         when N_Asynchronous_Select =>
+            Write_Indent_Str_Sloc ("select");
+            Indent_Begin;
+            Sprint_Node (Triggering_Alternative (Node));
+            Indent_End;
+
+            --  Note: let the printing of Abortable_Part handle outputting
+            --  the ABORT keyword, so that the Slco can be set correctly.
+
+            Write_Indent_Str ("then ");
+            Sprint_Node (Abortable_Part (Node));
+            Write_Indent_Str ("end select;");
+
+         when N_Attribute_Definition_Clause =>
+            Write_Indent_Str_Sloc ("for ");
+            Sprint_Node (Name (Node));
+            Write_Char (''');
+            Write_Name_With_Col_Check (Chars (Node));
+            Write_Str_With_Col_Check (" use ");
+            Sprint_Node (Expression (Node));
+            Write_Char (';');
+
+         when N_Attribute_Reference =>
+            if Is_Procedure_Attribute_Name (Attribute_Name (Node)) then
+               Write_Indent;
+            end if;
+
+            Sprint_Node (Prefix (Node));
+            Write_Char_Sloc (''');
+            Write_Name_With_Col_Check (Attribute_Name (Node));
+            Sprint_Paren_Comma_List (Expressions (Node));
+
+            if Is_Procedure_Attribute_Name (Attribute_Name (Node)) then
+               Write_Char (';');
+            end if;
+
+         when N_Block_Statement =>
+            Write_Indent;
+
+            if Present (Identifier (Node))
+              and then (not Has_Created_Identifier (Node)
+                          or else not Dump_Original_Only)
+            then
+               Write_Rewrite_Str ("<<<");
+               Write_Id (Identifier (Node));
+               Write_Str (" : ");
+               Write_Rewrite_Str (">>>");
+            end if;
+
+            if Present (Declarations (Node)) then
+               Write_Str_With_Col_Check_Sloc ("declare");
+               Sprint_Indented_List (Declarations (Node));
+               Write_Indent;
+            end if;
+
+            Write_Str_With_Col_Check_Sloc ("begin");
+            Sprint_Node (Handled_Statement_Sequence (Node));
+            Write_Indent_Str ("end");
+
+            if Present (Identifier (Node))
+              and then (not Has_Created_Identifier (Node)
+                          or else not Dump_Original_Only)
+            then
+               Write_Rewrite_Str ("<<<");
+               Write_Char (' ');
+               Write_Id (Identifier (Node));
+               Write_Rewrite_Str (">>>");
+            end if;
+
+            Write_Char (';');
+
+         when N_Case_Statement =>
+            Write_Indent_Str_Sloc ("case ");
+            Sprint_Node (Expression (Node));
+            Write_Str (" is");
+            Sprint_Indented_List (Alternatives (Node));
+            Write_Indent_Str ("end case;");
+
+         when N_Case_Statement_Alternative =>
+            Write_Indent_Str_Sloc ("when ");
+            Sprint_Bar_List (Discrete_Choices (Node));
+            Write_Str (" => ");
+            Sprint_Indented_List (Statements (Node));
+
+         when N_Character_Literal =>
+            if Column > 70 then
+               Write_Indent_Str ("  ");
+            end if;
+
+            Write_Char_Sloc (''');
+            Write_Char_Code (Char_Literal_Value (Node));
+            Write_Char (''');
+
+         when N_Code_Statement =>
+            Write_Indent;
+            Set_Debug_Sloc;
+            Sprint_Node (Expression (Node));
+            Write_Char (';');
+
+         when N_Compilation_Unit =>
+            Sprint_Node_List (Context_Items (Node));
+            Sprint_Opt_Node_List (Declarations (Aux_Decls_Node (Node)));
+
+            if Private_Present (Node) then
+               Write_Indent_Str ("private ");
+               Indent_Annull;
+            end if;
+
+            Sprint_Node_Sloc (Unit (Node));
+
+            if Present (Actions (Aux_Decls_Node (Node)))
+                 or else
+               Present (Pragmas_After (Aux_Decls_Node (Node)))
+            then
+               Write_Indent;
+            end if;
+
+            Sprint_Opt_Node_List (Actions (Aux_Decls_Node (Node)));
+            Sprint_Opt_Node_List (Pragmas_After (Aux_Decls_Node (Node)));
+
+         when N_Compilation_Unit_Aux =>
+            null; -- nothing to do, never used, see above
+
+         when N_Component_Association =>
+            Set_Debug_Sloc;
+            Sprint_Bar_List (Choices (Node));
+            Write_Str (" => ");
+            Sprint_Node (Expression (Node));
+
+         when N_Component_Clause =>
+            Write_Indent;
+            Sprint_Node (Component_Name (Node));
+            Write_Str_Sloc (" at ");
+            Sprint_Node (Position (Node));
+            Write_Char (' ');
+            Write_Str_With_Col_Check ("range ");
+            Sprint_Node (First_Bit (Node));
+            Write_Str (" .. ");
+            Sprint_Node (Last_Bit (Node));
+            Write_Char (';');
+
+         when N_Component_Declaration =>
+            if Write_Indent_Identifiers_Sloc (Node) then
+               Write_Str (" : ");
+
+               if Aliased_Present (Node) then
+                  Write_Str_With_Col_Check ("aliased ");
+               end if;
+
+               Sprint_Node (Subtype_Indication (Node));
+
+               if Present (Expression (Node)) then
+                  Write_Str (" := ");
+                  Sprint_Node (Expression (Node));
+               end if;
+
+               Write_Char (';');
+            end if;
+
+         when N_Component_List =>
+            if Null_Present (Node) then
+               Indent_Begin;
+               Write_Indent_Str_Sloc ("null");
+               Write_Char (';');
+               Indent_End;
+
+            else
+               Set_Debug_Sloc;
+               Sprint_Indented_List (Component_Items (Node));
+               Sprint_Node (Variant_Part (Node));
+            end if;
+
+         when N_Conditional_Entry_Call =>
+            Write_Indent_Str_Sloc ("select");
+            Indent_Begin;
+            Sprint_Node (Entry_Call_Alternative (Node));
+            Indent_End;
+            Write_Indent_Str ("else");
+            Sprint_Indented_List (Else_Statements (Node));
+            Write_Indent_Str ("end select;");
+
+         when N_Conditional_Expression =>
+            declare
+               Condition : constant Node_Id := First (Expressions (Node));
+               Then_Expr : constant Node_Id := Next (Condition);
+               Else_Expr : constant Node_Id := Next (Then_Expr);
+
+            begin
+               Write_Str_With_Col_Check_Sloc ("(if ");
+               Sprint_Node (Condition);
+               Write_Str_With_Col_Check (" then ");
+               Sprint_Node (Then_Expr);
+               Write_Str_With_Col_Check (" else ");
+               Sprint_Node (Else_Expr);
+               Write_Char (')');
+            end;
+
+         when N_Constrained_Array_Definition =>
+            Write_Str_With_Col_Check_Sloc ("array ");
+            Sprint_Paren_Comma_List (Discrete_Subtype_Definitions (Node));
+            Write_Str (" of ");
+
+            if Aliased_Present (Node) then
+               Write_Str_With_Col_Check ("aliased ");
+            end if;
+
+            Sprint_Node (Subtype_Indication (Node));
+
+         when N_Decimal_Fixed_Point_Definition =>
+            Write_Str_With_Col_Check_Sloc (" delta ");
+            Sprint_Node (Delta_Expression (Node));
+            Write_Str_With_Col_Check ("digits ");
+            Sprint_Node (Digits_Expression (Node));
+            Sprint_Opt_Node (Real_Range_Specification (Node));
+
+         when N_Defining_Character_Literal =>
+            Write_Name_With_Col_Check_Sloc (Chars (Node));
+
+         when N_Defining_Identifier =>
+            Set_Debug_Sloc;
+            Write_Id (Node);
+
+         when N_Defining_Operator_Symbol =>
+            Write_Name_With_Col_Check_Sloc (Chars (Node));
+
+         when N_Defining_Program_Unit_Name =>
+            Set_Debug_Sloc;
+            Sprint_Node (Name (Node));
+            Write_Char ('.');
+            Write_Id (Defining_Identifier (Node));
+
+         when N_Delay_Alternative =>
+            Sprint_Node_List (Pragmas_Before (Node));
+
+            if Present (Condition (Node)) then
+               Write_Indent;
+               Write_Str_With_Col_Check ("when ");
+               Sprint_Node (Condition (Node));
+               Write_Str (" => ");
+               Indent_Annull;
+            end if;
+
+            Sprint_Node_Sloc (Delay_Statement (Node));
+            Sprint_Node_List (Statements (Node));
+
+         when N_Delay_Relative_Statement =>
+            Write_Indent_Str_Sloc ("delay ");
+            Sprint_Node (Expression (Node));
+            Write_Char (';');
+
+         when N_Delay_Until_Statement =>
+            Write_Indent_Str_Sloc ("delay until ");
+            Sprint_Node (Expression (Node));
+            Write_Char (';');
+
+         when N_Delta_Constraint =>
+            Write_Str_With_Col_Check_Sloc ("delta ");
+            Sprint_Node (Delta_Expression (Node));
+            Sprint_Opt_Node (Range_Constraint (Node));
+
+         when N_Derived_Type_Definition =>
+            if Abstract_Present (Node) then
+               Write_Str_With_Col_Check ("abstract ");
+            end if;
+
+            Write_Str_With_Col_Check_Sloc ("new ");
+            Sprint_Node (Subtype_Indication (Node));
+
+            if Present (Record_Extension_Part (Node)) then
+               Write_Str_With_Col_Check (" with ");
+               Sprint_Node (Record_Extension_Part (Node));
+            end if;
+
+         when N_Designator =>
+            Sprint_Node (Name (Node));
+            Write_Char_Sloc ('.');
+            Write_Id (Identifier (Node));
+
+         when N_Digits_Constraint =>
+            Write_Str_With_Col_Check_Sloc ("digits ");
+            Sprint_Node (Digits_Expression (Node));
+            Sprint_Opt_Node (Range_Constraint (Node));
+
+         when N_Discriminant_Association =>
+            Set_Debug_Sloc;
+
+            if Present (Selector_Names (Node)) then
+               Sprint_Bar_List (Selector_Names (Node));
+               Write_Str (" => ");
+            end if;
+
+            Set_Debug_Sloc;
+            Sprint_Node (Expression (Node));
+
+         when N_Discriminant_Specification =>
+            Set_Debug_Sloc;
+
+            if Write_Identifiers (Node) then
+               Write_Str (" : ");
+               Sprint_Node (Discriminant_Type (Node));
+
+               if Present (Expression (Node)) then
+                  Write_Str (" := ");
+                  Sprint_Node (Expression (Node));
+               end if;
+            else
+               Write_Str (", ");
+            end if;
+
+         when N_Elsif_Part =>
+            Write_Indent_Str_Sloc ("elsif ");
+            Sprint_Node (Condition (Node));
+            Write_Str_With_Col_Check (" then");
+            Sprint_Indented_List (Then_Statements (Node));
+
+         when N_Empty =>
+            null;
+
+         when N_Entry_Body =>
+            Write_Indent_Str_Sloc ("entry ");
+            Write_Id (Defining_Identifier (Node));
+            Sprint_Node (Entry_Body_Formal_Part (Node));
+            Write_Str_With_Col_Check (" is");
+            Sprint_Indented_List (Declarations (Node));
+            Write_Indent_Str ("begin");
+            Sprint_Node (Handled_Statement_Sequence (Node));
+            Write_Indent_Str ("end ");
+            Write_Id (Defining_Identifier (Node));
+            Write_Char (';');
+
+         when N_Entry_Body_Formal_Part =>
+            if Present (Entry_Index_Specification (Node)) then
+               Write_Str_With_Col_Check_Sloc (" (");
+               Sprint_Node (Entry_Index_Specification (Node));
+               Write_Char (')');
+            end if;
+
+            Write_Param_Specs (Node);
+            Write_Str_With_Col_Check_Sloc (" when ");
+            Sprint_Node (Condition (Node));
+
+         when N_Entry_Call_Alternative =>
+            Sprint_Node_List (Pragmas_Before (Node));
+            Sprint_Node_Sloc (Entry_Call_Statement (Node));
+            Sprint_Node_List (Statements (Node));
+
+         when N_Entry_Call_Statement =>
+            Write_Indent;
+            Sprint_Node_Sloc (Name (Node));
+            Sprint_Opt_Paren_Comma_List (Parameter_Associations (Node));
+            Write_Char (';');
+
+         when N_Entry_Declaration =>
+            Write_Indent_Str_Sloc ("entry ");
+            Write_Id (Defining_Identifier (Node));
+
+            if Present (Discrete_Subtype_Definition (Node)) then
+               Write_Str_With_Col_Check (" (");
+               Sprint_Node (Discrete_Subtype_Definition (Node));
+               Write_Char (')');
+            end if;
+
+            Write_Param_Specs (Node);
+            Write_Char (';');
+
+         when N_Entry_Index_Specification =>
+            Write_Str_With_Col_Check_Sloc ("for ");
+            Write_Id (Defining_Identifier (Node));
+            Write_Str_With_Col_Check (" in ");
+            Sprint_Node (Discrete_Subtype_Definition (Node));
+
+         when N_Enumeration_Representation_Clause =>
+            Write_Indent_Str_Sloc ("for ");
+            Write_Id (Identifier (Node));
+            Write_Str_With_Col_Check (" use ");
+            Sprint_Node (Array_Aggregate (Node));
+            Write_Char (';');
+
+         when N_Enumeration_Type_Definition =>
+            Set_Debug_Sloc;
+
+            --  Skip attempt to print Literals field if it's not there and
+            --  we are in package Standard (case of Character, which is
+            --  handled specially (without an explicit literals list).
+
+            if Sloc (Node) > Standard_Location
+              or else Present (Literals (Node))
+            then
+               Sprint_Paren_Comma_List (Literals (Node));
+            end if;
+
+         when N_Error =>
+            Write_Str_With_Col_Check_Sloc ("<error>");
+
+         when N_Exception_Declaration =>
+            if Write_Indent_Identifiers (Node) then
+               Write_Str_With_Col_Check (" : ");
+               Write_Str_Sloc ("exception;");
+            end if;
+
+         when N_Exception_Handler =>
+            Write_Indent_Str_Sloc ("when ");
+
+            if Present (Choice_Parameter (Node)) then
+               Sprint_Node (Choice_Parameter (Node));
+               Write_Str (" : ");
+            end if;
+
+            Sprint_Bar_List (Exception_Choices (Node));
+            Write_Str (" => ");
+            Sprint_Indented_List (Statements (Node));
+
+         when N_Exception_Renaming_Declaration =>
+            Write_Indent;
+            Set_Debug_Sloc;
+            Sprint_Node (Defining_Identifier (Node));
+            Write_Str_With_Col_Check (" : exception renames ");
+            Sprint_Node (Name (Node));
+            Write_Char (';');
+
+         when N_Exit_Statement =>
+            Write_Indent_Str_Sloc ("exit");
+            Sprint_Opt_Node (Name (Node));
+
+            if Present (Condition (Node)) then
+               Write_Str_With_Col_Check (" when ");
+               Sprint_Node (Condition (Node));
+            end if;
+
+            Write_Char (';');
+
+         when N_Explicit_Dereference =>
+            Sprint_Node (Prefix (Node));
+            Write_Char ('.');
+            Write_Str_Sloc ("all");
+
+         when N_Extension_Aggregate =>
+            Write_Str_With_Col_Check_Sloc ("(");
+            Sprint_Node (Ancestor_Part (Node));
+            Write_Str_With_Col_Check (" with ");
+
+            if Null_Record_Present (Node) then
+               Write_Str_With_Col_Check ("null record");
+            else
+               if Present (Expressions (Node)) then
+                  Sprint_Comma_List (Expressions (Node));
+
+                  if Present (Component_Associations (Node)) then
+                     Write_Str (", ");
+                  end if;
+               end if;
+
+               if Present (Component_Associations (Node)) then
+                  Sprint_Comma_List (Component_Associations (Node));
+               end if;
+            end if;
+
+            Write_Char (')');
+
+         when N_Floating_Point_Definition =>
+            Write_Str_With_Col_Check_Sloc ("digits ");
+            Sprint_Node (Digits_Expression (Node));
+            Sprint_Opt_Node (Real_Range_Specification (Node));
+
+         when N_Formal_Decimal_Fixed_Point_Definition =>
+            Write_Str_With_Col_Check_Sloc ("delta <> digits <>");
+
+         when N_Formal_Derived_Type_Definition =>
+            Write_Str_With_Col_Check_Sloc ("new ");
+            Sprint_Node (Subtype_Mark (Node));
+
+            if Private_Present (Node) then
+               Write_Str_With_Col_Check (" with private");
+            end if;
+
+         when N_Formal_Discrete_Type_Definition =>
+            Write_Str_With_Col_Check_Sloc ("<>");
+
+         when N_Formal_Floating_Point_Definition =>
+            Write_Str_With_Col_Check_Sloc ("digits <>");
+
+         when N_Formal_Modular_Type_Definition =>
+            Write_Str_With_Col_Check_Sloc ("mod <>");
+
+         when N_Formal_Object_Declaration =>
+            Set_Debug_Sloc;
+
+            if Write_Indent_Identifiers (Node) then
+               Write_Str (" : ");
+
+               if In_Present (Node) then
+                  Write_Str_With_Col_Check ("in ");
+               end if;
+
+               if Out_Present (Node) then
+                  Write_Str_With_Col_Check ("out ");
+               end if;
+
+               Sprint_Node (Subtype_Mark (Node));
+
+               if Present (Expression (Node)) then
+                  Write_Str (" := ");
+                  Sprint_Node (Expression (Node));
+               end if;
+
+               Write_Char (';');
+            end if;
+
+         when N_Formal_Ordinary_Fixed_Point_Definition =>
+            Write_Str_With_Col_Check_Sloc ("delta <>");
+
+         when N_Formal_Package_Declaration =>
+            Write_Indent_Str_Sloc ("with package ");
+            Write_Id (Defining_Identifier (Node));
+            Write_Str_With_Col_Check (" is new ");
+            Sprint_Node (Name (Node));
+            Write_Str_With_Col_Check (" (<>);");
+
+         when N_Formal_Private_Type_Definition =>
+            if Abstract_Present (Node) then
+               Write_Str_With_Col_Check ("abstract ");
+            end if;
+
+            if Tagged_Present (Node) then
+               Write_Str_With_Col_Check ("tagged ");
+            end if;
+
+            if Limited_Present (Node) then
+               Write_Str_With_Col_Check ("limited ");
+            end if;
+
+            Write_Str_With_Col_Check_Sloc ("private");
+
+         when N_Formal_Signed_Integer_Type_Definition =>
+            Write_Str_With_Col_Check_Sloc ("range <>");
+
+         when N_Formal_Subprogram_Declaration =>
+            Write_Indent_Str_Sloc ("with ");
+            Sprint_Node (Specification (Node));
+
+            if Box_Present (Node) then
+               Write_Str_With_Col_Check (" is <>");
+            elsif Present (Default_Name (Node)) then
+               Write_Str_With_Col_Check (" is ");
+               Sprint_Node (Default_Name (Node));
+            end if;
+
+            Write_Char (';');
+
+         when N_Formal_Type_Declaration =>
+            Write_Indent_Str_Sloc ("type ");
+            Write_Id (Defining_Identifier (Node));
+
+            if Present (Discriminant_Specifications (Node)) then
+               Write_Discr_Specs (Node);
+            elsif Unknown_Discriminants_Present (Node) then
+               Write_Str_With_Col_Check ("(<>)");
+            end if;
+
+            Write_Str_With_Col_Check (" is ");
+            Sprint_Node (Formal_Type_Definition (Node));
+            Write_Char (';');
+
+         when N_Free_Statement =>
+            Write_Indent_Str_Sloc ("free ");
+            Sprint_Node (Expression (Node));
+            Write_Char (';');
+
+         when N_Freeze_Entity =>
+            if Dump_Original_Only then
+               null;
+
+            elsif Present (Actions (Node)) or else Dump_Freeze_Null then
+               Write_Indent;
+               Write_Rewrite_Str ("<<<");
+               Write_Str_With_Col_Check_Sloc ("freeze ");
+               Write_Id (Entity (Node));
+               Write_Str (" [");
+
+               if No (Actions (Node)) then
+                  Write_Char (']');
+
+               else
+                  Freeze_Indent := Freeze_Indent + 1;
+                  Sprint_Indented_List (Actions (Node));
+                  Freeze_Indent := Freeze_Indent - 1;
+                  Write_Indent_Str ("]");
+               end if;
+
+               Write_Rewrite_Str (">>>");
+            end if;
+
+         when N_Full_Type_Declaration =>
+            Write_Indent_Str_Sloc ("type ");
+            Write_Id (Defining_Identifier (Node));
+            Write_Discr_Specs (Node);
+            Write_Str_With_Col_Check (" is ");
+            Sprint_Node (Type_Definition (Node));
+            Write_Char (';');
+
+         when N_Function_Call =>
+            Set_Debug_Sloc;
+            Sprint_Node (Name (Node));
+            Sprint_Opt_Paren_Comma_List (Parameter_Associations (Node));
+
+         when N_Function_Instantiation =>
+            Write_Indent_Str_Sloc ("function ");
+            Sprint_Node (Defining_Unit_Name (Node));
+            Write_Str_With_Col_Check (" is new ");
+            Sprint_Node (Name (Node));
+            Sprint_Opt_Paren_Comma_List (Generic_Associations (Node));
+            Write_Char (';');
+
+         when N_Function_Specification =>
+            Write_Str_With_Col_Check_Sloc ("function ");
+            Sprint_Node (Defining_Unit_Name (Node));
+            Write_Param_Specs (Node);
+            Write_Str_With_Col_Check (" return ");
+            Sprint_Node (Subtype_Mark (Node));
+
+         when N_Generic_Association =>
+            Set_Debug_Sloc;
+
+            if Present (Selector_Name (Node)) then
+               Sprint_Node (Selector_Name (Node));
+               Write_Str (" => ");
+            end if;
+
+            Sprint_Node (Explicit_Generic_Actual_Parameter (Node));
+
+         when N_Generic_Function_Renaming_Declaration =>
+            Write_Indent_Str_Sloc ("generic function ");
+            Sprint_Node (Defining_Unit_Name (Node));
+            Write_Str_With_Col_Check (" renames ");
+            Sprint_Node (Name (Node));
+            Write_Char (';');
+
+         when N_Generic_Package_Declaration =>
+            Write_Indent;
+            Write_Indent_Str_Sloc ("generic ");
+            Sprint_Indented_List (Generic_Formal_Declarations (Node));
+            Write_Indent;
+            Sprint_Node (Specification (Node));
+            Write_Char (';');
+
+         when N_Generic_Package_Renaming_Declaration =>
+            Write_Indent_Str_Sloc ("generic package ");
+            Sprint_Node (Defining_Unit_Name (Node));
+            Write_Str_With_Col_Check (" renames ");
+            Sprint_Node (Name (Node));
+            Write_Char (';');
+
+         when N_Generic_Procedure_Renaming_Declaration =>
+            Write_Indent_Str_Sloc ("generic procedure ");
+            Sprint_Node (Defining_Unit_Name (Node));
+            Write_Str_With_Col_Check (" renames ");
+            Sprint_Node (Name (Node));
+            Write_Char (';');
+
+         when N_Generic_Subprogram_Declaration =>
+            Write_Indent;
+            Write_Indent_Str_Sloc ("generic ");
+            Sprint_Indented_List (Generic_Formal_Declarations (Node));
+            Write_Indent;
+            Sprint_Node (Specification (Node));
+            Write_Char (';');
+
+         when N_Goto_Statement =>
+            Write_Indent_Str_Sloc ("goto ");
+            Sprint_Node (Name (Node));
+            Write_Char (';');
+
+            if Nkind (Next (Node)) = N_Label then
+               Write_Indent;
+            end if;
+
+         when N_Handled_Sequence_Of_Statements =>
+            Set_Debug_Sloc;
+            Sprint_Indented_List (Statements (Node));
+
+            if Present (Exception_Handlers (Node)) then
+               Write_Indent_Str ("exception");
+               Indent_Begin;
+               Sprint_Node_List (Exception_Handlers (Node));
+               Indent_End;
+            end if;
+
+            if Present (At_End_Proc (Node)) then
+               Write_Indent_Str ("at end");
+               Indent_Begin;
+               Write_Indent;
+               Sprint_Node (At_End_Proc (Node));
+               Write_Char (';');
+               Indent_End;
+            end if;
+
+         when N_Identifier =>
+            Set_Debug_Sloc;
+            Write_Id (Node);
+
+         when N_If_Statement =>
+            Write_Indent_Str_Sloc ("if ");
+            Sprint_Node (Condition (Node));
+            Write_Str_With_Col_Check (" then");
+            Sprint_Indented_List (Then_Statements (Node));
+            Sprint_Opt_Node_List (Elsif_Parts (Node));
+
+            if Present (Else_Statements (Node)) then
+               Write_Indent_Str ("else");
+               Sprint_Indented_List (Else_Statements (Node));
+            end if;
+
+            Write_Indent_Str ("end if;");
+
+         when N_Implicit_Label_Declaration =>
+            if not Dump_Original_Only then
+               Write_Indent;
+               Write_Rewrite_Str ("<<<");
+               Set_Debug_Sloc;
+               Write_Id (Defining_Identifier (Node));
+               Write_Str (" : ");
+               Write_Str_With_Col_Check ("label");
+               Write_Rewrite_Str (">>>");
+            end if;
+
+         when N_In =>
+            Sprint_Node (Left_Opnd (Node));
+            Write_Str_Sloc (" in ");
+            Sprint_Node (Right_Opnd (Node));
+
+         when N_Incomplete_Type_Declaration =>
+            Write_Indent_Str_Sloc ("type ");
+            Write_Id (Defining_Identifier (Node));
+
+            if Present (Discriminant_Specifications (Node)) then
+               Write_Discr_Specs (Node);
+            elsif Unknown_Discriminants_Present (Node) then
+               Write_Str_With_Col_Check ("(<>)");
+            end if;
+
+            Write_Char (';');
+
+         when N_Index_Or_Discriminant_Constraint =>
+            Set_Debug_Sloc;
+            Sprint_Paren_Comma_List (Constraints (Node));
+
+         when N_Indexed_Component =>
+            Sprint_Node_Sloc (Prefix (Node));
+            Sprint_Opt_Paren_Comma_List (Expressions (Node));
+
+         when N_Integer_Literal =>
+            if Print_In_Hex (Node) then
+               Write_Uint_With_Col_Check_Sloc (Intval (Node), Hex);
+            else
+               Write_Uint_With_Col_Check_Sloc (Intval (Node), Auto);
+            end if;
+
+         when N_Iteration_Scheme =>
+            if Present (Condition (Node)) then
+               Write_Str_With_Col_Check_Sloc ("while ");
+               Sprint_Node (Condition (Node));
+            else
+               Write_Str_With_Col_Check_Sloc ("for ");
+               Sprint_Node (Loop_Parameter_Specification (Node));
+            end if;
+
+            Write_Char (' ');
+
+         when N_Itype_Reference =>
+            Write_Indent_Str_Sloc ("reference ");
+            Write_Id (Itype (Node));
+
+         when N_Label =>
+            Write_Indent_Str_Sloc ("<<");
+            Write_Id (Identifier (Node));
+            Write_Str (">>");
+
+         when N_Loop_Parameter_Specification =>
+            Set_Debug_Sloc;
+            Write_Id (Defining_Identifier (Node));
+            Write_Str_With_Col_Check (" in ");
+
+            if Reverse_Present (Node) then
+               Write_Str_With_Col_Check ("reverse ");
+            end if;
+
+            Sprint_Node (Discrete_Subtype_Definition (Node));
+
+         when N_Loop_Statement =>
+            Write_Indent;
+
+            if Present (Identifier (Node))
+              and then (not Has_Created_Identifier (Node)
+                          or else not Dump_Original_Only)
+            then
+               Write_Rewrite_Str ("<<<");
+               Write_Id (Identifier (Node));
+               Write_Str (" : ");
+               Write_Rewrite_Str (">>>");
+               Sprint_Node (Iteration_Scheme (Node));
+               Write_Str_With_Col_Check_Sloc ("loop");
+               Sprint_Indented_List (Statements (Node));
+               Write_Indent_Str ("end loop ");
+               Write_Rewrite_Str ("<<<");
+               Write_Id (Identifier (Node));
+               Write_Rewrite_Str (">>>");
+               Write_Char (';');
+
+            else
+               Sprint_Node (Iteration_Scheme (Node));
+               Write_Str_With_Col_Check_Sloc ("loop");
+               Sprint_Indented_List (Statements (Node));
+               Write_Indent_Str ("end loop;");
+            end if;
+
+         when N_Mod_Clause =>
+            Sprint_Node_List (Pragmas_Before (Node));
+            Write_Str_With_Col_Check_Sloc ("at mod ");
+            Sprint_Node (Expression (Node));
+
+         when N_Modular_Type_Definition =>
+            Write_Str_With_Col_Check_Sloc ("mod ");
+            Sprint_Node (Expression (Node));
+
+         when N_Not_In =>
+            Sprint_Node (Left_Opnd (Node));
+            Write_Str_Sloc (" not in ");
+            Sprint_Node (Right_Opnd (Node));
+
+         when N_Null =>
+            Write_Str_With_Col_Check_Sloc ("null");
+
+         when N_Null_Statement =>
+            if Comes_From_Source (Node)
+              or else Dump_Freeze_Null
+              or else not Is_List_Member (Node)
+              or else (No (Prev (Node)) and then No (Next (Node)))
+            then
+               Write_Indent_Str_Sloc ("null;");
+            end if;
+
+         when N_Number_Declaration =>
+            Set_Debug_Sloc;
+
+            if Write_Indent_Identifiers (Node) then
+               Write_Str_With_Col_Check (" : constant ");
+               Write_Str (" := ");
+               Sprint_Node (Expression (Node));
+               Write_Char (';');
+            end if;
+
+         when N_Object_Declaration =>
+
+            --  Put extra blank line before and after if this is a handler
+            --  record or a subprogram descriptor.
+
+            declare
+               Typ : constant Entity_Id := Etype (Defining_Identifier (Node));
+               Exc : constant Boolean :=
+                       Is_RTE (Typ, RE_Handler_Record)
+                         or else
+                       Is_RTE (Typ, RE_Subprogram_Descriptor);
+
+            begin
+               if Exc then
+                  Write_Indent;
+               end if;
+
+               Set_Debug_Sloc;
+
+               if Write_Indent_Identifiers (Node) then
+                  Write_Str (" : ");
+
+                  if Aliased_Present (Node) then
+                     Write_Str_With_Col_Check ("aliased ");
+                  end if;
+
+                  if Constant_Present (Node) then
+                     Write_Str_With_Col_Check ("constant ");
+                  end if;
+
+                  Sprint_Node (Object_Definition (Node));
+
+                  if Present (Expression (Node)) then
+                     Write_Str (" := ");
+                     Sprint_Node (Expression (Node));
+                  end if;
+
+                  Write_Char (';');
+               end if;
+
+               if Exc then
+                  Write_Indent;
+               end if;
+            end;
+
+         when N_Object_Renaming_Declaration =>
+            Write_Indent;
+            Set_Debug_Sloc;
+            Sprint_Node (Defining_Identifier (Node));
+            Write_Str (" : ");
+            Sprint_Node (Subtype_Mark (Node));
+            Write_Str_With_Col_Check (" renames ");
+            Sprint_Node (Name (Node));
+            Write_Char (';');
+
+         when N_Op_Abs =>
+            Write_Operator (Node, "abs ");
+            Sprint_Node (Right_Opnd (Node));
+
+         when N_Op_Add =>
+            Sprint_Node (Left_Opnd (Node));
+            Write_Operator (Node, " + ");
+            Sprint_Node (Right_Opnd (Node));
+
+         when N_Op_And =>
+            Sprint_Node (Left_Opnd (Node));
+            Write_Operator (Node, " and ");
+            Sprint_Node (Right_Opnd (Node));
+
+         when N_Op_Concat =>
+            Sprint_Node (Left_Opnd (Node));
+            Write_Operator (Node, " & ");
+            Sprint_Node (Right_Opnd (Node));
+
+         when N_Op_Divide =>
+            Sprint_Node (Left_Opnd (Node));
+            Write_Char (' ');
+            Process_TFAI_RR_Flags (Node);
+            Write_Operator (Node, "/ ");
+            Sprint_Node (Right_Opnd (Node));
+
+         when N_Op_Eq =>
+            Sprint_Node (Left_Opnd (Node));
+            Write_Operator (Node, " = ");
+            Sprint_Node (Right_Opnd (Node));
+
+         when N_Op_Expon =>
+            Sprint_Node (Left_Opnd (Node));
+            Write_Operator (Node, " ** ");
+            Sprint_Node (Right_Opnd (Node));
+
+         when N_Op_Ge =>
+            Sprint_Node (Left_Opnd (Node));
+            Write_Operator (Node, " >= ");
+            Sprint_Node (Right_Opnd (Node));
+
+         when N_Op_Gt =>
+            Sprint_Node (Left_Opnd (Node));
+            Write_Operator (Node, " > ");
+            Sprint_Node (Right_Opnd (Node));
+
+         when N_Op_Le =>
+            Sprint_Node (Left_Opnd (Node));
+            Write_Operator (Node, " <= ");
+            Sprint_Node (Right_Opnd (Node));
+
+         when N_Op_Lt =>
+            Sprint_Node (Left_Opnd (Node));
+            Write_Operator (Node, " < ");
+            Sprint_Node (Right_Opnd (Node));
+
+         when N_Op_Minus =>
+            Write_Operator (Node, "-");
+            Sprint_Node (Right_Opnd (Node));
+
+         when N_Op_Mod =>
+            Sprint_Node (Left_Opnd (Node));
+
+            if Treat_Fixed_As_Integer (Node) then
+               Write_Str (" #");
+            end if;
+
+            Write_Operator (Node, " mod ");
+            Sprint_Node (Right_Opnd (Node));
+
+         when N_Op_Multiply =>
+            Sprint_Node (Left_Opnd (Node));
+            Write_Char (' ');
+            Process_TFAI_RR_Flags (Node);
+            Write_Operator (Node, "* ");
+            Sprint_Node (Right_Opnd (Node));
+
+         when N_Op_Ne =>
+            Sprint_Node (Left_Opnd (Node));
+            Write_Operator (Node, " /= ");
+            Sprint_Node (Right_Opnd (Node));
+
+         when N_Op_Not =>
+            Write_Operator (Node, "not ");
+            Sprint_Node (Right_Opnd (Node));
+
+         when N_Op_Or =>
+            Sprint_Node (Left_Opnd (Node));
+            Write_Operator (Node, " or ");
+            Sprint_Node (Right_Opnd (Node));
+
+         when N_Op_Plus =>
+            Write_Operator (Node, "+");
+            Sprint_Node (Right_Opnd (Node));
+
+         when N_Op_Rem =>
+            Sprint_Node (Left_Opnd (Node));
+
+            if Treat_Fixed_As_Integer (Node) then
+               Write_Str (" #");
+            end if;
+
+            Write_Operator (Node, " rem ");
+            Sprint_Node (Right_Opnd (Node));
+
+         when N_Op_Shift =>
+            Set_Debug_Sloc;
+            Write_Id (Node);
+            Write_Char ('!');
+            Write_Str_With_Col_Check ("(");
+            Sprint_Node (Left_Opnd (Node));
+            Write_Str (", ");
+            Sprint_Node (Right_Opnd (Node));
+            Write_Char (')');
+
+         when N_Op_Subtract =>
+            Sprint_Node (Left_Opnd (Node));
+            Write_Operator (Node, " - ");
+            Sprint_Node (Right_Opnd (Node));
+
+         when N_Op_Xor =>
+            Sprint_Node (Left_Opnd (Node));
+            Write_Operator (Node, " xor ");
+            Sprint_Node (Right_Opnd (Node));
+
+         when N_Operator_Symbol =>
+            Write_Name_With_Col_Check_Sloc (Chars (Node));
+
+         when N_Ordinary_Fixed_Point_Definition =>
+            Write_Str_With_Col_Check_Sloc ("delta ");
+            Sprint_Node (Delta_Expression (Node));
+            Sprint_Opt_Node (Real_Range_Specification (Node));
+
+         when N_Or_Else =>
+            Sprint_Node (Left_Opnd (Node));
+            Write_Str_Sloc (" or else ");
+            Sprint_Node (Right_Opnd (Node));
+
+         when N_Others_Choice =>
+            if All_Others (Node) then
+               Write_Str_With_Col_Check ("all ");
+            end if;
+
+            Write_Str_With_Col_Check_Sloc ("others");
+
+         when N_Package_Body =>
+            Write_Indent;
+            Write_Indent_Str_Sloc ("package body ");
+            Sprint_Node (Defining_Unit_Name (Node));
+            Write_Str (" is");
+            Sprint_Indented_List (Declarations (Node));
+
+            if Present (Handled_Statement_Sequence (Node)) then
+               Write_Indent_Str ("begin");
+               Sprint_Node (Handled_Statement_Sequence (Node));
+            end if;
+
+            Write_Indent_Str ("end ");
+            Sprint_Node (Defining_Unit_Name (Node));
+            Write_Char (';');
+
+         when N_Package_Body_Stub =>
+            Write_Indent_Str_Sloc ("package body ");
+            Sprint_Node (Defining_Identifier (Node));
+            Write_Str_With_Col_Check (" is separate;");
+
+         when N_Package_Declaration =>
+            Write_Indent;
+            Write_Indent;
+            Sprint_Node_Sloc (Specification (Node));
+            Write_Char (';');
+
+         when N_Package_Instantiation =>
+            Write_Indent;
+            Write_Indent_Str_Sloc ("package ");
+            Sprint_Node (Defining_Unit_Name (Node));
+            Write_Str (" is new ");
+            Sprint_Node (Name (Node));
+            Sprint_Opt_Paren_Comma_List (Generic_Associations (Node));
+            Write_Char (';');
+
+         when N_Package_Renaming_Declaration =>
+            Write_Indent_Str_Sloc ("package ");
+            Sprint_Node (Defining_Unit_Name (Node));
+            Write_Str_With_Col_Check (" renames ");
+            Sprint_Node (Name (Node));
+            Write_Char (';');
+
+         when N_Package_Specification =>
+            Write_Str_With_Col_Check_Sloc ("package ");
+            Sprint_Node (Defining_Unit_Name (Node));
+            Write_Str (" is");
+            Sprint_Indented_List (Visible_Declarations (Node));
+
+            if Present (Private_Declarations (Node)) then
+               Write_Indent_Str ("private");
+               Sprint_Indented_List (Private_Declarations (Node));
+            end if;
+
+            Write_Indent_Str ("end ");
+            Sprint_Node (Defining_Unit_Name (Node));
+
+         when N_Parameter_Association =>
+            Sprint_Node_Sloc (Selector_Name (Node));
+            Write_Str (" => ");
+            Sprint_Node (Explicit_Actual_Parameter (Node));
+
+         when N_Parameter_Specification =>
+            Set_Debug_Sloc;
+
+            if Write_Identifiers (Node) then
+               Write_Str (" : ");
+
+               if In_Present (Node) then
+                  Write_Str_With_Col_Check ("in ");
+               end if;
+
+               if Out_Present (Node) then
+                  Write_Str_With_Col_Check ("out ");
+               end if;
+
+               Sprint_Node (Parameter_Type (Node));
+
+               if Present (Expression (Node)) then
+                  Write_Str (" := ");
+                  Sprint_Node (Expression (Node));
+               end if;
+            else
+               Write_Str (", ");
+            end if;
+
+         when N_Pragma =>
+            Write_Indent_Str_Sloc ("pragma ");
+            Write_Name_With_Col_Check (Chars (Node));
+
+            if Present (Pragma_Argument_Associations (Node)) then
+               Sprint_Opt_Paren_Comma_List
+                 (Pragma_Argument_Associations (Node));
+            end if;
+
+            Write_Char (';');
+
+         when N_Pragma_Argument_Association =>
+            Set_Debug_Sloc;
+
+            if Chars (Node) /= No_Name then
+               Write_Name_With_Col_Check (Chars (Node));
+               Write_Str (" => ");
+            end if;
+
+            Sprint_Node (Expression (Node));
+
+         when N_Private_Type_Declaration =>
+            Write_Indent_Str_Sloc ("type ");
+            Write_Id (Defining_Identifier (Node));
+
+            if Present (Discriminant_Specifications (Node)) then
+               Write_Discr_Specs (Node);
+            elsif Unknown_Discriminants_Present (Node) then
+               Write_Str_With_Col_Check ("(<>)");
+            end if;
+
+            Write_Str (" is ");
+
+            if Tagged_Present (Node) then
+               Write_Str_With_Col_Check ("tagged ");
+            end if;
+
+            if Limited_Present (Node) then
+               Write_Str_With_Col_Check ("limited ");
+            end if;
+
+            Write_Str_With_Col_Check ("private;");
+
+         when N_Private_Extension_Declaration =>
+            Write_Indent_Str_Sloc ("type ");
+            Write_Id (Defining_Identifier (Node));
+
+            if Present (Discriminant_Specifications (Node)) then
+               Write_Discr_Specs (Node);
+            elsif Unknown_Discriminants_Present (Node) then
+               Write_Str_With_Col_Check ("(<>)");
+            end if;
+
+            Write_Str_With_Col_Check (" is new ");
+            Sprint_Node (Subtype_Indication (Node));
+            Write_Str_With_Col_Check (" with private;");
+
+         when N_Procedure_Call_Statement =>
+            Write_Indent;
+            Set_Debug_Sloc;
+            Sprint_Node (Name (Node));
+            Sprint_Opt_Paren_Comma_List (Parameter_Associations (Node));
+            Write_Char (';');
+
+         when N_Procedure_Instantiation =>
+            Write_Indent_Str_Sloc ("procedure ");
+            Sprint_Node (Defining_Unit_Name (Node));
+            Write_Str_With_Col_Check (" is new ");
+            Sprint_Node (Name (Node));
+            Sprint_Opt_Paren_Comma_List (Generic_Associations (Node));
+            Write_Char (';');
+
+         when N_Procedure_Specification =>
+            Write_Str_With_Col_Check_Sloc ("procedure ");
+            Sprint_Node (Defining_Unit_Name (Node));
+            Write_Param_Specs (Node);
+
+         when N_Protected_Body =>
+            Write_Indent_Str_Sloc ("protected body ");
+            Write_Id (Defining_Identifier (Node));
+            Write_Str (" is");
+            Sprint_Indented_List (Declarations (Node));
+            Write_Indent_Str ("end ");
+            Write_Id (Defining_Identifier (Node));
+            Write_Char (';');
+
+         when N_Protected_Body_Stub =>
+            Write_Indent_Str_Sloc ("protected body ");
+            Write_Id (Defining_Identifier (Node));
+            Write_Str_With_Col_Check (" is separate;");
+
+         when N_Protected_Definition =>
+            Set_Debug_Sloc;
+            Sprint_Indented_List (Visible_Declarations (Node));
+
+            if Present (Private_Declarations (Node)) then
+               Write_Indent_Str ("private");
+               Sprint_Indented_List (Private_Declarations (Node));
+            end if;
+
+            Write_Indent_Str ("end ");
+
+         when N_Protected_Type_Declaration =>
+            Write_Indent_Str_Sloc ("protected type ");
+            Write_Id (Defining_Identifier (Node));
+            Write_Discr_Specs (Node);
+            Write_Str (" is");
+            Sprint_Node (Protected_Definition (Node));
+            Write_Id (Defining_Identifier (Node));
+            Write_Char (';');
+
+         when N_Qualified_Expression =>
+            Sprint_Node (Subtype_Mark (Node));
+            Write_Char_Sloc (''');
+            Sprint_Node (Expression (Node));
+
+         when N_Raise_Constraint_Error =>
+
+            --  This node can be used either as a subexpression or as a
+            --  statement form. The following test is a reasonably reliable
+            --  way to distinguish the two cases.
+
+            if Is_List_Member (Node)
+              and then Nkind (Parent (Node)) not in N_Subexpr
+            then
+               Write_Indent;
+            end if;
+
+            Write_Str_With_Col_Check_Sloc ("[constraint_error");
+
+            if Present (Condition (Node)) then
+               Write_Str_With_Col_Check (" when ");
+               Sprint_Node (Condition (Node));
+            end if;
+
+            Write_Char (']');
+
+         when N_Raise_Program_Error =>
+            Write_Indent;
+            Write_Str_With_Col_Check_Sloc ("[program_error");
+
+            if Present (Condition (Node)) then
+               Write_Str_With_Col_Check (" when ");
+               Sprint_Node (Condition (Node));
+            end if;
+
+            Write_Char (']');
+
+         when N_Raise_Storage_Error =>
+            Write_Indent;
+            Write_Str_With_Col_Check_Sloc ("[storage_error");
+
+            if Present (Condition (Node)) then
+               Write_Str_With_Col_Check (" when ");
+               Sprint_Node (Condition (Node));
+            end if;
+
+            Write_Char (']');
+
+         when N_Raise_Statement =>
+            Write_Indent_Str_Sloc ("raise ");
+            Sprint_Node (Name (Node));
+            Write_Char (';');
+
+         when N_Range =>
+            Sprint_Node (Low_Bound (Node));
+            Write_Str_Sloc (" .. ");
+            Sprint_Node (High_Bound (Node));
+
+         when N_Range_Constraint =>
+            Write_Str_With_Col_Check_Sloc ("range ");
+            Sprint_Node (Range_Expression (Node));
+
+         when N_Real_Literal =>
+            Write_Ureal_With_Col_Check_Sloc (Realval (Node));
+
+         when N_Real_Range_Specification =>
+            Write_Str_With_Col_Check_Sloc ("range ");
+            Sprint_Node (Low_Bound (Node));
+            Write_Str (" .. ");
+            Sprint_Node (High_Bound (Node));
+
+         when N_Record_Definition =>
+            if Abstract_Present (Node) then
+               Write_Str_With_Col_Check ("abstract ");
+            end if;
+
+            if Tagged_Present (Node) then
+               Write_Str_With_Col_Check ("tagged ");
+            end if;
+
+            if Limited_Present (Node) then
+               Write_Str_With_Col_Check ("limited ");
+            end if;
+
+            if Null_Present (Node) then
+               Write_Str_With_Col_Check_Sloc ("null record");
+
+            else
+               Write_Str_With_Col_Check_Sloc ("record");
+               Sprint_Node (Component_List (Node));
+               Write_Indent_Str ("end record");
+            end if;
+
+         when N_Record_Representation_Clause =>
+            Write_Indent_Str_Sloc ("for ");
+            Sprint_Node (Identifier (Node));
+            Write_Str_With_Col_Check (" use record ");
+
+            if Present (Mod_Clause (Node)) then
+               Sprint_Node (Mod_Clause (Node));
+            end if;
+
+            Sprint_Indented_List (Component_Clauses (Node));
+            Write_Indent_Str ("end record;");
+
+         when N_Reference =>
+            Sprint_Node (Prefix (Node));
+            Write_Str_With_Col_Check_Sloc ("'reference");
+
+         when N_Requeue_Statement =>
+            Write_Indent_Str_Sloc ("requeue ");
+            Sprint_Node (Name (Node));
+
+            if Abort_Present (Node) then
+               Write_Str_With_Col_Check (" with abort");
+            end if;
+
+            Write_Char (';');
+
+         when N_Return_Statement =>
+            if Present (Expression (Node)) then
+               Write_Indent_Str_Sloc ("return ");
+               Sprint_Node (Expression (Node));
+               Write_Char (';');
+            else
+               Write_Indent_Str_Sloc ("return;");
+            end if;
+
+         when N_Selective_Accept =>
+            Write_Indent_Str_Sloc ("select");
+
+            declare
+               Alt_Node : Node_Id;
+
+            begin
+               Alt_Node := First (Select_Alternatives (Node));
+               loop
+                  Indent_Begin;
+                  Sprint_Node (Alt_Node);
+                  Indent_End;
+                  Next (Alt_Node);
+                  exit when No (Alt_Node);
+                  Write_Indent_Str ("or");
+               end loop;
+            end;
+
+            if Present (Else_Statements (Node)) then
+               Write_Indent_Str ("else");
+               Sprint_Indented_List (Else_Statements (Node));
+            end if;
+
+            Write_Indent_Str ("end select;");
+
+         when N_Signed_Integer_Type_Definition =>
+            Write_Str_With_Col_Check_Sloc ("range ");
+            Sprint_Node (Low_Bound (Node));
+            Write_Str (" .. ");
+            Sprint_Node (High_Bound (Node));
+
+         when N_Single_Protected_Declaration =>
+            Write_Indent_Str_Sloc ("protected ");
+            Write_Id (Defining_Identifier (Node));
+            Write_Str (" is");
+            Sprint_Node (Protected_Definition (Node));
+            Write_Id (Defining_Identifier (Node));
+            Write_Char (';');
+
+         when N_Single_Task_Declaration =>
+            Write_Indent_Str_Sloc ("task ");
+            Write_Id (Defining_Identifier (Node));
+
+            if Present (Task_Definition (Node)) then
+               Write_Str (" is");
+               Sprint_Node (Task_Definition (Node));
+               Write_Id (Defining_Identifier (Node));
+            end if;
+
+            Write_Char (';');
+
+         when N_Selected_Component | N_Expanded_Name =>
+            Sprint_Node (Prefix (Node));
+            Write_Char_Sloc ('.');
+            Sprint_Node (Selector_Name (Node));
+
+         when N_Slice =>
+            Set_Debug_Sloc;
+            Sprint_Node (Prefix (Node));
+            Write_Str_With_Col_Check (" (");
+            Sprint_Node (Discrete_Range (Node));
+            Write_Char (')');
+
+         when N_String_Literal =>
+            if String_Length (Strval (Node)) + Column > 75 then
+               Write_Indent_Str ("  ");
+            end if;
+
+            Set_Debug_Sloc;
+            Write_String_Table_Entry (Strval (Node));
+
+         when N_Subprogram_Body =>
+            if Freeze_Indent = 0 then
+               Write_Indent;
+            end if;
+
+            Write_Indent;
+            Sprint_Node_Sloc (Specification (Node));
+            Write_Str (" is");
+
+            Sprint_Indented_List (Declarations (Node));
+            Write_Indent_Str ("begin");
+            Sprint_Node (Handled_Statement_Sequence (Node));
+
+            Write_Indent_Str ("end ");
+            Sprint_Node (Defining_Unit_Name (Specification (Node)));
+            Write_Char (';');
+
+            if Is_List_Member (Node)
+              and then Present (Next (Node))
+              and then Nkind (Next (Node)) /= N_Subprogram_Body
+            then
+               Write_Indent;
+            end if;
+
+         when N_Subprogram_Body_Stub =>
+            Write_Indent;
+            Sprint_Node_Sloc (Specification (Node));
+            Write_Str_With_Col_Check (" is separate;");
+
+         when N_Subprogram_Declaration =>
+            Write_Indent;
+            Sprint_Node_Sloc (Specification (Node));
+            Write_Char (';');
+
+         when N_Subprogram_Info =>
+            Sprint_Node (Identifier (Node));
+            Write_Str_With_Col_Check_Sloc ("'subprogram_info");
+
+         when N_Subprogram_Renaming_Declaration =>
+            Write_Indent;
+            Sprint_Node (Specification (Node));
+            Write_Str_With_Col_Check_Sloc (" renames ");
+            Sprint_Node (Name (Node));
+            Write_Char (';');
+
+         when N_Subtype_Declaration =>
+            Write_Indent_Str_Sloc ("subtype ");
+            Write_Id (Defining_Identifier (Node));
+            Write_Str (" is ");
+            Sprint_Node (Subtype_Indication (Node));
+            Write_Char (';');
+
+         when N_Subtype_Indication =>
+            Sprint_Node_Sloc (Subtype_Mark (Node));
+            Write_Char (' ');
+            Sprint_Node (Constraint (Node));
+
+         when N_Subunit =>
+            Write_Indent_Str_Sloc ("separate (");
+            Sprint_Node (Name (Node));
+            Write_Char (')');
+            Print_Eol;
+            Sprint_Node (Proper_Body (Node));
+
+         when N_Task_Body =>
+            Write_Indent_Str_Sloc ("task body ");
+            Write_Id (Defining_Identifier (Node));
+            Write_Str (" is");
+            Sprint_Indented_List (Declarations (Node));
+            Write_Indent_Str ("begin");
+            Sprint_Node (Handled_Statement_Sequence (Node));
+            Write_Indent_Str ("end ");
+            Write_Id (Defining_Identifier (Node));
+            Write_Char (';');
+
+         when N_Task_Body_Stub =>
+            Write_Indent_Str_Sloc ("task body ");
+            Write_Id (Defining_Identifier (Node));
+            Write_Str_With_Col_Check (" is separate;");
+
+         when N_Task_Definition =>
+            Set_Debug_Sloc;
+            Sprint_Indented_List (Visible_Declarations (Node));
+
+            if Present (Private_Declarations (Node)) then
+               Write_Indent_Str ("private");
+               Sprint_Indented_List (Private_Declarations (Node));
+            end if;
+
+            Write_Indent_Str ("end ");
+
+         when N_Task_Type_Declaration =>
+            Write_Indent_Str_Sloc ("task type ");
+            Write_Id (Defining_Identifier (Node));
+            Write_Discr_Specs (Node);
+            if Present (Task_Definition (Node)) then
+               Write_Str (" is");
+               Sprint_Node (Task_Definition (Node));
+               Write_Id (Defining_Identifier (Node));
+            end if;
+
+            Write_Char (';');
+
+         when N_Terminate_Alternative =>
+            Sprint_Node_List (Pragmas_Before (Node));
+
+            Write_Indent;
+
+            if Present (Condition (Node)) then
+               Write_Str_With_Col_Check ("when ");
+               Sprint_Node (Condition (Node));
+               Write_Str (" => ");
+            end if;
+
+            Write_Str_With_Col_Check_Sloc ("terminate;");
+            Sprint_Node_List (Pragmas_After (Node));
+
+         when N_Timed_Entry_Call =>
+            Write_Indent_Str_Sloc ("select");
+            Indent_Begin;
+            Sprint_Node (Entry_Call_Alternative (Node));
+            Indent_End;
+            Write_Indent_Str ("or");
+            Indent_Begin;
+            Sprint_Node (Delay_Alternative (Node));
+            Indent_End;
+            Write_Indent_Str ("end select;");
+
+         when N_Triggering_Alternative =>
+            Sprint_Node_List (Pragmas_Before (Node));
+            Sprint_Node_Sloc (Triggering_Statement (Node));
+            Sprint_Node_List (Statements (Node));
+
+         when N_Type_Conversion =>
+            Set_Debug_Sloc;
+            Sprint_Node (Subtype_Mark (Node));
+            Col_Check (4);
+
+            if Conversion_OK (Node) then
+               Write_Char ('?');
+            end if;
+
+            if Float_Truncate (Node) then
+               Write_Char ('^');
+            end if;
+
+            if Rounded_Result (Node) then
+               Write_Char ('@');
+            end if;
+
+            Write_Char ('(');
+            Sprint_Node (Expression (Node));
+            Write_Char (')');
+
+         when N_Unchecked_Expression =>
+            Col_Check (10);
+            Write_Str ("`(");
+            Sprint_Node_Sloc (Expression (Node));
+            Write_Char (')');
+
+         when N_Unchecked_Type_Conversion =>
+            Sprint_Node (Subtype_Mark (Node));
+            Write_Char ('!');
+            Write_Str_With_Col_Check ("(");
+            Sprint_Node_Sloc (Expression (Node));
+            Write_Char (')');
+
+         when N_Unconstrained_Array_Definition =>
+            Write_Str_With_Col_Check_Sloc ("array (");
+
+            declare
+               Node1 : Node_Id;
+
+            begin
+               Node1 := First (Subtype_Marks (Node));
+               loop
+                  Sprint_Node (Node1);
+                  Write_Str_With_Col_Check (" range <>");
+                  Next (Node1);
+                  exit when Node1 = Empty;
+                  Write_Str (", ");
+               end loop;
+            end;
+
+            Write_Str (") of ");
+
+            if Aliased_Present (Node) then
+               Write_Str_With_Col_Check ("aliased ");
+            end if;
+
+            Sprint_Node (Subtype_Indication (Node));
+
+         when N_Unused_At_Start | N_Unused_At_End =>
+            Write_Indent_Str ("***** Error, unused node encountered *****");
+            Print_Eol;
+
+         when N_Use_Package_Clause =>
+            Write_Indent_Str_Sloc ("use ");
+            Sprint_Comma_List (Names (Node));
+            Write_Char (';');
+
+         when N_Use_Type_Clause =>
+            Write_Indent_Str_Sloc ("use type ");
+            Sprint_Comma_List (Subtype_Marks (Node));
+            Write_Char (';');
+
+         when N_Validate_Unchecked_Conversion =>
+            Write_Indent_Str_Sloc ("validate unchecked_conversion (");
+            Sprint_Node (Source_Type (Node));
+            Write_Str (", ");
+            Sprint_Node (Target_Type (Node));
+            Write_Str (");");
+
+         when N_Variant =>
+            Write_Indent_Str_Sloc ("when ");
+            Sprint_Bar_List (Discrete_Choices (Node));
+            Write_Str (" => ");
+            Sprint_Node (Component_List (Node));
+
+         when N_Variant_Part =>
+            Indent_Begin;
+            Write_Indent_Str_Sloc ("case ");
+            Sprint_Node (Name (Node));
+            Write_Str (" is ");
+            Sprint_Indented_List (Variants (Node));
+            Write_Indent_Str ("end case");
+            Indent_End;
+
+         when N_With_Clause =>
+
+            --  Special test, if we are dumping the original tree only,
+            --  then we want to eliminate the bogus with clauses that
+            --  correspond to the non-existent children of Text_IO.
+
+            if Dump_Original_Only
+              and then Is_Text_IO_Kludge_Unit (Name (Node))
+            then
+               null;
+
+            --  Normal case, output the with clause
+
+            else
+               if First_Name (Node) or else not Dump_Original_Only then
+                  Write_Indent_Str ("with ");
+               else
+                  Write_Str (", ");
+               end if;
+
+               Sprint_Node_Sloc (Name (Node));
+
+               if Last_Name (Node) or else not Dump_Original_Only then
+                  Write_Char (';');
+               end if;
+            end if;
+
+         when N_With_Type_Clause =>
+
+            Write_Indent_Str ("with type ");
+            Sprint_Node_Sloc (Name (Node));
+
+            if Tagged_Present (Node) then
+               Write_Str (" is tagged;");
+            else
+               Write_Str (" is access;");
+            end if;
+
+      end case;
+
+      if Nkind (Node) in N_Subexpr
+        and then Do_Range_Check (Node)
+      then
+         Write_Str ("}");
+      end if;
+
+      for J in 1 .. Paren_Count (Node) loop
+         Write_Char (')');
+      end loop;
+
+      pragma Assert (No (Debug_Node));
+      Debug_Node := Save_Debug_Node;
+   end Sprint_Node_Actual;
+
+   ----------------------
+   -- Sprint_Node_List --
+   ----------------------
+
+   procedure Sprint_Node_List (List : List_Id) is
+      Node : Node_Id;
+
+   begin
+      if Is_Non_Empty_List (List) then
+         Node := First (List);
+
+         loop
+            Sprint_Node (Node);
+            Next (Node);
+            exit when Node = Empty;
+         end loop;
+      end if;
+   end Sprint_Node_List;
+
+   ----------------------
+   -- Sprint_Node_Sloc --
+   ----------------------
+
+   procedure Sprint_Node_Sloc (Node : Node_Id) is
+   begin
+      Sprint_Node (Node);
+
+      if Present (Debug_Node) then
+         Set_Sloc (Debug_Node, Sloc (Node));
+         Debug_Node := Empty;
+      end if;
+   end Sprint_Node_Sloc;
+
+   ---------------------
+   -- Sprint_Opt_Node --
+   ---------------------
+
+   procedure Sprint_Opt_Node (Node : Node_Id) is
+   begin
+      if Present (Node) then
+         Write_Char (' ');
+         Sprint_Node (Node);
+      end if;
+   end Sprint_Opt_Node;
+
+   --------------------------
+   -- Sprint_Opt_Node_List --
+   --------------------------
+
+   procedure Sprint_Opt_Node_List (List : List_Id) is
+   begin
+      if Present (List) then
+         Sprint_Node_List (List);
+      end if;
+   end Sprint_Opt_Node_List;
+
+   ---------------------------------
+   -- Sprint_Opt_Paren_Comma_List --
+   ---------------------------------
+
+   procedure Sprint_Opt_Paren_Comma_List (List : List_Id) is
+   begin
+      if Is_Non_Empty_List (List) then
+         Write_Char (' ');
+         Sprint_Paren_Comma_List (List);
+      end if;
+   end Sprint_Opt_Paren_Comma_List;
+
+   -----------------------------
+   -- Sprint_Paren_Comma_List --
+   -----------------------------
+
+   procedure Sprint_Paren_Comma_List (List : List_Id) is
+      N           : Node_Id;
+      Node_Exists : Boolean := False;
+
+   begin
+
+      if Is_Non_Empty_List (List) then
+
+         if Dump_Original_Only then
+            N := First (List);
+
+            while Present (N) loop
+
+               if not Is_Rewrite_Insertion (N) then
+                  Node_Exists := True;
+                  exit;
+               end if;
+
+               Next (N);
+            end loop;
+
+            if not Node_Exists then
+               return;
+            end if;
+         end if;
+
+         Write_Str_With_Col_Check ("(");
+         Sprint_Comma_List (List);
+         Write_Char (')');
+      end if;
+   end Sprint_Paren_Comma_List;
+
+   ---------------------
+   -- Write_Char_Sloc --
+   ---------------------
+
+   procedure Write_Char_Sloc (C : Character) is
+   begin
+      if Debug_Generated_Code and then C /= ' ' then
+         Set_Debug_Sloc;
+      end if;
+
+      Write_Char (C);
+   end Write_Char_Sloc;
+
+   ------------------------
+   --  Write_Discr_Specs --
+   ------------------------
+
+   procedure Write_Discr_Specs (N : Node_Id) is
+      Specs  : List_Id;
+      Spec   : Node_Id;
+
+   begin
+      Specs := Discriminant_Specifications (N);
+
+      if Present (Specs) then
+         Write_Str_With_Col_Check (" (");
+         Spec := First (Specs);
+
+         loop
+            Sprint_Node (Spec);
+            Next (Spec);
+            exit when Spec = Empty;
+
+            --  Add semicolon, unless we are printing original tree and the
+            --  next specification is part of a list (but not the first
+            --  element of that list)
+
+            if not Dump_Original_Only or else not Prev_Ids (Spec) then
+               Write_Str ("; ");
+            end if;
+         end loop;
+
+         Write_Char (')');
+      end if;
+   end Write_Discr_Specs;
+
+   -----------------
+   -- Write_Ekind --
+   -----------------
+
+   procedure Write_Ekind (E : Entity_Id) is
+      S : constant String := Entity_Kind'Image (Ekind (E));
+
+   begin
+      Name_Len := S'Length;
+      Name_Buffer (1 .. Name_Len) := S;
+      Set_Casing (Mixed_Case);
+      Write_Str_With_Col_Check (Name_Buffer (1 .. Name_Len));
+   end Write_Ekind;
+
+   --------------
+   -- Write_Id --
+   --------------
+
+   procedure Write_Id (N : Node_Id) is
+   begin
+      --  Case of a defining identifier
+
+      if Nkind (N) = N_Defining_Identifier then
+
+         --  If defining identifier has an interface name (and no
+         --  address clause), then we output the interface name.
+
+         if (Is_Imported (N) or else Is_Exported (N))
+           and then Present (Interface_Name (N))
+           and then No (Address_Clause (N))
+         then
+            String_To_Name_Buffer (Strval (Interface_Name (N)));
+            Write_Str_With_Col_Check (Name_Buffer (1 .. Name_Len));
+
+         --  If no interface name (or inactive because there was
+         --  an address clause), then just output the Chars name.
+
+         else
+            Write_Name_With_Col_Check (Chars (N));
+         end if;
+
+      --  Case of selector of an expanded name where the expanded name
+      --  has an associated entity, output this entity.
+
+      elsif Nkind (Parent (N)) = N_Expanded_Name
+        and then Selector_Name (Parent (N)) = N
+        and then Present (Entity (Parent (N)))
+      then
+         Write_Id (Entity (Parent (N)));
+
+      --  For any other kind of node with an associated entity, output it.
+
+      elsif Nkind (N) in N_Has_Entity
+        and then Present (Entity (N))
+      then
+         Write_Id (Entity (N));
+
+      --  All other cases, we just print the Chars field
+
+      else
+         Write_Name_With_Col_Check (Chars (N));
+      end if;
+   end Write_Id;
+
+   -----------------------
+   -- Write_Identifiers --
+   -----------------------
+
+   function Write_Identifiers (Node : Node_Id) return Boolean is
+   begin
+      Sprint_Node (Defining_Identifier (Node));
+
+      --  The remainder of the declaration must be printed unless we are
+      --  printing the original tree and this is not the last identifier
+
+      return
+         not Dump_Original_Only or else not More_Ids (Node);
+
+   end Write_Identifiers;
+
+   ------------------------
+   -- Write_Implicit_Def --
+   ------------------------
+
+   procedure Write_Implicit_Def (E : Entity_Id) is
+      Ind : Node_Id;
+
+   begin
+      case Ekind (E) is
+         when E_Array_Subtype =>
+            Write_Str_With_Col_Check ("subtype ");
+            Write_Id (E);
+            Write_Str_With_Col_Check (" is ");
+            Write_Id (Base_Type (E));
+            Write_Str_With_Col_Check (" (");
+
+            Ind := First_Index (E);
+
+            while Present (Ind) loop
+               Sprint_Node (Ind);
+               Next_Index (Ind);
+
+               if Present (Ind) then
+                  Write_Str (", ");
+               end if;
+            end loop;
+
+            Write_Str (");");
+
+         when E_Signed_Integer_Subtype | E_Enumeration_Subtype =>
+            Write_Str_With_Col_Check ("subtype ");
+            Write_Id (E);
+            Write_Str (" is ");
+            Write_Id (Etype (E));
+            Write_Str_With_Col_Check (" range ");
+            Sprint_Node (Scalar_Range (E));
+            Write_Str (";");
+
+         when others =>
+            Write_Str_With_Col_Check ("type ");
+            Write_Id (E);
+            Write_Str_With_Col_Check (" is <");
+            Write_Ekind (E);
+            Write_Str (">;");
+      end case;
+
+   end Write_Implicit_Def;
+
+   ------------------
+   -- Write_Indent --
+   ------------------
+
+   procedure Write_Indent is
+   begin
+      if Indent_Annull_Flag then
+         Indent_Annull_Flag := False;
+      else
+         Print_Eol;
+         for J in 1 .. Indent loop
+            Write_Char (' ');
+         end loop;
+      end if;
+   end Write_Indent;
+
+   ------------------------------
+   -- Write_Indent_Identifiers --
+   ------------------------------
+
+   function Write_Indent_Identifiers (Node : Node_Id) return Boolean is
+   begin
+      --  We need to start a new line for every node, except in the case
+      --  where we are printing the original tree and this is not the first
+      --  defining identifier in the list.
+
+      if not Dump_Original_Only or else not Prev_Ids (Node) then
+         Write_Indent;
+
+      --  If printing original tree and this is not the first defining
+      --  identifier in the list, then the previous call to this procedure
+      --  printed only the name, and we add a comma to separate the names.
+
+      else
+         Write_Str (", ");
+      end if;
+
+      Sprint_Node (Defining_Identifier (Node));
+
+      --  The remainder of the declaration must be printed unless we are
+      --  printing the original tree and this is not the last identifier
+
+      return
+         not Dump_Original_Only or else not More_Ids (Node);
+
+   end Write_Indent_Identifiers;
+
+   -----------------------------------
+   -- Write_Indent_Identifiers_Sloc --
+   -----------------------------------
+
+   function Write_Indent_Identifiers_Sloc (Node : Node_Id) return Boolean is
+   begin
+      --  We need to start a new line for every node, except in the case
+      --  where we are printing the original tree and this is not the first
+      --  defining identifier in the list.
+
+      if not Dump_Original_Only or else not Prev_Ids (Node) then
+         Write_Indent;
+
+      --  If printing original tree and this is not the first defining
+      --  identifier in the list, then the previous call to this procedure
+      --  printed only the name, and we add a comma to separate the names.
+
+      else
+         Write_Str (", ");
+      end if;
+
+      Set_Debug_Sloc;
+      Sprint_Node (Defining_Identifier (Node));
+
+      --  The remainder of the declaration must be printed unless we are
+      --  printing the original tree and this is not the last identifier
+
+      return
+         not Dump_Original_Only or else not More_Ids (Node);
+
+   end Write_Indent_Identifiers_Sloc;
+
+   ----------------------
+   -- Write_Indent_Str --
+   ----------------------
+
+   procedure Write_Indent_Str (S : String) is
+   begin
+      Write_Indent;
+      Write_Str (S);
+   end Write_Indent_Str;
+
+   ---------------------------
+   -- Write_Indent_Str_Sloc --
+   ---------------------------
+
+   procedure Write_Indent_Str_Sloc (S : String) is
+   begin
+      Write_Indent;
+      Write_Str_Sloc (S);
+   end Write_Indent_Str_Sloc;
+
+   -------------------------------
+   -- Write_Name_With_Col_Check --
+   -------------------------------
+
+   procedure Write_Name_With_Col_Check (N : Name_Id) is
+      J : Natural;
+
+   begin
+      Get_Name_String (N);
+
+      --  Deal with -gnatI which replaces digits in an internal
+      --  name by three dots (e.g. R7b becomes R...b).
+
+      if Debug_Flag_II and then Name_Buffer (1) in 'A' .. 'Z' then
+
+         J := 2;
+         while J < Name_Len loop
+            exit when Name_Buffer (J) not in 'A' .. 'Z';
+            J := J + 1;
+         end loop;
+
+         if Name_Buffer (J) in '0' .. '9' then
+            Write_Str_With_Col_Check (Name_Buffer (1 .. J - 1));
+            Write_Str ("...");
+
+            while J <= Name_Len loop
+               if Name_Buffer (J) not in '0' .. '9' then
+                  Write_Str (Name_Buffer (J .. Name_Len));
+                  exit;
+
+               else
+                  J := J + 1;
+               end if;
+            end loop;
+
+            return;
+         end if;
+      end if;
+
+      --  Fall through for normal case
+
+      Write_Str_With_Col_Check (Name_Buffer (1 .. Name_Len));
+   end Write_Name_With_Col_Check;
+
+   ------------------------------------
+   -- Write_Name_With_Col_Check_Sloc --
+   ------------------------------------
+
+   procedure Write_Name_With_Col_Check_Sloc (N : Name_Id) is
+   begin
+      Get_Name_String (N);
+      Write_Str_With_Col_Check_Sloc (Name_Buffer (1 .. Name_Len));
+   end Write_Name_With_Col_Check_Sloc;
+
+   --------------------
+   -- Write_Operator --
+   --------------------
+
+   procedure Write_Operator (N : Node_Id; S : String) is
+      F : Natural := S'First;
+      T : Natural := S'Last;
+
+   begin
+      if S (F) = ' ' then
+         Write_Char (' ');
+         F := F + 1;
+      end if;
+
+      if S (T) = ' ' then
+         T := T - 1;
+      end if;
+
+      if Do_Overflow_Check (N) then
+         Write_Char ('{');
+         Write_Str_Sloc (S (F .. T));
+         Write_Char ('}');
+      else
+         Write_Str_Sloc (S);
+      end if;
+
+      if S (S'Last) = ' ' then
+         Write_Char (' ');
+      end if;
+   end Write_Operator;
+
+   -----------------------
+   -- Write_Param_Specs --
+   -----------------------
+
+   procedure Write_Param_Specs (N : Node_Id) is
+      Specs  : List_Id;
+      Spec   : Node_Id;
+      Formal : Node_Id;
+
+   begin
+      Specs := Parameter_Specifications (N);
+
+      if Is_Non_Empty_List (Specs) then
+         Write_Str_With_Col_Check (" (");
+         Spec := First (Specs);
+
+         loop
+            Sprint_Node (Spec);
+            Formal := Defining_Identifier (Spec);
+            Next (Spec);
+            exit when Spec = Empty;
+
+            --  Add semicolon, unless we are printing original tree and the
+            --  next specification is part of a list (but not the first
+            --  element of that list)
+
+            if not Dump_Original_Only or else not Prev_Ids (Spec) then
+               Write_Str ("; ");
+            end if;
+         end loop;
+
+         --  Write out any extra formals
+
+         while Present (Extra_Formal (Formal)) loop
+            Formal := Extra_Formal (Formal);
+            Write_Str ("; ");
+            Write_Name_With_Col_Check (Chars (Formal));
+            Write_Str (" : ");
+            Write_Name_With_Col_Check (Chars (Etype (Formal)));
+         end loop;
+
+         Write_Char (')');
+      end if;
+   end Write_Param_Specs;
+
+   --------------------------
+   -- Write_Rewrite_Str --
+   --------------------------
+
+   procedure Write_Rewrite_Str (S : String) is
+   begin
+      if not Dump_Generated_Only then
+         if S'Length = 3 and then S = ">>>" then
+            Write_Str (">>>");
+         else
+            Write_Str_With_Col_Check (S);
+         end if;
+      end if;
+   end Write_Rewrite_Str;
+
+   --------------------
+   -- Write_Str_Sloc --
+   --------------------
+
+   procedure Write_Str_Sloc (S : String) is
+   begin
+      for J in S'Range loop
+         Write_Char_Sloc (S (J));
+      end loop;
+   end Write_Str_Sloc;
+
+   ------------------------------
+   -- Write_Str_With_Col_Check --
+   ------------------------------
+
+   procedure Write_Str_With_Col_Check (S : String) is
+   begin
+      if Int (S'Last) + Column > Line_Limit then
+         Write_Indent_Str ("  ");
+
+         if S (1) = ' ' then
+            Write_Str (S (2 .. S'Length));
+         else
+            Write_Str (S);
+         end if;
+
+      else
+         Write_Str (S);
+      end if;
+   end Write_Str_With_Col_Check;
+
+   -----------------------------------
+   -- Write_Str_With_Col_Check_Sloc --
+   -----------------------------------
+
+   procedure Write_Str_With_Col_Check_Sloc (S : String) is
+   begin
+      if Int (S'Last) + Column > Line_Limit then
+         Write_Indent_Str ("  ");
+
+         if S (1) = ' ' then
+            Write_Str_Sloc (S (2 .. S'Length));
+         else
+            Write_Str_Sloc (S);
+         end if;
+
+      else
+         Write_Str_Sloc (S);
+      end if;
+   end Write_Str_With_Col_Check_Sloc;
+
+   ------------------------------------
+   -- Write_Uint_With_Col_Check_Sloc --
+   ------------------------------------
+
+   procedure Write_Uint_With_Col_Check_Sloc (U : Uint; Format : UI_Format) is
+   begin
+      Col_Check (UI_Decimal_Digits_Hi (U));
+      Set_Debug_Sloc;
+      UI_Write (U, Format);
+   end Write_Uint_With_Col_Check_Sloc;
+
+   -------------------------------------
+   -- Write_Ureal_With_Col_Check_Sloc --
+   -------------------------------------
+
+   procedure Write_Ureal_With_Col_Check_Sloc (U : Ureal) is
+      D : constant Uint := Denominator (U);
+      N : constant Uint := Numerator (U);
+
+   begin
+      Col_Check
+        (UI_Decimal_Digits_Hi (D) + UI_Decimal_Digits_Hi (N) + 4);
+      Set_Debug_Sloc;
+      UR_Write (U);
+   end Write_Ureal_With_Col_Check_Sloc;
+
+end Sprint;
diff --git a/gcc/ada/sprint.ads b/gcc/ada/sprint.ads
new file mode 100644 (file)
index 0000000..d307eb7
--- /dev/null
@@ -0,0 +1,148 @@
+------------------------------------------------------------------------------
+--                                                                          --
+--                         GNAT COMPILER COMPONENTS                         --
+--                                                                          --
+--                               S P R I N T                                --
+--                                                                          --
+--                                 S p e c                                  --
+--                                                                          --
+--                            $Revision: 1.44 $
+--                                                                          --
+--          Copyright (C) 1992-1999, 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- --
+-- ware  Foundation;  either version 2,  or (at your option) any later ver- --
+-- sion.  GNAT is distributed in the hope that it will be useful, but WITH- --
+-- OUT ANY WARRANTY;  without even the  implied warranty of MERCHANTABILITY --
+-- or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License --
+-- for  more details.  You should have  received  a copy of the GNU General --
+-- Public License  distributed with GNAT;  see file COPYING.  If not, write --
+-- to  the Free Software Foundation,  59 Temple Place - Suite 330,  Boston, --
+-- MA 02111-1307, USA.                                                      --
+--                                                                          --
+-- GNAT was originally developed  by the GNAT team at  New York University. --
+-- It is now maintained by Ada Core Technologies Inc (http://www.gnat.com). --
+--                                                                          --
+------------------------------------------------------------------------------
+
+--  This package (source print) contains routines for printing the source
+--  program corresponding to a specified syntax tree. These routines are
+--  intended for debugging use in the compiler (not as a user level pretty
+--  print tool). Only information present in the tree is output (e.g. no
+--  comments are present in the output), and as far as possible we avoid
+--  making any assumptions about the correctness of the tree, so a bad
+--  tree may either blow up on a debugging check, or list incorrect source.
+
+with Types; use Types;
+package Sprint is
+
+   -----------------------
+   -- Syntax Extensions --
+   -----------------------
+
+   --  When the generated tree is printed, it contains constructs that are not
+   --  pure Ada. For convenience, syntactic extensions to Ada have been defined
+   --  purely for the purposes of this printout (they are not recognized by the
+   --  parser)
+
+   --    Allocator                           new xxx [storage_pool = xxx]
+   --    Cleanup action                      at end procedure name;
+   --    Conditional expression              (if expr then expr else expr)
+   --    Conversion wi Float_Truncate        target^(source)
+   --    Convert wi Conversion_OK            target?(source)
+   --    Convert wi Rounded_Result           target@(source)
+   --    Divide wi Treat_Fixed_As_Integer    x #/ y
+   --    Divide wi Rounded_Result            x @/ y
+   --    Expression with range check         {expression}
+   --    Operator with range check           {operator} (e.g. {+})
+   --    Free statement                      free expr [storage_pool = xxx]
+   --    Freeze entity with freeze actions   freeze entityname [ actions ]
+   --    Interpretation                      interpretation type [, entity]
+   --    Intrinsic calls                     function-name!(arg, arg, arg)
+   --    Itype reference                     reference itype
+   --    Label declaration                   labelname : label
+   --    Mod wi Treat_Fixed_As_Integer       x #mod y
+   --    Multiple concatenation              expr && expr && expr ... && expr
+   --    Multiply wi Treat_Fixed_As_Integer  x #* y
+   --    Multiply wi Rounded_Result          x @* y
+   --    Others choice for cleanup           when all others
+   --    Raise xxx error                     [xxx_error [when condition]]
+   --    Rational literal                    See UR_Write for details
+   --    Rem wi Treat_Fixed_As_Integer       x #rem y
+   --    Reference                           expression'reference
+   --    Shift nodes                         shift_name!(expr, count)
+   --    Subprogram_Info                     subprog'Subprogram_Info
+   --    Unchecked conversion                target_type!(source_expression)
+   --    Unchecked expression                `(expression)
+   --    Validate_Unchecked_Conversion       validate unchecked_conversion
+   --                                                  (src-type, target-typ);
+
+   --  Note: the storage_pool parameters for allocators and the free node
+   --  are omitted if the Storage_Pool field is Empty, indicating use of
+   --  the standard default pool.
+
+   -----------------
+   -- Subprograms --
+   -----------------
+
+   procedure Source_Dump;
+   --  This routine is called from the GNAT main program to dump source as
+   --  requested by debug options. The relevant debug options are:
+   --    -ds  print source from tree, both original and generated code
+   --    -dg  print source from tree, including only the generated code
+   --    -do  print source from tree, including only the original code
+   --    -df  modify the above to include all units, not just the main unit
+   --    -sz  print source from tree for package Standard
+
+   procedure Sprint_Comma_List (List : List_Id);
+   --  Prints the nodes in a list, with separating commas. If the list
+   --  is empty then no output is generated.
+
+   procedure Sprint_Paren_Comma_List (List : List_Id);
+   --  Prints the nodes in a list, surrounded by parentheses, and separated
+   --  by comas. If the list is empty, then no output is generated. A blank
+   --  is output before the initial left parenthesis.
+
+   procedure Sprint_Opt_Paren_Comma_List (List : List_Id);
+   --  Same as normal Sprint_Paren_Comma_List procedure, except that
+   --  an extra blank is output if List is non-empty, and nothing at all is
+   --  printed it the argument is No_List.
+
+   procedure Sprint_Node_List (List : List_Id);
+   --  Prints the nodes in a list with no separating characters. This is used
+   --  in the case of lists of items which are printed on separate lines using
+   --  the current indentation amount. Note that Sprint_Node_List itself
+   --  does not generate any New_Line calls.
+
+   procedure Sprint_Opt_Node_List (List : List_Id);
+   --  Like Sprint_Node_List, but prints nothing if List = No_List.
+
+   procedure Sprint_Indented_List (List : List_Id);
+   --  Like Sprint_Line_List, except that the indentation level is
+   --  increased before outputting the list of items, and then decremented
+   --  (back to its original level) before returning to the caller.
+
+   procedure Sprint_Node (Node : Node_Id);
+   --  Prints a single node. No new lines are output, except as required for
+   --  splitting lines that are too long to fit on a single physical line.
+   --  No output is generated at all if Node is Empty. No trailing or leading
+   --  blank characters are generated.
+
+   procedure Sprint_Opt_Node (Node : Node_Id);
+   --  Same as normal Sprint_Node procedure, except that one leading
+   --  blank is output before the node if it is non-empty.
+
+   procedure PG (Node : Node_Id);
+   --  Print generated source for node N (like -gnatdg output). This is
+   --  intended only for use from gdb for debugging purposes.
+
+   procedure PO (Node : Node_Id);
+   --  Print original source for node N (like -gnatdo output). This is
+   --  intended only for use from gdb for debugging purposes.
+
+   procedure PS (Node : Node_Id);
+   --  Print generated and original source for node N (like -gnatds output).
+   --  This is intended only for use from gdb for debugging purposes.
+
+end Sprint;
diff --git a/gcc/ada/stand.adb b/gcc/ada/stand.adb
new file mode 100644 (file)
index 0000000..b0001b1
--- /dev/null
@@ -0,0 +1,131 @@
+------------------------------------------------------------------------------
+--                                                                          --
+--                         GNAT COMPILER COMPONENTS                         --
+--                                                                          --
+--                                S T A N D                                 --
+--                                                                          --
+--                                 B o d y                                  --
+--                                                                          --
+--                            $Revision: 1.6 $                              --
+--                                                                          --
+--     Copyright (C) 1992,1993,1994,1995 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- --
+-- ware  Foundation;  either version 2,  or (at your option) any later ver- --
+-- sion.  GNAT is distributed in the hope that it will be useful, but WITH- --
+-- OUT ANY WARRANTY;  without even the  implied warranty of MERCHANTABILITY --
+-- or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License --
+-- for  more details.  You should have  received  a copy of the GNU General --
+-- Public License  distributed with GNAT;  see file COPYING.  If not, write --
+-- to  the Free Software Foundation,  59 Temple Place - Suite 330,  Boston, --
+-- MA 02111-1307, USA.                                                      --
+--                                                                          --
+-- As a special exception,  if other files  instantiate  generics from this --
+-- unit, or you link  this unit with other files  to produce an executable, --
+-- this  unit  does not  by itself cause  the resulting  executable  to  be --
+-- covered  by the  GNU  General  Public  License.  This exception does not --
+-- however invalidate  any other reasons why  the executable file  might be --
+-- covered by the  GNU Public License.                                      --
+--                                                                          --
+-- GNAT was originally developed  by the GNAT team at  New York University. --
+-- It is now maintained by Ada Core Technologies Inc (http://www.gnat.com). --
+--                                                                          --
+------------------------------------------------------------------------------
+
+with System;  use System;
+with Tree_IO; use Tree_IO;
+
+package body Stand is
+
+   ---------------
+   -- Tree_Read --
+   ---------------
+
+   procedure Tree_Read is
+   begin
+      Tree_Read_Data (Standard_Entity'Address,
+                       Standard_Entity_Array_Type'Size / Storage_Unit);
+
+      Tree_Read_Int (Int (Standard_Package_Node));
+      Tree_Read_Int (Int (Last_Standard_Node_Id));
+      Tree_Read_Int (Int (Last_Standard_List_Id));
+      Tree_Read_Int (Int (Standard_Void_Type));
+      Tree_Read_Int (Int (Standard_Exception_Type));
+      Tree_Read_Int (Int (Standard_A_String));
+      Tree_Read_Int (Int (Any_Id));
+      Tree_Read_Int (Int (Any_Type));
+      Tree_Read_Int (Int (Any_Access));
+      Tree_Read_Int (Int (Any_Array));
+      Tree_Read_Int (Int (Any_Boolean));
+      Tree_Read_Int (Int (Any_Character));
+      Tree_Read_Int (Int (Any_Composite));
+      Tree_Read_Int (Int (Any_Discrete));
+      Tree_Read_Int (Int (Any_Fixed));
+      Tree_Read_Int (Int (Any_Integer));
+      Tree_Read_Int (Int (Any_Numeric));
+      Tree_Read_Int (Int (Any_Real));
+      Tree_Read_Int (Int (Any_Scalar));
+      Tree_Read_Int (Int (Any_String));
+      Tree_Read_Int (Int (Universal_Integer));
+      Tree_Read_Int (Int (Universal_Real));
+      Tree_Read_Int (Int (Universal_Fixed));
+      Tree_Read_Int (Int (Standard_Integer_8));
+      Tree_Read_Int (Int (Standard_Integer_16));
+      Tree_Read_Int (Int (Standard_Integer_32));
+      Tree_Read_Int (Int (Standard_Integer_64));
+      Tree_Read_Int (Int (Abort_Signal));
+      Tree_Read_Int (Int (Standard_Op_Rotate_Left));
+      Tree_Read_Int (Int (Standard_Op_Rotate_Right));
+      Tree_Read_Int (Int (Standard_Op_Shift_Left));
+      Tree_Read_Int (Int (Standard_Op_Shift_Right));
+      Tree_Read_Int (Int (Standard_Op_Shift_Right_Arithmetic));
+
+   end Tree_Read;
+
+   ----------------
+   -- Tree_Write --
+   ----------------
+
+   procedure Tree_Write is
+   begin
+      Tree_Write_Data (Standard_Entity'Address,
+                       Standard_Entity_Array_Type'Size / Storage_Unit);
+
+      Tree_Write_Int (Int (Standard_Package_Node));
+      Tree_Write_Int (Int (Last_Standard_Node_Id));
+      Tree_Write_Int (Int (Last_Standard_List_Id));
+      Tree_Write_Int (Int (Standard_Void_Type));
+      Tree_Write_Int (Int (Standard_Exception_Type));
+      Tree_Write_Int (Int (Standard_A_String));
+      Tree_Write_Int (Int (Any_Id));
+      Tree_Write_Int (Int (Any_Type));
+      Tree_Write_Int (Int (Any_Access));
+      Tree_Write_Int (Int (Any_Array));
+      Tree_Write_Int (Int (Any_Boolean));
+      Tree_Write_Int (Int (Any_Character));
+      Tree_Write_Int (Int (Any_Composite));
+      Tree_Write_Int (Int (Any_Discrete));
+      Tree_Write_Int (Int (Any_Fixed));
+      Tree_Write_Int (Int (Any_Integer));
+      Tree_Write_Int (Int (Any_Numeric));
+      Tree_Write_Int (Int (Any_Real));
+      Tree_Write_Int (Int (Any_Scalar));
+      Tree_Write_Int (Int (Any_String));
+      Tree_Write_Int (Int (Universal_Integer));
+      Tree_Write_Int (Int (Universal_Real));
+      Tree_Write_Int (Int (Universal_Fixed));
+      Tree_Write_Int (Int (Standard_Integer_8));
+      Tree_Write_Int (Int (Standard_Integer_16));
+      Tree_Write_Int (Int (Standard_Integer_32));
+      Tree_Write_Int (Int (Standard_Integer_64));
+      Tree_Write_Int (Int (Abort_Signal));
+      Tree_Write_Int (Int (Standard_Op_Rotate_Left));
+      Tree_Write_Int (Int (Standard_Op_Rotate_Right));
+      Tree_Write_Int (Int (Standard_Op_Shift_Left));
+      Tree_Write_Int (Int (Standard_Op_Shift_Right));
+      Tree_Write_Int (Int (Standard_Op_Shift_Right_Arithmetic));
+
+   end Tree_Write;
+
+end Stand;
diff --git a/gcc/ada/stand.ads b/gcc/ada/stand.ads
new file mode 100644 (file)
index 0000000..65cfa4f
--- /dev/null
@@ -0,0 +1,456 @@
+------------------------------------------------------------------------------
+--                                                                          --
+--                         GNAT COMPILER COMPONENTS                         --
+--                                                                          --
+--                                S T A N D                                 --
+--                                                                          --
+--                                 S p e c                                  --
+--                                                                          --
+--                            $Revision: 1.68 $
+--                                                                          --
+--          Copyright (C) 1992-2001 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- --
+-- ware  Foundation;  either version 2,  or (at your option) any later ver- --
+-- sion.  GNAT is distributed in the hope that it will be useful, but WITH- --
+-- OUT ANY WARRANTY;  without even the  implied warranty of MERCHANTABILITY --
+-- or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License --
+-- for  more details.  You should have  received  a copy of the GNU General --
+-- Public License  distributed with GNAT;  see file COPYING.  If not, write --
+-- to  the Free Software Foundation,  59 Temple Place - Suite 330,  Boston, --
+-- MA 02111-1307, USA.                                                      --
+--                                                                          --
+-- As a special exception,  if other files  instantiate  generics from this --
+-- unit, or you link  this unit with other files  to produce an executable, --
+-- this  unit  does not  by itself cause  the resulting  executable  to  be --
+-- covered  by the  GNU  General  Public  License.  This exception does not --
+-- however invalidate  any other reasons why  the executable file  might be --
+-- covered by the  GNU Public License.                                      --
+--                                                                          --
+-- GNAT was originally developed  by the GNAT team at  New York University. --
+-- It is now maintained by Ada Core Technologies Inc (http://www.gnat.com). --
+--                                                                          --
+------------------------------------------------------------------------------
+
+--  This package contains the declarations of entities in package Standard,
+--  These values are initialized either by calling CStand.Create_Standard,
+--  or by calling Stand.Tree_Read.
+
+with Types; use Types;
+
+--  Do we really need the with of Namet?
+
+pragma Warnings (Off);
+with Namet; use Namet;
+pragma Elaborate_All (Namet);
+pragma Warnings (On);
+
+package Stand is
+
+   type Standard_Entity_Type is (
+   --  This enumeration type contains an entry for each name in Standard
+
+      --  Package names
+
+      S_Standard,
+      S_ASCII,
+
+      --  Types defined in package Standard
+
+      S_Boolean,
+      S_Character,
+      S_Wide_Character,
+      S_String,
+      S_Wide_String,
+      S_Duration,
+
+      S_Short_Short_Integer,
+      S_Short_Integer,
+      S_Integer,
+      S_Long_Integer,
+      S_Long_Long_Integer,
+
+      S_Short_Float,
+      S_Float,
+      S_Long_Float,
+      S_Long_Long_Float,
+
+      --  Enumeration literals for type Boolean
+
+      S_False,
+      S_True,
+
+      --  Subtypes declared in package Standard
+
+      S_Natural,
+      S_Positive,
+
+      --  Exceptions declared in package Standard
+
+      S_Constraint_Error,
+      S_Numeric_Error,
+      S_Program_Error,
+      S_Storage_Error,
+      S_Tasking_Error,
+
+      --  Binary Operators declared in package Standard.
+
+      S_Op_Add,
+      S_Op_And,
+      S_Op_Concat,
+      S_Op_Concatw,
+      S_Op_Divide,
+      S_Op_Eq,
+      S_Op_Expon,
+      S_Op_Ge,
+      S_Op_Gt,
+      S_Op_Le,
+      S_Op_Lt,
+      S_Op_Mod,
+      S_Op_Multiply,
+      S_Op_Ne,
+      S_Op_Or,
+      S_Op_Rem,
+      S_Op_Subtract,
+      S_Op_Xor,
+
+      --  Unary operators declared in package Standard
+
+      S_Op_Abs,
+      S_Op_Minus,
+      S_Op_Not,
+      S_Op_Plus,
+
+      --  Constants defined in package ASCII (with value in hex).
+      --  First the thirty-two C0 control characters)
+
+      S_NUL,            -- 16#00#
+      S_SOH,            -- 16#01#
+      S_STX,            -- 16#02#
+      S_ETX,            -- 16#03#
+      S_EOT,            -- 16#04#
+      S_ENQ,            -- 16#05#
+      S_ACK,            -- 16#06#
+      S_BEL,            -- 16#07#
+      S_BS,             -- 16#08#
+      S_HT,             -- 16#09#
+      S_LF,             -- 16#0A#
+      S_VT,             -- 16#0B#
+      S_FF,             -- 16#0C#
+      S_CR,             -- 16#0D#
+      S_SO,             -- 16#0E#
+      S_SI,             -- 16#0F#
+      S_DLE,            -- 16#10#
+      S_DC1,            -- 16#11#
+      S_DC2,            -- 16#12#
+      S_DC3,            -- 16#13#
+      S_DC4,            -- 16#14#
+      S_NAK,            -- 16#15#
+      S_SYN,            -- 16#16#
+      S_ETB,            -- 16#17#
+      S_CAN,            -- 16#18#
+      S_EM,             -- 16#19#
+      S_SUB,            -- 16#1A#
+      S_ESC,            -- 16#1B#
+      S_FS,             -- 16#1C#
+      S_GS,             -- 16#1D#
+      S_RS,             -- 16#1E#
+      S_US,             -- 16#1F#
+
+      --  Here are the ones for Colonel Whitaker's O26 keypunch!
+
+      S_Exclam,         -- 16#21#
+      S_Quotation,      -- 16#22#
+      S_Sharp,          -- 16#23#
+      S_Dollar,         -- 16#24#
+      S_Percent,        -- 16#25#
+      S_Ampersand,      -- 16#26#
+
+      S_Colon,          -- 16#3A#
+      S_Semicolon,      -- 16#3B#
+
+      S_Query,          -- 16#3F#
+      S_At_Sign,        -- 16#40#
+
+      S_L_Bracket,      -- 16#5B#
+      S_Back_Slash,     -- 16#5C#
+      S_R_Bracket,      -- 16#5D#
+      S_Circumflex,     -- 16#5E#
+      S_Underline,      -- 16#5F#
+      S_Grave,          -- 16#60#
+
+      S_LC_A,           -- 16#61#
+      S_LC_B,           -- 16#62#
+      S_LC_C,           -- 16#63#
+      S_LC_D,           -- 16#64#
+      S_LC_E,           -- 16#65#
+      S_LC_F,           -- 16#66#
+      S_LC_G,           -- 16#67#
+      S_LC_H,           -- 16#68#
+      S_LC_I,           -- 16#69#
+      S_LC_J,           -- 16#6A#
+      S_LC_K,           -- 16#6B#
+      S_LC_L,           -- 16#6C#
+      S_LC_M,           -- 16#6D#
+      S_LC_N,           -- 16#6E#
+      S_LC_O,           -- 16#6F#
+      S_LC_P,           -- 16#70#
+      S_LC_Q,           -- 16#71#
+      S_LC_R,           -- 16#72#
+      S_LC_S,           -- 16#73#
+      S_LC_T,           -- 16#74#
+      S_LC_U,           -- 16#75#
+      S_LC_V,           -- 16#76#
+      S_LC_W,           -- 16#77#
+      S_LC_X,           -- 16#78#
+      S_LC_Y,           -- 16#79#
+      S_LC_Z,           -- 16#7A#
+
+      S_L_BRACE,        -- 16#7B#
+      S_BAR,            -- 16#7C#
+      S_R_BRACE,        -- 16#7D#
+      S_TILDE,          -- 16#7E#
+
+      --  And one more control character, all on its own
+
+      S_DEL);           -- 16#7F#
+
+   subtype S_Types is
+     Standard_Entity_Type range S_Boolean .. S_Long_Long_Float;
+
+   subtype S_Exceptions is
+     Standard_Entity_Type range S_Constraint_Error .. S_Tasking_Error;
+
+   subtype S_ASCII_Names is
+     Standard_Entity_Type range S_NUL .. S_DEL;
+
+   subtype S_Binary_Ops is
+      Standard_Entity_Type range S_Op_Add .. S_Op_Xor;
+
+   subtype S_Unary_Ops is
+      Standard_Entity_Type range S_Op_Abs .. S_Op_Plus;
+
+   type Standard_Entity_Array_Type is array (Standard_Entity_Type) of Node_Id;
+
+   Standard_Entity : Standard_Entity_Array_Type;
+   --  This array contains pointers to the Defining Identifier nodes
+   --  for each of the entities defined in Standard_Entities_Type. It
+   --  is initialized by the Create_Standard procedure.
+
+   Standard_Package_Node : Node_Id;
+   --  Points to the N_Package_Declaration node for standard. Also
+   --  initialized by the Create_Standard procedure.
+
+   --  The following Entities are the pointers to the Defining Identifier
+   --  nodes for some visible entities defined in Standard_Entities_Type.
+
+   SE : Standard_Entity_Array_Type renames Standard_Entity;
+
+   Standard_Standard            : Entity_Id renames SE (S_Standard);
+
+   Standard_ASCII               : Entity_Id renames SE (S_ASCII);
+   Standard_Character           : Entity_Id renames SE (S_Character);
+   Standard_Wide_Character      : Entity_Id renames SE (S_Wide_Character);
+   Standard_String              : Entity_Id renames SE (S_String);
+   Standard_Wide_String         : Entity_Id renames SE (S_Wide_String);
+
+   Standard_Boolean             : Entity_Id renames SE (S_Boolean);
+   Standard_False               : Entity_Id renames SE (S_False);
+   Standard_True                : Entity_Id renames SE (S_True);
+
+   Standard_Duration            : Entity_Id renames SE (S_Duration);
+
+   Standard_Natural             : Entity_Id renames SE (S_Natural);
+   Standard_Positive            : Entity_Id renames SE (S_Positive);
+
+   Standard_Constraint_Error    : Entity_Id renames SE (S_Constraint_Error);
+   Standard_Numeric_Error       : Entity_Id renames SE (S_Numeric_Error);
+   Standard_Program_Error       : Entity_Id renames SE (S_Program_Error);
+   Standard_Storage_Error       : Entity_Id renames SE (S_Storage_Error);
+   Standard_Tasking_Error       : Entity_Id renames SE (S_Tasking_Error);
+
+   Standard_Short_Float         : Entity_Id renames SE (S_Short_Float);
+   Standard_Float               : Entity_Id renames SE (S_Float);
+   Standard_Long_Float          : Entity_Id renames SE (S_Long_Float);
+   Standard_Long_Long_Float     : Entity_Id renames SE (S_Long_Long_Float);
+
+   Standard_Short_Short_Integer : Entity_Id renames SE (S_Short_Short_Integer);
+   Standard_Short_Integer       : Entity_Id renames SE (S_Short_Integer);
+   Standard_Integer             : Entity_Id renames SE (S_Integer);
+   Standard_Long_Integer        : Entity_Id renames SE (S_Long_Integer);
+   Standard_Long_Long_Integer   : Entity_Id renames SE (S_Long_Long_Integer);
+
+   Standard_Op_Add              : Entity_Id renames SE (S_Op_Add);
+   Standard_Op_And              : Entity_Id renames SE (S_Op_And);
+   Standard_Op_Concat           : Entity_Id renames SE (S_Op_Concat);
+   Standard_Op_Concatw          : Entity_Id renames SE (S_Op_Concatw);
+   Standard_Op_Divide           : Entity_Id renames SE (S_Op_Divide);
+   Standard_Op_Eq               : Entity_Id renames SE (S_Op_Eq);
+   Standard_Op_Expon            : Entity_Id renames SE (S_Op_Expon);
+   Standard_Op_Ge               : Entity_Id renames SE (S_Op_Ge);
+   Standard_Op_Gt               : Entity_Id renames SE (S_Op_Gt);
+   Standard_Op_Le               : Entity_Id renames SE (S_Op_Le);
+   Standard_Op_Lt               : Entity_Id renames SE (S_Op_Lt);
+   Standard_Op_Mod              : Entity_Id renames SE (S_Op_Mod);
+   Standard_Op_Multiply         : Entity_Id renames SE (S_Op_Multiply);
+   Standard_Op_Ne               : Entity_Id renames SE (S_Op_Ne);
+   Standard_Op_Or               : Entity_Id renames SE (S_Op_Or);
+   Standard_Op_Rem              : Entity_Id renames SE (S_Op_Rem);
+   Standard_Op_Subtract         : Entity_Id renames SE (S_Op_Subtract);
+   Standard_Op_Xor              : Entity_Id renames SE (S_Op_Xor);
+
+   Standard_Op_Abs              : Entity_Id renames SE (S_Op_Abs);
+   Standard_Op_Minus            : Entity_Id renames SE (S_Op_Minus);
+   Standard_Op_Not              : Entity_Id renames SE (S_Op_Not);
+   Standard_Op_Plus             : Entity_Id renames SE (S_Op_Plus);
+
+   Last_Standard_Node_Id : Node_Id;
+   --  Highest Node_Id value used by Standard
+
+   Last_Standard_List_Id : List_Id;
+   --  Highest List_Id value used by Standard (including those used by
+   --  normal list headers, element list headers, and list elements)
+
+   -------------------------------------
+   -- Semantic Phase Special Entities --
+   -------------------------------------
+
+   --  The semantic phase needs a number of entities for internal processing
+   --  that are logically at the level of Standard, and hence defined in this
+   --  package. However, they are never visible to a program, and are not
+   --  chained on to the Decls list of Standard. The names of all these
+   --  types are relevant only in certain debugging and error message
+   --  situations. They have names that are suitable for use in such
+   --  error messages (see body for actual names used).
+
+   Standard_Void_Type  : Entity_Id;
+   --  This is a type used to represent the return type of procedures
+
+   Standard_Exception_Type  : Entity_Id;
+   --  This is a type used to represent the Etype of exceptions.
+
+   Standard_A_String   : Entity_Id;
+   --  An access to String type used for building elements of tables
+   --  carrying the enumeration literal names.
+
+   Standard_A_Char : Entity_Id;
+   --  Access to character, used as a component of the exception type to
+   --  denote a thin pointer component.
+
+   --  The entities labeled Any_xxx are used in situations where the full
+   --  characteristics of an entity are not yet known, e.g. Any_Character
+   --  is used to label a character literal before resolution is complete.
+   --  These entities are also used to construct appropriate references in
+   --  error messages ("expecting an integer type").
+
+   Any_Id : Entity_Id;
+   --  Used to represent some unknown identifier. Used to lable undefined
+   --  identifier references to prevent cascaded errors.
+
+   Any_Type : Entity_Id;
+   --  Used to represent some unknown type. Plays an important role in
+   --  avoiding cascaded errors, since any node that remains labaled with
+   --  this type corresponds to an already issued error message. Any_Type
+   --  is propagated to avoid cascaded errors from a single type error.
+
+   Any_Access : Entity_Id;
+   --  Used to resolve the overloaded literal NULL.
+
+   Any_Array : Entity_Id;
+   --  Used to represent some unknown array type
+
+   Any_Boolean : Entity_Id;
+   --  The context type of conditions in IF and WHILE statements.
+
+   Any_Character : Entity_Id;
+   --  Any_Character is used to label character literals, which in general
+   --  will not have an explicit declaration (this is true of the predefined
+   --  character types).
+
+   Any_Composite : Entity_Id;
+   --  The type Any_Composite is used for aggregates before type resolution.
+   --  It is compatible with any array or non-limited record type.
+
+   Any_Discrete : Entity_Id;
+   --  Used to represent some unknown discrete type
+
+   Any_Fixed : Entity_Id;
+   --  Used to represent some unknown fixed-point type
+
+   Any_Integer : Entity_Id;
+   --  Used to represent some unknown integer type.
+
+   Any_Modular : Entity_Id;
+   --  Used to represent the result type of a boolean operation on an
+   --  integer literal. The result is not Universal_Integer, because it is
+   --  only legal in a modular context.
+
+   Any_Numeric : Entity_Id;
+   --  Used to represent some unknown numeric type.
+
+   Any_Real : Entity_Id;
+   --  Used to represent some unknown real type.
+
+   Any_Scalar : Entity_Id;
+   --  Used to represent some unknown scalar type
+
+   Any_String : Entity_Id;
+   --  The type Any_String is used for string literals before type
+   --  resolution. It corresponds to array (Positive range <>) of character
+   --  where the component type is compatible with any character type,
+   --  not just Standard_Character.
+
+   Universal_Integer : Entity_Id;
+   --  Entity for universal integer type. The bounds of this type correspond
+   --  to the largest supported integer type (i.e. Long_Long_Integer). It is
+   --  the type used for runtime calculations in type universal integer.
+
+   Universal_Real : Entity_Id;
+   --  Entity for universal real type. The bounds of this type correspond to
+   --  to the largest supported real type (i.e. Long_Long_Real). It is the
+   --  type used for runtime calculations in type universal real.
+
+   Universal_Fixed : Entity_Id;
+   --  Entity for universal fixed type. This is a type with  arbitrary
+   --  precision that can only appear in  a context with a specific type.
+   --  Universal_Fixed labels the result of multiplication or division of
+   --  two fixed point numbers, and has no specified bounds (since, unlike
+   --  universal integer and universal real, it is never used for runtime
+   --  calculations).
+
+   Standard_Integer_8  : Entity_Id;
+   Standard_Integer_16 : Entity_Id;
+   Standard_Integer_32 : Entity_Id;
+   Standard_Integer_64 : Entity_Id;
+   --  These are signed integer types with the indicated sizes, They are
+   --  used for the underlying implementation types for fixed-point and
+   --  enumeration types.
+
+   Standard_Unsigned : Entity_Id;
+   --  An unsigned type of the same size as Standard_Integer
+
+   Abort_Signal : Entity_Id;
+   --  Entity for abort signal exception
+
+   Standard_Op_Rotate_Left            : Entity_Id;
+   Standard_Op_Rotate_Right           : Entity_Id;
+   Standard_Op_Shift_Left             : Entity_Id;
+   Standard_Op_Shift_Right            : Entity_Id;
+   Standard_Op_Shift_Right_Arithmetic : Entity_Id;
+   --  These entities are used for shift operators generated by the expander
+
+   -----------------
+   -- Subprograms --
+   -----------------
+
+   procedure Tree_Read;
+   --  Initializes entity values in this package from the current tree
+   --  file using Osint.Tree_Read. Note that Tree_Read includes all the
+   --  initialization that is carried out by Create_Standard.
+
+   procedure Tree_Write;
+   --  Writes out the entity values in this package to the current
+   --  tree file using Osint.Tree_Write.
+
+end Stand;
diff --git a/gcc/ada/stringt.adb b/gcc/ada/stringt.adb
new file mode 100644 (file)
index 0000000..b2631ad
--- /dev/null
@@ -0,0 +1,419 @@
+------------------------------------------------------------------------------
+--                                                                          --
+--                         GNAT COMPILER COMPONENTS                         --
+--                                                                          --
+--                              S T R I N G T                               --
+--                                                                          --
+--                                 B o d y                                  --
+--                                                                          --
+--                            $Revision: 1.43 $
+--                                                                          --
+--          Copyright (C) 1992-2001 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- --
+-- ware  Foundation;  either version 2,  or (at your option) any later ver- --
+-- sion.  GNAT is distributed in the hope that it will be useful, but WITH- --
+-- OUT ANY WARRANTY;  without even the  implied warranty of MERCHANTABILITY --
+-- or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License --
+-- for  more details.  You should have  received  a copy of the GNU General --
+-- Public License  distributed with GNAT;  see file COPYING.  If not, write --
+-- to  the Free Software Foundation,  59 Temple Place - Suite 330,  Boston, --
+-- MA 02111-1307, USA.                                                      --
+--                                                                          --
+-- As a special exception,  if other files  instantiate  generics from this --
+-- unit, or you link  this unit with other files  to produce an executable, --
+-- this  unit  does not  by itself cause  the resulting  executable  to  be --
+-- covered  by the  GNU  General  Public  License.  This exception does not --
+-- however invalidate  any other reasons why  the executable file  might be --
+-- covered by the  GNU Public License.                                      --
+--                                                                          --
+-- GNAT was originally developed  by the GNAT team at  New York University. --
+-- It is now maintained by Ada Core Technologies Inc (http://www.gnat.com). --
+--                                                                          --
+------------------------------------------------------------------------------
+
+with Alloc;
+with Namet;  use Namet;
+with Output; use Output;
+with Table;
+
+package body Stringt is
+
+   --  The following table stores the sequence of character codes for the
+   --  stored string constants. The entries are referenced from the
+   --  separate Strings table.
+
+   package String_Chars is new Table.Table (
+     Table_Component_Type => Char_Code,
+     Table_Index_Type     => Int,
+     Table_Low_Bound      => 0,
+     Table_Initial        => Alloc.String_Chars_Initial,
+     Table_Increment      => Alloc.String_Chars_Increment,
+     Table_Name           => "String_Chars");
+
+   --  The String_Id values reference entries in the Strings table, which
+   --  contains String_Entry records that record the length of each stored
+   --  string and its starting location in the String_Chars table.
+
+   type String_Entry is record
+      String_Index : Int;
+      Length       : Nat;
+   end record;
+
+   package Strings is new Table.Table (
+     Table_Component_Type => String_Entry,
+     Table_Index_Type     => String_Id,
+     Table_Low_Bound      => First_String_Id,
+     Table_Initial        => Alloc.Strings_Initial,
+     Table_Increment      => Alloc.Strings_Increment,
+     Table_Name           => "Strings");
+
+   --  Note: it is possible that two entries in the Strings table can share
+   --  string data in the String_Chars table, and in particular this happens
+   --  when Start_String is called with a parameter that is the last string
+   --  currently allocated in the table.
+
+   -------------------------------
+   -- Add_String_To_Name_Buffer --
+   -------------------------------
+
+   procedure Add_String_To_Name_Buffer (S : String_Id) is
+      Len : constant Natural := Natural (String_Length (S));
+   begin
+      for J in 1 .. Len loop
+         Name_Buffer (Name_Len + J) :=
+           Get_Character (Get_String_Char (S, Int (J)));
+      end loop;
+
+      Name_Len := Name_Len + Len;
+   end Add_String_To_Name_Buffer;
+
+   ----------------
+   -- End_String --
+   ----------------
+
+   function End_String return String_Id is
+   begin
+      return Strings.Last;
+   end End_String;
+
+   ---------------------
+   -- Get_String_Char --
+   ---------------------
+
+   function Get_String_Char (Id : String_Id; Index : Int) return Char_Code is
+   begin
+      pragma Assert (Id in First_String_Id .. Strings.Last
+                       and then Index in 1 .. Strings.Table (Id).Length);
+
+      return String_Chars.Table (Strings.Table (Id).String_Index + Index - 1);
+   end Get_String_Char;
+
+   ----------------
+   -- Initialize --
+   ----------------
+
+   procedure Initialize is
+   begin
+      String_Chars.Init;
+      Strings.Init;
+   end Initialize;
+
+   ----------
+   -- Lock --
+   ----------
+
+   procedure Lock is
+   begin
+      String_Chars.Locked := True;
+      Strings.Locked := True;
+      String_Chars.Release;
+      Strings.Release;
+   end Lock;
+
+   ------------------
+   -- Start_String --
+   ------------------
+
+   --  Version to start completely new string
+
+   procedure Start_String is
+   begin
+      Strings.Increment_Last;
+      Strings.Table (Strings.Last).String_Index := String_Chars.Last + 1;
+      Strings.Table (Strings.Last).Length := 0;
+   end Start_String;
+
+   --  Version to start from initially stored string
+
+   procedure Start_String (S : String_Id) is
+   begin
+      Strings.Increment_Last;
+
+      --  Case of initial string value is at the end of the string characters
+      --  table, so it does not need copying, instead it can be shared.
+
+      if Strings.Table (S).String_Index + Strings.Table (S).Length =
+                                                    String_Chars.Last + 1
+      then
+         Strings.Table (Strings.Last).String_Index :=
+           Strings.Table (S).String_Index;
+
+      --  Case of initial string value must be copied to new string
+
+      else
+         Strings.Table (Strings.Last).String_Index :=
+           String_Chars.Last + 1;
+
+         for J in 1 .. Strings.Table (S).Length loop
+            String_Chars.Increment_Last;
+            String_Chars.Table (String_Chars.Last) :=
+              String_Chars.Table (Strings.Table (S).String_Index + (J - 1));
+         end loop;
+      end if;
+
+      --  In either case the result string length is copied from the argument
+
+      Strings.Table (Strings.Last).Length := Strings.Table (S).Length;
+   end Start_String;
+
+   -----------------------
+   -- Store_String_Char --
+   -----------------------
+
+   procedure Store_String_Char (C : Char_Code) is
+   begin
+      String_Chars.Increment_Last;
+      String_Chars.Table (String_Chars.Last) := C;
+      Strings.Table (Strings.Last).Length :=
+        Strings.Table (Strings.Last).Length + 1;
+   end Store_String_Char;
+
+   procedure Store_String_Char (C : Character) is
+   begin
+      Store_String_Char (Get_Char_Code (C));
+   end Store_String_Char;
+
+   ------------------------
+   -- Store_String_Chars --
+   ------------------------
+
+   procedure Store_String_Chars (S : String) is
+   begin
+      for J in S'First .. S'Last loop
+         Store_String_Char (Get_Char_Code (S (J)));
+      end loop;
+   end Store_String_Chars;
+
+   procedure Store_String_Chars (S : String_Id) is
+   begin
+      for J in 1 .. String_Length (S) loop
+         Store_String_Char (Get_String_Char (S, J));
+      end loop;
+   end Store_String_Chars;
+
+   ----------------------
+   -- Store_String_Int --
+   ----------------------
+
+   procedure Store_String_Int (N : Int) is
+   begin
+      if N < 0 then
+         Store_String_Char ('-');
+         Store_String_Int (-N);
+
+      else
+         if N > 9 then
+            Store_String_Int (N / 10);
+         end if;
+
+         Store_String_Char (Character'Val (Character'Pos ('0') + N mod 10));
+      end if;
+   end Store_String_Int;
+
+   --------------------------
+   -- String_Chars_Address --
+   --------------------------
+
+   function String_Chars_Address return System.Address is
+   begin
+      return String_Chars.Table (0)'Address;
+   end String_Chars_Address;
+
+   ------------------
+   -- String_Equal --
+   ------------------
+
+   function String_Equal (L, R : String_Id) return Boolean is
+      Len : constant Nat := Strings.Table (L).Length;
+
+   begin
+      if Len /= Strings.Table (R).Length then
+         return False;
+      else
+         for J in 1 .. Len loop
+            if Get_String_Char (L, J) /= Get_String_Char (R, J) then
+               return False;
+            end if;
+         end loop;
+
+         return True;
+      end if;
+   end String_Equal;
+
+   -----------------------------
+   -- String_From_Name_Buffer --
+   -----------------------------
+
+   function String_From_Name_Buffer return String_Id is
+   begin
+      Start_String;
+
+      for J in 1 .. Name_Len loop
+         Store_String_Char (Get_Char_Code (Name_Buffer (J)));
+      end loop;
+
+      return End_String;
+   end String_From_Name_Buffer;
+
+   -------------------
+   -- String_Length --
+   -------------------
+
+   function String_Length (Id : String_Id) return Nat is
+   begin
+      return Strings.Table (Id).Length;
+   end String_Length;
+
+   ---------------------------
+   -- String_To_Name_Buffer --
+   ---------------------------
+
+   procedure String_To_Name_Buffer (S : String_Id) is
+   begin
+      Name_Len := Natural (String_Length (S));
+
+      for J in 1 .. Name_Len loop
+         Name_Buffer (J) :=
+           Get_Character (Get_String_Char (S, Int (J)));
+      end loop;
+   end String_To_Name_Buffer;
+
+   ---------------------
+   -- Strings_Address --
+   ---------------------
+
+   function Strings_Address return System.Address is
+   begin
+      return Strings.Table (First_String_Id)'Address;
+   end Strings_Address;
+
+   ---------------
+   -- Tree_Read --
+   ---------------
+
+   procedure Tree_Read is
+   begin
+      String_Chars.Tree_Read;
+      Strings.Tree_Read;
+   end Tree_Read;
+
+   ----------------
+   -- Tree_Write --
+   ----------------
+
+   procedure Tree_Write is
+   begin
+      String_Chars.Tree_Write;
+      Strings.Tree_Write;
+   end Tree_Write;
+
+   ------------
+   -- Unlock --
+   ------------
+
+   procedure Unlock is
+   begin
+      String_Chars.Locked := False;
+      Strings.Locked := False;
+   end Unlock;
+
+   -------------------------
+   -- Unstore_String_Char --
+   -------------------------
+
+   procedure Unstore_String_Char is
+   begin
+      String_Chars.Decrement_Last;
+      Strings.Table (Strings.Last).Length :=
+        Strings.Table (Strings.Last).Length - 1;
+   end Unstore_String_Char;
+
+   ---------------------
+   -- Write_Char_Code --
+   ---------------------
+
+   procedure Write_Char_Code (Code : Char_Code) is
+
+      procedure Write_Hex_Byte (J : Natural);
+      --  Write single hex digit
+
+      procedure Write_Hex_Byte (J : Natural) is
+         Hexd : String := "0123456789abcdef";
+
+      begin
+         Write_Char (Hexd (J / 16 + 1));
+         Write_Char (Hexd (J mod 16 + 1));
+      end Write_Hex_Byte;
+
+   --  Start of processing for Write_Char_Code
+
+   begin
+      if Code in 16#20# .. 16#7E# then
+         Write_Char (Character'Val (Code));
+
+      else
+         Write_Char ('[');
+         Write_Char ('"');
+
+         if Code > 16#FF# then
+            Write_Hex_Byte (Natural (Code / 256));
+         end if;
+
+         Write_Hex_Byte (Natural (Code mod 256));
+         Write_Char ('"');
+         Write_Char (']');
+      end if;
+   end Write_Char_Code;
+
+   ------------------------------
+   -- Write_String_Table_Entry --
+   ------------------------------
+
+   procedure Write_String_Table_Entry (Id : String_Id) is
+      C : Char_Code;
+
+   begin
+      if Id = No_String then
+         Write_Str ("no string");
+
+      else
+         Write_Char ('"');
+
+         for J in 1 .. String_Length (Id) loop
+            C := Get_String_Char (Id, J);
+
+            if Character'Val (C) = '"' then
+               Write_Str ("""""");
+
+            else
+               Write_Char_Code (C);
+            end if;
+         end loop;
+
+         Write_Char ('"');
+      end if;
+   end Write_String_Table_Entry;
+
+end Stringt;
diff --git a/gcc/ada/stringt.ads b/gcc/ada/stringt.ads
new file mode 100644 (file)
index 0000000..0d4350e
--- /dev/null
@@ -0,0 +1,161 @@
+------------------------------------------------------------------------------
+--                                                                          --
+--                         GNAT COMPILER COMPONENTS                         --
+--                                                                          --
+--                              S T R I N G T                               --
+--                                                                          --
+--                                 S p e c                                  --
+--                                                                          --
+--                            $Revision: 1.39 $
+--                                                                          --
+--          Copyright (C) 1992-2001 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- --
+-- ware  Foundation;  either version 2,  or (at your option) any later ver- --
+-- sion.  GNAT is distributed in the hope that it will be useful, but WITH- --
+-- OUT ANY WARRANTY;  without even the  implied warranty of MERCHANTABILITY --
+-- or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License --
+-- for  more details.  You should have  received  a copy of the GNU General --
+-- Public License  distributed with GNAT;  see file COPYING.  If not, write --
+-- to  the Free Software Foundation,  59 Temple Place - Suite 330,  Boston, --
+-- MA 02111-1307, USA.                                                      --
+--                                                                          --
+-- As a special exception,  if other files  instantiate  generics from this --
+-- unit, or you link  this unit with other files  to produce an executable, --
+-- this  unit  does not  by itself cause  the resulting  executable  to  be --
+-- covered  by the  GNU  General  Public  License.  This exception does not --
+-- however invalidate  any other reasons why  the executable file  might be --
+-- covered by the  GNU Public License.                                      --
+--                                                                          --
+-- GNAT was originally developed  by the GNAT team at  New York University. --
+-- It is now maintained by Ada Core Technologies Inc (http://www.gnat.com). --
+--                                                                          --
+------------------------------------------------------------------------------
+
+with System; use System;
+with Types;  use Types;
+
+package Stringt is
+
+--  This package contains routines for handling the strings table which is
+--  used to store string constants encountered in the source, and also those
+--  additional string constants generated by compile time concatenation and
+--  other similar processing.
+
+--  A string constant in this table consists of a series of Char_Code values,
+--  so that 16-bit character codes can be properly handled if this feature
+--  is implemented in the scanner.
+
+--  There is no guarantee that hashing is used in the implementation, although
+--  it maybe. This means that the caller cannot count on having the same Id
+--  value for two identical strings stored separately and also cannot count on
+--  the two Id values being different.
+
+   --------------------------------------
+   -- String Table Access Subprograms --
+   --------------------------------------
+
+   procedure Initialize;
+   --  Initializes the strings table for a new compilation. Note that
+   --  Initialize must not be called if Tree_Read is used.
+
+   procedure Lock;
+   --  Lock internal tables before calling back end
+
+   procedure Unlock;
+   --  Unlock internal tables, in case back end needs to modify them
+
+   procedure Start_String;
+   --  Sets up for storing a new string in the table. To store a string, a
+   --  call is first made to Start_String, then successive calls are
+   --  made to Store_String_Character to store the characters of the string.
+   --  Finally, a call to End_String terminates the entry and returns it Id.
+
+   procedure Start_String (S : String_Id);
+   --  Like Start_String with no parameter, except that the contents of the
+   --  new string is initialized to be a copy of the given string. A test is
+   --  made to see if S is the last created string, and if so it is shared,
+   --  rather than copied, this can be particularly helpful for the case of
+   --  a continued concatenaion of string constants.
+
+   procedure Store_String_Char (C : Char_Code);
+   procedure Store_String_Char (C : Character);
+   --  Store next character of string, see description above for Start_String
+
+   procedure Store_String_Chars (S : String);
+   procedure Store_String_Chars (S : String_Id);
+   --  Store character codes of given string in sequence
+
+   procedure Store_String_Int (N : Int);
+   --  Stored decimal representation of integer with possible leading minus
+
+   procedure Unstore_String_Char;
+   --  Undoes effect of previous Store_String_Char call, used in some error
+   --  situations of unterminated string constants.
+
+   function End_String return String_Id;
+   --  Terminates current string and returns its Id
+
+   function String_Length (Id : String_Id) return Nat;
+   --  Returns length of previously stored string
+
+   function Get_String_Char (Id : String_Id; Index : Int) return Char_Code;
+   --  Obtains the specified character from a stored string. The lower bound
+   --  of stored strings is always 1, so the range is 1 .. String_Length (Id).
+
+   function String_Equal (L, R : String_Id) return Boolean;
+   --  Determines if two string literals represent the same string
+
+   procedure String_To_Name_Buffer (S : String_Id);
+   --  Place characters of given string in Name_Buffer, setting Name_Len
+
+   procedure Add_String_To_Name_Buffer (S : String_Id);
+   --  Append characters of given string to Name_Buffer, updating Name_Len
+
+   function String_Chars_Address return System.Address;
+   --  Return address of String_Chars table (used by Back_End call to Gigi)
+
+   function String_From_Name_Buffer return String_Id;
+   --  Given a name stored in Namet.Name_Buffer (length in Namet.Name_Len),
+   --  returns a string of the corresponding value. The value in Name_Buffer
+   --  is unchanged, and the cases of letters are unchanged.
+
+   function Strings_Address return System.Address;
+   --  Return address of Strings table (used by Back_End call to Gigi)
+
+   procedure Tree_Read;
+   --  Initializes internal tables from current tree file using Tree_Read.
+   --  Note that Initialize should not be called if Tree_Read is used.
+   --  Tree_Read includes all necessary initialization.
+
+   procedure Tree_Write;
+   --  Writes out internal tables to current tree file using Tree_Write
+
+   procedure Write_Char_Code (Code : Char_Code);
+   --  Procedure to write a character code value, used for debugging purposes
+   --  for writing character codes. If the character code is in the range
+   --  16#20# .. 16#7E#, then the single graphic character corresponding to
+   --  the code is output. For any other codes in the range 16#00# .. 16#FF#,
+   --  the code is output as ["hh"] where hh is the two digit hex value for
+   --  the code. Codes greater than 16#FF# are output as ["hhhh"] where hhhh
+   --  is the four digit hex representation of the code value (high order
+   --  byte first). Hex letters are always in upper case.
+
+   procedure Write_String_Table_Entry (Id : String_Id);
+   --  Writes a string value with enclosing quotes to the current file using
+   --  routines in package Output. Does not write an end of line character.
+   --  This procedure is used for debug output purposes, and also for output
+   --  of strings specified by pragma Linker Option to the ali file. 7-bit
+   --  ASCII graphics (except for double quote and left brace) are output
+   --  literally. The double quote appears as two successive double quotes.
+   --  All other codes, are output as described for Write_Char_Code. For
+   --  example, the string created by folding "A" & ASCII.LF & "Hello" will
+   --  print as "A{0A}Hello". A No_String value prints simply as "no string"
+   --  without surrounding quote marks.
+
+private
+   pragma Inline (End_String);
+   pragma Inline (String_Length);
+
+end Stringt;
diff --git a/gcc/ada/stringt.h b/gcc/ada/stringt.h
new file mode 100644 (file)
index 0000000..3a1e1f6
--- /dev/null
@@ -0,0 +1,92 @@
+/****************************************************************************
+ *                                                                          *
+ *                         GNAT COMPILER COMPONENTS                         *
+ *                                                                          *
+ *                              S T R I N G T                               *
+ *                                                                          *
+ *                              C Header File                               *
+ *                                                                          *
+ *                            $Revision: 1.1 $
+ *                                                                          *
+ *          Copyright (C) 1992-2001 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- *
+ * ware  Foundation;  either version 2,  or (at your option) any later ver- *
+ * sion.  GNAT is distributed in the hope that it will be useful, but WITH- *
+ * OUT ANY WARRANTY;  without even the  implied warranty of MERCHANTABILITY *
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License *
+ * for  more details.  You should have  received  a copy of the GNU General *
+ * Public License  distributed with GNAT;  see file COPYING.  If not, write *
+ * to  the Free Software Foundation,  59 Temple Place - Suite 330,  Boston, *
+ * MA 02111-1307, USA.                                                      *
+ *                                                                          *
+ * GNAT was originally developed  by the GNAT team at  New York University. *
+ * It is now maintained by Ada Core Technologies Inc (http://www.gnat.com). *
+ *                                                                          *
+ ****************************************************************************/
+
+/* This file is the C file that corresponds to the Ada package spec
+   Stringt. It was created manually from stringt.ads and stringt.adb
+                                                                           
+   Note: only the access functions are provided, since the tree transformer
+   is not allowed to modify the tree or its auxiliary structures.
+                                                                           
+   This package contains routines for handling the strings table which is
+   used to store string constants encountered in the source, and also those
+   additional string constants generated by compile time concatenation and
+   other similar processing.
+                                                                           
+   A string constant in this table consists of a series of Char_Code values,
+   so that 16-bit character codes can be properly handled if this feature is
+   implemented in the scanner.
+                                                                           
+   There is no guarantee that hashing is used in the implementation. This
+   means that the caller cannot count on having the same Id value for two
+   identical strings stored separately.
+                                                                           
+   The String_Id values reference entries in the Strings table, which
+   contains String_Entry records that record the length of each stored string
+   and its starting location in the String_Chars table.  */
+
+struct String_Entry
+{
+  Int String_Index;
+  Int Length;
+};
+
+/* Pointer to string entry vector. This pointer is passed to the tree
+   transformer and stored in a global location for access from here after
+   subtracting String_First_Entry, so that String_Id values can be used as
+   subscripts into the vector. */
+extern struct String_Entry *Strings_Ptr;
+
+/* Pointer to name characters table. This pointer is passed to the tree
+   transformer and stored in a global location for access from here. The
+   String_Index values are subscripts into this array.  */
+extern Char_Code *String_Chars_Ptr;
+
+
+/* String_Length returns the length of the specified string.  */
+INLINE Int String_Length PARAMS ((String_Id));
+
+INLINE Int
+String_Length (Id)
+     String_Id Id;
+{
+  return Strings_Ptr [Id].Length;
+}
+
+
+/* Get_String_Char obtains the specified character from a stored string.  The
+   lower bound of stored strings is always 1, so the range of values is 1 to
+   String_Length (Id).  */
+INLINE Char_Code Get_String_Char PARAMS ((String_Id, Int));
+
+INLINE Char_Code
+Get_String_Char (Id, Index)
+     String_Id Id;
+     Int Index;
+{
+  return String_Chars_Ptr [Strings_Ptr [Id].String_Index + Index - 1];
+}
diff --git a/gcc/ada/style.adb b/gcc/ada/style.adb
new file mode 100644 (file)
index 0000000..638333c
--- /dev/null
@@ -0,0 +1,833 @@
+------------------------------------------------------------------------------
+--                                                                          --
+--                         GNAT COMPILER COMPONENTS                         --
+--                                                                          --
+--                                S T Y L E                                 --
+--                                                                          --
+--                                 B o d y                                  --
+--                                                                          --
+--                            $Revision: 1.48 $
+--                                                                          --
+--          Copyright (C) 1992-2001 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- --
+-- ware  Foundation;  either version 2,  or (at your option) any later ver- --
+-- sion.  GNAT is distributed in the hope that it will be useful, but WITH- --
+-- OUT ANY WARRANTY;  without even the  implied warranty of MERCHANTABILITY --
+-- or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License --
+-- for  more details.  You should have  received  a copy of the GNU General --
+-- Public License  distributed with GNAT;  see file COPYING.  If not, write --
+-- to  the Free Software Foundation,  59 Temple Place - Suite 330,  Boston, --
+-- MA 02111-1307, USA.                                                      --
+--                                                                          --
+-- GNAT was originally developed  by the GNAT team at  New York University. --
+-- It is now maintained by Ada Core Technologies Inc (http://www.gnat.com). --
+--                                                                          --
+------------------------------------------------------------------------------
+
+--  This version of the Style package implements the standard GNAT style
+--  checking rules. For documentation of these rules, see comments on the
+--  individual procedures.
+
+with Atree;    use Atree;
+with Casing;   use Casing;
+with Csets;    use Csets;
+with Einfo;    use Einfo;
+with Errout;   use Errout;
+with Namet;    use Namet;
+with Opt;      use Opt;
+with Scn;      use Scn;
+with Scans;    use Scans;
+with Sinfo;    use Sinfo;
+with Sinput;   use Sinput;
+with Stand;    use Stand;
+with Stylesw;  use Stylesw;
+
+package body Style is
+
+   -----------------------
+   -- Local Subprograms --
+   -----------------------
+
+   procedure Error_Space_Not_Allowed (S : Source_Ptr);
+   --  Posts an error message indicating that a space is not allowed
+   --  at the given source location.
+
+   procedure Error_Space_Required (S : Source_Ptr);
+   --  Posts an error message indicating that a space is required at
+   --  the given source location.
+
+   procedure Require_Following_Space;
+   pragma Inline (Require_Following_Space);
+   --  Require token to be followed by white space. Used only if in GNAT
+   --  style checking mode.
+
+   procedure Require_Preceding_Space;
+   pragma Inline (Require_Preceding_Space);
+   --  Require token to be preceded by white space. Used only if in GNAT
+   --  style checking mode.
+
+   -----------------------
+   -- Body_With_No_Spec --
+   -----------------------
+
+   --  If the check specs mode (-gnatys) is set, then all subprograms must
+   --  have specs unless they are parameterless procedures that are not child
+   --  units at the library level (i.e. they are possible main programs).
+
+   procedure Body_With_No_Spec (N : Node_Id) is
+   begin
+      if Style_Check_Specs then
+         if Nkind (Parent (N)) = N_Compilation_Unit then
+            declare
+               Spec  : constant Node_Id := Specification (N);
+               Defnm : constant Node_Id := Defining_Unit_Name (Spec);
+
+            begin
+               if Nkind (Spec) = N_Procedure_Specification
+                 and then Nkind (Defnm) = N_Defining_Identifier
+                 and then No (First_Formal (Defnm))
+               then
+                  return;
+               end if;
+            end;
+         end if;
+
+         Error_Msg_N ("(style): subprogram body has no previous spec", N);
+      end if;
+   end Body_With_No_Spec;
+
+   ----------------------
+   -- Check_Abs_Or_Not --
+   ----------------------
+
+   --  In check tokens mode (-gnatyt), ABS/NOT must be followed by a space
+
+   procedure Check_Abs_Not is
+   begin
+      if Style_Check_Tokens then
+         if Source (Scan_Ptr) > ' ' then
+            Error_Space_Required (Scan_Ptr);
+         end if;
+      end if;
+   end Check_Abs_Not;
+
+   -----------------
+   -- Check_Arrow --
+   -----------------
+
+   --  In check tokens mode (-gnatys), arrow must be surrounded by spaces
+
+   procedure Check_Arrow is
+   begin
+      if Style_Check_Tokens then
+         Require_Preceding_Space;
+         Require_Following_Space;
+      end if;
+   end Check_Arrow;
+
+   --------------------------
+   -- Check_Attribute_Name --
+   --------------------------
+
+   --  In check attribute casing mode (-gnatya), attribute names must be
+   --  mixed case, i.e. start with an upper case letter, and otherwise
+   --  lower case, except after an underline character.
+
+   procedure Check_Attribute_Name (Reserved : Boolean) is
+   begin
+      if Style_Check_Attribute_Casing then
+         if Determine_Token_Casing /= Mixed_Case then
+            Error_Msg_SC ("(style) bad capitalization, mixed case required");
+         end if;
+      end if;
+   end Check_Attribute_Name;
+
+   ---------------------------
+   -- Check_Binary_Operator --
+   ---------------------------
+
+   --  In check token mode (-gnatyt), binary operators other than the special
+   --  case of exponentiation require surrounding space characters.
+
+   procedure Check_Binary_Operator is
+   begin
+      if Style_Check_Tokens then
+         Require_Preceding_Space;
+         Require_Following_Space;
+      end if;
+   end Check_Binary_Operator;
+
+   ---------------
+   -- Check_Box --
+   ---------------
+
+   --  In check token mode (-gnatyt), box must be preceded by a space or by
+   --  a left parenthesis. Spacing checking on the surrounding tokens takes
+   --  care of the remaining checks.
+
+   procedure Check_Box is
+   begin
+      if Style_Check_Tokens then
+         if Prev_Token /= Tok_Left_Paren then
+            Require_Preceding_Space;
+         end if;
+      end if;
+   end Check_Box;
+
+   -----------------
+   -- Check_Colon --
+   -----------------
+
+   --  In check token mode (-gnatyt), colon must be surrounded by spaces
+
+   procedure Check_Colon is
+   begin
+      if Style_Check_Tokens then
+         Require_Preceding_Space;
+         Require_Following_Space;
+      end if;
+   end Check_Colon;
+
+   -----------------------
+   -- Check_Colon_Equal --
+   -----------------------
+
+   --  In check token mode (-gnatyt), := must be surrounded by spaces
+
+   procedure Check_Colon_Equal is
+   begin
+      if Style_Check_Tokens then
+         Require_Preceding_Space;
+         Require_Following_Space;
+      end if;
+   end Check_Colon_Equal;
+
+   -----------------
+   -- Check_Comma --
+   -----------------
+
+   --  In check token mode (-gnatyt), comma must be either the first
+   --  token on a line, or be preceded by a non-blank character.
+   --  It must also always be followed by a blank.
+
+   procedure Check_Comma is
+   begin
+      if Style_Check_Tokens then
+         if Token_Ptr > First_Non_Blank_Location
+           and then Source (Token_Ptr - 1) = ' '
+         then
+            Error_Space_Not_Allowed (Token_Ptr - 1);
+         end if;
+
+         if Source (Scan_Ptr) > ' ' then
+            Error_Space_Required (Scan_Ptr);
+         end if;
+      end if;
+   end Check_Comma;
+
+   -------------------
+   -- Check_Comment --
+   -------------------
+
+   --  In check comment mode (-gnatyc) there are several requirements on the
+   --  format of comments. The following are permissible comment formats:
+
+   --    1. Any comment that is not at the start of a line, i.e. where the
+   --       initial minuses are not the first non-blank characters on the
+   --       line must have at least one blank after the second minus.
+
+   --    2. A row of all minuses of any length is permitted (see procedure
+   --       box above in the source of this routine).
+
+   --    3. A comment line starting with two minuses and a space, and ending
+   --       with a space and two minuses. Again see the procedure title box
+   --       immediately above in the source.
+
+   --    4. A full line comment where two spaces follow the two minus signs.
+   --       This is the normal comment format in GNAT style, as typified by
+   --       the comments you are reading now.
+
+   --    5. A full line comment where the first character after the second
+   --       minus is a special character, i.e. a character in the ASCII
+   --       range 16#21#..16#2F# or 16#3A#..16#3F#. This allows special
+   --       comments, such as those generated by gnatprep, or those that
+   --       appear in the SPARK annotation language to be accepted.
+
+   procedure Check_Comment is
+      S : Source_Ptr;
+      C : Character;
+
+   begin
+      --  Can never have a non-blank character preceding the first minus
+
+      if Style_Check_Comments then
+         if Scan_Ptr > Source_First (Current_Source_File)
+           and then Source (Scan_Ptr - 1) > ' '
+         then
+            Error_Msg_S ("(style) space required");
+         end if;
+      end if;
+
+      --  For a comment that is not at the start of the line, the only
+      --  requirement is that we cannot have a non-blank character after
+      --  the second minus sign.
+
+      if Scan_Ptr /= First_Non_Blank_Location then
+         if Style_Check_Comments then
+            if Source (Scan_Ptr + 2) > ' ' then
+               Error_Msg ("(style) space required", Scan_Ptr + 2);
+            end if;
+         end if;
+
+         return;
+
+      --  Case of a comment that is at the start of a line
+
+      else
+         --  First check, must be in appropriately indented column
+
+         if Style_Check_Indentation /= 0 then
+            if Start_Column rem Style_Check_Indentation /= 0 then
+               Error_Msg_S ("(style) bad column");
+               return;
+            end if;
+         end if;
+
+         --  Now check form of the comment
+
+         if not Style_Check_Comments then
+            return;
+
+         --  Case of not followed by a blank. Usually wrong, but there are
+         --  some exceptions that we permit.
+
+         elsif Source (Scan_Ptr + 2) /= ' ' then
+            C := Source (Scan_Ptr + 2);
+
+            --  Case of -- all on its own on a line is OK
+
+            if C < ' ' then
+               return;
+
+            --  Case of --x, x special character is OK (gnatprep/SPARK/etc.)
+
+            elsif Character'Pos (C) in 16#21# .. 16#2F#
+                    or else
+                  Character'Pos (C) in 16#3A# .. 16#3F#
+            then
+               return;
+
+            --  Otherwise only cases allowed are when the entire line is
+            --  made up of minus signs (case of a box comment).
+
+            else
+               S := Scan_Ptr + 2;
+
+               while Source (S) >= ' ' loop
+                  if Source (S) /= '-' then
+                     Error_Space_Required (Scan_Ptr + 2);
+                     return;
+                  end if;
+
+                  S := S + 1;
+               end loop;
+            end if;
+
+         --  If we are followed by a blank, then the comment is OK if the
+         --  character following this blank is another blank or a format
+         --  effector.
+
+         elsif Source (Scan_Ptr + 3) <= ' ' then
+            return;
+
+         --  Here is the case where we only have one blank after the two minus
+         --  signs, which is an error unless the line ends with two blanks, the
+         --  case of a box comment.
+
+         else
+            S := Scan_Ptr + 3;
+
+            while Source (S) not in Line_Terminator loop
+               S := S + 1;
+            end loop;
+
+            if Source (S - 1) /= '-' or else Source (S - 2) /= '-' then
+               Error_Space_Required (Scan_Ptr + 3);
+            end if;
+         end if;
+      end if;
+   end Check_Comment;
+
+   -------------------
+   -- Check_Dot_Dot --
+   -------------------
+
+   --  In check token mode (-gnatyt), colon must be surrounded by spaces
+
+   procedure Check_Dot_Dot is
+   begin
+      if Style_Check_Tokens then
+         Require_Preceding_Space;
+         Require_Following_Space;
+      end if;
+   end Check_Dot_Dot;
+
+   -----------------------------------
+   -- Check_Exponentiation_Operator --
+   -----------------------------------
+
+   --  No spaces are required for the ** operator in GNAT style check mode
+
+   procedure Check_Exponentiation_Operator is
+   begin
+      null;
+   end Check_Exponentiation_Operator;
+
+   --------------
+   -- Check_HT --
+   --------------
+
+   --  In check horizontal tab mode (-gnatyh), tab characters are not allowed
+
+   procedure Check_HT is
+   begin
+      if Style_Check_Horizontal_Tabs then
+         Error_Msg_S ("(style) horizontal tab not allowed");
+      end if;
+   end Check_HT;
+
+   ----------------------
+   -- Check_Identifier --
+   ----------------------
+
+   --  In check references mode (-gnatyr), identifier uses must be cased
+   --  the same way as the corresponding identifier declaration.
+
+   procedure Check_Identifier
+     (Ref : Node_Or_Entity_Id;
+      Def : Node_Or_Entity_Id)
+   is
+      SRef : Source_Ptr := Sloc (Ref);
+      SDef : Source_Ptr := Sloc (Def);
+      TRef : Source_Buffer_Ptr;
+      TDef : Source_Buffer_Ptr;
+      Nlen : Nat;
+      Cas  : Casing_Type;
+
+   begin
+      --  If reference does not come from source, nothing to check
+
+      if not Comes_From_Source (Ref) then
+         return;
+
+      --  Case of definition comes from source
+
+      elsif Comes_From_Source (Def) then
+
+         --  Check same casing if we are checking references
+
+         if Style_Check_References then
+            TRef := Source_Text (Get_Source_File_Index (SRef));
+            TDef := Source_Text (Get_Source_File_Index (SDef));
+
+            --  Ignore operator name case completely. This also catches the
+            --  case of where one is an operator and the other is not. This
+            --  is a phenomenon from rewriting of operators as functions,
+            --  and is to be ignored.
+
+            if TRef (SRef) = '"' or else TDef (SDef) = '"' then
+               return;
+
+            else
+               for J in 1 .. Length_Of_Name (Chars (Ref)) loop
+                  if TRef (SRef) /= TDef (SDef) then
+                     Error_Msg_Node_1 := Def;
+                     Error_Msg_Sloc := Sloc (Def);
+                     Error_Msg
+                       ("(style) bad casing of & declared#", SRef);
+                     return;
+                  end if;
+
+                  SRef := SRef + 1;
+                  SDef := SDef + 1;
+               end loop;
+            end if;
+         end if;
+
+      --  Case of definition in package Standard
+
+      elsif SDef = Standard_Location then
+
+         --  Check case of identifiers in Standard
+
+         if Style_Check_Standard then
+            TRef := Source_Text (Get_Source_File_Index (SRef));
+
+            --  Ignore operators
+
+            if TRef (SRef) = '"' then
+               null;
+
+            --  Special case of ASCII
+
+            else
+               if Entity (Ref) = Standard_ASCII then
+                  Cas := All_Upper_Case;
+
+               elsif Entity (Ref) in SE (S_LC_A) .. SE (S_LC_Z)
+                       or else
+                     Entity (Ref) in SE (S_NUL) .. SE (S_US)
+                       or else
+                     Entity (Ref) = SE (S_DEL)
+               then
+                  Cas := All_Upper_Case;
+
+               else
+                  Cas := Mixed_Case;
+               end if;
+
+               Nlen  := Length_Of_Name (Chars (Ref));
+
+               if Determine_Casing
+                    (TRef (SRef .. SRef + Source_Ptr (Nlen) - 1)) = Cas
+               then
+                  null;
+               else
+                  Error_Msg_N
+                    ("(style) bad casing for entity in Standard", Ref);
+               end if;
+            end if;
+         end if;
+      end if;
+   end Check_Identifier;
+
+   -----------------------
+   -- Check_Indentation --
+   -----------------------
+
+   --  In check indentation mode (-gnatyn for n a digit), a new statement or
+   --  declaration is required to start in a column that is a multiple of the
+   --  indentiation amount.
+
+   procedure Check_Indentation is
+   begin
+      if Style_Check_Indentation /= 0 then
+         if Token_Ptr = First_Non_Blank_Location
+           and then Start_Column rem Style_Check_Indentation /= 0
+         then
+            Error_Msg_SC ("(style) bad indentation");
+         end if;
+      end if;
+   end Check_Indentation;
+
+   ----------------------
+   -- Check_Left_Paren --
+   ----------------------
+
+   --  In tone check mode (-gnatyt), left paren must not be preceded by an
+   --  identifier character or digit (a separating space is required) and
+   --  may never be followed by a space.
+
+   procedure Check_Left_Paren is
+      S : Source_Ptr;
+
+   begin
+      if Style_Check_Tokens then
+         if Token_Ptr > Source_First (Current_Source_File)
+           and then Identifier_Char (Source (Token_Ptr - 1))
+         then
+            Error_Space_Required (Token_Ptr);
+         end if;
+
+         if Source (Scan_Ptr) = ' ' then
+
+            --  Allow one or more spaces if followed by comment
+
+            S := Scan_Ptr + 1;
+            loop
+               if Source (S) = '-' and then Source (S + 1) = '-' then
+                  return;
+               elsif Source (S) /= ' ' then
+                  exit;
+               else
+                  S := S + 1;
+               end if;
+            end loop;
+
+            Error_Space_Not_Allowed (Scan_Ptr);
+         end if;
+      end if;
+   end Check_Left_Paren;
+
+   ---------------------------
+   -- Check_Line_Terminator --
+   ---------------------------
+
+   --  In check blanks at end mode (-gnatyb), lines may not end with a
+   --  trailing space.
+
+   --  In check max line length mode (-gnatym), the line length must
+   --  not exceed the permitted maximum value.
+
+   --  In check form feeds mode (-gnatyf), the line terminator may not
+   --  be either of the characters FF or VT.
+
+   procedure Check_Line_Terminator (Len : Int) is
+      S : Source_Ptr;
+
+   begin
+      --  Check FF/VT terminators
+
+      if Style_Check_Form_Feeds then
+         if Source (Scan_Ptr) = ASCII.FF then
+            Error_Msg_S ("(style) form feed not allowed");
+
+         elsif Source (Scan_Ptr) = ASCII.VT then
+            Error_Msg_S ("(style) vertical tab not allowed");
+         end if;
+      end if;
+
+      --  Check trailing space
+
+      if Style_Check_Blanks_At_End then
+         if Scan_Ptr >= First_Non_Blank_Location then
+            if Source (Scan_Ptr - 1) = ' ' then
+               S := Scan_Ptr - 1;
+
+               while Source (S - 1) = ' ' loop
+                  S := S - 1;
+               end loop;
+
+               Error_Msg ("(style) trailing spaces not permitted", S);
+            end if;
+         end if;
+      end if;
+
+      --  Check max line length
+
+      if Style_Check_Max_Line_Length then
+         if Len > Style_Max_Line_Length then
+            Error_Msg
+              ("(style) this line is too long",
+               Current_Line_Start + Source_Ptr (Style_Max_Line_Length));
+         end if;
+      end if;
+
+   end Check_Line_Terminator;
+
+   -----------------------
+   -- Check_Pragma_Name --
+   -----------------------
+
+   --  In check pragma casing mode (-gnatyp), pragma names must be mixed
+   --  case, i.e. start with an upper case letter, and otherwise lower case,
+   --  except after an underline character.
+
+   procedure Check_Pragma_Name is
+   begin
+      if Style_Check_Pragma_Casing then
+         if Determine_Token_Casing /= Mixed_Case then
+            Error_Msg_SC ("(style) bad capitalization, mixed case required");
+         end if;
+      end if;
+   end Check_Pragma_Name;
+
+   -----------------------
+   -- Check_Right_Paren --
+   -----------------------
+
+   --  In check tokens mode (-gnatyt), right paren must never be preceded by
+   --  a space unless it is the initial non-blank character on the line.
+
+   procedure Check_Right_Paren is
+   begin
+      if Style_Check_Tokens then
+         if Token_Ptr > First_Non_Blank_Location
+           and then Source (Token_Ptr - 1) = ' '
+         then
+            Error_Space_Not_Allowed (Token_Ptr - 1);
+         end if;
+      end if;
+   end Check_Right_Paren;
+
+   ---------------------
+   -- Check_Semicolon --
+   ---------------------
+
+   --  In check tokens mode (-gnatyt), semicolon does not permit a preceding
+   --  space and a following space is required.
+
+   procedure Check_Semicolon is
+   begin
+      if Style_Check_Tokens then
+         if Scan_Ptr > Source_First (Current_Source_File)
+           and then Source (Token_Ptr - 1) = ' '
+         then
+            Error_Space_Not_Allowed (Token_Ptr - 1);
+
+         elsif Source (Scan_Ptr) > ' ' then
+            Error_Space_Required (Scan_Ptr);
+         end if;
+      end if;
+   end Check_Semicolon;
+
+   ----------------
+   -- Check_Then --
+   ----------------
+
+   --  In check if then layout mode (-gnatyi), we expect a THEN keyword
+   --  to appear either on the same line as the IF, or on a separate line
+   --  after multiple conditions. In any case, it may not appear on the
+   --  line immediately following the line with the IF.
+
+   procedure Check_Then (If_Loc : Source_Ptr) is
+   begin
+      if Style_Check_If_Then_Layout then
+         if Get_Physical_Line_Number (Token_Ptr) =
+            Get_Physical_Line_Number (If_Loc) + 1
+         then
+            Error_Msg_SC ("(style) misplaced THEN");
+         end if;
+      end if;
+   end Check_Then;
+
+   -------------------------------
+   -- Check_Unary_Plus_Or_Minus --
+   -------------------------------
+
+   --  In check tokem mode (-gnatyt), unary plus or minus must not be
+   --  followed by a space.
+
+   procedure Check_Unary_Plus_Or_Minus is
+   begin
+      if Style_Check_Tokens then
+         if Source (Scan_Ptr) = ' ' then
+            Error_Space_Not_Allowed (Scan_Ptr);
+         end if;
+      end if;
+   end Check_Unary_Plus_Or_Minus;
+
+   ------------------------
+   -- Check_Vertical_Bar --
+   ------------------------
+
+   --  In check token mode (-gnatyt), vertical bar must be surrounded by spaces
+
+   procedure Check_Vertical_Bar is
+   begin
+      if Style_Check_Tokens then
+         Require_Preceding_Space;
+         Require_Following_Space;
+      end if;
+   end Check_Vertical_Bar;
+
+   -----------------------------
+   -- Error_Space_Not_Allowed --
+   -----------------------------
+
+   procedure Error_Space_Not_Allowed (S : Source_Ptr) is
+   begin
+      Error_Msg ("(style) space not allowed", S);
+   end Error_Space_Not_Allowed;
+
+   --------------------------
+   -- Error_Space_Required --
+   --------------------------
+
+   procedure Error_Space_Required (S : Source_Ptr) is
+   begin
+      Error_Msg ("(style) space required", S);
+   end Error_Space_Required;
+
+   -----------------
+   -- No_End_Name --
+   -----------------
+
+   --  In check end/exit labels mode (-gnatye), always require the name of
+   --  a subprogram or package to be present on the END, so this is an error.
+
+   procedure No_End_Name (Name : Node_Id) is
+   begin
+      if Style_Check_End_Labels then
+         Error_Msg_Node_1 := Name;
+         Error_Msg_SP ("(style) `END &` required");
+      end if;
+   end No_End_Name;
+
+   ------------------
+   -- No_Exit_Name --
+   ------------------
+
+   --  In check end/exit labels mode (-gnatye), always require the name of
+   --  the loop to be present on the EXIT when exiting a named loop.
+
+   procedure No_Exit_Name (Name : Node_Id) is
+   begin
+      if Style_Check_End_Labels then
+         Error_Msg_Node_1 := Name;
+         Error_Msg_SP ("(style) `EXIT &` required");
+      end if;
+   end No_Exit_Name;
+
+   ----------------------------
+   -- Non_Lower_Case_Keyword --
+   ----------------------------
+
+   --  In check casing mode (-gnatyk), reserved keywords must be be spelled
+   --  in all lower case (excluding keywords range, access, delta and digits
+   --  used as attribute designators).
+
+   procedure Non_Lower_Case_Keyword is
+   begin
+      if Style_Check_Keyword_Casing then
+         Error_Msg_SC ("(style) reserved words must be all lower case");
+      end if;
+   end Non_Lower_Case_Keyword;
+
+   -----------------------------
+   -- Require_Following_Space --
+   -----------------------------
+
+   procedure Require_Following_Space is
+   begin
+      if Source (Scan_Ptr) > ' ' then
+         Error_Space_Required (Scan_Ptr);
+      end if;
+   end Require_Following_Space;
+
+   -----------------------------
+   -- Require_Preceding_Space --
+   -----------------------------
+
+   procedure Require_Preceding_Space is
+   begin
+      if Token_Ptr > Source_First (Current_Source_File)
+        and then Source (Token_Ptr - 1) > ' '
+      then
+         Error_Space_Required (Token_Ptr);
+      end if;
+   end Require_Preceding_Space;
+
+   ---------------------
+   -- RM_Column_Check --
+   ---------------------
+
+   function RM_Column_Check return Boolean is
+   begin
+      return Style_Check and Style_Check_Layout;
+   end RM_Column_Check;
+
+   -----------------------------------
+   -- Subprogram_Not_In_Alpha_Order --
+   -----------------------------------
+
+   procedure Subprogram_Not_In_Alpha_Order (Name : Node_Id) is
+   begin
+      if Style_Check_Subprogram_Order then
+         Error_Msg_N
+           ("(style) subprogram body& not in alphabetical order", Name);
+      end if;
+   end Subprogram_Not_In_Alpha_Order;
+end Style;
diff --git a/gcc/ada/style.ads b/gcc/ada/style.ads
new file mode 100644 (file)
index 0000000..a75807c
--- /dev/null
@@ -0,0 +1,156 @@
+------------------------------------------------------------------------------
+--                                                                          --
+--                         GNAT COMPILER COMPONENTS                         --
+--                                                                          --
+--                                S T Y L E                                 --
+--                                                                          --
+--                                 S p e c                                  --
+--                                                                          --
+--                            $Revision: 1.12 $
+--                                                                          --
+--          Copyright (C) 1992-2000 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- --
+-- ware  Foundation;  either version 2,  or (at your option) any later ver- --
+-- sion.  GNAT is distributed in the hope that it will be useful, but WITH- --
+-- OUT ANY WARRANTY;  without even the  implied warranty of MERCHANTABILITY --
+-- or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License --
+-- for  more details.  You should have  received  a copy of the GNU General --
+-- Public License  distributed with GNAT;  see file COPYING.  If not, write --
+-- to  the Free Software Foundation,  59 Temple Place - Suite 330,  Boston, --
+-- MA 02111-1307, USA.                                                      --
+--                                                                          --
+-- GNAT was originally developed  by the GNAT team at  New York University. --
+-- It is now maintained by Ada Core Technologies Inc (http://www.gnat.com). --
+--                                                                          --
+------------------------------------------------------------------------------
+
+--  This package collects all the routines used for style checking, as
+--  activated by the relevant command line option. These are gathered in
+--  a separate package so that they can more easily be customized. Calls
+--  to these subprograms are only made if Opt.Style_Check is set True.
+
+with Types; use Types;
+
+package Style is
+
+   procedure Body_With_No_Spec (N : Node_Id);
+   --  Called where N is a subprogram body node for a subprogram body
+   --  for which no spec was given, i.e. a body acting as its own spec.
+
+   procedure Check_Abs_Not;
+   --  Called after scanning an ABS or NOT operator to check spacing
+
+   procedure Check_Arrow;
+   --  Called after scanning out an arrow to check spacing
+
+   procedure Check_Attribute_Name (Reserved : Boolean);
+   --  The current token is an attribute designator. Check that it is
+   --  capitalized in an appropriate manner. Reserved is set if the
+   --  attribute designator is a reserved word (access, digits, delta
+   --  or range) to allow differing rules for the two cases.
+
+   procedure Check_Box;
+   --  Called after scanning out a box to check spacing
+
+   procedure Check_Binary_Operator;
+   --  Called after scanning out a binary operator other than a plus, minus
+   --  or exponentiation operator. Intended for checking spacing rules.
+
+   procedure Check_Exponentiation_Operator;
+   --  Called after scanning out an exponentiation operator. Intended for
+   --  checking spacing rules.
+
+   procedure Check_Colon;
+   --  Called after scanning out colon to check spacing
+
+   procedure Check_Colon_Equal;
+   --  Called after scanning out colon equal to check spacing
+
+   procedure Check_Comma;
+   --  Called after scanning out comma to check spacing
+
+   procedure Check_Comment;
+   --  Called with Scan_Ptr pointing to the first minus sign of a comment.
+   --  Intended for checking any specific rules for comment placement/format.
+
+   procedure Check_Dot_Dot;
+   --  Called after scanning out dot dot to check spacing
+
+   procedure Check_HT;
+   --  Called with Scan_Ptr pointing to a horizontal tab character
+
+   procedure Check_Identifier
+     (Ref : Node_Or_Entity_Id;
+      Def : Node_Or_Entity_Id);
+   --  Check style of identifier occurrence. Ref is an N_Identifier node whose
+   --  spelling is to be checked against the Chars spelling in identifier node
+   --  Def (which may be either an N_Identifier, or N_Defining_Identifier node)
+
+   procedure Check_Indentation;
+   --  Called at the start of a new statement or declaration, with Token_Ptr
+   --  pointing to the first token of the statement or declaration. The check
+   --  is that the starting column is appropriate to the indentation rules if
+   --  Token_Ptr is the first token on the line.
+
+   procedure Check_Left_Paren;
+   --  Called after scanning out a left parenthesis to check spacing.
+
+   procedure Check_Line_Terminator (Len : Int);
+   --  Called with Scan_Ptr pointing to the first line terminator terminating
+   --  the current line, used to check for appropriate line terminator and
+   --  to check the line length (Len is the length of the current line).
+   --  Note that the terminator may be the EOF character.
+
+   procedure Check_Pragma_Name;
+   --  The current token is a pragma identifier. Check that it is spelled
+   --  properly (i.e. with an appropriate casing convention).
+
+   procedure Check_Right_Paren;
+   --  Called after scanning out a right parenthesis to check spacing.
+
+   procedure Check_Semicolon;
+   --  Called after scanning out a semicolon to check spacing
+
+   procedure Check_Then (If_Loc : Source_Ptr);
+   --  Called to check that THEN and IF keywords are appropriately positioned.
+   --  The parameters show the first characters of the two keywords. This
+   --  procedure is called only if THEN appears at the start of a line with
+   --  Token_Ptr pointing to the THEN keyword.
+
+   procedure Check_Unary_Plus_Or_Minus;
+   --  Called after scanning a unary plus or minus to check spacing
+
+   procedure Check_Vertical_Bar;
+   --  Called after scanning a vertical bar to check spacing
+
+   procedure No_End_Name (Name : Node_Id);
+   --  Called if an END is encountered where a name is allowed but not present.
+   --  The parameter is the node whose name is the name that is permitted in
+   --  the END line, and the scan pointer is positioned so that if an error
+   --  message is to be generated in this situation, it should be generated
+   --  using Error_Msg_SP.
+
+   procedure No_Exit_Name (Name : Node_Id);
+   --  Called when exiting a named loop, but a name is not present on the EXIT.
+   --  The parameter is the node whose name should have followed EXIT, and the
+   --  scan pointer is positioned so that if an error message is to be
+   --  generated, it should be generated using Error_Msg_SP.
+
+   procedure Non_Lower_Case_Keyword;
+   --  Called if a reserved keyword is scanned which is not spelled in all
+   --  lower case letters. On entry Token_Ptr points to the keyword token.
+   --  This is not used for keywords appearing as attribute designators,
+   --  where instead Check_Attribute_Name (True) is called.
+
+   function RM_Column_Check return Boolean;
+   pragma Inline (RM_Column_Check);
+   --  Determines whether style checking is active and the RM column check
+   --  mode is set requiring checking of RM format layout.
+
+   procedure Subprogram_Not_In_Alpha_Order (Name : Node_Id);
+   --  Called if Name is the name of a subprogram body in a package body
+   --  that is not in alphabetical order.
+
+end Style;
diff --git a/gcc/ada/stylesw.adb b/gcc/ada/stylesw.adb
new file mode 100644 (file)
index 0000000..aae4d04
--- /dev/null
@@ -0,0 +1,255 @@
+------------------------------------------------------------------------------
+--                                                                          --
+--                         GNAT COMPILER COMPONENTS                         --
+--                                                                          --
+--                              S T Y L E S W                               --
+--                                                                          --
+--                                 B o d y                                  --
+--                                                                          --
+--                            $Revision: 1.14 $
+--                                                                          --
+--          Copyright (C) 1992-2001, 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- --
+-- ware  Foundation;  either version 2,  or (at your option) any later ver- --
+-- sion.  GNAT is distributed in the hope that it will be useful, but WITH- --
+-- OUT ANY WARRANTY;  without even the  implied warranty of MERCHANTABILITY --
+-- or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License --
+-- for  more details.  You should have  received  a copy of the GNU General --
+-- Public License  distributed with GNAT;  see file COPYING.  If not, write --
+-- to  the Free Software Foundation,  59 Temple Place - Suite 330,  Boston, --
+-- MA 02111-1307, USA.                                                      --
+--                                                                          --
+-- GNAT was originally developed  by the GNAT team at  New York University. --
+-- It is now maintained by Ada Core Technologies Inc (http://www.gnat.com). --
+--                                                                          --
+------------------------------------------------------------------------------
+
+with Hostparm; use Hostparm;
+with Opt;      use Opt;
+
+package body Stylesw is
+
+   -------------------------------
+   -- Reset_Style_Check_Options --
+   -------------------------------
+
+   procedure Reset_Style_Check_Options is
+   begin
+      Style_Check_Indentation      := 0;
+      Style_Check_Attribute_Casing := False;
+      Style_Check_Blanks_At_End    := False;
+      Style_Check_Comments         := False;
+      Style_Check_End_Labels       := False;
+      Style_Check_Form_Feeds       := False;
+      Style_Check_Horizontal_Tabs  := False;
+      Style_Check_If_Then_Layout   := False;
+      Style_Check_Keyword_Casing   := False;
+      Style_Check_Layout           := False;
+      Style_Check_Max_Line_Length  := False;
+      Style_Check_Pragma_Casing    := False;
+      Style_Check_References       := False;
+      Style_Check_Specs            := False;
+      Style_Check_Standard         := False;
+      Style_Check_Subprogram_Order := False;
+      Style_Check_Tokens           := False;
+   end Reset_Style_Check_Options;
+
+   ------------------------------
+   -- Save_Style_Check_Options --
+   ------------------------------
+
+   procedure Save_Style_Check_Options (Options : out Style_Check_Options) is
+      P : Natural := 0;
+      J : Natural;
+
+      procedure Add (C : Character; S : Boolean);
+      --  Add given character C to string if switch S is true
+
+      procedure Add (C : Character; S : Boolean) is
+      begin
+         if S then
+            P := P + 1;
+            Options (P) := C;
+         end if;
+      end Add;
+
+   --  Start of processing for Save_Style_Check_Options
+
+   begin
+      for K in Options'Range loop
+         Options (K) := ' ';
+      end loop;
+
+      Add (Character'Val (Style_Check_Indentation + Character'Pos ('0')),
+           Style_Check_Indentation /= 0);
+
+      Add ('a', Style_Check_Attribute_Casing);
+      Add ('b', Style_Check_Blanks_At_End);
+      Add ('c', Style_Check_Comments);
+      Add ('e', Style_Check_End_Labels);
+      Add ('f', Style_Check_Form_Feeds);
+      Add ('h', Style_Check_Horizontal_Tabs);
+      Add ('i', Style_Check_If_Then_Layout);
+      Add ('k', Style_Check_Keyword_Casing);
+      Add ('l', Style_Check_Layout);
+      Add ('m', Style_Check_Max_Line_Length);
+      Add ('n', Style_Check_Standard);
+      Add ('o', Style_Check_Subprogram_Order);
+      Add ('p', Style_Check_Pragma_Casing);
+      Add ('r', Style_Check_References);
+      Add ('s', Style_Check_Specs);
+      Add ('t', Style_Check_Tokens);
+
+      if Style_Check_Max_Line_Length then
+         P := Options'Last;
+         J := Natural (Style_Max_Line_Length);
+
+         loop
+            Options (P) := Character'Val (J mod 10 + Character'Pos ('0'));
+            P := P - 1;
+            J := J / 10;
+            exit when J = 0;
+         end loop;
+
+         Options (P) := 'M';
+      end if;
+
+   end Save_Style_Check_Options;
+
+   -------------------------------------
+   -- Set_Default_Style_Check_Options --
+   -------------------------------------
+
+   procedure Set_Default_Style_Check_Options is
+   begin
+      Reset_Style_Check_Options;
+      Set_Style_Check_Options ("3abcefhiklmnprst");
+   end Set_Default_Style_Check_Options;
+
+   -----------------------------
+   -- Set_Style_Check_Options --
+   -----------------------------
+
+   --  Version used when no error checking is required
+
+   procedure Set_Style_Check_Options (Options : String) is
+      OK : Boolean;
+      EC : Natural;
+
+   begin
+      Set_Style_Check_Options (Options, OK, EC);
+   end Set_Style_Check_Options;
+
+   --  Normal version with error checking
+
+   procedure Set_Style_Check_Options
+     (Options  : String;
+      OK       : out Boolean;
+      Err_Col  : out Natural)
+   is
+      J : Natural;
+      C : Character;
+
+   begin
+      J := Options'First;
+      while J <= Options'Last loop
+         C := Options (J);
+         J := J + 1;
+
+         case C is
+            when '1' .. '9' =>
+               Style_Check_Indentation
+                  := Character'Pos (C) - Character'Pos ('0');
+
+            when 'a' =>
+               Style_Check_Attribute_Casing := True;
+
+            when 'b' =>
+               Style_Check_Blanks_At_End    := True;
+
+            when 'c' =>
+               Style_Check_Comments         := True;
+
+            when 'e' =>
+               Style_Check_End_Labels       := True;
+
+            when 'f' =>
+               Style_Check_Form_Feeds       := True;
+
+            when 'h' =>
+               Style_Check_Horizontal_Tabs  := True;
+
+            when 'i' =>
+               Style_Check_If_Then_Layout   := True;
+
+            when 'k' =>
+               Style_Check_Keyword_Casing   := True;
+
+            when 'l' =>
+               Style_Check_Layout           := True;
+
+            when 'm' =>
+               Style_Check_Max_Line_Length  := True;
+               Style_Max_Line_Length        := 79;
+
+            when 'n' =>
+               Style_Check_Standard         := True;
+
+            when 'M' =>
+               Style_Max_Line_Length := 0;
+
+               if J > Options'Last
+                 or else Options (J) not in '0' .. '9'
+               then
+                  OK := False;
+                  Err_Col := J;
+                  return;
+               end if;
+
+               loop
+                  Style_Max_Line_Length :=
+                    Style_Max_Line_Length * 10 +
+                      Character'Pos (Options (J)) - Character'Pos ('0');
+                  J := J + 1;
+                  exit when J > Options'Last
+                    or else Options (J) not in '0' .. '9';
+               end loop;
+
+               Style_Max_Line_Length :=
+                  Int'Min (Style_Max_Line_Length, Hostparm.Max_Line_Length);
+
+               Style_Check_Max_Line_Length := Style_Max_Line_Length /= 0;
+
+            when 'o' =>
+               Style_Check_Subprogram_Order := True;
+
+            when 'p' =>
+               Style_Check_Pragma_Casing    := True;
+
+            when 'r' =>
+               Style_Check_References       := True;
+
+            when 's' =>
+               Style_Check_Specs            := True;
+
+            when 't' =>
+               Style_Check_Tokens           := True;
+
+            when ' ' =>
+               null;
+
+            when others =>
+               OK      := False;
+               Err_Col := J - 1;
+               return;
+         end case;
+      end loop;
+
+      Style_Check := True;
+      OK := True;
+      Err_Col := Options'Last + 1;
+   end Set_Style_Check_Options;
+
+end Stylesw;
diff --git a/gcc/ada/stylesw.ads b/gcc/ada/stylesw.ads
new file mode 100644 (file)
index 0000000..3352b4c
--- /dev/null
@@ -0,0 +1,264 @@
+------------------------------------------------------------------------------
+--                                                                          --
+--                         GNAT COMPILER COMPONENTS                         --
+--                                                                          --
+--                              S T Y L E S W                               --
+--                                                                          --
+--                                 S p e c                                  --
+--                                                                          --
+--                            $Revision: 1.12 $
+--                                                                          --
+--          Copyright (C) 1992-2001, 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- --
+-- ware  Foundation;  either version 2,  or (at your option) any later ver- --
+-- sion.  GNAT is distributed in the hope that it will be useful, but WITH- --
+-- OUT ANY WARRANTY;  without even the  implied warranty of MERCHANTABILITY --
+-- or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License --
+-- for  more details.  You should have  received  a copy of the GNU General --
+-- Public License  distributed with GNAT;  see file COPYING.  If not, write --
+-- to  the Free Software Foundation,  59 Temple Place - Suite 330,  Boston, --
+-- MA 02111-1307, USA.                                                      --
+--                                                                          --
+-- GNAT was originally developed  by the GNAT team at  New York University. --
+-- It is now maintained by Ada Core Technologies Inc (http://www.gnat.com). --
+--                                                                          --
+------------------------------------------------------------------------------
+
+--  This package contains the style switches used for setting style options.
+--  The only clients of this package are the body of Style and the body of
+--  Switches. All other style checking issues are handled using the public
+--  interfaces in the spec of Style.
+
+with Types; use Types;
+
+package Stylesw is
+
+   --------------------------
+   -- Style Check Switches --
+   --------------------------
+
+   --  These flags are used to control the details of the style checking
+   --  options. The default values shown here correspond to no style
+   --  checking. If any of these values is set to a non-default value,
+   --  then Opt.Style_Check is set True to active calls to this package.
+
+   --  The actual mechanism for setting these switches to other than
+   --  default values is via the Set_Style_Check_Option procedure or
+   --  through a call to Set_Default_Style_Check_Options. They should
+   --  not be set directly in any other manner.
+
+   Style_Check_Attribute_Casing : Boolean := False;
+   --  This can be set True by using the -gnatg or -gnatya switches. If
+   --  it is True, then attribute names (including keywords such as
+   --  digits used as attribute names) must be in mixed case.
+
+   Style_Check_Blanks_At_End : Boolean := False;
+   --  This can be set True by using the -gnatg or -gnatyb switches. If
+   --  it is True, then spaces at the end of lines are not permitted.
+
+   Style_Check_Comments : Boolean := False;
+   --  This can be set True by using the -gnatg or -gnatyc switches. If
+   --  it is True, then comments are style checked as follows:
+   --
+   --    All comments must be at the start of the line, or the first
+   --    minus must be preceded by at least one space.
+   --
+   --    For a comment that is not at the start of a line, the only
+   --    requirement is that a space follow the comment characters.
+   --
+   --    For a coment that is at the start of the line, one of the
+   --    following conditions must hold:
+   --
+   --      The comment characters are the only non-blank characters on the line
+   --
+   --      The comment characters are followed by an exclamation point (the
+   --      sequence --! is used by gnatprep for marking deleted lines).
+   --
+   --      The comment characters are followed by two space characters
+   --
+   --      The line consists entirely of minus signs
+   --
+   --      The comment characters are followed by a single space, and the
+   --      last two characters on the line are also comment characters.
+   --
+   --  Note: the reason for the last two conditions is to allow "boxed"
+   --  comments where only a single space separates the comment characters.
+
+   Style_Check_End_Labels : Boolean := False;
+   --  This can be set True by using the -gnatg or -gnatye switches. If
+   --  it is True, then optional END labels must always be present.
+
+   Style_Check_Form_Feeds : Boolean := False;
+   --  This can be set True by using the -gnatg or -gnatyf switches. If
+   --  it is True, then form feeds and vertical tabs are not allowed in
+   --  the source text.
+
+   Style_Check_Horizontal_Tabs : Boolean := False;
+   --  This can be set True by using the -gnatg or -gnatyh switches. If
+   --  it is True, then horizontal tabs are not allowed in source text.
+
+   Style_Check_If_Then_Layout : Boolean := False;
+   --  This can be set True by using the -gnatg or -gnatyi switches. If
+   --  it is True, then a THEN keyword may not appear on the line that
+   --  immediately follows the line containing the corresponding IF.
+   --
+   --  This permits one of two styles for IF-THEN layout. Either the
+   --  IF and THEN keywords are on the same line, where the condition
+   --  is short enough, or the conditions are continued over to the
+   --  lines following the IF and the THEN stands on its own. For
+   --  example:
+   --
+   --    if X > Y then
+   --
+   --    if X > Y
+   --      and then Y < Z
+   --    then
+   --
+   --  are allowed, but
+   --
+   --    if X > Y
+   --    then
+   --
+   --  is not allowed.
+
+   Style_Check_Indentation : Column_Number range 0 .. 9 := 0;
+   --  This can be set non-zero by using the -gnatg or -gnatyn (n a digit)
+   --  switches. If it is non-zero it activates indentation checking with
+   --  the indicated indentation value. A value of zero turns off checking.
+   --  The requirement is that any new statement, line comment, declaration
+   --  or keyword such as END, start on a column that is a multiple of the
+   --  indentiation value.
+
+   Style_Check_Keyword_Casing : Boolean := False;
+   --  This can be set True by using the -gnatg or -gnatyk switches. If
+   --  it is True, then keywords are required to be in all lower case.
+   --  This rule does not apply to keywords such as digits appearing as
+   --  an attribute name.
+
+   Style_Check_Max_Line_Length : Boolean := False;
+   --  This can be set True by using the -gnatg or -gnatym switches. If
+   --  it is True, it activates checking for a maximum line length of 79
+   --  characters (chosen to fit in standard 80 column displays that don't
+   --  handle the limiting case of 80 characters cleanly).
+
+   Style_Check_Pragma_Casing : Boolean := False;
+   --  This can be set True by using the -gnatg or -gnatyp switches. If
+   --  it is True, then pragma names must use mixed case.
+
+   Style_Check_Layout : Boolean := False;
+   --  This can be set True by using the -gnatg or -gnatyl switches. If
+   --  it is True, it activates checks that constructs are indented as
+   --  suggested by the examples in the RM syntax, e.g. that the ELSE
+   --  keyword must line up with the IF keyword.
+
+   Style_Check_References : Boolean := False;
+   --  This can be set True by using the -gnatg or -gnatyr switches. If
+   --  it is True, then all references to declared identifiers are
+   --  checked. The requirement is that casing of the reference be the
+   --  same as the casing of the corresponding declaration.
+
+   Style_Check_Specs : Boolean := False;
+   --  This can be set True by using the -gnatg or -gnatys switches. If
+   --  it is True, then separate specs are required to be present for
+   --  all procedures except parameterless library level procedures.
+   --  The exception means that typical main programs do not require
+   --  separate specs.
+
+   Style_Check_Standard : Boolean := False;
+   --  This can be set True by using the -gnatg or -gnatyn switches. If
+   --  it is True, then any references to names in Standard have to be
+   --  in mixed case mode (e.g. Integer, Boolean).
+
+   Style_Check_Tokens : Boolean := False;
+   --  This can be set True by using the -gnatg or -gnatyt switches. If
+   --  it is True, then the style check that requires canonical spacing
+   --  between various punctuation tokens as follows:
+   --
+   --    ABS and NOT must be followed by a space
+   --
+   --    => must be surrounded by spaces
+   --
+   --    <> must be preceded by a space or left paren
+   --
+   --    Binary operators other than ** must be surrounded by spaces.
+   --    There is no restriction on the layout of the ** binary operator.
+   --
+   --    Colon must be surrounded by spaces
+   --
+   --    Colon-equal (assignment) must be surrounded by spaces
+   --
+   --    Comma must be the first non-blank character on the line, or be
+   --    immediately preceded by a non-blank character, and must be followed
+   --    by a blank.
+   --
+   --    A space must precede a left paren following a digit or letter,
+   --    and a right paren must not be followed by a space (it can be
+   --    at the end of the line).
+   --
+   --    A right paren must either be the first non-blank character on
+   --    a line, or it must be preceded by a non-blank character.
+   --
+   --    A semicolon must not be preceded by a blank, and must not be
+   --    followed by a non-blank character.
+   --
+   --    A unary plus or minus may not be followed by a space
+   --
+   --    A vertical bar must be surrounded by spaces
+   --
+   --  Note that a requirement that a token be preceded by a space is
+   --  met by placing the token at the start of the line, and similarly
+   --  a requirement that a token be followed by a space is met by
+   --  placing the token at the end of the line. Note that in the case
+   --  where horizontal tabs are permitted, a horizontal tab is acceptable
+   --  for meeting the requirement for a space.
+
+   Style_Check_Subprogram_Order : Boolean := False;
+   --  This can be set True by using the -gnatg or -gnatyo switch. If it
+   --  is True, then names of subprogram bodies must be in alphabetical
+   --  order (not taking casing into account).
+
+   Style_Max_Line_Length : Int := 79;
+   --  Value used to check maximum line length. Can be reset by a call to
+   --  Set_Max_Line_Length. The value here is the default if no such call.
+
+   -----------------
+   -- Subprograms --
+   -----------------
+
+   procedure Set_Default_Style_Check_Options;
+   --  This procedure is called to set the default style checking options
+   --  in response to a -gnatg switch or -gnaty with no suboptions.
+
+   procedure Set_Style_Check_Options
+     (Options  : String;
+      OK       : out Boolean;
+      Err_Col  : out Natural);
+   --  This procedure is called to set the style check options that
+   --  correspond to the characters in the given Options string. If
+   --  all options are valid, they are set in an additive manner:
+   --  any previous options are retained unless overridden. If any
+   --  invalid character is found, then OK is False on exit, and
+   --  Err_Col is the index in options of the bad character. If all
+   --  options are valid, OK is True on return, and Err_Col is set
+   --  to Options'Last + 1.
+
+   procedure Set_Style_Check_Options (Options : String);
+   --  Like the above procedure, except that the call is simply ignored if
+   --  there are any error conditions, this is for example appopriate for
+   --  calls where the string is known to be valid, e.g. because it was
+   --  obtained by Save_Style_Check_Options.
+
+   procedure Reset_Style_Check_Options;
+   --  Sets all style check options to off
+
+   subtype Style_Check_Options is String (1 .. 32);
+   --  Long enough string to hold all options from Save call below
+
+   procedure Save_Style_Check_Options (Options : out Style_Check_Options);
+   --  Sets Options to represent current selection of options. This
+   --  set can be restored by first calling Reset_Style_Check_Options,
+   --  and then calling Set_Style_Check_Options with the Options string.
+
+end Stylesw;
diff --git a/gcc/ada/switch.adb b/gcc/ada/switch.adb
new file mode 100644 (file)
index 0000000..ee97c6f
--- /dev/null
@@ -0,0 +1,1364 @@
+------------------------------------------------------------------------------
+--                                                                          --
+--                         GNAT COMPILER COMPONENTS                         --
+--                                                                          --
+--                               S W I T C H                                --
+--                                                                          --
+--                                 B o d y                                  --
+--                                                                          --
+--                            $Revision: 1.194 $
+--                                                                          --
+--          Copyright (C) 1992-2001, 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- --
+-- ware  Foundation;  either version 2,  or (at your option) any later ver- --
+-- sion.  GNAT is distributed in the hope that it will be useful, but WITH- --
+-- OUT ANY WARRANTY;  without even the  implied warranty of MERCHANTABILITY --
+-- or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License --
+-- for  more details.  You should have  received  a copy of the GNU General --
+-- Public License  distributed with GNAT;  see file COPYING.  If not, write --
+-- to  the Free Software Foundation,  59 Temple Place - Suite 330,  Boston, --
+-- MA 02111-1307, USA.                                                      --
+--                                                                          --
+-- GNAT was originally developed  by the GNAT team at  New York University. --
+-- It is now maintained by Ada Core Technologies Inc (http://www.gnat.com). --
+--                                                                          --
+------------------------------------------------------------------------------
+
+--  Option switch scanning for both the compiler and the binder
+
+--  Note: this version of the package should be usable in both Unix and DOS
+
+with Debug;    use Debug;
+with Osint;    use Osint;
+with Opt;      use Opt;
+with Validsw;  use Validsw;
+with Stylesw;  use Stylesw;
+with Types;    use Types;
+
+with System.WCh_Con; use System.WCh_Con;
+
+package body Switch is
+
+   Bad_Switch : exception;
+   --  Exception raised if bad switch encountered
+
+   Bad_Switch_Value : exception;
+   --  Exception raised if bad switch value encountered
+
+   Missing_Switch_Value : exception;
+   --  Exception raised if no switch value encountered
+
+   Too_Many_Output_Files : exception;
+   --  Exception raised if the -o switch is encountered more than once
+
+   Switch_Max_Value : constant := 999;
+   --  Maximum value permitted in switches that take a value
+
+   procedure Scan_Nat
+     (Switch_Chars : String;
+      Max          : Integer;
+      Ptr          : in out Integer;
+      Result       : out Nat);
+   --  Scan natural integer parameter for switch. On entry, Ptr points
+   --  just past the switch character, on exit it points past the last
+   --  digit of the integer value.
+
+   procedure Scan_Pos
+     (Switch_Chars : String;
+      Max          : Integer;
+      Ptr          : in out Integer;
+      Result       : out Pos);
+   --  Scan positive integer parameter for switch. On entry, Ptr points
+   --  just past the switch character, on exit it points past the last
+   --  digit of the integer value.
+
+   -------------------------
+   -- Is_Front_End_Switch --
+   -------------------------
+
+   function Is_Front_End_Switch (Switch_Chars : String) return Boolean is
+      Ptr       : constant Positive := Switch_Chars'First;
+   begin
+      return Is_Switch (Switch_Chars)
+        and then
+          (Switch_Chars (Ptr + 1) = 'I'
+             or else
+          (Switch_Chars'Length >= 5
+                         and then Switch_Chars (Ptr + 1 .. Ptr + 4) = "gnat"));
+   end Is_Front_End_Switch;
+
+   ---------------
+   -- Is_Switch --
+   ---------------
+
+   function Is_Switch (Switch_Chars : String) return Boolean is
+   begin
+      return Switch_Chars'Length > 1
+        and then (Switch_Chars (Switch_Chars'First) = '-'
+                     or
+                  Switch_Chars (Switch_Chars'First) = Switch_Character);
+   end Is_Switch;
+
+   --------------------------
+   -- Scan_Binder_Switches --
+   --------------------------
+
+   procedure Scan_Binder_Switches (Switch_Chars : String) is
+      Ptr : Integer := Switch_Chars'First;
+      Max : Integer := Switch_Chars'Last;
+      C   : Character := ' ';
+
+   begin
+      --  Skip past the initial character (must be the switch character)
+
+      if Ptr = Max then
+         raise Bad_Switch;
+      else
+         Ptr := Ptr + 1;
+      end if;
+
+      --  A little check, "gnat" at the start of a switch is not allowed
+      --  except for the compiler
+
+      if Switch_Chars'Last >= Ptr + 3
+        and then Switch_Chars (Ptr .. Ptr + 3) = "gnat"
+      then
+         Osint.Fail ("invalid switch: """, Switch_Chars, """"
+            & " (gnat not needed here)");
+
+      end if;
+
+      --  Loop to scan through switches given in switch string
+
+      while Ptr <= Max loop
+         C := Switch_Chars (Ptr);
+
+         case C is
+
+         --  Processing for A switch
+
+         when 'A' =>
+            Ptr := Ptr + 1;
+
+            Ada_Bind_File := True;
+
+         --  Processing for b switch
+
+         when 'b' =>
+            Ptr := Ptr + 1;
+            Brief_Output := True;
+
+         --  Processing for c switch
+
+         when 'c' =>
+            Ptr := Ptr + 1;
+
+            Check_Only := True;
+
+         --  Processing for C switch
+
+         when 'C' =>
+            Ptr := Ptr + 1;
+
+            Ada_Bind_File := False;
+
+         --  Processing for d switch
+
+         when 'd' =>
+
+            --  Note: for the debug switch, the remaining characters in this
+            --  switch field must all be debug flags, since all valid switch
+            --  characters are also valid debug characters.
+
+            --  Loop to scan out debug flags
+
+            while Ptr < Max loop
+               Ptr := Ptr + 1;
+               C := Switch_Chars (Ptr);
+               exit when C = ASCII.NUL or else C = '/' or else C = '-';
+
+               if C in '1' .. '9' or else
+                  C in 'a' .. 'z' or else
+                  C in 'A' .. 'Z'
+               then
+                  Set_Debug_Flag (C);
+               else
+                  raise Bad_Switch;
+               end if;
+            end loop;
+
+            --  Make sure Zero_Cost_Exceptions is set if gnatdX set. This
+            --  is for backwards compatibility with old versions and usage.
+
+            if Debug_Flag_XX then
+               Zero_Cost_Exceptions_Set := True;
+               Zero_Cost_Exceptions_Val := True;
+            end if;
+
+            return;
+
+         --  Processing for e switch
+
+         when 'e' =>
+            Ptr := Ptr + 1;
+            Elab_Dependency_Output := True;
+
+         --  Processing for E switch
+
+         when 'E' =>
+            Ptr := Ptr + 1;
+            Exception_Tracebacks := True;
+
+         --  Processing for f switch
+
+         when 'f' =>
+            Ptr := Ptr + 1;
+            Force_RM_Elaboration_Order := True;
+
+         --  Processing for g switch
+
+         when 'g' =>
+            Ptr := Ptr + 1;
+            if Ptr <= Max then
+               C := Switch_Chars (Ptr);
+               if C in '0' .. '3' then
+                  Debugger_Level :=
+                    Character'Pos
+                      (Switch_Chars (Ptr)) - Character'Pos ('0');
+                  Ptr := Ptr + 1;
+               end if;
+            else
+               Debugger_Level := 2;
+            end if;
+
+         --  Processing for G switch
+
+         when 'G' =>
+            Ptr := Ptr + 1;
+            Print_Generated_Code := True;
+
+         --  Processing for h switch
+
+         when 'h' =>
+            Ptr := Ptr + 1;
+            Usage_Requested := True;
+
+         --  Processing for i switch
+
+         when 'i' =>
+            if Ptr = Max then
+               raise Bad_Switch;
+            end if;
+
+            Ptr := Ptr + 1;
+            C := Switch_Chars (Ptr);
+
+            if C = '1' or else
+               C = '2' or else
+               C = '3' or else
+               C = '4' or else
+               C = '8' or else
+               C = 'p' or else
+               C = 'f' or else
+               C = 'n' or else
+               C = 'w'
+            then
+               Identifier_Character_Set := C;
+               Ptr := Ptr + 1;
+            else
+               raise Bad_Switch;
+            end if;
+
+         --  Processing for K switch
+
+         when 'K' =>
+            Ptr := Ptr + 1;
+
+            if Program = Binder then
+               Output_Linker_Option_List := True;
+            else
+               raise Bad_Switch;
+            end if;
+
+         --  Processing for l switch
+
+         when 'l' =>
+            Ptr := Ptr + 1;
+            Elab_Order_Output := True;
+
+         --  Processing for m switch
+
+         when 'm' =>
+            Ptr := Ptr + 1;
+            Scan_Pos (Switch_Chars, Max, Ptr, Maximum_Errors);
+
+         --  Processing for n switch
+
+         when 'n' =>
+            Ptr := Ptr + 1;
+            Bind_Main_Program := False;
+
+            --  Note: The -L option of the binder also implies -n, so
+            --  any change here must also be reflected in the processing
+            --  for -L that is found in Gnatbind.Scan_Bind_Arg.
+
+         --  Processing for o switch
+
+         when 'o' =>
+            Ptr := Ptr + 1;
+
+            if Output_File_Name_Present then
+               raise Too_Many_Output_Files;
+
+            else
+               Output_File_Name_Present := True;
+            end if;
+
+         --  Processing for O switch
+
+         when 'O' =>
+            Ptr := Ptr + 1;
+            Output_Object_List := True;
+
+         --  Processing for p switch
+
+         when 'p' =>
+            Ptr := Ptr + 1;
+            Pessimistic_Elab_Order := True;
+
+         --  Processing for q switch
+
+         when 'q' =>
+            Ptr := Ptr + 1;
+            Quiet_Output := True;
+
+         --  Processing for s switch
+
+         when 's' =>
+            Ptr := Ptr + 1;
+            All_Sources := True;
+            Check_Source_Files := True;
+
+         --  Processing for t switch
+
+         when 't' =>
+            Ptr := Ptr + 1;
+            Tolerate_Consistency_Errors := True;
+
+         --  Processing for T switch
+
+         when 'T' =>
+            Ptr := Ptr + 1;
+            Time_Slice_Set := True;
+            Scan_Nat (Switch_Chars, Max, Ptr, Time_Slice_Value);
+
+         --  Processing for v switch
+
+         when 'v' =>
+            Ptr := Ptr + 1;
+            Verbose_Mode := True;
+
+         --  Processing for w switch
+
+         when 'w' =>
+
+            --  For the binder we only allow suppress/error cases
+
+            Ptr := Ptr + 1;
+
+            case Switch_Chars (Ptr) is
+
+               when 'e' =>
+                  Warning_Mode  := Treat_As_Error;
+
+               when 's' =>
+                  Warning_Mode  := Suppress;
+
+               when others =>
+                  raise Bad_Switch;
+            end case;
+
+            Ptr := Ptr + 1;
+
+         --  Processing for W switch
+
+         when 'W' =>
+            Ptr := Ptr + 1;
+
+            for J in WC_Encoding_Method loop
+               if Switch_Chars (Ptr) = WC_Encoding_Letters (J) then
+                  Wide_Character_Encoding_Method := J;
+                  exit;
+
+               elsif J = WC_Encoding_Method'Last then
+                  raise Bad_Switch;
+               end if;
+            end loop;
+
+            Upper_Half_Encoding :=
+              Wide_Character_Encoding_Method in
+                WC_Upper_Half_Encoding_Method;
+
+            Ptr := Ptr + 1;
+
+         --  Processing for x switch
+
+         when 'x' =>
+            Ptr := Ptr + 1;
+            All_Sources := False;
+            Check_Source_Files := False;
+
+         --  Processing for z switch
+
+         when 'z' =>
+            Ptr := Ptr + 1;
+            No_Main_Subprogram := True;
+
+         --  Ignore extra switch character
+
+         when '/' | '-' =>
+            Ptr := Ptr + 1;
+
+         --  Anything else is an error (illegal switch character)
+
+         when others =>
+            raise Bad_Switch;
+         end case;
+      end loop;
+
+   exception
+      when Bad_Switch =>
+         Osint.Fail ("invalid switch: ", (1 => C));
+
+      when Bad_Switch_Value =>
+         Osint.Fail ("numeric value too big for switch: ", (1 => C));
+
+      when Missing_Switch_Value =>
+         Osint.Fail ("missing numeric value for switch: ", (1 => C));
+
+      when Too_Many_Output_Files =>
+         Osint.Fail ("duplicate -o switch");
+   end Scan_Binder_Switches;
+
+   -----------------------------
+   -- Scan_Front_End_Switches --
+   -----------------------------
+
+   procedure Scan_Front_End_Switches (Switch_Chars : String) is
+      Switch_Starts_With_Gnat : Boolean;
+      Ptr : Integer := Switch_Chars'First;
+      Max : constant Integer := Switch_Chars'Last;
+      C   : Character := ' ';
+
+   begin
+      --  Skip past the initial character (must be the switch character)
+
+      if Ptr = Max then
+         raise Bad_Switch;
+
+      else
+         Ptr := Ptr + 1;
+      end if;
+
+      --  A little check, "gnat" at the start of a switch is not allowed
+      --  except for the compiler (where it was already removed)
+
+      Switch_Starts_With_Gnat :=
+         Ptr + 3 <= Max and then Switch_Chars (Ptr .. Ptr + 3) = "gnat";
+
+      if Switch_Starts_With_Gnat then
+         Ptr := Ptr + 4;
+      end if;
+
+      --  Loop to scan through switches given in switch string
+
+      while Ptr <= Max loop
+         C := Switch_Chars (Ptr);
+
+         --  Processing for a switch
+
+         case Switch_Starts_With_Gnat is
+
+         when False =>
+            --  There is only one front-end switch that
+            --  does not start with -gnat, namely -I
+
+            case C is
+
+            when 'I' =>
+               Ptr := Ptr + 1;
+
+               if Ptr > Max then
+                  raise Bad_Switch;
+               end if;
+
+               --  Find out whether this is a -I- or regular -Ixxx switch
+
+               if Ptr = Max and then Switch_Chars (Ptr) = '-' then
+                  Look_In_Primary_Dir := False;
+
+               else
+                  Add_Src_Search_Dir (Switch_Chars (Ptr .. Max));
+               end if;
+
+               Ptr := Max + 1;
+
+            when others =>
+               --  Should not happen, as Scan_Switches is supposed
+               --  to be called for front-end switches only.
+               --  Still, it is safest to raise Bad_Switch error.
+
+               raise Bad_Switch;
+            end case;
+
+         when True =>
+            --  Process -gnat* options
+
+            case C is
+
+            when 'a' =>
+               Ptr := Ptr + 1;
+               Assertions_Enabled := True;
+
+            --  Processing for A switch
+
+            when 'A' =>
+               Ptr := Ptr + 1;
+               Config_File := False;
+
+            --  Processing for b switch
+
+            when 'b' =>
+               Ptr := Ptr + 1;
+               Brief_Output := True;
+
+            --  Processing for c switch
+
+            when 'c' =>
+               Ptr := Ptr + 1;
+               Operating_Mode := Check_Semantics;
+
+            --  Processing for C switch
+
+            when 'C' =>
+               Ptr := Ptr + 1;
+               Compress_Debug_Names := True;
+
+            --  Processing for d switch
+
+            when 'd' =>
+
+               --  Note: for the debug switch, the remaining characters in this
+               --  switch field must all be debug flags, since all valid switch
+               --  characters are also valid debug characters.
+
+               --  Loop to scan out debug flags
+
+               while Ptr < Max loop
+                  Ptr := Ptr + 1;
+                  C := Switch_Chars (Ptr);
+                  exit when C = ASCII.NUL or else C = '/' or else C = '-';
+
+                  if C in '1' .. '9' or else
+                     C in 'a' .. 'z' or else
+                     C in 'A' .. 'Z'
+                  then
+                     Set_Debug_Flag (C);
+
+                  else
+                     raise Bad_Switch;
+                  end if;
+               end loop;
+
+               --  Make sure Zero_Cost_Exceptions is set if gnatdX set. This
+               --  is for backwards compatibility with old versions and usage.
+
+               if Debug_Flag_XX then
+                  Zero_Cost_Exceptions_Set := True;
+                  Zero_Cost_Exceptions_Val := True;
+               end if;
+
+               return;
+
+            --  Processing for D switch
+
+            when 'D' =>
+               Ptr := Ptr + 1;
+
+               --  Note: -gnatD also sets -gnatx (to turn off cross-reference
+               --  generation in the ali file) since otherwise this generation
+               --  gets confused by the "wrong" Sloc values put in the tree.
+
+               Debug_Generated_Code := True;
+               Xref_Active := False;
+               Set_Debug_Flag ('g');
+
+            --  Processing for e switch
+
+            when 'e' =>
+               Ptr := Ptr + 1;
+
+               if Ptr > Max then
+                  raise Bad_Switch;
+               end if;
+
+               case Switch_Chars (Ptr) is
+
+                  when 'c' =>
+                     Ptr := Ptr + 1;
+                     if Ptr > Max then
+                        Osint.Fail ("Invalid switch: ", "ec");
+                     end if;
+
+                     Config_File_Name :=
+                        new String'(Switch_Chars (Ptr .. Max));
+
+                     return;
+
+                  when others =>
+                     Osint.Fail ("Invalid switch: ",
+                                   (1 => 'e', 2 => Switch_Chars (Ptr)));
+               end case;
+
+            --  Processing for E switch
+
+            when 'E' =>
+               Ptr := Ptr + 1;
+               Dynamic_Elaboration_Checks := True;
+
+            --  Processing for f switch
+
+            when 'f' =>
+               Ptr := Ptr + 1;
+               All_Errors_Mode := True;
+
+            --  Processing for F switch
+
+            when 'F' =>
+               Ptr := Ptr + 1;
+               External_Name_Exp_Casing := Uppercase;
+               External_Name_Imp_Casing := Uppercase;
+
+            --  Processing for g switch
+
+            when 'g' =>
+               Ptr := Ptr + 1;
+               GNAT_Mode                := True;
+               Identifier_Character_Set := 'n';
+               Warning_Mode             := Treat_As_Error;
+               Check_Unreferenced       := True;
+               Check_Withs              := True;
+
+               Set_Default_Style_Check_Options;
+
+            --  Processing for G switch
+
+            when 'G' =>
+               Ptr := Ptr + 1;
+               Print_Generated_Code := True;
+
+            --  Processing for h switch
+
+            when 'h' =>
+               Ptr := Ptr + 1;
+               Usage_Requested := True;
+
+            --  Processing for H switch
+
+            when 'H' =>
+               Ptr := Ptr + 1;
+               HLO_Active := True;
+
+            --  Processing for i switch
+
+            when 'i' =>
+               if Ptr = Max then
+                  raise Bad_Switch;
+               end if;
+
+               Ptr := Ptr + 1;
+               C := Switch_Chars (Ptr);
+
+               if C = '1' or else
+                  C = '2' or else
+                  C = '3' or else
+                  C = '4' or else
+                  C = '8' or else
+                  C = 'p' or else
+                  C = 'f' or else
+                  C = 'n' or else
+                  C = 'w'
+               then
+                  Identifier_Character_Set := C;
+                  Ptr := Ptr + 1;
+
+               else
+                  raise Bad_Switch;
+               end if;
+
+            --  Processing for k switch
+
+            when 'k' =>
+               Ptr := Ptr + 1;
+               Scan_Pos (Switch_Chars, Max, Ptr, Maximum_File_Name_Length);
+
+            --  Processing for l switch
+
+            when 'l' =>
+               Ptr := Ptr + 1;
+               Full_List := True;
+
+            --  Processing for L switch
+
+            when 'L' =>
+               Ptr := Ptr + 1;
+               Zero_Cost_Exceptions_Set := True;
+               Zero_Cost_Exceptions_Val := False;
+
+            --  Processing for m switch
+
+            when 'm' =>
+               Ptr := Ptr + 1;
+               Scan_Pos (Switch_Chars, Max, Ptr, Maximum_Errors);
+
+            --  Processing for n switch
+
+            when 'n' =>
+               Ptr := Ptr + 1;
+               Inline_Active := True;
+
+            --  Processing for N switch
+
+            when 'N' =>
+               Ptr := Ptr + 1;
+               Inline_Active := True;
+               Front_End_Inlining := True;
+
+            --  Processing for o switch
+
+            when 'o' =>
+               Ptr := Ptr + 1;
+               Suppress_Options.Overflow_Checks := False;
+
+            --  Processing for O switch
+
+            when 'O' =>
+               Ptr := Ptr + 1;
+               Output_File_Name_Present := True;
+
+            --  Processing for p switch
+
+            when 'p' =>
+               Ptr := Ptr + 1;
+               Suppress_Options.Access_Checks        := True;
+               Suppress_Options.Accessibility_Checks := True;
+               Suppress_Options.Discriminant_Checks  := True;
+               Suppress_Options.Division_Checks      := True;
+               Suppress_Options.Elaboration_Checks   := True;
+               Suppress_Options.Index_Checks         := True;
+               Suppress_Options.Length_Checks        := True;
+               Suppress_Options.Overflow_Checks      := True;
+               Suppress_Options.Range_Checks         := True;
+               Suppress_Options.Division_Checks      := True;
+               Suppress_Options.Length_Checks        := True;
+               Suppress_Options.Range_Checks         := True;
+               Suppress_Options.Storage_Checks       := True;
+               Suppress_Options.Tag_Checks           := True;
+
+               Validity_Checks_On := False;
+
+            --  Processing for P switch
+
+            when 'P' =>
+               Ptr := Ptr + 1;
+               Polling_Required := True;
+
+            --  Processing for q switch
+
+            when 'q' =>
+               Ptr := Ptr + 1;
+               Try_Semantics := True;
+
+            --  Processing for q switch
+
+            when 'Q' =>
+               Ptr := Ptr + 1;
+               Force_ALI_Tree_File := True;
+               Try_Semantics := True;
+
+            --  Processing for r switch
+
+            when 'r' =>
+               Ptr := Ptr + 1;
+
+               --  Temporarily allow -gnatr to mean -gnatyl (use RM layout)
+               --  for compatibility with pre 3.12 versions of GNAT,
+               --  to be removed for 3.13 ???
+
+               Set_Style_Check_Options ("l");
+
+            --  Processing for R switch
+
+            when 'R' =>
+               Ptr := Ptr + 1;
+               Back_Annotate_Rep_Info := True;
+
+               if Ptr <= Max
+                 and then Switch_Chars (Ptr) in '0' .. '9'
+               then
+                  C := Switch_Chars (Ptr);
+
+                  if C in '4' .. '9' then
+                     raise Bad_Switch;
+                  else
+                     List_Representation_Info :=
+                       Character'Pos (C) - Character'Pos ('0');
+                     Ptr := Ptr + 1;
+                  end if;
+
+               else
+                  List_Representation_Info := 1;
+               end if;
+
+            --  Processing for s switch
+
+            when 's' =>
+               Ptr := Ptr + 1;
+               Operating_Mode := Check_Syntax;
+
+            --  Processing for t switch
+
+            when 't' =>
+               Ptr := Ptr + 1;
+               Tree_Output := True;
+               Back_Annotate_Rep_Info := True;
+
+            --  Processing for T switch
+
+            when 'T' =>
+               Ptr := Ptr + 1;
+               Time_Slice_Set := True;
+               Scan_Nat (Switch_Chars, Max, Ptr, Time_Slice_Value);
+
+            --  Processing for u switch
+
+            when 'u' =>
+               Ptr := Ptr + 1;
+               List_Units := True;
+
+            --  Processing for U switch
+
+            when 'U' =>
+               Ptr := Ptr + 1;
+               Unique_Error_Tag := True;
+
+            --  Processing for v switch
+
+            when 'v' =>
+               Ptr := Ptr + 1;
+               Verbose_Mode := True;
+
+            --  Processing for V switch
+
+            when 'V' =>
+               Ptr := Ptr + 1;
+
+               if Ptr > Max then
+                  raise Bad_Switch;
+
+               else
+                  declare
+                     OK  : Boolean;
+
+                  begin
+                     Set_Validity_Check_Options
+                       (Switch_Chars (Ptr .. Max), OK, Ptr);
+
+                     if not OK then
+                        raise Bad_Switch;
+                     end if;
+                  end;
+               end if;
+
+            --  Processing for w switch
+
+            when 'w' =>
+               Ptr := Ptr + 1;
+
+               if Ptr > Max then
+                  raise Bad_Switch;
+               end if;
+
+               while Ptr <= Max loop
+                  C := Switch_Chars (Ptr);
+
+                  case C is
+
+                     when 'a' =>
+                        Constant_Condition_Warnings  := True;
+                        Elab_Warnings                := True;
+                        Check_Unreferenced           := True;
+                        Check_Withs                  := True;
+                        Implementation_Unit_Warnings := True;
+                        Ineffective_Inline_Warnings  := True;
+                        Warn_On_Redundant_Constructs := True;
+
+                     when 'A' =>
+                        Constant_Condition_Warnings  := False;
+                        Elab_Warnings                := False;
+                        Check_Unreferenced           := False;
+                        Check_Withs                  := False;
+                        Implementation_Unit_Warnings := False;
+                        Warn_On_Biased_Rounding      := False;
+                        Warn_On_Hiding               := False;
+                        Warn_On_Redundant_Constructs := False;
+                        Ineffective_Inline_Warnings  := False;
+
+                     when 'c' =>
+                        Constant_Condition_Warnings := True;
+
+                     when 'C' =>
+                        Constant_Condition_Warnings := False;
+
+                     when 'b' =>
+                        Warn_On_Biased_Rounding := True;
+
+                     when 'B' =>
+                        Warn_On_Biased_Rounding := False;
+
+                     when 'e' =>
+                        Warning_Mode := Treat_As_Error;
+
+                     when 'h' =>
+                        Warn_On_Hiding := True;
+
+                     when 'H' =>
+                        Warn_On_Hiding := False;
+
+                     when 'i' =>
+                        Implementation_Unit_Warnings := True;
+
+                     when 'I' =>
+                        Implementation_Unit_Warnings := False;
+
+                     when 'l' =>
+                        Elab_Warnings := True;
+
+                     when 'L' =>
+                        Elab_Warnings := False;
+
+                     when 'o' =>
+                        Address_Clause_Overlay_Warnings := True;
+
+                     when 'O' =>
+                        Address_Clause_Overlay_Warnings := False;
+
+                     when 'p' =>
+                        Ineffective_Inline_Warnings := True;
+
+                     when 'P' =>
+                        Ineffective_Inline_Warnings := False;
+
+                     when 'r' =>
+                        Warn_On_Redundant_Constructs := True;
+
+                     when 'R' =>
+                        Warn_On_Redundant_Constructs := False;
+
+                     when 's' =>
+                        Warning_Mode  := Suppress;
+
+                     when 'u' =>
+                        Check_Unreferenced := True;
+                        Check_Withs        := True;
+
+                     when 'U' =>
+                        Check_Unreferenced := False;
+                        Check_Withs        := False;
+
+                        --  Allow and ignore 'w' so that the old
+                        --  format (e.g. -gnatwuwl) will work.
+
+                     when 'w' =>
+                        null;
+
+                     when others =>
+                        raise Bad_Switch;
+                  end case;
+
+                  Ptr := Ptr + 1;
+               end loop;
+
+               return;
+
+            --  Processing for W switch
+
+            when 'W' =>
+               Ptr := Ptr + 1;
+
+               for J in WC_Encoding_Method loop
+                  if Switch_Chars (Ptr) = WC_Encoding_Letters (J) then
+                     Wide_Character_Encoding_Method := J;
+                     exit;
+
+                  elsif J = WC_Encoding_Method'Last then
+                     raise Bad_Switch;
+                  end if;
+               end loop;
+
+               Upper_Half_Encoding :=
+                 Wide_Character_Encoding_Method in
+                 WC_Upper_Half_Encoding_Method;
+
+               Ptr := Ptr + 1;
+
+            --  Processing for x switch
+
+            when 'x' =>
+               Ptr := Ptr + 1;
+               Xref_Active := False;
+
+            --  Processing for X switch
+
+            when 'X' =>
+               Ptr := Ptr + 1;
+               Extensions_Allowed := True;
+
+            --  Processing for y switch
+
+            when 'y' =>
+               Ptr := Ptr + 1;
+
+               if Ptr > Max then
+                  Set_Default_Style_Check_Options;
+
+               else
+                  declare
+                     OK  : Boolean;
+
+                  begin
+                     Set_Style_Check_Options
+                       (Switch_Chars (Ptr .. Max), OK, Ptr);
+
+                     if not OK then
+                        raise Bad_Switch;
+                     end if;
+                  end;
+               end if;
+
+            --  Processing for z switch
+
+            when 'z' =>
+               Ptr := Ptr + 1;
+
+               --  Allowed for compiler, only if this is the only
+               --  -z switch, we do not allow multiple occurrences
+
+               if Distribution_Stub_Mode = No_Stubs then
+                  case Switch_Chars (Ptr) is
+                     when 'r' =>
+                        Distribution_Stub_Mode := Generate_Receiver_Stub_Body;
+
+                     when 'c' =>
+                        Distribution_Stub_Mode := Generate_Caller_Stub_Body;
+
+                     when others =>
+                        raise Bad_Switch;
+                  end case;
+
+                  Ptr := Ptr + 1;
+
+               end if;
+
+            --  Processing for Z switch
+
+            when 'Z' =>
+               Ptr := Ptr + 1;
+               Zero_Cost_Exceptions_Set := True;
+               Zero_Cost_Exceptions_Val := True;
+
+            --  Processing for 83 switch
+
+            when '8' =>
+
+               if Ptr = Max then
+                  raise Bad_Switch;
+               end if;
+
+               Ptr := Ptr + 1;
+
+               if Switch_Chars (Ptr) /= '3' then
+                  raise Bad_Switch;
+               else
+                  Ptr := Ptr + 1;
+                  Ada_95 := False;
+                  Ada_83 := True;
+               end if;
+
+            --  Ignore extra switch character
+
+            when '/' | '-' =>
+               Ptr := Ptr + 1;
+
+            --  Anything else is an error (illegal switch character)
+
+            when others =>
+               raise Bad_Switch;
+            end case;
+         end case;
+      end loop;
+
+   exception
+      when Bad_Switch =>
+         Osint.Fail ("invalid switch: ", (1 => C));
+
+      when Bad_Switch_Value =>
+         Osint.Fail ("numeric value too big for switch: ", (1 => C));
+
+      when Missing_Switch_Value =>
+         Osint.Fail ("missing numeric value for switch: ", (1 => C));
+
+   end Scan_Front_End_Switches;
+
+   ------------------------
+   -- Scan_Make_Switches --
+   ------------------------
+
+   procedure Scan_Make_Switches (Switch_Chars : String) is
+      Ptr : Integer := Switch_Chars'First;
+      Max : Integer := Switch_Chars'Last;
+      C   : Character := ' ';
+
+   begin
+      --  Skip past the initial character (must be the switch character)
+
+      if Ptr = Max then
+         raise Bad_Switch;
+
+      else
+         Ptr := Ptr + 1;
+      end if;
+
+      --  A little check, "gnat" at the start of a switch is not allowed
+      --  except for the compiler (where it was already removed)
+
+      if Switch_Chars'Length >= Ptr + 3
+        and then Switch_Chars (Ptr .. Ptr + 3) = "gnat"
+      then
+         Osint.Fail
+           ("invalid switch: """, Switch_Chars, """ (gnat not needed here)");
+      end if;
+
+      --  Loop to scan through switches given in switch string
+
+      while Ptr <= Max loop
+         C := Switch_Chars (Ptr);
+
+         --  Processing for a switch
+
+         case C is
+
+         when 'a' =>
+            Ptr := Ptr + 1;
+            Check_Readonly_Files := True;
+
+         --  Processing for c switch
+
+         when 'c' =>
+            Ptr := Ptr + 1;
+            Compile_Only := True;
+
+         when 'd' =>
+
+            --  Note: for the debug switch, the remaining characters in this
+            --  switch field must all be debug flags, since all valid switch
+            --  characters are also valid debug characters.
+
+            --  Loop to scan out debug flags
+
+            while Ptr < Max loop
+               Ptr := Ptr + 1;
+               C := Switch_Chars (Ptr);
+               exit when C = ASCII.NUL or else C = '/' or else C = '-';
+
+               if C in '1' .. '9' or else
+                  C in 'a' .. 'z' or else
+                  C in 'A' .. 'Z'
+               then
+                  Set_Debug_Flag (C);
+               else
+                  raise Bad_Switch;
+               end if;
+            end loop;
+
+            --  Make sure Zero_Cost_Exceptions is set if gnatdX set. This
+            --  is for backwards compatibility with old versions and usage.
+
+            if Debug_Flag_XX then
+               Zero_Cost_Exceptions_Set := True;
+               Zero_Cost_Exceptions_Val := True;
+            end if;
+
+            return;
+
+         --  Processing for f switch
+
+         when 'f' =>
+            Ptr := Ptr + 1;
+            Force_Compilations := True;
+
+         --  Processing for G switch
+
+         when 'G' =>
+            Ptr := Ptr + 1;
+            Print_Generated_Code := True;
+
+         --  Processing for h switch
+
+         when 'h' =>
+            Ptr := Ptr + 1;
+            Usage_Requested := True;
+
+         --  Processing for i switch
+
+         when 'i' =>
+            Ptr := Ptr + 1;
+            In_Place_Mode := True;
+
+         --  Processing for j switch
+
+         when 'j' =>
+            Ptr := Ptr + 1;
+
+            declare
+               Max_Proc : Pos;
+            begin
+               Scan_Pos (Switch_Chars, Max, Ptr, Max_Proc);
+               Maximum_Processes := Positive (Max_Proc);
+            end;
+
+         --  Processing for k switch
+
+         when 'k' =>
+            Ptr := Ptr + 1;
+            Keep_Going := True;
+
+         when 'M' =>
+            Ptr := Ptr + 1;
+            List_Dependencies := True;
+
+         --  Processing for n switch
+
+         when 'n' =>
+            Ptr := Ptr + 1;
+            Do_Not_Execute := True;
+
+         --  Processing for o switch
+
+         when 'o' =>
+            Ptr := Ptr + 1;
+
+            if Output_File_Name_Present then
+               raise Too_Many_Output_Files;
+            else
+               Output_File_Name_Present := True;
+            end if;
+
+         --  Processing for q switch
+
+         when 'q' =>
+            Ptr := Ptr + 1;
+            Quiet_Output := True;
+
+         --  Processing for s switch
+
+         when 's' =>
+            Ptr := Ptr + 1;
+            Check_Switches := True;
+
+         --  Processing for v switch
+
+         when 'v' =>
+            Ptr := Ptr + 1;
+            Verbose_Mode := True;
+
+         --  Processing for z switch
+
+         when 'z' =>
+            Ptr := Ptr + 1;
+            No_Main_Subprogram := True;
+
+         --  Ignore extra switch character
+
+         when '/' | '-' =>
+            Ptr := Ptr + 1;
+
+         --  Anything else is an error (illegal switch character)
+
+         when others =>
+            raise Bad_Switch;
+
+         end case;
+      end loop;
+
+   exception
+      when Bad_Switch =>
+         Osint.Fail ("invalid switch: ", (1 => C));
+
+      when Bad_Switch_Value =>
+         Osint.Fail ("numeric value too big for switch: ", (1 => C));
+
+      when Missing_Switch_Value =>
+         Osint.Fail ("missing numeric value for switch: ", (1 => C));
+
+      when Too_Many_Output_Files =>
+         Osint.Fail ("duplicate -o switch");
+
+   end Scan_Make_Switches;
+
+   --------------
+   -- Scan_Nat --
+   --------------
+
+   procedure Scan_Nat
+     (Switch_Chars : String;
+      Max          : Integer;
+      Ptr          : in out Integer;
+      Result       : out Nat) is
+   begin
+      Result := 0;
+      if Ptr > Max or else Switch_Chars (Ptr) not in '0' .. '9' then
+         raise Missing_Switch_Value;
+      end if;
+
+      while Ptr <= Max and then Switch_Chars (Ptr) in '0' .. '9' loop
+         Result := Result * 10 +
+           Character'Pos (Switch_Chars (Ptr)) - Character'Pos ('0');
+         Ptr := Ptr + 1;
+
+         if Result > Switch_Max_Value then
+            raise Bad_Switch_Value;
+         end if;
+      end loop;
+   end Scan_Nat;
+
+   --------------
+   -- Scan_Pos --
+   --------------
+
+   procedure Scan_Pos
+     (Switch_Chars : String;
+      Max          : Integer;
+      Ptr          : in out Integer;
+      Result       : out Pos) is
+
+   begin
+      Scan_Nat (Switch_Chars, Max, Ptr, Result);
+      if Result = 0 then
+         raise Bad_Switch_Value;
+      end if;
+   end Scan_Pos;
+
+end Switch;
diff --git a/gcc/ada/switch.ads b/gcc/ada/switch.ads
new file mode 100644 (file)
index 0000000..7153cda
--- /dev/null
@@ -0,0 +1,69 @@
+------------------------------------------------------------------------------
+--                                                                          --
+--                         GNAT COMPILER COMPONENTS                         --
+--                                                                          --
+--                               S W I T C H                                --
+--                                                                          --
+--                                 S p e c                                  --
+--                                                                          --
+--                            $Revision: 1.17 $                             --
+--                                                                          --
+--          Copyright (C) 1992-2001 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- --
+-- ware  Foundation;  either version 2,  or (at your option) any later ver- --
+-- sion.  GNAT is distributed in the hope that it will be useful, but WITH- --
+-- OUT ANY WARRANTY;  without even the  implied warranty of MERCHANTABILITY --
+-- or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License --
+-- for  more details.  You should have  received  a copy of the GNU General --
+-- Public License  distributed with GNAT;  see file COPYING.  If not, write --
+-- to  the Free Software Foundation,  59 Temple Place - Suite 330,  Boston, --
+-- MA 02111-1307, USA.                                                      --
+--                                                                          --
+-- GNAT was originally developed  by the GNAT team at  New York University. --
+-- It is now maintained by Ada Core Technologies Inc (http://www.gnat.com). --
+--                                                                          --
+------------------------------------------------------------------------------
+
+--  This package scans switches. Note that the body of Usage must be
+--  coordinated with the switches that are recognized by this package.
+--  The Usage package also acts as the official documentation for the
+--  switches that are recognized. In addition, package Debug documents
+--  the otherwise undocumented debug switches that are also recognized.
+
+package Switch is
+
+   --  Note: The default switch character is indicated by Switch_Character,
+   --  but regardless of what it is, a hyphen is always allowed as an
+   --  (alternative) switch character.
+
+   --  Note: In GNAT, the case of switches is not significant if
+   --  Switches_Case_Sensitive is False. If this is the case, switch
+   --  characters, or letters appearing in the parameter to a switch, may be
+   --  either upper case or lower case.
+
+   -----------------
+   -- Subprograms --
+   -----------------
+
+   function Is_Switch (Switch_Chars : String) return Boolean;
+   --  Returns True iff Switch_Chars is at least two characters long,
+   --  and the first character indicates it is a switch.
+
+   function Is_Front_End_Switch (Switch_Chars : String) return Boolean;
+   --  Returns True iff Switch_Chars represents a front-end switch,
+   --  ie. it starts with -I or -gnat.
+
+   procedure Scan_Front_End_Switches (Switch_Chars : String);
+   procedure Scan_Binder_Switches (Switch_Chars : String);
+   procedure Scan_Make_Switches (Switch_Chars : String);
+   --  Procedures to scan out switches stored in the given string. The first
+   --  character is known to be a valid switch character, and there are no
+   --  blanks or other switch terminator characters in the string, so the
+   --  entire string should consist of valid switch characters, except that
+   --  an optional terminating NUL character is allowed. A bad switch causes
+   --  a fatal error exit and control does not return. The call also sets
+   --  Usage_Requested to True if a ? switch is encountered.
+
+end Switch;
diff --git a/gcc/ada/sysdep.c b/gcc/ada/sysdep.c
new file mode 100644 (file)
index 0000000..5473ebe
--- /dev/null
@@ -0,0 +1,605 @@
+/****************************************************************************
+ *                                                                          *
+ *                         GNAT COMPILER COMPONENTS                         *
+ *                                                                          *
+ *                                S Y S D E P                               *
+ *                                                                          *
+ *                          C Implementation File                           *
+ *                                                                          *
+ *                            $Revision: 1.2 $
+ *                                                                          *
+ *          Copyright (C) 1992-2001 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- *
+ * ware  Foundation;  either version 2,  or (at your option) any later ver- *
+ * sion.  GNAT is distributed in the hope that it will be useful, but WITH- *
+ * OUT ANY WARRANTY;  without even the  implied warranty of MERCHANTABILITY *
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License *
+ * for  more details.  You should have  received  a copy of the GNU General *
+ * Public License  distributed with GNAT;  see file COPYING.  If not, write *
+ * to  the Free Software Foundation,  59 Temple Place - Suite 330,  Boston, *
+ * MA 02111-1307, USA.                                                      *
+ *                                                                          *
+ * As a  special  exception,  if you  link  this file  with other  files to *
+ * produce an executable,  this file does not by itself cause the resulting *
+ * executable to be covered by the GNU General Public License. This except- *
+ * ion does not  however invalidate  any other reasons  why the  executable *
+ * file might be covered by the  GNU Public License.                        *
+ *                                                                          *
+ * GNAT was originally developed  by the GNAT team at  New York University. *
+ * It is now maintained by Ada Core Technologies Inc (http://www.gnat.com). *
+ *                                                                          *
+ ****************************************************************************/
+
+/* This file contains system dependent symbols that are referenced in the
+   GNAT Run Time Library */
+
+#ifdef __vxworks
+#include "vxWorks.h"
+#endif
+#ifdef IN_RTS
+#define POSIX
+#include "tconfig.h"
+#include "tsystem.h"
+#include <fcntl.h>
+#include <sys/stat.h>
+#include "time.h"
+#else
+#include "config.h"
+#include "system.h"
+#endif
+
+#include "adaint.h"
+
+/*
+   mode_read_text
+   open text file for reading
+   rt for DOS and Windows NT, r for Unix
+
+   mode_write_text
+   truncate to zero length or create text file for writing
+   wt for DOS and Windows NT, w for Unix
+
+   mode_append_text
+   append; open or create text file for writing at end-of-file
+   at for DOS and Windows NT, a for Unix
+
+   mode_read_binary
+   open binary file for reading
+   rb for DOS and Windows NT, r for Unix
+
+   mode_write_binary
+   truncate to zero length or create binary file for writing
+   wb for DOS and Windows NT, w for Unix
+
+   mode_append_binary
+   append; open or create binary file for writing at end-of-file
+   ab for DOS and Windows NT, a for Unix
+
+   mode_read_text_plus
+   open text file for update (reading and writing)
+   r+t for DOS and Windows NT, r+ for Unix
+
+   mode_write_text_plus
+   truncate to zero length or create text file for update
+   w+t for DOS and Windows NT, w+ for Unix
+
+   mode_append_text_plus
+   append; open or create text file for update, writing at end-of-file
+   a+t for DOS and Windows NT, a+ for Unix
+
+   mode_read_binary_plus
+   open binary file for update (reading and writing)
+   r+b for DOS and Windows NT, r+ for Unix
+
+   mode_write_binary_plus
+   truncate to zero length or create binary file for update
+   w+b for DOS and Windows NT, w+ for Unix
+
+   mode_append_binary_plus
+   append; open or create binary file for update, writing at end-of-file
+   a+b for DOS and Windows NT, a+ for Unix
+
+   Notes:
+
+   (1) Opening a file with read mode fails if the file does not exist or
+   cannot be read.
+
+   (2) Opening a file with append mode causes all subsequent writes to the
+   file to be forced to the then current end-of-file, regardless of
+   intervening calls to the fseek function.
+
+   (3) When a file is opened with update mode, both input and output may be
+   performed on the associated stream.  However, output may not be directly
+   followed by input without an intervening call to the fflush function or
+   to a file positioning function (fseek, fsetpos, or rewind), and input
+   may not be directly followed by output without an intervening call to a
+   file positioning function, unless the input operation encounters
+   end-of-file.
+
+   The other target dependent declarations here are for the two functions
+   __gnat_set_binary_mode and __gnat_set_text_mode:
+
+      void __gnat_set_binary_mode (int handle);
+      void __gnat_set_text_mode   (int handle);
+
+   These functions have no effect in Unix (or similar systems where there is
+   no distinction between binary and text files), but in DOS (and similar
+   systems where text mode does CR/LF translation), these functions allow
+   the mode of the stream with the given handle (fileno can be used to get
+   the handle of a stream) to be changed dynamically. The returned result
+   is 0 if no error occurs and -1 if an error occurs.
+
+   Finally there is a boolean (character) variable
+
+      char __gnat_text_translation_required;
+
+   which is zero (false) in Unix mode, and one (true) in DOS mode, with a
+   true value indicating that text translation is required on text files
+   and that fopen supports the trailing t and b modifiers.
+
+*/
+
+#if defined(WINNT) || defined (MSDOS) || defined (__EMX__)
+const char *mode_read_text = "rt";
+const char *mode_write_text = "wt";
+const char *mode_append_text = "at";
+const char *mode_read_binary = "rb";
+const char *mode_write_binary = "wb";
+const char *mode_append_binary = "ab";
+const char *mode_read_text_plus = "r+t";
+const char *mode_write_text_plus = "w+t";
+const char *mode_append_text_plus = "a+t";
+const char *mode_read_binary_plus = "r+b";
+const char *mode_write_binary_plus = "w+b";
+const char *mode_append_binary_plus = "a+b";
+const char __gnat_text_translation_required = 1;
+
+void
+__gnat_set_binary_mode (handle)
+     int handle;
+{
+  _setmode (handle, O_BINARY);
+}
+
+void
+__gnat_set_text_mode (handle)
+     int handle;
+{
+  _setmode (handle, O_TEXT);
+}
+
+#ifdef __MINGW32__
+#include <windows.h>
+
+/* Return the name of the tty.   Under windows there is no name for
+   the tty, so this function, if connected to a tty, returns the generic name
+   "console".  */
+
+char *
+__gnat_ttyname (filedes)
+     int filedes;
+{
+  if (isatty (filedes))
+    return "console";
+  else
+    return NULL;
+}
+
+/* This function is needed to fix a bug under Win95/98. Under these plateforms
+   doing :
+                ch1 = getch();
+               ch2 = fgetc (stdin);
+
+   will put the same character into ch1 and ch2. It seem that the character
+   read by getch() is not correctly removed from the buffer. Even a
+   fflush(stdin) does not fix the bug. This bug does not appear under Window
+   NT. So we have two version of this routine below one for 95/98 and one for
+   NT/2000 version of Windows. There is also a special routine (winflushinit)
+   that will be called only the first time to check which version of Windows
+   we are running running on to set the right routine to use.
+
+   This problem occurs when using Text_IO.Get_Line after Text_IO.Get_Immediate
+   for example.
+
+   Calling FlushConsoleInputBuffer just after getch() fix the bug under 
+   95/98. */
+
+static void winflush_init PARAMS ((void));
+
+static void winflush_95 PARAMS ((void));
+
+static void winflush_nt PARAMS ((void));
+
+/* winflusfunction is set first to the winflushinit function which will check
+   the OS version 95/98 or NT/2000 */
+
+static void (*winflush_function) PARAMS ((void)) = winflush_init;
+
+/* This function does the runtime check of the OS version and then sets
+   winflush_function to the appropriate function and then call it. */ 
+
+static void
+winflush_init ()
+{ 
+  DWORD dwVersion = GetVersion();
+
+  if (dwVersion < 0x80000000)                /* Windows NT/2000 */
+    winflush_function = winflush_nt;
+  else                                       /* Windows 95/98   */
+    winflush_function = winflush_95;
+
+  (*winflush_function)();      /* Perform the 'flush' */
+
+}
+
+static void winflush_95 ()
+{ 
+  FlushConsoleInputBuffer (GetStdHandle (STD_INPUT_HANDLE));
+}
+
+static void winflush_nt ()
+{
+  /* Does nothing as there is no problem under NT.  */
+}
+#endif
+
+#else
+
+const char *mode_read_text = "r";
+const char *mode_write_text = "w";
+const char *mode_append_text = "a";
+const char *mode_read_binary = "r";
+const char *mode_write_binary = "w";
+const char *mode_append_binary = "a";
+const char *mode_read_text_plus = "r+";
+const char *mode_write_text_plus = "w+";
+const char *mode_append_text_plus = "a+";
+const char *mode_read_binary_plus = "r+";
+const char *mode_write_binary_plus = "w+";
+const char *mode_append_binary_plus = "a+";
+const char __gnat_text_translation_required = 0;
+
+/* These functions do nothing in non-DOS systems. */
+
+void
+__gnat_set_binary_mode (stream)
+     FILE *stream ATTRIBUTE_UNUSED;
+{
+}
+
+void
+__gnat_set_text_mode (stream)
+     FILE *stream ATTRIBUTE_UNUSED;
+{
+}
+char *
+__gnat_ttyname (filedes)
+     int filedes;
+{
+#ifndef __vxworks
+  extern char *ttyname PARAMS ((int));
+
+  return ttyname (filedes);
+
+#else
+  return "";
+
+#endif
+}
+#endif
+\f
+#if defined (linux) || defined (sun) || defined (sgi) || defined (__EMX__) \
+  || (defined (__osf__) && ! defined (__alpha_vxworks)) || defined (WINNT) \
+  || defined (__MACHTEN__)
+#include <termios.h>
+
+#elif defined (VMS)
+extern char *decc$ga_stdscr;
+static int initted = 0;
+#endif
+
+/* Implements the common processing for getc_immediate and
+   getc_immediate_nowait. */
+
+extern void getc_immediate             PARAMS ((FILE *, int *, int *));
+extern void getc_immediate_nowait      PARAMS ((FILE *, int *, int *, int *));
+extern void getc_immediate_common      PARAMS ((FILE *, int *, int *,
+                                                int *, int));
+
+/* Called by Get_Immediate (Foo); */
+
+void
+getc_immediate (stream, ch, end_of_file)
+     FILE *stream;
+     int *ch;
+     int *end_of_file;
+{
+  int avail;
+
+  getc_immediate_common (stream, ch, end_of_file, &avail, 1);
+}
+
+/* Called by Get_Immediate (Foo, Available); */
+
+void
+getc_immediate_nowait (stream, ch, end_of_file, avail)
+     FILE *stream;
+     int *ch;
+     int *end_of_file;
+     int *avail;
+{
+  getc_immediate_common (stream, ch, end_of_file, avail, 0);
+}
+
+/* Called by getc_immediate () and getc_immediate_nowait () */
+
+void
+getc_immediate_common (stream, ch, end_of_file, avail, waiting)
+     FILE *stream;
+     int *ch;
+     int *end_of_file;
+     int *avail;
+     int waiting;
+{
+#if defined (linux) || defined (sun) || defined (sgi) || defined (__EMX__) \
+    || (defined (__osf__) && ! defined (__alpha_vxworks)) \
+    || defined (__CYGWIN32__) || defined (__MACHTEN__)
+  char c;
+  int nread;
+  int good_one = 0;
+  int eof_ch = 4; /* Ctrl-D */
+  int fd = fileno (stream);
+  struct termios otermios_rec, termios_rec;
+
+  if (isatty (fd))
+    {
+      tcgetattr (fd, &termios_rec);
+      memcpy (&otermios_rec, &termios_rec, sizeof (struct termios));
+      while (! good_one)
+        {
+          /* Set RAW mode */
+          termios_rec.c_lflag = termios_rec.c_lflag & ~ICANON;
+#if defined(sgi) || defined (sun) || defined (__EMX__) || defined (__osf__) \
+      || defined (linux) || defined (__MACHTEN__)
+          eof_ch = termios_rec.c_cc[VEOF];
+
+          /* If waiting (i.e. Get_Immediate (Char)), set MIN = 1 and wait for
+             a character forever. This doesn't seem to effect Ctrl-Z or
+             Ctrl-C processing except on OS/2 where Ctrl-C won't work right
+             unless we do a read loop. Luckily we can delay a bit between
+             iterations. If not waiting (i.e. Get_Immediate (Char, Available)),
+             don't wait for anything but timeout immediately. */
+#ifdef __EMX__
+          termios_rec.c_cc[VMIN] = 0;
+          termios_rec.c_cc[VTIME] = waiting;
+#else
+          termios_rec.c_cc[VMIN] = waiting;
+          termios_rec.c_cc[VTIME] = 0;
+#endif
+#endif
+          tcsetattr (fd, TCSANOW, &termios_rec);
+
+          /* Read() is used here instead of fread(), because fread() doesn't
+             work on Solaris5 and Sunos4 in this situation.  Maybe because we
+             are mixing calls that use file descriptors and streams. */
+
+          nread = read (fd, &c, 1);
+          if (nread > 0)
+            {
+              /* On Unix terminals, Ctrl-D (EOT) is an End of File. */
+              if (c == eof_ch)
+                {
+                  *avail = 0;
+                  *end_of_file = 1;
+                  good_one = 1;
+                }
+
+              /* Everything else is ok */
+              else if (c != eof_ch)
+                {
+                  *avail = 1;
+                  *end_of_file = 0;
+                  good_one = 1;
+                }
+            }
+
+          else if (! waiting)
+            {
+              *avail = 0;
+              *end_of_file = 0;
+              good_one = 1;
+            }
+          else
+            {
+              good_one = 0;
+            }
+        }
+
+      tcsetattr (fd, TCSANOW, &otermios_rec);
+      *ch = c;
+    }
+
+  else
+#elif defined (VMS)
+  int fd = fileno (stream);
+
+  if (isatty (fd))
+    {
+      if (initted == 0)
+       {
+         decc$bsd_initscr ();
+         initted = 1;
+       }
+      decc$bsd_cbreak ();
+      *ch = decc$bsd_wgetch (decc$ga_stdscr);
+
+      if (*ch == 4)
+       *end_of_file = 1;
+      else
+       *end_of_file = 0;
+
+      *avail = 1;
+      decc$bsd_nocbreak ();
+    }
+  else
+#elif defined (__MINGW32__)
+  int fd = fileno (stream);
+  int char_waiting;
+  int eot_ch = 4; /* Ctrl-D */
+
+  if (isatty (fd))
+    {
+      if (waiting)
+       {
+         *ch = getch();
+         (*winflush_function)();
+
+         if (*ch == eot_ch)
+           *end_of_file = 1;
+         else
+           *end_of_file = 0;
+
+         *avail = 1;
+       }
+      else /* ! waiting */
+       {
+         char_waiting = kbhit();
+
+         if (char_waiting == 1)
+           {
+             *avail = 1;
+             *ch = getch();
+             (*winflush_function)();
+
+             if (*ch == eot_ch)
+               *end_of_file = 1;
+             else
+               *end_of_file = 0;
+           }
+         else
+           {
+             *avail = 0;
+             *end_of_file = 0;
+           }
+       }
+    }
+  else
+#endif
+    {
+      /* If we're not on a terminal, then we don't need any fancy processing.
+        Also this is the only thing that's left if we're not on one of the
+        supported systems. */
+      *ch = fgetc (stream);
+      if (feof (stream))
+        {
+          *end_of_file = 1;
+          *avail = 0;
+        }
+      else
+        {
+          *end_of_file = 0;
+          *avail = 1;
+        }
+    }
+}
+
+/* The following definitions are provided in NT to support Windows based
+   Ada programs.  */
+
+#ifdef WINNT
+#include <windows.h>
+
+/* Provide functions to echo the values passed to WinMain (windows bindings
+   will want to import these).  We use the same names as the routines used
+   by AdaMagic for compatibility.  */
+
+char *rts_get_hInstance     (void) { return (GetModuleHandleA (0)); }
+char *rts_get_hPrevInstance (void) { return (0); }
+char *rts_get_lpCommandLine (void) { return (GetCommandLineA ()); }
+int   rts_get_nShowCmd      (void) { return (1); }
+
+#endif /* WINNT */
+#ifdef VMS
+
+/* This gets around a problem with using the old threads library on VMS 7.0. */
+
+#include <time.h>
+
+extern long get_gmtoff PARAMS ((void));
+
+long
+get_gmtoff ()
+{
+  time_t t;
+  struct tm *ts;
+
+  t = time ((time_t) 0);
+  ts = localtime (&t);
+  return ts->tm_gmtoff;
+}
+#endif
+
+/* Definition of __gnat_locatime_r used by a-calend.adb */
+
+#if defined (_AIX) || defined (__EMX__)
+#define Lock_Task system__soft_links__lock_task
+extern void (*Lock_Task) (void);
+
+#define Unlock_Task system__soft_links__unlock_task
+extern void (*Unlock_Task) (void);
+
+/* Provide reentrant version of localtime on Aix and OS/2. Note that AiX does
+   provide localtime_r, but in the library libc_r which doesn't get included
+   systematically, so we can't use it. */
+
+exrern void struct tm *__gnat_localtime_r PARAMS ((const time_t *,
+                                                  struct tm *));
+
+struct tm *
+__gnat_localtime_r (timer, tp)
+     const time_t *timer;
+     struct tm *tp;
+{
+  struct tm *tmp;
+
+  (*Lock_Task) ();
+  tmp = localtime (timer);
+  memcpy (tp, tmp, sizeof (struct tm));
+  (*Unlock_Task) ();
+  return tp;
+}
+
+#elif defined (__Lynx__)
+
+/* LynxOS provides a non standard localtime_r */
+
+extern struct tm *__gnat_localtime_r PARAMS ((const time_t *, struct tm *));
+
+struct tm *
+__gnat_localtime_r (timer, tp)
+     const time_t *timer;
+     struct tm *tp;
+{
+  return localtime_r (tp, timer);
+}
+
+#elif defined (VMS) || defined (__MINGW32__)
+
+/* __gnat_localtime_r is not needed on NT and VMS */
+
+#else
+
+/* All other targets provide a standard localtime_r */
+
+extern struct tm *__gnat_localtime_r PARAMS ((const time_t *, struct tm *));
+
+struct tm *
+__gnat_localtime_r (timer, tp)
+     const time_t *timer;
+     struct tm *tp;
+{
+  return (struct tm *) localtime_r (timer, tp);
+}
+#endif