annotate gcc/ada/sem_ch11.adb @ 145:1830386684a0

gcc-9.2.0
author anatofuz
date Thu, 13 Feb 2020 11:34:05 +0900
parents 84e7813d76e9
children
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
111
kono
parents:
diff changeset
1 ------------------------------------------------------------------------------
kono
parents:
diff changeset
2 -- --
kono
parents:
diff changeset
3 -- GNAT COMPILER COMPONENTS --
kono
parents:
diff changeset
4 -- --
kono
parents:
diff changeset
5 -- S E M _ C H 1 1 --
kono
parents:
diff changeset
6 -- --
kono
parents:
diff changeset
7 -- B o d y --
kono
parents:
diff changeset
8 -- --
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
9 -- Copyright (C) 1992-2019, Free Software Foundation, Inc. --
111
kono
parents:
diff changeset
10 -- --
kono
parents:
diff changeset
11 -- GNAT is free software; you can redistribute it and/or modify it under --
kono
parents:
diff changeset
12 -- terms of the GNU General Public License as published by the Free Soft- --
kono
parents:
diff changeset
13 -- ware Foundation; either version 3, or (at your option) any later ver- --
kono
parents:
diff changeset
14 -- sion. GNAT is distributed in the hope that it will be useful, but WITH- --
kono
parents:
diff changeset
15 -- OUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY --
kono
parents:
diff changeset
16 -- or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License --
kono
parents:
diff changeset
17 -- for more details. You should have received a copy of the GNU General --
kono
parents:
diff changeset
18 -- Public License distributed with GNAT; see file COPYING3. If not, go to --
kono
parents:
diff changeset
19 -- http://www.gnu.org/licenses for a complete copy of the license. --
kono
parents:
diff changeset
20 -- --
kono
parents:
diff changeset
21 -- GNAT was originally developed by the GNAT team at New York University. --
kono
parents:
diff changeset
22 -- Extensive contributions were provided by Ada Core Technologies Inc. --
kono
parents:
diff changeset
23 -- --
kono
parents:
diff changeset
24 ------------------------------------------------------------------------------
kono
parents:
diff changeset
25
kono
parents:
diff changeset
26 with Atree; use Atree;
kono
parents:
diff changeset
27 with Checks; use Checks;
kono
parents:
diff changeset
28 with Einfo; use Einfo;
kono
parents:
diff changeset
29 with Errout; use Errout;
kono
parents:
diff changeset
30 with Lib; use Lib;
kono
parents:
diff changeset
31 with Lib.Xref; use Lib.Xref;
kono
parents:
diff changeset
32 with Namet; use Namet;
kono
parents:
diff changeset
33 with Nlists; use Nlists;
kono
parents:
diff changeset
34 with Nmake; use Nmake;
kono
parents:
diff changeset
35 with Opt; use Opt;
kono
parents:
diff changeset
36 with Restrict; use Restrict;
kono
parents:
diff changeset
37 with Rident; use Rident;
kono
parents:
diff changeset
38 with Rtsfind; use Rtsfind;
kono
parents:
diff changeset
39 with Sem; use Sem;
kono
parents:
diff changeset
40 with Sem_Aux; use Sem_Aux;
kono
parents:
diff changeset
41 with Sem_Ch5; use Sem_Ch5;
kono
parents:
diff changeset
42 with Sem_Ch8; use Sem_Ch8;
kono
parents:
diff changeset
43 with Sem_Ch13; use Sem_Ch13;
kono
parents:
diff changeset
44 with Sem_Res; use Sem_Res;
kono
parents:
diff changeset
45 with Sem_Util; use Sem_Util;
kono
parents:
diff changeset
46 with Sem_Warn; use Sem_Warn;
kono
parents:
diff changeset
47 with Sinfo; use Sinfo;
kono
parents:
diff changeset
48 with Snames; use Snames;
kono
parents:
diff changeset
49 with Stand; use Stand;
kono
parents:
diff changeset
50
kono
parents:
diff changeset
51 package body Sem_Ch11 is
kono
parents:
diff changeset
52
kono
parents:
diff changeset
53 -----------------------------------
kono
parents:
diff changeset
54 -- Analyze_Exception_Declaration --
kono
parents:
diff changeset
55 -----------------------------------
kono
parents:
diff changeset
56
kono
parents:
diff changeset
57 procedure Analyze_Exception_Declaration (N : Node_Id) is
kono
parents:
diff changeset
58 Id : constant Entity_Id := Defining_Identifier (N);
kono
parents:
diff changeset
59 PF : constant Boolean := Is_Pure (Current_Scope);
kono
parents:
diff changeset
60
kono
parents:
diff changeset
61 begin
kono
parents:
diff changeset
62 Generate_Definition (Id);
kono
parents:
diff changeset
63 Enter_Name (Id);
kono
parents:
diff changeset
64 Set_Ekind (Id, E_Exception);
kono
parents:
diff changeset
65 Set_Etype (Id, Standard_Exception_Type);
kono
parents:
diff changeset
66 Set_Is_Statically_Allocated (Id);
kono
parents:
diff changeset
67 Set_Is_Pure (Id, PF);
kono
parents:
diff changeset
68
kono
parents:
diff changeset
69 if Has_Aspects (N) then
kono
parents:
diff changeset
70 Analyze_Aspect_Specifications (N, Id);
kono
parents:
diff changeset
71 end if;
kono
parents:
diff changeset
72 end Analyze_Exception_Declaration;
kono
parents:
diff changeset
73
kono
parents:
diff changeset
74 --------------------------------
kono
parents:
diff changeset
75 -- Analyze_Exception_Handlers --
kono
parents:
diff changeset
76 --------------------------------
kono
parents:
diff changeset
77
kono
parents:
diff changeset
78 procedure Analyze_Exception_Handlers (L : List_Id) is
kono
parents:
diff changeset
79 Handler : Node_Id;
kono
parents:
diff changeset
80 Choice : Entity_Id;
kono
parents:
diff changeset
81 Id : Node_Id;
kono
parents:
diff changeset
82 H_Scope : Entity_Id := Empty;
kono
parents:
diff changeset
83
kono
parents:
diff changeset
84 procedure Check_Duplication (Id : Node_Id);
kono
parents:
diff changeset
85 -- Iterate through the identifiers in each handler to find duplicates
kono
parents:
diff changeset
86
kono
parents:
diff changeset
87 function Others_Present return Boolean;
kono
parents:
diff changeset
88 -- Returns True if others handler is present
kono
parents:
diff changeset
89
kono
parents:
diff changeset
90 -----------------------
kono
parents:
diff changeset
91 -- Check_Duplication --
kono
parents:
diff changeset
92 -----------------------
kono
parents:
diff changeset
93
kono
parents:
diff changeset
94 procedure Check_Duplication (Id : Node_Id) is
kono
parents:
diff changeset
95 Handler : Node_Id;
kono
parents:
diff changeset
96 Id1 : Node_Id;
kono
parents:
diff changeset
97 Id_Entity : Entity_Id := Entity (Id);
kono
parents:
diff changeset
98
kono
parents:
diff changeset
99 begin
kono
parents:
diff changeset
100 if Present (Renamed_Entity (Id_Entity)) then
kono
parents:
diff changeset
101 Id_Entity := Renamed_Entity (Id_Entity);
kono
parents:
diff changeset
102 end if;
kono
parents:
diff changeset
103
kono
parents:
diff changeset
104 Handler := First_Non_Pragma (L);
kono
parents:
diff changeset
105 while Present (Handler) loop
kono
parents:
diff changeset
106 Id1 := First (Exception_Choices (Handler));
kono
parents:
diff changeset
107 while Present (Id1) loop
kono
parents:
diff changeset
108
kono
parents:
diff changeset
109 -- Only check against the exception choices which precede
kono
parents:
diff changeset
110 -- Id in the handler, since the ones that follow Id have not
kono
parents:
diff changeset
111 -- been analyzed yet and will be checked in a subsequent call.
kono
parents:
diff changeset
112
kono
parents:
diff changeset
113 if Id = Id1 then
kono
parents:
diff changeset
114 return;
kono
parents:
diff changeset
115
kono
parents:
diff changeset
116 elsif Nkind (Id1) /= N_Others_Choice
kono
parents:
diff changeset
117 and then
kono
parents:
diff changeset
118 (Id_Entity = Entity (Id1)
kono
parents:
diff changeset
119 or else (Id_Entity = Renamed_Entity (Entity (Id1))))
kono
parents:
diff changeset
120 then
kono
parents:
diff changeset
121 if Handler /= Parent (Id) then
kono
parents:
diff changeset
122 Error_Msg_Sloc := Sloc (Id1);
kono
parents:
diff changeset
123 Error_Msg_NE ("exception choice duplicates &#", Id, Id1);
kono
parents:
diff changeset
124
kono
parents:
diff changeset
125 else
kono
parents:
diff changeset
126 if Ada_Version = Ada_83
kono
parents:
diff changeset
127 and then Comes_From_Source (Id)
kono
parents:
diff changeset
128 then
kono
parents:
diff changeset
129 Error_Msg_N
kono
parents:
diff changeset
130 ("(Ada 83): duplicate exception choice&", Id);
kono
parents:
diff changeset
131 end if;
kono
parents:
diff changeset
132 end if;
kono
parents:
diff changeset
133 end if;
kono
parents:
diff changeset
134
kono
parents:
diff changeset
135 Next_Non_Pragma (Id1);
kono
parents:
diff changeset
136 end loop;
kono
parents:
diff changeset
137
kono
parents:
diff changeset
138 Next (Handler);
kono
parents:
diff changeset
139 end loop;
kono
parents:
diff changeset
140 end Check_Duplication;
kono
parents:
diff changeset
141
kono
parents:
diff changeset
142 --------------------
kono
parents:
diff changeset
143 -- Others_Present --
kono
parents:
diff changeset
144 --------------------
kono
parents:
diff changeset
145
kono
parents:
diff changeset
146 function Others_Present return Boolean is
kono
parents:
diff changeset
147 H : Node_Id;
kono
parents:
diff changeset
148
kono
parents:
diff changeset
149 begin
kono
parents:
diff changeset
150 H := First (L);
kono
parents:
diff changeset
151 while Present (H) loop
kono
parents:
diff changeset
152 if Nkind (H) /= N_Pragma
kono
parents:
diff changeset
153 and then Nkind (First (Exception_Choices (H))) = N_Others_Choice
kono
parents:
diff changeset
154 then
kono
parents:
diff changeset
155 return True;
kono
parents:
diff changeset
156 end if;
kono
parents:
diff changeset
157
kono
parents:
diff changeset
158 Next (H);
kono
parents:
diff changeset
159 end loop;
kono
parents:
diff changeset
160
kono
parents:
diff changeset
161 return False;
kono
parents:
diff changeset
162 end Others_Present;
kono
parents:
diff changeset
163
kono
parents:
diff changeset
164 -- Start of processing for Analyze_Exception_Handlers
kono
parents:
diff changeset
165
kono
parents:
diff changeset
166 begin
kono
parents:
diff changeset
167 Handler := First (L);
kono
parents:
diff changeset
168
kono
parents:
diff changeset
169 -- Pragma Restriction_Warnings has more related semantics than pragma
kono
parents:
diff changeset
170 -- Restrictions in that it flags exception handlers as violators. Note
kono
parents:
diff changeset
171 -- that the compiler must still generate handlers for certain critical
kono
parents:
diff changeset
172 -- scenarios such as finalization. As a result, these handlers should
kono
parents:
diff changeset
173 -- not be subjected to the restriction check when in warnings mode.
kono
parents:
diff changeset
174
kono
parents:
diff changeset
175 if not Comes_From_Source (Handler)
kono
parents:
diff changeset
176 and then (Restriction_Warnings (No_Exception_Handlers)
kono
parents:
diff changeset
177 or else Restriction_Warnings (No_Exception_Propagation)
kono
parents:
diff changeset
178 or else Restriction_Warnings (No_Exceptions))
kono
parents:
diff changeset
179 then
kono
parents:
diff changeset
180 null;
kono
parents:
diff changeset
181
kono
parents:
diff changeset
182 else
kono
parents:
diff changeset
183 Check_Restriction (No_Exceptions, Handler);
kono
parents:
diff changeset
184 Check_Restriction (No_Exception_Handlers, Handler);
kono
parents:
diff changeset
185 end if;
kono
parents:
diff changeset
186
kono
parents:
diff changeset
187 -- Kill current remembered values, since we don't know where we were
kono
parents:
diff changeset
188 -- when the exception was raised.
kono
parents:
diff changeset
189
kono
parents:
diff changeset
190 Kill_Current_Values;
kono
parents:
diff changeset
191
kono
parents:
diff changeset
192 -- Loop through handlers (which can include pragmas)
kono
parents:
diff changeset
193
kono
parents:
diff changeset
194 while Present (Handler) loop
kono
parents:
diff changeset
195
kono
parents:
diff changeset
196 -- If pragma just analyze it
kono
parents:
diff changeset
197
kono
parents:
diff changeset
198 if Nkind (Handler) = N_Pragma then
kono
parents:
diff changeset
199 Analyze (Handler);
kono
parents:
diff changeset
200
kono
parents:
diff changeset
201 -- Otherwise we have a real exception handler
kono
parents:
diff changeset
202
kono
parents:
diff changeset
203 else
kono
parents:
diff changeset
204 -- Deal with choice parameter. The exception handler is a
kono
parents:
diff changeset
205 -- declarative part for the choice parameter, so it constitutes a
kono
parents:
diff changeset
206 -- scope for visibility purposes. We create an entity to denote
kono
parents:
diff changeset
207 -- the whole exception part, and use it as the scope of all the
kono
parents:
diff changeset
208 -- choices, which may even have the same name without conflict.
kono
parents:
diff changeset
209 -- This scope plays no other role in expansion or code generation.
kono
parents:
diff changeset
210
kono
parents:
diff changeset
211 Choice := Choice_Parameter (Handler);
kono
parents:
diff changeset
212
kono
parents:
diff changeset
213 if Present (Choice) then
kono
parents:
diff changeset
214 Set_Local_Raise_Not_OK (Handler);
kono
parents:
diff changeset
215
kono
parents:
diff changeset
216 if Comes_From_Source (Choice) then
kono
parents:
diff changeset
217 Check_Restriction (No_Exception_Propagation, Choice);
kono
parents:
diff changeset
218 Set_Debug_Info_Needed (Choice);
kono
parents:
diff changeset
219 end if;
kono
parents:
diff changeset
220
kono
parents:
diff changeset
221 if No (H_Scope) then
kono
parents:
diff changeset
222 H_Scope :=
kono
parents:
diff changeset
223 New_Internal_Entity
kono
parents:
diff changeset
224 (E_Block, Current_Scope, Sloc (Choice), 'E');
kono
parents:
diff changeset
225 Set_Is_Exception_Handler (H_Scope);
kono
parents:
diff changeset
226 end if;
kono
parents:
diff changeset
227
kono
parents:
diff changeset
228 Push_Scope (H_Scope);
kono
parents:
diff changeset
229 Set_Etype (H_Scope, Standard_Void_Type);
kono
parents:
diff changeset
230
kono
parents:
diff changeset
231 Enter_Name (Choice);
kono
parents:
diff changeset
232 Set_Ekind (Choice, E_Variable);
kono
parents:
diff changeset
233
kono
parents:
diff changeset
234 if RTE_Available (RE_Exception_Occurrence) then
kono
parents:
diff changeset
235 Set_Etype (Choice, RTE (RE_Exception_Occurrence));
kono
parents:
diff changeset
236 end if;
kono
parents:
diff changeset
237
kono
parents:
diff changeset
238 Generate_Definition (Choice);
kono
parents:
diff changeset
239
kono
parents:
diff changeset
240 -- Indicate that choice has an initial value, since in effect
kono
parents:
diff changeset
241 -- this field is assigned an initial value by the exception.
kono
parents:
diff changeset
242 -- We also consider that it is modified in the source.
kono
parents:
diff changeset
243
kono
parents:
diff changeset
244 Set_Has_Initial_Value (Choice, True);
kono
parents:
diff changeset
245 Set_Never_Set_In_Source (Choice, False);
kono
parents:
diff changeset
246 end if;
kono
parents:
diff changeset
247
kono
parents:
diff changeset
248 Id := First (Exception_Choices (Handler));
kono
parents:
diff changeset
249 while Present (Id) loop
kono
parents:
diff changeset
250 if Nkind (Id) = N_Others_Choice then
kono
parents:
diff changeset
251 if Present (Next (Id))
kono
parents:
diff changeset
252 or else Present (Next (Handler))
kono
parents:
diff changeset
253 or else Present (Prev (Id))
kono
parents:
diff changeset
254 then
kono
parents:
diff changeset
255 Error_Msg_N ("OTHERS must appear alone and last", Id);
kono
parents:
diff changeset
256 end if;
kono
parents:
diff changeset
257
kono
parents:
diff changeset
258 else
kono
parents:
diff changeset
259 Analyze (Id);
kono
parents:
diff changeset
260
kono
parents:
diff changeset
261 -- In most cases the choice has already been analyzed in
kono
parents:
diff changeset
262 -- Analyze_Handled_Statement_Sequence, in order to expand
kono
parents:
diff changeset
263 -- local handlers. This advance analysis does not take into
kono
parents:
diff changeset
264 -- account the case in which a choice has the same name as
kono
parents:
diff changeset
265 -- the choice parameter of the handler, which may hide an
kono
parents:
diff changeset
266 -- outer exception. This pathological case appears in ACATS
kono
parents:
diff changeset
267 -- B80001_3.adb, and requires an explicit check to verify
kono
parents:
diff changeset
268 -- that the id is not hidden.
kono
parents:
diff changeset
269
kono
parents:
diff changeset
270 if not Is_Entity_Name (Id)
kono
parents:
diff changeset
271 or else Ekind (Entity (Id)) /= E_Exception
kono
parents:
diff changeset
272 or else
kono
parents:
diff changeset
273 (Nkind (Id) = N_Identifier
kono
parents:
diff changeset
274 and then Chars (Id) = Chars (Choice))
kono
parents:
diff changeset
275 then
kono
parents:
diff changeset
276 Error_Msg_N ("exception name expected", Id);
kono
parents:
diff changeset
277
kono
parents:
diff changeset
278 else
kono
parents:
diff changeset
279 -- Emit a warning at the declaration level when a local
kono
parents:
diff changeset
280 -- exception is never raised explicitly.
kono
parents:
diff changeset
281
kono
parents:
diff changeset
282 if Warn_On_Redundant_Constructs
kono
parents:
diff changeset
283 and then not Is_Raised (Entity (Id))
kono
parents:
diff changeset
284 and then Scope (Entity (Id)) = Current_Scope
kono
parents:
diff changeset
285 then
kono
parents:
diff changeset
286 Error_Msg_NE
kono
parents:
diff changeset
287 ("exception & is never raised?r?", Entity (Id), Id);
kono
parents:
diff changeset
288 end if;
kono
parents:
diff changeset
289
kono
parents:
diff changeset
290 if Present (Renamed_Entity (Entity (Id))) then
kono
parents:
diff changeset
291 if Entity (Id) = Standard_Numeric_Error then
kono
parents:
diff changeset
292 Check_Restriction (No_Obsolescent_Features, Id);
kono
parents:
diff changeset
293
kono
parents:
diff changeset
294 if Warn_On_Obsolescent_Feature then
kono
parents:
diff changeset
295 Error_Msg_N
kono
parents:
diff changeset
296 ("Numeric_Error is an " &
kono
parents:
diff changeset
297 "obsolescent feature (RM J.6(1))?j?", Id);
kono
parents:
diff changeset
298 Error_Msg_N
kono
parents:
diff changeset
299 ("\use Constraint_Error instead?j?", Id);
kono
parents:
diff changeset
300 end if;
kono
parents:
diff changeset
301 end if;
kono
parents:
diff changeset
302 end if;
kono
parents:
diff changeset
303
kono
parents:
diff changeset
304 Check_Duplication (Id);
kono
parents:
diff changeset
305
kono
parents:
diff changeset
306 -- Check for exception declared within generic formal
kono
parents:
diff changeset
307 -- package (which is illegal, see RM 11.2(8))
kono
parents:
diff changeset
308
kono
parents:
diff changeset
309 declare
kono
parents:
diff changeset
310 Ent : Entity_Id := Entity (Id);
kono
parents:
diff changeset
311 Scop : Entity_Id;
kono
parents:
diff changeset
312
kono
parents:
diff changeset
313 begin
kono
parents:
diff changeset
314 if Present (Renamed_Entity (Ent)) then
kono
parents:
diff changeset
315 Ent := Renamed_Entity (Ent);
kono
parents:
diff changeset
316 end if;
kono
parents:
diff changeset
317
kono
parents:
diff changeset
318 Scop := Scope (Ent);
kono
parents:
diff changeset
319 while Scop /= Standard_Standard
kono
parents:
diff changeset
320 and then Ekind (Scop) = E_Package
kono
parents:
diff changeset
321 loop
kono
parents:
diff changeset
322 if Nkind (Declaration_Node (Scop)) =
kono
parents:
diff changeset
323 N_Package_Specification
kono
parents:
diff changeset
324 and then
kono
parents:
diff changeset
325 Nkind (Original_Node (Parent
kono
parents:
diff changeset
326 (Declaration_Node (Scop)))) =
kono
parents:
diff changeset
327 N_Formal_Package_Declaration
kono
parents:
diff changeset
328 then
kono
parents:
diff changeset
329 Error_Msg_NE
kono
parents:
diff changeset
330 ("exception& is declared in generic formal "
kono
parents:
diff changeset
331 & "package", Id, Ent);
kono
parents:
diff changeset
332 Error_Msg_N
kono
parents:
diff changeset
333 ("\and therefore cannot appear in handler "
kono
parents:
diff changeset
334 & "(RM 11.2(8))", Id);
kono
parents:
diff changeset
335 exit;
kono
parents:
diff changeset
336
kono
parents:
diff changeset
337 -- If the exception is declared in an inner
kono
parents:
diff changeset
338 -- instance, nothing else to check.
kono
parents:
diff changeset
339
kono
parents:
diff changeset
340 elsif Is_Generic_Instance (Scop) then
kono
parents:
diff changeset
341 exit;
kono
parents:
diff changeset
342 end if;
kono
parents:
diff changeset
343
kono
parents:
diff changeset
344 Scop := Scope (Scop);
kono
parents:
diff changeset
345 end loop;
kono
parents:
diff changeset
346 end;
kono
parents:
diff changeset
347 end if;
kono
parents:
diff changeset
348 end if;
kono
parents:
diff changeset
349
kono
parents:
diff changeset
350 Next (Id);
kono
parents:
diff changeset
351 end loop;
kono
parents:
diff changeset
352
kono
parents:
diff changeset
353 -- Check for redundant handler (has only raise statement) and is
kono
parents:
diff changeset
354 -- either an others handler, or is a specific handler when no
kono
parents:
diff changeset
355 -- others handler is present.
kono
parents:
diff changeset
356
kono
parents:
diff changeset
357 if Warn_On_Redundant_Constructs
kono
parents:
diff changeset
358 and then List_Length (Statements (Handler)) = 1
kono
parents:
diff changeset
359 and then Nkind (First (Statements (Handler))) = N_Raise_Statement
kono
parents:
diff changeset
360 and then No (Name (First (Statements (Handler))))
kono
parents:
diff changeset
361 and then (not Others_Present
kono
parents:
diff changeset
362 or else Nkind (First (Exception_Choices (Handler))) =
kono
parents:
diff changeset
363 N_Others_Choice)
kono
parents:
diff changeset
364 then
kono
parents:
diff changeset
365 Error_Msg_N
kono
parents:
diff changeset
366 ("useless handler contains only a reraise statement?r?",
kono
parents:
diff changeset
367 Handler);
kono
parents:
diff changeset
368 end if;
kono
parents:
diff changeset
369
kono
parents:
diff changeset
370 -- Now analyze the statements of this handler
kono
parents:
diff changeset
371
kono
parents:
diff changeset
372 Analyze_Statements (Statements (Handler));
kono
parents:
diff changeset
373
kono
parents:
diff changeset
374 -- If a choice was present, we created a special scope for it, so
kono
parents:
diff changeset
375 -- this is where we pop that special scope to get rid of it.
kono
parents:
diff changeset
376
kono
parents:
diff changeset
377 if Present (Choice) then
kono
parents:
diff changeset
378 End_Scope;
kono
parents:
diff changeset
379 end if;
kono
parents:
diff changeset
380 end if;
kono
parents:
diff changeset
381
kono
parents:
diff changeset
382 Next (Handler);
kono
parents:
diff changeset
383 end loop;
kono
parents:
diff changeset
384 end Analyze_Exception_Handlers;
kono
parents:
diff changeset
385
kono
parents:
diff changeset
386 --------------------------------
kono
parents:
diff changeset
387 -- Analyze_Handled_Statements --
kono
parents:
diff changeset
388 --------------------------------
kono
parents:
diff changeset
389
kono
parents:
diff changeset
390 procedure Analyze_Handled_Statements (N : Node_Id) is
kono
parents:
diff changeset
391 Handlers : constant List_Id := Exception_Handlers (N);
kono
parents:
diff changeset
392 Handler : Node_Id;
kono
parents:
diff changeset
393 Choice : Node_Id;
kono
parents:
diff changeset
394
kono
parents:
diff changeset
395 begin
kono
parents:
diff changeset
396 if Present (Handlers) then
kono
parents:
diff changeset
397 Kill_All_Checks;
kono
parents:
diff changeset
398 end if;
kono
parents:
diff changeset
399
kono
parents:
diff changeset
400 -- We are now going to analyze the statements and then the exception
kono
parents:
diff changeset
401 -- handlers. We certainly need to do things in this order to get the
kono
parents:
diff changeset
402 -- proper sequential semantics for various warnings.
kono
parents:
diff changeset
403
kono
parents:
diff changeset
404 -- However, there is a glitch. When we process raise statements, an
kono
parents:
diff changeset
405 -- optimization is to look for local handlers and specialize the code
kono
parents:
diff changeset
406 -- in this case.
kono
parents:
diff changeset
407
kono
parents:
diff changeset
408 -- In order to detect if a handler is matching, we must have at least
kono
parents:
diff changeset
409 -- analyzed the choices in the proper scope so that proper visibility
kono
parents:
diff changeset
410 -- analysis is performed. Hence we analyze just the choices first,
kono
parents:
diff changeset
411 -- before we analyze the statement sequence.
kono
parents:
diff changeset
412
kono
parents:
diff changeset
413 Handler := First_Non_Pragma (Handlers);
kono
parents:
diff changeset
414 while Present (Handler) loop
kono
parents:
diff changeset
415 Choice := First_Non_Pragma (Exception_Choices (Handler));
kono
parents:
diff changeset
416 while Present (Choice) loop
kono
parents:
diff changeset
417 Analyze (Choice);
kono
parents:
diff changeset
418 Next_Non_Pragma (Choice);
kono
parents:
diff changeset
419 end loop;
kono
parents:
diff changeset
420
kono
parents:
diff changeset
421 Next_Non_Pragma (Handler);
kono
parents:
diff changeset
422 end loop;
kono
parents:
diff changeset
423
kono
parents:
diff changeset
424 -- Analyze statements in sequence
kono
parents:
diff changeset
425
kono
parents:
diff changeset
426 Analyze_Statements (Statements (N));
kono
parents:
diff changeset
427
kono
parents:
diff changeset
428 -- If the current scope is a subprogram, entry or task body or declare
kono
parents:
diff changeset
429 -- block then this is the right place to check for hanging useless
kono
parents:
diff changeset
430 -- assignments from the statement sequence. Skip this in the body of a
kono
parents:
diff changeset
431 -- postcondition, since in that case there are no source references, and
kono
parents:
diff changeset
432 -- we need to preserve deferred references from the enclosing scope.
kono
parents:
diff changeset
433
kono
parents:
diff changeset
434 if ((Is_Subprogram (Current_Scope) or else Is_Entry (Current_Scope))
kono
parents:
diff changeset
435 and then Chars (Current_Scope) /= Name_uPostconditions)
kono
parents:
diff changeset
436 or else Ekind_In (Current_Scope, E_Block, E_Task_Type)
kono
parents:
diff changeset
437 then
kono
parents:
diff changeset
438 Warn_On_Useless_Assignments (Current_Scope);
kono
parents:
diff changeset
439 end if;
kono
parents:
diff changeset
440
kono
parents:
diff changeset
441 -- Deal with handlers or AT END proc
kono
parents:
diff changeset
442
kono
parents:
diff changeset
443 if Present (Handlers) then
kono
parents:
diff changeset
444 Analyze_Exception_Handlers (Handlers);
kono
parents:
diff changeset
445 elsif Present (At_End_Proc (N)) then
kono
parents:
diff changeset
446 Analyze (At_End_Proc (N));
kono
parents:
diff changeset
447 end if;
kono
parents:
diff changeset
448 end Analyze_Handled_Statements;
kono
parents:
diff changeset
449
kono
parents:
diff changeset
450 ------------------------------
kono
parents:
diff changeset
451 -- Analyze_Raise_Expression --
kono
parents:
diff changeset
452 ------------------------------
kono
parents:
diff changeset
453
kono
parents:
diff changeset
454 procedure Analyze_Raise_Expression (N : Node_Id) is
kono
parents:
diff changeset
455 Exception_Id : constant Node_Id := Name (N);
kono
parents:
diff changeset
456 Exception_Name : Entity_Id := Empty;
kono
parents:
diff changeset
457
kono
parents:
diff changeset
458 begin
kono
parents:
diff changeset
459 if Comes_From_Source (N) then
kono
parents:
diff changeset
460 Check_Compiler_Unit ("raise expression", N);
kono
parents:
diff changeset
461 end if;
kono
parents:
diff changeset
462
kono
parents:
diff changeset
463 Check_SPARK_05_Restriction ("raise expression is not allowed", N);
kono
parents:
diff changeset
464
kono
parents:
diff changeset
465 -- Check exception restrictions on the original source
kono
parents:
diff changeset
466
kono
parents:
diff changeset
467 if Comes_From_Source (N) then
kono
parents:
diff changeset
468 Check_Restriction (No_Exceptions, N);
kono
parents:
diff changeset
469 end if;
kono
parents:
diff changeset
470
kono
parents:
diff changeset
471 Analyze (Exception_Id);
kono
parents:
diff changeset
472
kono
parents:
diff changeset
473 if Is_Entity_Name (Exception_Id) then
kono
parents:
diff changeset
474 Exception_Name := Entity (Exception_Id);
kono
parents:
diff changeset
475 end if;
kono
parents:
diff changeset
476
kono
parents:
diff changeset
477 if No (Exception_Name)
kono
parents:
diff changeset
478 or else Ekind (Exception_Name) /= E_Exception
kono
parents:
diff changeset
479 then
kono
parents:
diff changeset
480 Error_Msg_N
kono
parents:
diff changeset
481 ("exception name expected in raise statement", Exception_Id);
kono
parents:
diff changeset
482 else
kono
parents:
diff changeset
483 Set_Is_Raised (Exception_Name);
kono
parents:
diff changeset
484 end if;
kono
parents:
diff changeset
485
kono
parents:
diff changeset
486 -- Deal with RAISE WITH case
kono
parents:
diff changeset
487
kono
parents:
diff changeset
488 if Present (Expression (N)) then
kono
parents:
diff changeset
489 Analyze_And_Resolve (Expression (N), Standard_String);
kono
parents:
diff changeset
490 end if;
kono
parents:
diff changeset
491
kono
parents:
diff changeset
492 -- Check obsolescent use of Numeric_Error
kono
parents:
diff changeset
493
kono
parents:
diff changeset
494 if Exception_Name = Standard_Numeric_Error then
kono
parents:
diff changeset
495 Check_Restriction (No_Obsolescent_Features, Exception_Id);
kono
parents:
diff changeset
496 end if;
kono
parents:
diff changeset
497
kono
parents:
diff changeset
498 -- Kill last assignment indication
kono
parents:
diff changeset
499
kono
parents:
diff changeset
500 Kill_Current_Values (Last_Assignment_Only => True);
kono
parents:
diff changeset
501
kono
parents:
diff changeset
502 -- Raise_Type is compatible with all other types so that the raise
kono
parents:
diff changeset
503 -- expression is legal in any expression context. It will be eventually
kono
parents:
diff changeset
504 -- replaced by the concrete type imposed by the context.
kono
parents:
diff changeset
505
kono
parents:
diff changeset
506 Set_Etype (N, Raise_Type);
kono
parents:
diff changeset
507 end Analyze_Raise_Expression;
kono
parents:
diff changeset
508
kono
parents:
diff changeset
509 -----------------------------
kono
parents:
diff changeset
510 -- Analyze_Raise_Statement --
kono
parents:
diff changeset
511 -----------------------------
kono
parents:
diff changeset
512
kono
parents:
diff changeset
513 procedure Analyze_Raise_Statement (N : Node_Id) is
kono
parents:
diff changeset
514 Exception_Id : constant Node_Id := Name (N);
kono
parents:
diff changeset
515 Exception_Name : Entity_Id := Empty;
kono
parents:
diff changeset
516 P : Node_Id;
kono
parents:
diff changeset
517 Par : Node_Id;
kono
parents:
diff changeset
518
kono
parents:
diff changeset
519 begin
kono
parents:
diff changeset
520 if Comes_From_Source (N) then
kono
parents:
diff changeset
521 Check_SPARK_05_Restriction ("raise statement is not allowed", N);
kono
parents:
diff changeset
522 end if;
kono
parents:
diff changeset
523
kono
parents:
diff changeset
524 Check_Unreachable_Code (N);
kono
parents:
diff changeset
525
kono
parents:
diff changeset
526 -- Check exception restrictions on the original source
kono
parents:
diff changeset
527
kono
parents:
diff changeset
528 if Comes_From_Source (N) then
kono
parents:
diff changeset
529 Check_Restriction (No_Exceptions, N);
kono
parents:
diff changeset
530 end if;
kono
parents:
diff changeset
531
kono
parents:
diff changeset
532 -- Check for useless assignment to OUT or IN OUT scalar preceding the
kono
parents:
diff changeset
533 -- raise. Right now only look at assignment statements, could do more???
kono
parents:
diff changeset
534
kono
parents:
diff changeset
535 if Is_List_Member (N) then
kono
parents:
diff changeset
536 declare
kono
parents:
diff changeset
537 P : Node_Id;
kono
parents:
diff changeset
538 L : Node_Id;
kono
parents:
diff changeset
539
kono
parents:
diff changeset
540 begin
kono
parents:
diff changeset
541 P := Prev (N);
kono
parents:
diff changeset
542
kono
parents:
diff changeset
543 -- Skip past null statements and pragmas
kono
parents:
diff changeset
544
kono
parents:
diff changeset
545 while Present (P)
kono
parents:
diff changeset
546 and then Nkind_In (P, N_Null_Statement, N_Pragma)
kono
parents:
diff changeset
547 loop
kono
parents:
diff changeset
548 P := Prev (P);
kono
parents:
diff changeset
549 end loop;
kono
parents:
diff changeset
550
kono
parents:
diff changeset
551 -- See if preceding statement is an assignment
kono
parents:
diff changeset
552
kono
parents:
diff changeset
553 if Present (P) and then Nkind (P) = N_Assignment_Statement then
kono
parents:
diff changeset
554 L := Name (P);
kono
parents:
diff changeset
555
kono
parents:
diff changeset
556 -- Give warning for assignment to scalar formal
kono
parents:
diff changeset
557
kono
parents:
diff changeset
558 if Is_Scalar_Type (Etype (L))
kono
parents:
diff changeset
559 and then Is_Entity_Name (L)
kono
parents:
diff changeset
560 and then Is_Formal (Entity (L))
kono
parents:
diff changeset
561
kono
parents:
diff changeset
562 -- Do this only for parameters to the current subprogram.
kono
parents:
diff changeset
563 -- This avoids some false positives for the nested case.
kono
parents:
diff changeset
564
kono
parents:
diff changeset
565 and then Nearest_Dynamic_Scope (Current_Scope) =
kono
parents:
diff changeset
566 Scope (Entity (L))
kono
parents:
diff changeset
567
kono
parents:
diff changeset
568 then
kono
parents:
diff changeset
569 -- Don't give warning if we are covered by an exception
kono
parents:
diff changeset
570 -- handler, since this may result in false positives, since
kono
parents:
diff changeset
571 -- the handler may handle the exception and return normally.
kono
parents:
diff changeset
572
kono
parents:
diff changeset
573 -- First find the enclosing handled sequence of statements
kono
parents:
diff changeset
574 -- (note, we could also look for a handler in an outer block
kono
parents:
diff changeset
575 -- but currently we don't, and in that case we'll emit the
kono
parents:
diff changeset
576 -- warning).
kono
parents:
diff changeset
577
kono
parents:
diff changeset
578 Par := N;
kono
parents:
diff changeset
579 loop
kono
parents:
diff changeset
580 Par := Parent (Par);
kono
parents:
diff changeset
581 exit when Nkind (Par) = N_Handled_Sequence_Of_Statements;
kono
parents:
diff changeset
582 end loop;
kono
parents:
diff changeset
583
kono
parents:
diff changeset
584 -- See if there is a handler, give message if not
kono
parents:
diff changeset
585
kono
parents:
diff changeset
586 if No (Exception_Handlers (Par)) then
kono
parents:
diff changeset
587 Error_Msg_N
kono
parents:
diff changeset
588 ("assignment to pass-by-copy formal "
kono
parents:
diff changeset
589 & "may have no effect??", P);
kono
parents:
diff changeset
590 Error_Msg_N
kono
parents:
diff changeset
591 ("\RAISE statement may result in abnormal return "
kono
parents:
diff changeset
592 & "(RM 6.4.1(17))??", P);
kono
parents:
diff changeset
593 end if;
kono
parents:
diff changeset
594 end if;
kono
parents:
diff changeset
595 end if;
kono
parents:
diff changeset
596 end;
kono
parents:
diff changeset
597 end if;
kono
parents:
diff changeset
598
kono
parents:
diff changeset
599 -- Reraise statement
kono
parents:
diff changeset
600
kono
parents:
diff changeset
601 if No (Exception_Id) then
kono
parents:
diff changeset
602 P := Parent (N);
kono
parents:
diff changeset
603 while not Nkind_In (P, N_Exception_Handler,
kono
parents:
diff changeset
604 N_Subprogram_Body,
kono
parents:
diff changeset
605 N_Package_Body,
kono
parents:
diff changeset
606 N_Task_Body,
kono
parents:
diff changeset
607 N_Entry_Body)
kono
parents:
diff changeset
608 loop
kono
parents:
diff changeset
609 P := Parent (P);
kono
parents:
diff changeset
610 end loop;
kono
parents:
diff changeset
611
kono
parents:
diff changeset
612 if Nkind (P) /= N_Exception_Handler then
kono
parents:
diff changeset
613 Error_Msg_N
kono
parents:
diff changeset
614 ("reraise statement must appear directly in a handler", N);
kono
parents:
diff changeset
615
kono
parents:
diff changeset
616 -- If a handler has a reraise, it cannot be the target of a local
kono
parents:
diff changeset
617 -- raise (goto optimization is impossible), and if the no exception
kono
parents:
diff changeset
618 -- propagation restriction is set, this is a violation.
kono
parents:
diff changeset
619
kono
parents:
diff changeset
620 else
kono
parents:
diff changeset
621 Set_Local_Raise_Not_OK (P);
kono
parents:
diff changeset
622
kono
parents:
diff changeset
623 -- Do not check the restriction if the reraise statement is part
kono
parents:
diff changeset
624 -- of the code generated for an AT-END handler. That's because
kono
parents:
diff changeset
625 -- if the restriction is actually active, we never generate this
kono
parents:
diff changeset
626 -- raise anyway, so the apparent violation is bogus.
kono
parents:
diff changeset
627
kono
parents:
diff changeset
628 if not From_At_End (N) then
kono
parents:
diff changeset
629 Check_Restriction (No_Exception_Propagation, N);
kono
parents:
diff changeset
630 end if;
kono
parents:
diff changeset
631 end if;
kono
parents:
diff changeset
632
kono
parents:
diff changeset
633 -- Normal case with exception id present
kono
parents:
diff changeset
634
kono
parents:
diff changeset
635 else
kono
parents:
diff changeset
636 Analyze (Exception_Id);
kono
parents:
diff changeset
637
kono
parents:
diff changeset
638 if Is_Entity_Name (Exception_Id) then
kono
parents:
diff changeset
639 Exception_Name := Entity (Exception_Id);
kono
parents:
diff changeset
640 end if;
kono
parents:
diff changeset
641
kono
parents:
diff changeset
642 if No (Exception_Name)
kono
parents:
diff changeset
643 or else Ekind (Exception_Name) /= E_Exception
kono
parents:
diff changeset
644 then
kono
parents:
diff changeset
645 Error_Msg_N
kono
parents:
diff changeset
646 ("exception name expected in raise statement", Exception_Id);
kono
parents:
diff changeset
647 else
kono
parents:
diff changeset
648 Set_Is_Raised (Exception_Name);
kono
parents:
diff changeset
649 end if;
kono
parents:
diff changeset
650
kono
parents:
diff changeset
651 -- Deal with RAISE WITH case
kono
parents:
diff changeset
652
kono
parents:
diff changeset
653 if Present (Expression (N)) then
kono
parents:
diff changeset
654 Analyze_And_Resolve (Expression (N), Standard_String);
kono
parents:
diff changeset
655 end if;
kono
parents:
diff changeset
656 end if;
kono
parents:
diff changeset
657
kono
parents:
diff changeset
658 -- Check obsolescent use of Numeric_Error
kono
parents:
diff changeset
659
kono
parents:
diff changeset
660 if Exception_Name = Standard_Numeric_Error then
kono
parents:
diff changeset
661 Check_Restriction (No_Obsolescent_Features, Exception_Id);
kono
parents:
diff changeset
662 end if;
kono
parents:
diff changeset
663
kono
parents:
diff changeset
664 -- Kill last assignment indication
kono
parents:
diff changeset
665
kono
parents:
diff changeset
666 Kill_Current_Values (Last_Assignment_Only => True);
kono
parents:
diff changeset
667 end Analyze_Raise_Statement;
kono
parents:
diff changeset
668
kono
parents:
diff changeset
669 -----------------------------
kono
parents:
diff changeset
670 -- Analyze_Raise_xxx_Error --
kono
parents:
diff changeset
671 -----------------------------
kono
parents:
diff changeset
672
kono
parents:
diff changeset
673 -- Normally, the Etype is already set (when this node is used within
kono
parents:
diff changeset
674 -- an expression, since it is copied from the node which it rewrites).
kono
parents:
diff changeset
675 -- If this node is used in a statement context, then we set the type
kono
parents:
diff changeset
676 -- Standard_Void_Type. This is used both by Gigi and by the front end
kono
parents:
diff changeset
677 -- to distinguish the statement use and the subexpression use.
kono
parents:
diff changeset
678
kono
parents:
diff changeset
679 -- The only other required processing is to take care of the Condition
kono
parents:
diff changeset
680 -- field if one is present.
kono
parents:
diff changeset
681
kono
parents:
diff changeset
682 procedure Analyze_Raise_xxx_Error (N : Node_Id) is
kono
parents:
diff changeset
683
kono
parents:
diff changeset
684 function Same_Expression (C1, C2 : Node_Id) return Boolean;
kono
parents:
diff changeset
685 -- It often occurs that two identical raise statements are generated in
kono
parents:
diff changeset
686 -- succession (for example when dynamic elaboration checks take place on
kono
parents:
diff changeset
687 -- separate expressions in a call). If the two statements are identical
kono
parents:
diff changeset
688 -- according to the simple criterion that follows, the raise is
kono
parents:
diff changeset
689 -- converted into a null statement.
kono
parents:
diff changeset
690
kono
parents:
diff changeset
691 ---------------------
kono
parents:
diff changeset
692 -- Same_Expression --
kono
parents:
diff changeset
693 ---------------------
kono
parents:
diff changeset
694
kono
parents:
diff changeset
695 function Same_Expression (C1, C2 : Node_Id) return Boolean is
kono
parents:
diff changeset
696 begin
kono
parents:
diff changeset
697 if No (C1) and then No (C2) then
kono
parents:
diff changeset
698 return True;
kono
parents:
diff changeset
699
kono
parents:
diff changeset
700 elsif Is_Entity_Name (C1) and then Is_Entity_Name (C2) then
kono
parents:
diff changeset
701 return Entity (C1) = Entity (C2);
kono
parents:
diff changeset
702
kono
parents:
diff changeset
703 elsif Nkind (C1) /= Nkind (C2) then
kono
parents:
diff changeset
704 return False;
kono
parents:
diff changeset
705
kono
parents:
diff changeset
706 elsif Nkind (C1) in N_Unary_Op then
kono
parents:
diff changeset
707 return Same_Expression (Right_Opnd (C1), Right_Opnd (C2));
kono
parents:
diff changeset
708
kono
parents:
diff changeset
709 elsif Nkind (C1) in N_Binary_Op then
kono
parents:
diff changeset
710 return Same_Expression (Left_Opnd (C1), Left_Opnd (C2))
kono
parents:
diff changeset
711 and then
kono
parents:
diff changeset
712 Same_Expression (Right_Opnd (C1), Right_Opnd (C2));
kono
parents:
diff changeset
713
kono
parents:
diff changeset
714 elsif Nkind (C1) = N_Null then
kono
parents:
diff changeset
715 return True;
kono
parents:
diff changeset
716
kono
parents:
diff changeset
717 else
kono
parents:
diff changeset
718 return False;
kono
parents:
diff changeset
719 end if;
kono
parents:
diff changeset
720 end Same_Expression;
kono
parents:
diff changeset
721
kono
parents:
diff changeset
722 -- Start of processing for Analyze_Raise_xxx_Error
kono
parents:
diff changeset
723
kono
parents:
diff changeset
724 begin
kono
parents:
diff changeset
725 if Nkind (Original_Node (N)) = N_Raise_Statement then
kono
parents:
diff changeset
726 Check_SPARK_05_Restriction ("raise statement is not allowed", N);
kono
parents:
diff changeset
727 end if;
kono
parents:
diff changeset
728
kono
parents:
diff changeset
729 if No (Etype (N)) then
kono
parents:
diff changeset
730 Set_Etype (N, Standard_Void_Type);
kono
parents:
diff changeset
731 end if;
kono
parents:
diff changeset
732
kono
parents:
diff changeset
733 if Present (Condition (N)) then
kono
parents:
diff changeset
734 Analyze_And_Resolve (Condition (N), Standard_Boolean);
kono
parents:
diff changeset
735 end if;
kono
parents:
diff changeset
736
kono
parents:
diff changeset
737 -- Deal with static cases in obvious manner
kono
parents:
diff changeset
738
kono
parents:
diff changeset
739 if Nkind (Condition (N)) = N_Identifier then
kono
parents:
diff changeset
740 if Entity (Condition (N)) = Standard_True then
kono
parents:
diff changeset
741 Set_Condition (N, Empty);
kono
parents:
diff changeset
742
kono
parents:
diff changeset
743 elsif Entity (Condition (N)) = Standard_False then
kono
parents:
diff changeset
744 Rewrite (N, Make_Null_Statement (Sloc (N)));
kono
parents:
diff changeset
745 end if;
kono
parents:
diff changeset
746 end if;
kono
parents:
diff changeset
747
kono
parents:
diff changeset
748 -- Remove duplicate raise statements. Note that the previous one may
kono
parents:
diff changeset
749 -- already have been removed as well.
kono
parents:
diff changeset
750
kono
parents:
diff changeset
751 if not Comes_From_Source (N)
kono
parents:
diff changeset
752 and then Nkind (N) /= N_Null_Statement
kono
parents:
diff changeset
753 and then Is_List_Member (N)
kono
parents:
diff changeset
754 and then Present (Prev (N))
kono
parents:
diff changeset
755 and then Nkind (N) = Nkind (Original_Node (Prev (N)))
kono
parents:
diff changeset
756 and then Same_Expression
kono
parents:
diff changeset
757 (Condition (N), Condition (Original_Node (Prev (N))))
kono
parents:
diff changeset
758 then
kono
parents:
diff changeset
759 Rewrite (N, Make_Null_Statement (Sloc (N)));
kono
parents:
diff changeset
760 end if;
kono
parents:
diff changeset
761 end Analyze_Raise_xxx_Error;
kono
parents:
diff changeset
762
kono
parents:
diff changeset
763 end Sem_Ch11;