1 ------------------------------------------------------------------------------
3 -- GNAT COMPILER COMPONENTS --
9 -- Copyright (C) 1992-2023, Free Software Foundation, Inc. --
11 -- GNAT is free software; you can redistribute it and/or modify it under --
12 -- terms of the GNU General Public License as published by the Free Soft- --
13 -- ware Foundation; either version 3, or (at your option) any later ver- --
14 -- sion. GNAT is distributed in the hope that it will be useful, but WITH- --
15 -- OUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY --
16 -- or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License --
17 -- for more details. You should have received a copy of the GNU General --
18 -- Public License distributed with GNAT; see file COPYING3. If not, go to --
19 -- http://www.gnu.org/licenses for a complete copy of the license. --
21 -- GNAT was originally developed by the GNAT team at New York University. --
22 -- Extensive contributions were provided by Ada Core Technologies Inc. --
24 ------------------------------------------------------------------------------
26 with Atree
; use Atree
;
27 with Csets
; use Csets
;
28 with Namet
; use Namet
;
29 with Restrict
; use Restrict
;
30 with Rident
; use Rident
;
31 with Scans
; use Scans
;
32 with Sinfo
; use Sinfo
;
33 with Sinfo
.Nodes
; use Sinfo
.Nodes
;
34 with Sinput
; use Sinput
;
35 with Uintp
; use Uintp
;
36 with Warnsw
; use Warnsw
;
40 Used_As_Identifier
: array (Token_Type
) of Boolean;
41 -- Flags set True if a given keyword is used as an identifier (used to
42 -- make sure that we only post an error message for incorrect use of a
43 -- keyword as an identifier once for a given keyword).
45 ----------------------------
46 -- Determine_Token_Casing --
47 ----------------------------
49 function Determine_Token_Casing
return Casing_Type
is
51 return Scanner
.Determine_Token_Casing
;
52 end Determine_Token_Casing
;
54 ------------------------
55 -- Initialize_Scanner --
56 ------------------------
58 procedure Initialize_Scanner
59 (Unit
: Unit_Number_Type
;
60 Index
: Source_File_Index
) is
62 Scanner
.Initialize_Scanner
(Index
);
63 Set_Unit
(Index
, Unit
);
65 Current_Source_Unit
:= Unit
;
67 -- Set default for Comes_From_Source. All nodes built now until we
68 -- reenter the analyzer will have Comes_From_Source set to True
70 Set_Comes_From_Source_Default
(True);
74 -- Because of the License stuff above, Scng.Initialize_Scanner cannot
75 -- call Scan. Scan initial token (note this initializes Prev_Token,
80 -- Clear flags for reserved words used as identifiers
82 Used_As_Identifier
:= (others => False);
83 end Initialize_Scanner
;
89 procedure Post_Scan
is
90 procedure Check_Obsolescent_Features_Restriction
(S
: Source_Ptr
);
91 -- This checks for Obsolescent_Features restriction being active, and
92 -- if so, flags the restriction as occurring at the given scan location.
94 procedure Check_Obsolete_Base_Char
;
95 -- Check for numeric literal using ':' instead of '#' for based case
97 --------------------------------------------
98 -- Check_Obsolescent_Features_Restriction --
99 --------------------------------------------
101 procedure Check_Obsolescent_Features_Restriction
(S
: Source_Ptr
) is
103 -- Normally we have a node handy for posting restrictions. We don't
104 -- have such a node here, so construct a dummy one with the right
105 -- scan pointer. This is only used to get the Sloc value anyway.
107 Check_Restriction
(No_Obsolescent_Features
, New_Node
(N_Empty
, S
));
108 end Check_Obsolescent_Features_Restriction
;
110 ------------------------------
111 -- Check_Obsolete_Base_Char --
112 ------------------------------
114 procedure Check_Obsolete_Base_Char
is
118 if Based_Literal_Uses_Colon
then
120 -- Find the : for the restriction or warning message
123 while Source
(S
) /= ':' loop
127 Check_Obsolescent_Features_Restriction
(S
);
129 if Warn_On_Obsolescent_Feature
then
131 ("?j?use of "":"" is an obsolescent feature (RM J.2(3))", S
);
133 ("\?j?use ""'#"" instead", S
);
136 end Check_Obsolete_Base_Char
;
138 -- Start of processing for Post_Scan
142 when Tok_Char_Literal
=>
143 Token_Node
:= New_Node
(N_Character_Literal
, Token_Ptr
);
144 Set_Char_Literal_Value
(Token_Node
, UI_From_CC
(Character_Code
));
145 Set_Chars
(Token_Node
, Token_Name
);
147 when Tok_Identifier
=>
148 Token_Node
:= New_Node
(N_Identifier
, Token_Ptr
);
149 Set_Chars
(Token_Node
, Token_Name
);
151 when Tok_Real_Literal
=>
152 Token_Node
:= New_Node
(N_Real_Literal
, Token_Ptr
);
153 Set_Realval
(Token_Node
, Real_Literal_Value
);
154 Check_Obsolete_Base_Char
;
156 when Tok_Integer_Literal
=>
157 Token_Node
:= New_Node
(N_Integer_Literal
, Token_Ptr
);
159 -- Int_Literal_Value can be No_Uint in some cases in syntax-only
160 -- mode (see Scng.Scan.Nlit).
162 if Present
(Int_Literal_Value
) then
163 Set_Intval
(Token_Node
, Int_Literal_Value
);
166 Check_Obsolete_Base_Char
;
168 when Tok_String_Literal
=>
169 Token_Node
:= New_Node
(N_String_Literal
, Token_Ptr
);
170 Set_Has_Wide_Character
171 (Token_Node
, Wide_Character_Found
);
172 Set_Has_Wide_Wide_Character
173 (Token_Node
, Wide_Wide_Character_Found
);
174 Set_Strval
(Token_Node
, String_Literal_Id
);
176 if Source
(Token_Ptr
) = '%' then
177 Check_Obsolescent_Features_Restriction
(Token_Ptr
);
179 if Warn_On_Obsolescent_Feature
then
181 ("?j?use of ""'%"" is an obsolescent feature (RM J.2(4))");
182 Error_Msg_SC
("\?j?use """""" instead");
186 when Tok_Operator_Symbol
=>
187 Token_Node
:= New_Node
(N_Operator_Symbol
, Token_Ptr
);
188 Set_Chars
(Token_Node
, Token_Name
);
189 Set_Strval
(Token_Node
, String_Literal_Id
);
191 when Tok_Vertical_Bar
=>
192 if Source
(Token_Ptr
) = '!' then
193 Check_Obsolescent_Features_Restriction
(Token_Ptr
);
195 if Warn_On_Obsolescent_Feature
then
197 ("?j?use of ""'!"" is an obsolescent feature (RM J.2(2))");
198 Error_Msg_SC
("\?j?use ""'|"" instead");
207 ------------------------------
208 -- Scan_Reserved_Identifier --
209 ------------------------------
211 procedure Scan_Reserved_Identifier
(Force_Msg
: Boolean) is
212 Token_Chars
: String := Token_Type
'Image (Token
);
216 -- AI12-0125 : '@' denotes the target_name, i.e. serves as an
217 -- abbreviation for the LHS of an assignment.
219 if Token
= Tok_At_Sign
then
220 Token_Node
:= New_Node
(N_Target_Name
, Token_Ptr
);
224 -- We have in Token_Chars the image of the Token name, i.e. Tok_xxx.
225 -- This code extracts the xxx and makes an identifier out of it.
227 for J
in 5 .. Token_Chars
'Length loop
229 Token_Chars
(Len
) := Fold_Lower
(Token_Chars
(J
));
232 Token_Name
:= Name_Find
(Token_Chars
(1 .. Len
));
234 -- If Inside_Pragma is True, we don't give an error. This is to allow
235 -- things like "pragma Ignore_Pragma (Interface)", where "Interface" is
236 -- a reserved word. There is no danger of missing errors, because any
237 -- misuse must have been preceded by an illegal declaration. For
238 -- example, in "pragma Pack (Begin);", either Begin is not declared,
239 -- which is an error, or it is declared, which will be an error on that
242 if (not Used_As_Identifier
(Token
) or else Force_Msg
)
243 and then not Inside_Pragma
245 Error_Msg_Name_1
:= Token_Name
;
246 Error_Msg_SC
("reserved word* cannot be used as identifier!");
247 Used_As_Identifier
(Token
) := True;
250 Token
:= Tok_Identifier
;
251 Token_Node
:= New_Node
(N_Identifier
, Token_Ptr
);
252 Set_Chars
(Token_Node
, Token_Name
);
253 end Scan_Reserved_Identifier
;