summaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorkenner <kenner@138bc75d-0d04-0410-961f-82ee72b054a4>2001-10-02 14:52:00 +0000
committerkenner <kenner@138bc75d-0d04-0410-961f-82ee72b054a4>2001-10-02 14:52:00 +0000
commitd6f39728ae3cc12d4f867eeb4659d01322643264 (patch)
tree2e58881ac983eb14cefbc37dcb02b8fd6e9f6990 /gcc
parentb1a749bacce901a0cad8abbbfc0addb482a8adfa (diff)
downloadgcc-d6f39728ae3cc12d4f867eeb4659d01322643264.tar.gz
New Language: Ada
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@45959 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc')
-rw-r--r--gcc/ada/scans.adb76
-rw-r--r--gcc/ada/scans.ads418
-rw-r--r--gcc/ada/scn-nlit.adb371
-rw-r--r--gcc/ada/scn-slit.adb373
-rw-r--r--gcc/ada/scn.adb1570
-rw-r--r--gcc/ada/scn.ads69
-rw-r--r--gcc/ada/sdefault.ads40
-rw-r--r--gcc/ada/sem.adb1184
-rw-r--r--gcc/ada/sem.ads492
-rw-r--r--gcc/ada/sem_aggr.adb2848
-rw-r--r--gcc/ada/sem_aggr.ads39
-rw-r--r--gcc/ada/sem_attr.adb6822
-rw-r--r--gcc/ada/sem_attr.ads595
-rw-r--r--gcc/ada/sem_case.adb681
-rw-r--r--gcc/ada/sem_case.ads122
-rw-r--r--gcc/ada/sem_cat.adb1804
-rw-r--r--gcc/ada/sem_cat.ads144
-rw-r--r--gcc/ada/sem_ch10.adb3072
-rw-r--r--gcc/ada/sem_ch10.ads60
-rw-r--r--gcc/ada/sem_ch11.adb387
-rw-r--r--gcc/ada/sem_ch11.ads40
-rw-r--r--gcc/ada/sem_ch12.adb8932
-rw-r--r--gcc/ada/sem_ch12.ads109
-rw-r--r--gcc/ada/sem_ch13.adb3912
-rw-r--r--gcc/ada/sem_ch13.ads171
-rw-r--r--gcc/ada/sem_ch2.adb117
-rw-r--r--gcc/ada/sem_ch2.ads46
-rw-r--r--gcc/ada/sem_ch3.adb12122
-rw-r--r--gcc/ada/sem_ch3.ads224
-rw-r--r--gcc/ada/sem_ch4.adb4272
-rw-r--r--gcc/ada/sem_ch4.ads66
-rw-r--r--gcc/ada/sem_ch5.adb1256
-rw-r--r--gcc/ada/sem_ch5.ads58
-rw-r--r--gcc/ada/sem_ch6.adb4779
-rw-r--r--gcc/ada/sem_ch6.ads170
-rw-r--r--gcc/ada/sem_ch7.adb1703
-rw-r--r--gcc/ada/sem_ch7.ads87
-rw-r--r--gcc/ada/sem_ch8.adb5224
-rw-r--r--gcc/ada/sem_ch8.ads190
-rw-r--r--gcc/ada/sem_ch9.adb1705
-rw-r--r--gcc/ada/sem_ch9.ads58
-rw-r--r--gcc/ada/sem_disp.adb992
-rw-r--r--gcc/ada/sem_disp.ads91
-rw-r--r--gcc/ada/sem_dist.adb686
-rw-r--r--gcc/ada/sem_dist.ads95
-rw-r--r--gcc/ada/sem_elab.adb2278
-rw-r--r--gcc/ada/sem_elab.ads156
-rw-r--r--gcc/ada/sem_elim.adb557
-rw-r--r--gcc/ada/sem_elim.ads54
-rw-r--r--gcc/ada/sem_eval.adb3663
-rw-r--r--gcc/ada/sem_eval.ads377
-rw-r--r--gcc/ada/sem_intr.adb352
-rw-r--r--gcc/ada/sem_intr.ads49
-rw-r--r--gcc/ada/sem_maps.adb376
-rw-r--r--gcc/ada/sem_maps.ads170
-rw-r--r--gcc/ada/sem_mech.adb437
-rw-r--r--gcc/ada/sem_mech.ads173
-rw-r--r--gcc/ada/sem_prag.adb8796
-rw-r--r--gcc/ada/sem_prag.ads62
-rw-r--r--gcc/ada/sem_res.adb6403
-rw-r--r--gcc/ada/sem_res.ads118
-rw-r--r--gcc/ada/sem_smem.adb150
-rw-r--r--gcc/ada/sem_smem.ads43
-rw-r--r--gcc/ada/sem_type.adb2028
-rw-r--r--gcc/ada/sem_type.ads262
-rw-r--r--gcc/ada/sem_util.adb5205
-rw-r--r--gcc/ada/sem_util.ads698
-rw-r--r--gcc/ada/sem_vfpt.adb168
-rw-r--r--gcc/ada/sem_vfpt.ads58
-rw-r--r--gcc/ada/sem_warn.adb1062
-rw-r--r--gcc/ada/sem_warn.ads161
-rw-r--r--gcc/ada/sequenio.ads21
-rw-r--r--gcc/ada/sfn_scan.adb659
-rw-r--r--gcc/ada/sfn_scan.ads94
-rw-r--r--gcc/ada/sinfo-cn.adb114
-rw-r--r--gcc/ada/sinfo-cn.ads71
-rw-r--r--gcc/ada/sinfo.adb4798
-rw-r--r--gcc/ada/sinfo.ads8684
-rw-r--r--gcc/ada/sinput-l.adb533
-rw-r--r--gcc/ada/sinput-l.ads141
-rw-r--r--gcc/ada/sinput-p.adb233
-rw-r--r--gcc/ada/sinput-p.ads65
-rw-r--r--gcc/ada/sinput.adb1132
-rw-r--r--gcc/ada/sinput.ads650
-rw-r--r--gcc/ada/snames.adb883
-rw-r--r--gcc/ada/snames.ads1373
-rw-r--r--gcc/ada/snames.h345
-rw-r--r--gcc/ada/sprint.adb3071
-rw-r--r--gcc/ada/sprint.ads148
-rw-r--r--gcc/ada/stand.adb131
-rw-r--r--gcc/ada/stand.ads456
-rw-r--r--gcc/ada/stringt.adb419
-rw-r--r--gcc/ada/stringt.ads161
-rw-r--r--gcc/ada/stringt.h92
-rw-r--r--gcc/ada/style.adb833
-rw-r--r--gcc/ada/style.ads156
-rw-r--r--gcc/ada/stylesw.adb255
-rw-r--r--gcc/ada/stylesw.ads264
-rw-r--r--gcc/ada/switch.adb1364
-rw-r--r--gcc/ada/switch.ads69
-rw-r--r--gcc/ada/sysdep.c605
101 files changed, 129948 insertions, 0 deletions
diff --git a/gcc/ada/scans.adb b/gcc/ada/scans.adb
new file mode 100644
index 00000000000..327f3aa1b58
--- /dev/null
+++ b/gcc/ada/scans.adb
@@ -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
index 00000000000..b9d89e1f0ef
--- /dev/null
+++ b/gcc/ada/scans.ads
@@ -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
index 00000000000..f027ba25b3a
--- /dev/null
+++ b/gcc/ada/scn-nlit.adb
@@ -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
index 00000000000..508d5c225ac
--- /dev/null
+++ b/gcc/ada/scn-slit.adb
@@ -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
index 00000000000..146314db117
--- /dev/null
+++ b/gcc/ada/scn.adb
@@ -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
index 00000000000..1fc5441f87a
--- /dev/null
+++ b/gcc/ada/scn.ads
@@ -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
index 00000000000..7d4cbc16718
--- /dev/null
+++ b/gcc/ada/sdefault.ads
@@ -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
index 00000000000..1eb315d481e
--- /dev/null
+++ b/gcc/ada/sem.adb
@@ -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
index 00000000000..a88761627fe
--- /dev/null
+++ b/gcc/ada/sem.ads
@@ -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
index 00000000000..29778ff49b0
--- /dev/null
+++ b/gcc/ada/sem_aggr.adb
@@ -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
index 00000000000..41a4bd759ab
--- /dev/null
+++ b/gcc/ada/sem_aggr.ads
@@ -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
index 00000000000..4574315dbff
--- /dev/null
+++ b/gcc/ada/sem_attr.adb
@@ -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
index 00000000000..ccbc3f49d4c
--- /dev/null
+++ b/gcc/ada/sem_attr.ads
@@ -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
index 00000000000..a9326c36384
--- /dev/null
+++ b/gcc/ada/sem_case.adb
@@ -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
index 00000000000..192b6b1573f
--- /dev/null
+++ b/gcc/ada/sem_case.ads
@@ -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
index 00000000000..29c48a5f1ab
--- /dev/null
+++ b/gcc/ada/sem_cat.adb
@@ -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
index 00000000000..3591e746c73
--- /dev/null
+++ b/gcc/ada/sem_cat.ads
@@ -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
index 00000000000..2bbe0a50081
--- /dev/null
+++ b/gcc/ada/sem_ch10.adb
@@ -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
index 00000000000..4ea1acca4cc
--- /dev/null
+++ b/gcc/ada/sem_ch10.ads
@@ -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
index 00000000000..2a3536b642a
--- /dev/null
+++ b/gcc/ada/sem_ch11.adb
@@ -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
index 00000000000..a56ddee2aa4
--- /dev/null
+++ b/gcc/ada/sem_ch11.ads
@@ -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
index 00000000000..3f47a62627c
--- /dev/null
+++ b/gcc/ada/sem_ch12.adb
@@ -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
index 00000000000..80af1ae6dd0
--- /dev/null
+++ b/gcc/ada/sem_ch12.ads
@@ -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
index 00000000000..ae674411d79
--- /dev/null
+++ b/gcc/ada/sem_ch13.adb
@@ -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
index 00000000000..5afe5adb208
--- /dev/null
+++ b/gcc/ada/sem_ch13.ads
@@ -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
index 00000000000..f8e85b3c02a
--- /dev/null
+++ b/gcc/ada/sem_ch2.adb
@@ -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
index 00000000000..d85de7f8b05
--- /dev/null
+++ b/gcc/ada/sem_ch2.ads
@@ -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
index 00000000000..dd9b6b07e73
--- /dev/null
+++ b/gcc/ada/sem_ch3.adb
@@ -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
index 00000000000..aefb310c647
--- /dev/null
+++ b/gcc/ada/sem_ch3.ads
@@ -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
index 00000000000..31f244d2795
--- /dev/null
+++ b/gcc/ada/sem_ch4.adb
@@ -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
index 00000000000..236785facc8
--- /dev/null
+++ b/gcc/ada/sem_ch4.ads
@@ -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
index 00000000000..658a685ced7
--- /dev/null
+++ b/gcc/ada/sem_ch5.adb
@@ -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
index 00000000000..c7d94685fa1
--- /dev/null
+++ b/gcc/ada/sem_ch5.ads
@@ -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
index 00000000000..f8e0b4fce42
--- /dev/null
+++ b/gcc/ada/sem_ch6.adb
@@ -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
index 00000000000..beb47569a42
--- /dev/null
+++ b/gcc/ada/sem_ch6.ads
@@ -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
index 00000000000..c1b0521b38a
--- /dev/null
+++ b/gcc/ada/sem_ch7.adb
@@ -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
index 00000000000..057c73ca655
--- /dev/null
+++ b/gcc/ada/sem_ch7.ads
@@ -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
index 00000000000..ab90a102d70
--- /dev/null
+++ b/gcc/ada/sem_ch8.adb
@@ -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
index 00000000000..c2713657a4a
--- /dev/null
+++ b/gcc/ada/sem_ch8.ads
@@ -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
index 00000000000..2075e5e5342
--- /dev/null
+++ b/gcc/ada/sem_ch9.adb
@@ -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
index 00000000000..d4922b3a946
--- /dev/null
+++ b/gcc/ada/sem_ch9.ads
@@ -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
index 00000000000..31dae9026e9
--- /dev/null
+++ b/gcc/ada/sem_disp.adb
@@ -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
index 00000000000..75f415800de
--- /dev/null
+++ b/gcc/ada/sem_disp.ads
@@ -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
index 00000000000..f2b5c6c6bfa
--- /dev/null
+++ b/gcc/ada/sem_dist.adb
@@ -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
index 00000000000..b5c823ddc79
--- /dev/null
+++ b/gcc/ada/sem_dist.ads
@@ -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
index 00000000000..555abb8ca88
--- /dev/null
+++ b/gcc/ada/sem_elab.adb
@@ -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
index 00000000000..87071c2005f
--- /dev/null
+++ b/gcc/ada/sem_elab.ads
@@ -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
index 00000000000..e418657ec09
--- /dev/null
+++ b/gcc/ada/sem_elim.adb
@@ -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
index 00000000000..861ffc99686
--- /dev/null
+++ b/gcc/ada/sem_elim.ads
@@ -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
index 00000000000..dde46a4b487
--- /dev/null
+++ b/gcc/ada/sem_eval.adb
@@ -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
index 00000000000..b693ffdb5c3
--- /dev/null
+++ b/gcc/ada/sem_eval.ads
@@ -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
index 00000000000..20b1918d60a
--- /dev/null
+++ b/gcc/ada/sem_intr.adb
@@ -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
index 00000000000..3576ffb2c66
--- /dev/null
+++ b/gcc/ada/sem_intr.ads
@@ -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
index 00000000000..a876156c6ac
--- /dev/null
+++ b/gcc/ada/sem_maps.adb
@@ -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
index 00000000000..3033f890ff7
--- /dev/null
+++ b/gcc/ada/sem_maps.ads
@@ -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
index 00000000000..800a5e82dc4
--- /dev/null
+++ b/gcc/ada/sem_mech.adb
@@ -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
index 00000000000..4b0993db3ba
--- /dev/null
+++ b/gcc/ada/sem_mech.ads
@@ -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
index 00000000000..4910c7842ac
--- /dev/null
+++ b/gcc/ada/sem_prag.adb
@@ -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
index 00000000000..fca13a6f3de
--- /dev/null
+++ b/gcc/ada/sem_prag.ads
@@ -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
index 00000000000..641b120eb7b
--- /dev/null
+++ b/gcc/ada/sem_res.adb
@@ -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
index 00000000000..5c926540c3b
--- /dev/null
+++ b/gcc/ada/sem_res.ads
@@ -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
index 00000000000..5b0c29c73f6
--- /dev/null
+++ b/gcc/ada/sem_smem.adb
@@ -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
index 00000000000..a164659310e
--- /dev/null
+++ b/gcc/ada/sem_smem.ads
@@ -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
index 00000000000..9c335e6c4c6
--- /dev/null
+++ b/gcc/ada/sem_type.adb
@@ -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
index 00000000000..5498e3827b8
--- /dev/null
+++ b/gcc/ada/sem_type.ads
@@ -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
index 00000000000..c2474720fb3
--- /dev/null
+++ b/gcc/ada/sem_util.adb
@@ -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
index 00000000000..2d493944d41
--- /dev/null
+++ b/gcc/ada/sem_util.ads
@@ -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
index 00000000000..d4b76d4eeef
--- /dev/null
+++ b/gcc/ada/sem_vfpt.adb
@@ -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
index 00000000000..ed27175b0b3
--- /dev/null
+++ b/gcc/ada/sem_vfpt.ads
@@ -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
index 00000000000..f3133d2006d
--- /dev/null
+++ b/gcc/ada/sem_warn.adb
@@ -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
index 00000000000..0c5d75956a0
--- /dev/null
+++ b/gcc/ada/sem_warn.ads
@@ -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
index 00000000000..e191a5a1d40
--- /dev/null
+++ b/gcc/ada/sequenio.ads
@@ -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
index 00000000000..57bc534f582
--- /dev/null
+++ b/gcc/ada/sfn_scan.adb
@@ -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
index 00000000000..ed84fc6686d
--- /dev/null
+++ b/gcc/ada/sfn_scan.ads
@@ -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
index 00000000000..33e6da641b1
--- /dev/null
+++ b/gcc/ada/sinfo-cn.adb
@@ -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
index 00000000000..03dcae3d630
--- /dev/null
+++ b/gcc/ada/sinfo-cn.ads
@@ -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
index 00000000000..fb96678b814
--- /dev/null
+++ b/gcc/ada/sinfo.adb
@@ -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
index 00000000000..335f9fa379c
--- /dev/null
+++ b/gcc/ada/sinfo.ads
@@ -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
index 00000000000..f00cbbd26dc
--- /dev/null
+++ b/gcc/ada/sinput-l.adb
@@ -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
index 00000000000..bba983fd00b
--- /dev/null
+++ b/gcc/ada/sinput-l.ads
@@ -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
index 00000000000..10a20f4db9a
--- /dev/null
+++ b/gcc/ada/sinput-p.adb
@@ -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
index 00000000000..9292eaba543
--- /dev/null
+++ b/gcc/ada/sinput-p.ads
@@ -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
index 00000000000..b8612882550
--- /dev/null
+++ b/gcc/ada/sinput.adb
@@ -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
index 00000000000..585a8b95ea0
--- /dev/null
+++ b/gcc/ada/sinput.ads
@@ -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
index 00000000000..acda714b8ed
--- /dev/null
+++ b/gcc/ada/snames.adb
@@ -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
index 00000000000..4c365b8f63c
--- /dev/null
+++ b/gcc/ada/snames.ads
@@ -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
index 00000000000..e0c9b506b26
--- /dev/null
+++ b/gcc/ada/snames.h
@@ -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
index 00000000000..8c58ca81540
--- /dev/null
+++ b/gcc/ada/sprint.adb
@@ -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
index 00000000000..d307eb74250
--- /dev/null
+++ b/gcc/ada/sprint.ads
@@ -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
index 00000000000..b0001b17864
--- /dev/null
+++ b/gcc/ada/stand.adb
@@ -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
index 00000000000..65cfa4f5670
--- /dev/null
+++ b/gcc/ada/stand.ads
@@ -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
index 00000000000..b2631ad2c03
--- /dev/null
+++ b/gcc/ada/stringt.adb
@@ -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
index 00000000000..0d4350ec090
--- /dev/null
+++ b/gcc/ada/stringt.ads
@@ -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
index 00000000000..3a1e1f684a3
--- /dev/null
+++ b/gcc/ada/stringt.h
@@ -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
index 00000000000..638333c0ee0
--- /dev/null
+++ b/gcc/ada/style.adb
@@ -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
index 00000000000..a75807c1757
--- /dev/null
+++ b/gcc/ada/style.ads
@@ -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
index 00000000000..aae4d0475e9
--- /dev/null
+++ b/gcc/ada/stylesw.adb
@@ -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
index 00000000000..3352b4cf0be
--- /dev/null
+++ b/gcc/ada/stylesw.ads
@@ -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
index 00000000000..ee97c6ff746
--- /dev/null
+++ b/gcc/ada/switch.adb
@@ -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
index 00000000000..7153cdaa765
--- /dev/null
+++ b/gcc/ada/switch.ads
@@ -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
index 00000000000..5473ebee42e
--- /dev/null
+++ b/gcc/ada/sysdep.c
@@ -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
+
+#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