]>
Commit | Line | Data |
---|---|---|
56e94186 AC |
1 | ------------------------------------------------------------------------------ |
2 | -- -- | |
3 | -- GNAT COMPILER COMPONENTS -- | |
4 | -- -- | |
06b599fd | 5 | -- L I B . X R E F . S P A R K _ S P E C I F I C -- |
56e94186 AC |
6 | -- -- |
7 | -- B o d y -- | |
8 | -- -- | |
fb8d37ef | 9 | -- Copyright (C) 2011-2016, Free Software Foundation, Inc. -- |
56e94186 AC |
10 | -- -- |
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. -- | |
20 | -- -- | |
21 | -- GNAT was originally developed by the GNAT team at New York University. -- | |
22 | -- Extensive contributions were provided by Ada Core Technologies Inc. -- | |
23 | -- -- | |
24 | ------------------------------------------------------------------------------ | |
25 | ||
63b5225b YM |
26 | with Einfo; use Einfo; |
27 | with Nmake; use Nmake; | |
9db78a42 | 28 | with SPARK_Xrefs; use SPARK_Xrefs; |
996c8821 | 29 | |
56e94186 AC |
30 | with GNAT.HTable; |
31 | ||
32 | separate (Lib.Xref) | |
06b599fd | 33 | package body SPARK_Specific is |
56e94186 AC |
34 | |
35 | --------------------- | |
36 | -- Local Constants -- | |
37 | --------------------- | |
38 | ||
06b599fd | 39 | -- Table of SPARK_Entities, True for each entity kind used in SPARK |
e917aec2 | 40 | |
06b599fd | 41 | SPARK_Entities : constant array (Entity_Kind) of Boolean := |
cdc96e3e | 42 | (E_Constant => True, |
7b52257c | 43 | E_Entry => True, |
cdc96e3e AC |
44 | E_Function => True, |
45 | E_In_Out_Parameter => True, | |
46 | E_In_Parameter => True, | |
47 | E_Loop_Parameter => True, | |
48 | E_Operator => True, | |
49 | E_Out_Parameter => True, | |
50 | E_Procedure => True, | |
51 | E_Variable => True, | |
52 | others => False); | |
56e94186 | 53 | |
06b599fd | 54 | -- True for each reference type used in SPARK |
5b0113d6 | 55 | |
06b599fd | 56 | SPARK_References : constant array (Character) of Boolean := |
56e94186 AC |
57 | ('m' => True, |
58 | 'r' => True, | |
59 | 's' => True, | |
60 | others => False); | |
61 | ||
9466892f AC |
62 | type Entity_Hashed_Range is range 0 .. 255; |
63 | -- Size of hash table headers | |
64 | ||
226a7fa4 AC |
65 | --------------------- |
66 | -- Local Variables -- | |
67 | --------------------- | |
68 | ||
cdc96e3e AC |
69 | Heap : Entity_Id := Empty; |
70 | -- A special entity which denotes the heap object | |
71 | ||
226a7fa4 AC |
72 | package Drefs is new Table.Table ( |
73 | Table_Component_Type => Xref_Entry, | |
74 | Table_Index_Type => Xref_Entry_Number, | |
75 | Table_Low_Bound => 1, | |
ce5c2061 YM |
76 | Table_Initial => Alloc.Drefs_Initial, |
77 | Table_Increment => Alloc.Drefs_Increment, | |
226a7fa4 AC |
78 | Table_Name => "Drefs"); |
79 | -- Table of cross-references for reads and writes through explicit | |
80 | -- dereferences, that are output as reads/writes to the special variable | |
c01817d2 | 81 | -- "Heap". These references are added to the regular references when |
06b599fd | 82 | -- computing SPARK cross-references. |
226a7fa4 | 83 | |
56e94186 AC |
84 | ----------------------- |
85 | -- Local Subprograms -- | |
86 | ----------------------- | |
87 | ||
06b599fd YM |
88 | procedure Add_SPARK_File (Ubody, Uspec : Unit_Number_Type; Dspec : Nat); |
89 | -- Add file and corresponding scopes for unit to the tables | |
90 | -- SPARK_File_Table and SPARK_Scope_Table. When two units are present for | |
91 | -- the same compilation unit, as it happens for library-level | |
92 | -- instantiations of generics, then Ubody /= Uspec, and all scopes are | |
93 | -- added to the same SPARK file. Otherwise Ubody = Uspec. | |
56e94186 | 94 | |
06b599fd YM |
95 | procedure Add_SPARK_Scope (N : Node_Id); |
96 | -- Add scope N to the table SPARK_Scope_Table | |
56e94186 | 97 | |
06b599fd YM |
98 | procedure Add_SPARK_Xrefs; |
99 | -- Filter table Xrefs to add all references used in SPARK to the table | |
100 | -- SPARK_Xref_Table. | |
56e94186 | 101 | |
06b599fd YM |
102 | procedure Detect_And_Add_SPARK_Scope (N : Node_Id); |
103 | -- Call Add_SPARK_Scope on scopes | |
2c1b72d7 | 104 | |
9466892f AC |
105 | function Entity_Hash (E : Entity_Id) return Entity_Hashed_Range; |
106 | -- Hash function for hash table | |
107 | ||
ca7e6c26 AC |
108 | procedure Traverse_Declaration_Or_Statement |
109 | (N : Node_Id; | |
110 | Process : Node_Processing; | |
111 | Inside_Stubs : Boolean); | |
2c1b72d7 | 112 | procedure Traverse_Declarations_Or_Statements |
60370fb1 AC |
113 | (L : List_Id; |
114 | Process : Node_Processing; | |
115 | Inside_Stubs : Boolean); | |
2c1b72d7 | 116 | procedure Traverse_Handled_Statement_Sequence |
60370fb1 AC |
117 | (N : Node_Id; |
118 | Process : Node_Processing; | |
119 | Inside_Stubs : Boolean); | |
265ca04a AC |
120 | procedure Traverse_Protected_Body |
121 | (N : Node_Id; | |
122 | Process : Node_Processing; | |
123 | Inside_Stubs : Boolean); | |
2c1b72d7 | 124 | procedure Traverse_Package_Body |
60370fb1 AC |
125 | (N : Node_Id; |
126 | Process : Node_Processing; | |
127 | Inside_Stubs : Boolean); | |
2c1b72d7 | 128 | procedure Traverse_Subprogram_Body |
60370fb1 AC |
129 | (N : Node_Id; |
130 | Process : Node_Processing; | |
131 | Inside_Stubs : Boolean); | |
5b0113d6 | 132 | -- Traverse corresponding construct, calling Process on all declarations |
56e94186 | 133 | |
06b599fd YM |
134 | -------------------- |
135 | -- Add_SPARK_File -- | |
136 | -------------------- | |
56e94186 | 137 | |
06b599fd | 138 | procedure Add_SPARK_File (Ubody, Uspec : Unit_Number_Type; Dspec : Nat) is |
4b985e20 | 139 | File : constant Source_File_Index := Source_Index (Uspec); |
56e94186 AC |
140 | From : Scope_Index; |
141 | ||
a4956515 AC |
142 | File_Name : String_Ptr; |
143 | Unit_File_Name : String_Ptr; | |
1f163ef7 | 144 | |
56e94186 AC |
145 | begin |
146 | -- Source file could be inexistant as a result of an error, if option | |
147 | -- gnatQ is used. | |
148 | ||
cdc96e3e | 149 | if File = No_Source_File then |
56e94186 AC |
150 | return; |
151 | end if; | |
152 | ||
a5150cb1 AC |
153 | -- Subunits are traversed as part of the top-level unit to which they |
154 | -- belong. | |
155 | ||
444656ce | 156 | if Nkind (Unit (Cunit (Ubody))) = N_Subunit then |
a5150cb1 AC |
157 | return; |
158 | end if; | |
159 | ||
06b599fd | 160 | From := SPARK_Scope_Table.Last + 1; |
56e94186 | 161 | |
444656ce ES |
162 | Traverse_Compilation_Unit |
163 | (CU => Cunit (Ubody), | |
164 | Process => Detect_And_Add_SPARK_Scope'Access, | |
165 | Inside_Stubs => True); | |
56e94186 | 166 | |
4b985e20 AC |
167 | -- When two units are present for the same compilation unit, as it |
168 | -- happens for library-level instantiations of generics, then add all | |
06b599fd | 169 | -- scopes to the same SPARK file. |
4b985e20 AC |
170 | |
171 | if Ubody /= Uspec then | |
444656ce ES |
172 | Traverse_Compilation_Unit |
173 | (CU => Cunit (Uspec), | |
174 | Process => Detect_And_Add_SPARK_Scope'Access, | |
175 | Inside_Stubs => True); | |
4b985e20 AC |
176 | end if; |
177 | ||
56e94186 AC |
178 | -- Update scope numbers |
179 | ||
b5ea9143 | 180 | declare |
fb8d37ef | 181 | Scope_Id : Pos; |
b5ea9143 | 182 | begin |
cdc96e3e | 183 | Scope_Id := 1; |
06b599fd | 184 | for Index in From .. SPARK_Scope_Table.Last loop |
b5ea9143 | 185 | declare |
06b599fd | 186 | S : SPARK_Scope_Record renames SPARK_Scope_Table.Table (Index); |
b5ea9143 | 187 | begin |
cdc96e3e | 188 | S.Scope_Num := Scope_Id; |
4b985e20 | 189 | S.File_Num := Dspec; |
cdc96e3e | 190 | Scope_Id := Scope_Id + 1; |
b5ea9143 AC |
191 | end; |
192 | end loop; | |
193 | end; | |
194 | ||
56e94186 AC |
195 | -- Make entry for new file in file table |
196 | ||
cdc96e3e | 197 | Get_Name_String (Reference_Name (File)); |
1f163ef7 AC |
198 | File_Name := new String'(Name_Buffer (1 .. Name_Len)); |
199 | ||
2fa3b955 | 200 | -- For subunits, also retrieve the file name of the unit. Only do so if |
4b985e20 | 201 | -- unit has an associated compilation unit. |
1f163ef7 | 202 | |
444656ce | 203 | if Present (Cunit (Unit (File))) |
cdc96e3e | 204 | and then Nkind (Unit (Cunit (Unit (File)))) = N_Subunit |
1f163ef7 AC |
205 | then |
206 | Get_Name_String (Reference_Name (Main_Source_File)); | |
207 | Unit_File_Name := new String'(Name_Buffer (1 .. Name_Len)); | |
3bb91f98 AC |
208 | else |
209 | Unit_File_Name := null; | |
1f163ef7 | 210 | end if; |
56e94186 | 211 | |
06b599fd | 212 | SPARK_File_Table.Append ( |
1f163ef7 AC |
213 | (File_Name => File_Name, |
214 | Unit_File_Name => Unit_File_Name, | |
4b985e20 | 215 | File_Num => Dspec, |
1f163ef7 | 216 | From_Scope => From, |
06b599fd YM |
217 | To_Scope => SPARK_Scope_Table.Last)); |
218 | end Add_SPARK_File; | |
56e94186 | 219 | |
06b599fd YM |
220 | --------------------- |
221 | -- Add_SPARK_Scope -- | |
222 | --------------------- | |
56e94186 | 223 | |
06b599fd | 224 | procedure Add_SPARK_Scope (N : Node_Id) is |
56e94186 AC |
225 | E : constant Entity_Id := Defining_Entity (N); |
226 | Loc : constant Source_Ptr := Sloc (E); | |
ca7e6c26 AC |
227 | |
228 | -- The character describing the kind of scope is chosen to be the same | |
229 | -- as the one describing the corresponding entity in cross references, | |
230 | -- see Xref_Entity_Letters in lib-xrefs.ads | |
231 | ||
56e94186 AC |
232 | Typ : Character; |
233 | ||
234 | begin | |
235 | -- Ignore scopes without a proper location | |
236 | ||
237 | if Sloc (N) = No_Location then | |
238 | return; | |
239 | end if; | |
240 | ||
241 | case Ekind (E) is | |
ca7e6c26 | 242 | when E_Entry |
8e2d104b | 243 | | E_Entry_Family |
ca7e6c26 AC |
244 | | E_Generic_Function |
245 | | E_Generic_Package | |
246 | | E_Generic_Procedure | |
247 | | E_Package | |
4871a41d | 248 | | E_Protected_Type |
eff69022 | 249 | | E_Task_Type |
ca7e6c26 AC |
250 | => |
251 | Typ := Xref_Entity_Letters (Ekind (E)); | |
252 | ||
b269f477 BD |
253 | when E_Function |
254 | | E_Procedure | |
255 | => | |
4afcf3a5 | 256 | -- In SPARK we need to distinguish protected functions and |
b269f477 BD |
257 | -- procedures from ordinary subprograms, but there are no special |
258 | -- Xref letters for them. Since this distiction is only needed | |
4afcf3a5 | 259 | -- to detect protected calls, we pretend that such calls are entry |
b269f477 BD |
260 | -- calls. |
261 | ||
262 | if Ekind (Scope (E)) = E_Protected_Type then | |
263 | Typ := Xref_Entity_Letters (E_Entry); | |
264 | else | |
265 | Typ := Xref_Entity_Letters (Ekind (E)); | |
266 | end if; | |
267 | ||
4871a41d AC |
268 | when E_Package_Body |
269 | | E_Protected_Body | |
270 | | E_Subprogram_Body | |
271 | | E_Task_Body | |
272 | => | |
ca7e6c26 | 273 | Typ := Xref_Entity_Letters (Ekind (Unique_Entity (E))); |
56e94186 AC |
274 | |
275 | when E_Void => | |
56e94186 | 276 | |
ca7e6c26 AC |
277 | -- Compilation of prj-attr.adb with -gnatn creates a node with |
278 | -- entity E_Void for the package defined at a-charac.ads16:13. | |
56e94186 AC |
279 | -- ??? TBD |
280 | ||
281 | return; | |
282 | ||
283 | when others => | |
284 | raise Program_Error; | |
285 | end case; | |
286 | ||
287 | -- File_Num and Scope_Num are filled later. From_Xref and To_Xref are | |
288 | -- filled even later, but are initialized to represent an empty range. | |
289 | ||
06b599fd | 290 | SPARK_Scope_Table.Append ( |
5207696c | 291 | (Scope_Name => new String'(Unique_Name (E)), |
9466892f AC |
292 | File_Num => 0, |
293 | Scope_Num => 0, | |
294 | Spec_File_Num => 0, | |
295 | Spec_Scope_Num => 0, | |
296 | Line => Nat (Get_Logical_Line_Number (Loc)), | |
297 | Stype => Typ, | |
298 | Col => Nat (Get_Column_Number (Loc)), | |
299 | From_Xref => 1, | |
300 | To_Xref => 0, | |
301 | Scope_Entity => E)); | |
06b599fd | 302 | end Add_SPARK_Scope; |
56e94186 | 303 | |
06b599fd YM |
304 | --------------------- |
305 | -- Add_SPARK_Xrefs -- | |
306 | --------------------- | |
56e94186 | 307 | |
06b599fd | 308 | procedure Add_SPARK_Xrefs is |
cdc96e3e AC |
309 | function Entity_Of_Scope (S : Scope_Index) return Entity_Id; |
310 | -- Return the entity which maps to the input scope index | |
311 | ||
312 | function Get_Entity_Type (E : Entity_Id) return Character; | |
313 | -- Return a character representing the type of entity | |
314 | ||
24fd21c3 AC |
315 | function Is_Constant_Object_Without_Variable_Input |
316 | (E : Entity_Id) return Boolean; | |
317 | -- Return True if E is known to have no variable input, as defined in | |
318 | -- SPARK RM. | |
319 | ||
320 | function Is_Future_Scope_Entity | |
321 | (E : Entity_Id; | |
322 | S : Scope_Index) return Boolean; | |
323 | -- Check whether entity E is in SPARK_Scope_Table at index S or higher | |
324 | ||
06b599fd | 325 | function Is_SPARK_Reference |
cdc96e3e AC |
326 | (E : Entity_Id; |
327 | Typ : Character) return Boolean; | |
06b599fd YM |
328 | -- Return whether entity reference E meets SPARK requirements. Typ is |
329 | -- the reference type. | |
cdc96e3e | 330 | |
06b599fd | 331 | function Is_SPARK_Scope (E : Entity_Id) return Boolean; |
cdc96e3e | 332 | -- Return whether the entity or reference scope meets requirements for |
8e2d104b | 333 | -- being a SPARK scope. |
cdc96e3e | 334 | |
cdc96e3e AC |
335 | function Lt (Op1 : Natural; Op2 : Natural) return Boolean; |
336 | -- Comparison function for Sort call | |
337 | ||
338 | procedure Move (From : Natural; To : Natural); | |
339 | -- Move procedure for Sort call | |
340 | ||
341 | procedure Update_Scope_Range | |
342 | (S : Scope_Index; | |
343 | From : Xref_Index; | |
344 | To : Xref_Index); | |
345 | -- Update the scope which maps to S with the new range From .. To | |
346 | ||
347 | package Sorting is new GNAT.Heap_Sort_G (Move, Lt); | |
56e94186 | 348 | |
e0adfeb4 AC |
349 | function Get_Scope_Num (N : Entity_Id) return Nat; |
350 | -- Return the scope number associated to entity N | |
351 | ||
352 | procedure Set_Scope_Num (N : Entity_Id; Num : Nat); | |
353 | -- Associate entity N to scope number Num | |
354 | ||
355 | No_Scope : constant Nat := 0; | |
356 | -- Initial scope counter | |
357 | ||
358 | type Scope_Rec is record | |
359 | Num : Nat; | |
360 | Entity : Entity_Id; | |
361 | end record; | |
362 | -- Type used to relate an entity and a scope number | |
363 | ||
364 | package Scopes is new GNAT.HTable.Simple_HTable | |
365 | (Header_Num => Entity_Hashed_Range, | |
366 | Element => Scope_Rec, | |
367 | No_Element => (Num => No_Scope, Entity => Empty), | |
368 | Key => Entity_Id, | |
369 | Hash => Entity_Hash, | |
370 | Equal => "="); | |
eff69022 | 371 | -- Package used to build a correspondence between entities and scope |
06b599fd | 372 | -- numbers used in SPARK cross references. |
5b0113d6 | 373 | |
56e94186 AC |
374 | Nrefs : Nat := Xrefs.Last; |
375 | -- Number of references in table. This value may get reset (reduced) | |
376 | -- when we eliminate duplicate reference entries as well as references | |
377 | -- not suitable for local cross-references. | |
378 | ||
226a7fa4 | 379 | Nrefs_Add : constant Nat := Drefs.Last; |
ce5c2061 YM |
380 | -- Number of additional references which correspond to dereferences in |
381 | -- the source code. | |
226a7fa4 AC |
382 | |
383 | Rnums : array (0 .. Nrefs + Nrefs_Add) of Nat; | |
56e94186 AC |
384 | -- This array contains numbers of references in the Xrefs table. This |
385 | -- list is sorted in output order. The extra 0'th entry is convenient | |
386 | -- for the call to sort. When we sort the table, we move the entries in | |
387 | -- Rnums around, but we do not move the original table entries. | |
388 | ||
cdc96e3e AC |
389 | --------------------- |
390 | -- Entity_Of_Scope -- | |
391 | --------------------- | |
56e94186 | 392 | |
cdc96e3e AC |
393 | function Entity_Of_Scope (S : Scope_Index) return Entity_Id is |
394 | begin | |
06b599fd | 395 | return SPARK_Scope_Table.Table (S).Scope_Entity; |
cdc96e3e | 396 | end Entity_Of_Scope; |
56e94186 | 397 | |
cdc96e3e AC |
398 | --------------------- |
399 | -- Get_Entity_Type -- | |
400 | --------------------- | |
401 | ||
402 | function Get_Entity_Type (E : Entity_Id) return Character is | |
cdc96e3e AC |
403 | begin |
404 | case Ekind (E) is | |
5b0113d6 RD |
405 | when E_Out_Parameter => return '<'; |
406 | when E_In_Out_Parameter => return '='; | |
407 | when E_In_Parameter => return '>'; | |
408 | when others => return '*'; | |
cdc96e3e | 409 | end case; |
cdc96e3e AC |
410 | end Get_Entity_Type; |
411 | ||
e0adfeb4 AC |
412 | ------------------- |
413 | -- Get_Scope_Num -- | |
414 | ------------------- | |
415 | ||
416 | function Get_Scope_Num (N : Entity_Id) return Nat is | |
417 | begin | |
418 | return Scopes.Get (N).Num; | |
419 | end Get_Scope_Num; | |
420 | ||
24fd21c3 AC |
421 | ----------------------------------------------- |
422 | -- Is_Constant_Object_Without_Variable_Input -- | |
423 | ----------------------------------------------- | |
cdc96e3e | 424 | |
24fd21c3 AC |
425 | function Is_Constant_Object_Without_Variable_Input |
426 | (E : Entity_Id) return Boolean | |
cdc96e3e | 427 | is |
24fd21c3 AC |
428 | Result : Boolean; |
429 | ||
cdc96e3e | 430 | begin |
24fd21c3 | 431 | case Ekind (E) is |
cdc96e3e | 432 | |
24fd21c3 AC |
433 | -- A constant is known to have no variable input if its |
434 | -- initializing expression is static (a value which is | |
435 | -- compile-time-known is not guaranteed to have no variable input | |
436 | -- as defined in the SPARK RM). Otherwise, the constant may or not | |
437 | -- have variable input. | |
cdc96e3e | 438 | |
24fd21c3 AC |
439 | when E_Constant => |
440 | declare | |
441 | Decl : Node_Id; | |
442 | begin | |
443 | if Present (Full_View (E)) then | |
444 | Decl := Parent (Full_View (E)); | |
445 | else | |
446 | Decl := Parent (E); | |
447 | end if; | |
cdc96e3e | 448 | |
aff557c7 AC |
449 | if Is_Imported (E) then |
450 | Result := False; | |
451 | else | |
452 | pragma Assert (Present (Expression (Decl))); | |
453 | Result := Is_Static_Expression (Expression (Decl)); | |
454 | end if; | |
24fd21c3 | 455 | end; |
cdc96e3e | 456 | |
24fd21c3 AC |
457 | when E_Loop_Parameter | E_In_Parameter => |
458 | Result := True; | |
cdc96e3e | 459 | |
24fd21c3 AC |
460 | when others => |
461 | Result := False; | |
462 | end case; | |
cdc96e3e | 463 | |
24fd21c3 AC |
464 | return Result; |
465 | end Is_Constant_Object_Without_Variable_Input; | |
cdc96e3e AC |
466 | |
467 | ---------------------------- | |
468 | -- Is_Future_Scope_Entity -- | |
469 | ---------------------------- | |
470 | ||
471 | function Is_Future_Scope_Entity | |
472 | (E : Entity_Id; | |
473 | S : Scope_Index) return Boolean | |
474 | is | |
475 | function Is_Past_Scope_Entity return Boolean; | |
06b599fd | 476 | -- Check whether entity E is in SPARK_Scope_Table at index strictly |
cdc96e3e AC |
477 | -- lower than S. |
478 | ||
479 | -------------------------- | |
480 | -- Is_Past_Scope_Entity -- | |
481 | -------------------------- | |
482 | ||
483 | function Is_Past_Scope_Entity return Boolean is | |
484 | begin | |
06b599fd YM |
485 | for Index in SPARK_Scope_Table.First .. S - 1 loop |
486 | if SPARK_Scope_Table.Table (Index).Scope_Entity = E then | |
363f2c58 | 487 | return True; |
cdc96e3e AC |
488 | end if; |
489 | end loop; | |
490 | ||
491 | return False; | |
492 | end Is_Past_Scope_Entity; | |
493 | ||
494 | -- Start of processing for Is_Future_Scope_Entity | |
495 | ||
496 | begin | |
06b599fd YM |
497 | for Index in S .. SPARK_Scope_Table.Last loop |
498 | if SPARK_Scope_Table.Table (Index).Scope_Entity = E then | |
cdc96e3e AC |
499 | return True; |
500 | end if; | |
501 | end loop; | |
502 | ||
503 | -- If this assertion fails, this means that the scope which we are | |
504 | -- looking for has been treated already, which reveals a problem in | |
505 | -- the order of cross-references. | |
506 | ||
507 | pragma Assert (not Is_Past_Scope_Entity); | |
508 | ||
509 | return False; | |
510 | end Is_Future_Scope_Entity; | |
511 | ||
24fd21c3 AC |
512 | ------------------------ |
513 | -- Is_SPARK_Reference -- | |
514 | ------------------------ | |
515 | ||
516 | function Is_SPARK_Reference | |
517 | (E : Entity_Id; | |
518 | Typ : Character) return Boolean | |
519 | is | |
520 | begin | |
521 | -- The only references of interest on callable entities are calls. On | |
363f2c58 AC |
522 | -- uncallable entities, the only references of interest are reads and |
523 | -- writes. | |
24fd21c3 AC |
524 | |
525 | if Ekind (E) in Overloadable_Kind then | |
526 | return Typ = 's'; | |
527 | ||
363f2c58 | 528 | -- Objects of task or protected types are not SPARK references |
24fd21c3 AC |
529 | |
530 | elsif Present (Etype (E)) | |
531 | and then Ekind (Etype (E)) in Concurrent_Kind | |
532 | then | |
533 | return False; | |
534 | ||
535 | -- In all other cases, result is true for reference/modify cases, | |
536 | -- and false for all other cases. | |
537 | ||
538 | else | |
539 | return Typ = 'r' or else Typ = 'm'; | |
540 | end if; | |
541 | end Is_SPARK_Reference; | |
542 | ||
543 | -------------------- | |
544 | -- Is_SPARK_Scope -- | |
545 | -------------------- | |
546 | ||
547 | function Is_SPARK_Scope (E : Entity_Id) return Boolean is | |
548 | begin | |
549 | return Present (E) | |
550 | and then not Is_Generic_Unit (E) | |
551 | and then Renamed_Entity (E) = Empty | |
552 | and then Get_Scope_Num (E) /= No_Scope; | |
553 | end Is_SPARK_Scope; | |
554 | ||
56e94186 AC |
555 | -------- |
556 | -- Lt -- | |
557 | -------- | |
558 | ||
559 | function Lt (Op1, Op2 : Natural) return Boolean is | |
560 | T1 : constant Xref_Entry := Xrefs.Table (Rnums (Nat (Op1))); | |
561 | T2 : constant Xref_Entry := Xrefs.Table (Rnums (Nat (Op2))); | |
562 | ||
563 | begin | |
e917aec2 | 564 | -- First test: if entity is in different unit, sort by unit. Note: |
56e94186 | 565 | -- that we use Ent_Scope_File rather than Eun, as Eun may refer to |
e917aec2 RD |
566 | -- the file where the generic scope is defined, which may differ from |
567 | -- the file where the enclosing scope is defined. It is the latter | |
568 | -- which matters for a correct order here. | |
56e94186 AC |
569 | |
570 | if T1.Ent_Scope_File /= T2.Ent_Scope_File then | |
571 | return Dependency_Num (T1.Ent_Scope_File) < | |
5b0113d6 | 572 | Dependency_Num (T2.Ent_Scope_File); |
56e94186 AC |
573 | |
574 | -- Second test: within same unit, sort by location of the scope of | |
575 | -- the entity definition. | |
576 | ||
f7bb41af | 577 | elsif Get_Scope_Num (T1.Key.Ent_Scope) /= |
2c17ca0a | 578 | Get_Scope_Num (T2.Key.Ent_Scope) |
56e94186 | 579 | then |
f7bb41af | 580 | return Get_Scope_Num (T1.Key.Ent_Scope) < |
5b0113d6 | 581 | Get_Scope_Num (T2.Key.Ent_Scope); |
56e94186 AC |
582 | |
583 | -- Third test: within same unit and scope, sort by location of | |
584 | -- entity definition. | |
585 | ||
586 | elsif T1.Def /= T2.Def then | |
587 | return T1.Def < T2.Def; | |
588 | ||
e228f7ee AC |
589 | else |
590 | -- Both entities must be equal at this point | |
4b985e20 | 591 | |
e228f7ee | 592 | pragma Assert (T1.Key.Ent = T2.Key.Ent); |
a5150cb1 AC |
593 | pragma Assert (T1.Key.Ent_Scope = T2.Key.Ent_Scope); |
594 | pragma Assert (T1.Ent_Scope_File = T2.Ent_Scope_File); | |
4b985e20 | 595 | |
e228f7ee AC |
596 | -- Fourth test: if reference is in same unit as entity definition, |
597 | -- sort first. | |
56e94186 | 598 | |
e228f7ee AC |
599 | if T1.Key.Lun /= T2.Key.Lun |
600 | and then T1.Ent_Scope_File = T1.Key.Lun | |
601 | then | |
602 | return True; | |
f7bb41af | 603 | |
e228f7ee AC |
604 | elsif T1.Key.Lun /= T2.Key.Lun |
605 | and then T2.Ent_Scope_File = T2.Key.Lun | |
606 | then | |
607 | return False; | |
56e94186 | 608 | |
e228f7ee AC |
609 | -- Fifth test: if reference is in same unit and same scope as |
610 | -- entity definition, sort first. | |
56e94186 | 611 | |
e228f7ee AC |
612 | elsif T1.Ent_Scope_File = T1.Key.Lun |
613 | and then T1.Key.Ref_Scope /= T2.Key.Ref_Scope | |
614 | and then T1.Key.Ent_Scope = T1.Key.Ref_Scope | |
615 | then | |
616 | return True; | |
cdc96e3e | 617 | |
e228f7ee AC |
618 | elsif T2.Ent_Scope_File = T2.Key.Lun |
619 | and then T1.Key.Ref_Scope /= T2.Key.Ref_Scope | |
620 | and then T2.Key.Ent_Scope = T2.Key.Ref_Scope | |
621 | then | |
622 | return False; | |
56e94186 | 623 | |
e228f7ee | 624 | -- Sixth test: for same entity, sort by reference location unit |
56e94186 | 625 | |
e228f7ee AC |
626 | elsif T1.Key.Lun /= T2.Key.Lun then |
627 | return Dependency_Num (T1.Key.Lun) < | |
628 | Dependency_Num (T2.Key.Lun); | |
56e94186 | 629 | |
e228f7ee | 630 | -- Seventh test: for same entity, sort by reference location scope |
56e94186 | 631 | |
e228f7ee AC |
632 | elsif Get_Scope_Num (T1.Key.Ref_Scope) /= |
633 | Get_Scope_Num (T2.Key.Ref_Scope) | |
634 | then | |
635 | return Get_Scope_Num (T1.Key.Ref_Scope) < | |
636 | Get_Scope_Num (T2.Key.Ref_Scope); | |
56e94186 | 637 | |
e228f7ee | 638 | -- Eighth test: order of location within referencing unit |
56e94186 | 639 | |
e228f7ee AC |
640 | elsif T1.Key.Loc /= T2.Key.Loc then |
641 | return T1.Key.Loc < T2.Key.Loc; | |
56e94186 | 642 | |
e228f7ee AC |
643 | -- Finally, for two locations at the same address prefer the one |
644 | -- that does NOT have the type 'r', so that a modification or | |
645 | -- extension takes preference, when there are more than one | |
646 | -- reference at the same location. As a result, in the case of | |
647 | -- entities that are in-out actuals, the read reference follows | |
648 | -- the modify reference. | |
56e94186 | 649 | |
e228f7ee AC |
650 | else |
651 | return T2.Key.Typ = 'r'; | |
652 | end if; | |
56e94186 AC |
653 | end if; |
654 | end Lt; | |
655 | ||
656 | ---------- | |
657 | -- Move -- | |
658 | ---------- | |
659 | ||
660 | procedure Move (From : Natural; To : Natural) is | |
661 | begin | |
662 | Rnums (Nat (To)) := Rnums (Nat (From)); | |
663 | end Move; | |
664 | ||
e0adfeb4 AC |
665 | ------------------- |
666 | -- Set_Scope_Num -- | |
667 | ------------------- | |
668 | ||
669 | procedure Set_Scope_Num (N : Entity_Id; Num : Nat) is | |
670 | begin | |
671 | Scopes.Set (K => N, E => Scope_Rec'(Num => Num, Entity => N)); | |
672 | end Set_Scope_Num; | |
673 | ||
cdc96e3e AC |
674 | ------------------------ |
675 | -- Update_Scope_Range -- | |
676 | ------------------------ | |
677 | ||
678 | procedure Update_Scope_Range | |
679 | (S : Scope_Index; | |
680 | From : Xref_Index; | |
681 | To : Xref_Index) | |
682 | is | |
683 | begin | |
06b599fd YM |
684 | SPARK_Scope_Table.Table (S).From_Xref := From; |
685 | SPARK_Scope_Table.Table (S).To_Xref := To; | |
cdc96e3e AC |
686 | end Update_Scope_Range; |
687 | ||
688 | -- Local variables | |
689 | ||
690 | Col : Nat; | |
691 | From_Index : Xref_Index; | |
692 | Line : Nat; | |
693 | Loc : Source_Ptr; | |
694 | Prev_Typ : Character; | |
695 | Ref_Count : Nat; | |
696 | Ref_Id : Entity_Id; | |
697 | Ref_Name : String_Ptr; | |
698 | Scope_Id : Scope_Index; | |
226a7fa4 | 699 | |
06b599fd | 700 | -- Start of processing for Add_SPARK_Xrefs |
56e94186 | 701 | |
996c8821 | 702 | begin |
06b599fd | 703 | for Index in SPARK_Scope_Table.First .. SPARK_Scope_Table.Last loop |
cdc96e3e | 704 | declare |
06b599fd | 705 | S : SPARK_Scope_Record renames SPARK_Scope_Table.Table (Index); |
cdc96e3e AC |
706 | begin |
707 | Set_Scope_Num (S.Scope_Entity, S.Scope_Num); | |
708 | end; | |
56e94186 AC |
709 | end loop; |
710 | ||
711 | -- Set up the pointer vector for the sort | |
712 | ||
cdc96e3e AC |
713 | for Index in 1 .. Nrefs loop |
714 | Rnums (Index) := Index; | |
56e94186 AC |
715 | end loop; |
716 | ||
cdc96e3e AC |
717 | for Index in Drefs.First .. Drefs.Last loop |
718 | Xrefs.Append (Drefs.Table (Index)); | |
226a7fa4 AC |
719 | |
720 | Nrefs := Nrefs + 1; | |
721 | Rnums (Nrefs) := Xrefs.Last; | |
722 | end loop; | |
723 | ||
4b985e20 AC |
724 | -- Capture the definition Sloc values. As in the case of normal cross |
725 | -- references, we have to wait until now to get the correct value. | |
726 | ||
727 | for Index in 1 .. Nrefs loop | |
728 | Xrefs.Table (Index).Def := Sloc (Xrefs.Table (Index).Key.Ent); | |
729 | end loop; | |
730 | ||
06b599fd | 731 | -- Eliminate entries not appropriate for SPARK. Done prior to sorting |
e917aec2 RD |
732 | -- cross-references, as it discards useless references which do not have |
733 | -- a proper format for the comparison function (like no location). | |
56e94186 | 734 | |
cdc96e3e AC |
735 | Ref_Count := Nrefs; |
736 | Nrefs := 0; | |
d2b4b3da | 737 | |
cdc96e3e AC |
738 | for Index in 1 .. Ref_Count loop |
739 | declare | |
740 | Ref : Xref_Key renames Xrefs.Table (Rnums (Index)).Key; | |
56e94186 | 741 | |
1f9939b5 | 742 | begin |
06b599fd YM |
743 | if SPARK_Entities (Ekind (Ref.Ent)) |
744 | and then SPARK_References (Ref.Typ) | |
745 | and then Is_SPARK_Scope (Ref.Ent_Scope) | |
746 | and then Is_SPARK_Scope (Ref.Ref_Scope) | |
06b599fd | 747 | and then Is_SPARK_Reference (Ref.Ent, Ref.Typ) |
cdc96e3e | 748 | |
5b0113d6 | 749 | -- Discard references from unknown scopes, e.g. generic scopes |
cdc96e3e AC |
750 | |
751 | and then Get_Scope_Num (Ref.Ent_Scope) /= No_Scope | |
752 | and then Get_Scope_Num (Ref.Ref_Scope) /= No_Scope | |
56e94186 AC |
753 | then |
754 | Nrefs := Nrefs + 1; | |
cdc96e3e | 755 | Rnums (Nrefs) := Rnums (Index); |
56e94186 | 756 | end if; |
cdc96e3e AC |
757 | end; |
758 | end loop; | |
56e94186 AC |
759 | |
760 | -- Sort the references | |
761 | ||
762 | Sorting.Sort (Integer (Nrefs)); | |
763 | ||
cdc96e3e | 764 | -- Eliminate duplicate entries |
56e94186 | 765 | |
cdc96e3e AC |
766 | -- We need this test for Ref_Count because if we force ALI file |
767 | -- generation in case of errors detected, it may be the case that | |
768 | -- Nrefs is 0, so we should not reset it here. | |
56e94186 | 769 | |
cdc96e3e AC |
770 | if Nrefs >= 2 then |
771 | Ref_Count := Nrefs; | |
772 | Nrefs := 1; | |
56e94186 | 773 | |
cdc96e3e AC |
774 | for Index in 2 .. Ref_Count loop |
775 | if Xrefs.Table (Rnums (Index)) /= | |
776 | Xrefs.Table (Rnums (Nrefs)) | |
777 | then | |
778 | Nrefs := Nrefs + 1; | |
779 | Rnums (Nrefs) := Rnums (Index); | |
780 | end if; | |
781 | end loop; | |
782 | end if; | |
56e94186 | 783 | |
cdc96e3e AC |
784 | -- Eliminate the reference if it is at the same location as the previous |
785 | -- one, unless it is a read-reference indicating that the entity is an | |
786 | -- in-out actual in a call. | |
56e94186 | 787 | |
cdc96e3e AC |
788 | Ref_Count := Nrefs; |
789 | Nrefs := 0; | |
790 | Loc := No_Location; | |
791 | Prev_Typ := 'm'; | |
56e94186 | 792 | |
cdc96e3e AC |
793 | for Index in 1 .. Ref_Count loop |
794 | declare | |
795 | Ref : Xref_Key renames Xrefs.Table (Rnums (Index)).Key; | |
56e94186 | 796 | |
cdc96e3e AC |
797 | begin |
798 | if Ref.Loc /= Loc | |
5b0113d6 | 799 | or else (Prev_Typ = 'm' and then Ref.Typ = 'r') |
56e94186 | 800 | then |
cdc96e3e AC |
801 | Loc := Ref.Loc; |
802 | Prev_Typ := Ref.Typ; | |
56e94186 | 803 | Nrefs := Nrefs + 1; |
cdc96e3e | 804 | Rnums (Nrefs) := Rnums (Index); |
56e94186 | 805 | end if; |
cdc96e3e AC |
806 | end; |
807 | end loop; | |
56e94186 | 808 | |
cdc96e3e | 809 | -- The two steps have eliminated all references, nothing to do |
56e94186 | 810 | |
06b599fd | 811 | if SPARK_Scope_Table.Last = 0 then |
483361a6 | 812 | return; |
56e94186 AC |
813 | end if; |
814 | ||
cdc96e3e AC |
815 | Ref_Id := Empty; |
816 | Scope_Id := 1; | |
817 | From_Index := 1; | |
818 | ||
56e94186 AC |
819 | -- Loop to output references |
820 | ||
821 | for Refno in 1 .. Nrefs loop | |
cdc96e3e AC |
822 | declare |
823 | Ref_Entry : Xref_Entry renames Xrefs.Table (Rnums (Refno)); | |
824 | Ref : Xref_Key renames Ref_Entry.Key; | |
8fdafe44 | 825 | Typ : Character; |
56e94186 AC |
826 | |
827 | begin | |
e917aec2 | 828 | -- If this assertion fails, the scope which we are looking for is |
06b599fd | 829 | -- not in SPARK scope table, which reveals either a problem in the |
e917aec2 RD |
830 | -- construction of the scope table, or an erroneous scope for the |
831 | -- current cross-reference. | |
56e94186 | 832 | |
5b0113d6 | 833 | pragma Assert (Is_Future_Scope_Entity (Ref.Ent_Scope, Scope_Id)); |
56e94186 | 834 | |
483361a6 AC |
835 | -- Update the range of cross references to which the current scope |
836 | -- refers to. This may be the empty range only for the first scope | |
837 | -- considered. | |
838 | ||
cdc96e3e AC |
839 | if Ref.Ent_Scope /= Entity_Of_Scope (Scope_Id) then |
840 | Update_Scope_Range | |
841 | (S => Scope_Id, | |
842 | From => From_Index, | |
06b599fd | 843 | To => SPARK_Xref_Table.Last); |
cdc96e3e | 844 | |
06b599fd | 845 | From_Index := SPARK_Xref_Table.Last + 1; |
56e94186 AC |
846 | end if; |
847 | ||
cdc96e3e AC |
848 | while Ref.Ent_Scope /= Entity_Of_Scope (Scope_Id) loop |
849 | Scope_Id := Scope_Id + 1; | |
06b599fd | 850 | pragma Assert (Scope_Id <= SPARK_Scope_Table.Last); |
56e94186 AC |
851 | end loop; |
852 | ||
cdc96e3e AC |
853 | if Ref.Ent /= Ref_Id then |
854 | Ref_Name := new String'(Unique_Name (Ref.Ent)); | |
56e94186 AC |
855 | end if; |
856 | ||
cdc96e3e AC |
857 | if Ref.Ent = Heap then |
858 | Line := 0; | |
859 | Col := 0; | |
226a7fa4 | 860 | else |
e90e9503 AC |
861 | Line := Nat (Get_Logical_Line_Number (Ref_Entry.Def)); |
862 | Col := Nat (Get_Column_Number (Ref_Entry.Def)); | |
226a7fa4 | 863 | end if; |
cdc96e3e | 864 | |
24fd21c3 AC |
865 | -- References to constant objects without variable inputs (see |
866 | -- SPARK RM 3.3.1) are considered specially in SPARK section, | |
867 | -- because these will be translated as constants in the | |
868 | -- intermediate language for formal verification, and should | |
869 | -- therefore never appear in frame conditions. Other constants may | |
870 | -- later be treated the same, up to GNATprove to decide based on | |
871 | -- its flow analysis. | |
8fdafe44 | 872 | |
24fd21c3 | 873 | if Is_Constant_Object_Without_Variable_Input (Ref.Ent) then |
8fdafe44 AC |
874 | Typ := 'c'; |
875 | else | |
876 | Typ := Ref.Typ; | |
877 | end if; | |
878 | ||
06b599fd | 879 | SPARK_Xref_Table.Append ( |
cdc96e3e AC |
880 | (Entity_Name => Ref_Name, |
881 | Entity_Line => Line, | |
882 | Etype => Get_Entity_Type (Ref.Ent), | |
883 | Entity_Col => Col, | |
884 | File_Num => Dependency_Num (Ref.Lun), | |
885 | Scope_Num => Get_Scope_Num (Ref.Ref_Scope), | |
e90e9503 | 886 | Line => Nat (Get_Logical_Line_Number (Ref.Loc)), |
8fdafe44 | 887 | Rtype => Typ, |
e90e9503 | 888 | Col => Nat (Get_Column_Number (Ref.Loc)))); |
cdc96e3e | 889 | end; |
56e94186 AC |
890 | end loop; |
891 | ||
483361a6 AC |
892 | -- Update the range of cross references to which the scope refers to |
893 | ||
cdc96e3e AC |
894 | Update_Scope_Range |
895 | (S => Scope_Id, | |
896 | From => From_Index, | |
06b599fd YM |
897 | To => SPARK_Xref_Table.Last); |
898 | end Add_SPARK_Xrefs; | |
56e94186 | 899 | |
06b599fd YM |
900 | ------------------------- |
901 | -- Collect_SPARK_Xrefs -- | |
902 | ------------------------- | |
56e94186 | 903 | |
06b599fd YM |
904 | procedure Collect_SPARK_Xrefs |
905 | (Sdep_Table : Unit_Ref_Table; | |
906 | Num_Sdep : Nat) | |
907 | is | |
fb8d37ef AC |
908 | D1 : Pos; |
909 | D2 : Pos; | |
4b985e20 | 910 | |
56e94186 AC |
911 | begin |
912 | -- Cross-references should have been computed first | |
913 | ||
914 | pragma Assert (Xrefs.Last /= 0); | |
915 | ||
06b599fd | 916 | Initialize_SPARK_Tables; |
56e94186 | 917 | |
06b599fd | 918 | -- Generate file and scope SPARK cross-reference information |
56e94186 | 919 | |
4b985e20 AC |
920 | D1 := 1; |
921 | while D1 <= Num_Sdep loop | |
922 | ||
923 | -- In rare cases, when treating the library-level instantiation of a | |
924 | -- generic, two consecutive units refer to the same compilation unit | |
925 | -- node and entity. In that case, treat them as a single unit for the | |
06b599fd | 926 | -- sake of SPARK cross references by passing to Add_SPARK_File. |
4b985e20 AC |
927 | |
928 | if D1 < Num_Sdep | |
929 | and then Cunit_Entity (Sdep_Table (D1)) = | |
930 | Cunit_Entity (Sdep_Table (D1 + 1)) | |
931 | then | |
b48a45e3 AC |
932 | declare |
933 | Cunit1 : Node_Id renames Cunit (Sdep_Table (D1)); | |
934 | Cunit2 : Node_Id renames Cunit (Sdep_Table (D1 + 1)); | |
935 | begin | |
936 | -- Both Cunit point to compilation unit nodes | |
937 | pragma Assert (Nkind (Cunit1) = N_Compilation_Unit | |
938 | and then | |
939 | Nkind (Cunit2) = N_Compilation_Unit); | |
940 | ||
941 | -- Do not depend on the sorting order, which is based on | |
942 | -- Unit_Name and for library-level instances of nested | |
943 | -- generic-packages they are equal. | |
944 | ||
945 | -- If declaration comes before the body then just set D2 | |
946 | if Nkind (Unit (Cunit1)) = N_Package_Declaration | |
947 | and then | |
948 | Nkind (Unit (Cunit2)) = N_Package_Body | |
949 | then | |
950 | D2 := D1 + 1; | |
951 | ||
952 | -- If body comes before declaration then set D2 and adjust D1 | |
953 | ||
954 | elsif Nkind (Unit (Cunit1)) = N_Package_Body | |
955 | and then | |
956 | Nkind (Unit (Cunit2)) = N_Package_Declaration | |
957 | then | |
958 | D2 := D1; | |
959 | D1 := D1 + 1; | |
960 | ||
961 | else | |
962 | ||
963 | raise Program_Error; | |
964 | end if; | |
965 | end; | |
4b985e20 AC |
966 | else |
967 | D2 := D1; | |
968 | end if; | |
969 | ||
22da8770 AC |
970 | -- Skip dependencies with no entity node, e.g. configuration files |
971 | -- with pragmas (.adc) or target description (.atp), since they | |
972 | -- present no interest for SPARK cross references. | |
ccfe725b JK |
973 | |
974 | if Present (Cunit_Entity (Sdep_Table (D1))) then | |
975 | Add_SPARK_File | |
976 | (Ubody => Sdep_Table (D1), | |
977 | Uspec => Sdep_Table (D2), | |
978 | Dspec => D2); | |
979 | end if; | |
980 | ||
b48a45e3 | 981 | D1 := Pos'Max (D1, D2) + 1; |
56e94186 AC |
982 | end loop; |
983 | ||
9466892f AC |
984 | -- Fill in the spec information when relevant |
985 | ||
986 | declare | |
987 | package Entity_Hash_Table is new | |
988 | GNAT.HTable.Simple_HTable | |
989 | (Header_Num => Entity_Hashed_Range, | |
990 | Element => Scope_Index, | |
991 | No_Element => 0, | |
992 | Key => Entity_Id, | |
993 | Hash => Entity_Hash, | |
994 | Equal => "="); | |
995 | ||
996 | begin | |
997 | -- Fill in the hash-table | |
998 | ||
06b599fd | 999 | for S in SPARK_Scope_Table.First .. SPARK_Scope_Table.Last loop |
9466892f | 1000 | declare |
06b599fd | 1001 | Srec : SPARK_Scope_Record renames SPARK_Scope_Table.Table (S); |
9466892f AC |
1002 | begin |
1003 | Entity_Hash_Table.Set (Srec.Scope_Entity, S); | |
1004 | end; | |
1005 | end loop; | |
1006 | ||
1007 | -- Use the hash-table to locate spec entities | |
1008 | ||
06b599fd | 1009 | for S in SPARK_Scope_Table.First .. SPARK_Scope_Table.Last loop |
9466892f | 1010 | declare |
06b599fd | 1011 | Srec : SPARK_Scope_Record renames SPARK_Scope_Table.Table (S); |
9fde638d | 1012 | |
57a8057a | 1013 | Spec_Entity : constant Entity_Id := |
8d4611f7 | 1014 | Unique_Entity (Srec.Scope_Entity); |
57a8057a | 1015 | Spec_Scope : constant Scope_Index := |
8d4611f7 | 1016 | Entity_Hash_Table.Get (Spec_Entity); |
9fde638d | 1017 | |
9466892f | 1018 | begin |
5b0113d6 | 1019 | -- Generic spec may be missing in which case Spec_Scope is zero |
9466892f | 1020 | |
57a8057a AC |
1021 | if Spec_Entity /= Srec.Scope_Entity |
1022 | and then Spec_Scope /= 0 | |
1023 | then | |
1024 | Srec.Spec_File_Num := | |
06b599fd | 1025 | SPARK_Scope_Table.Table (Spec_Scope).File_Num; |
57a8057a | 1026 | Srec.Spec_Scope_Num := |
06b599fd | 1027 | SPARK_Scope_Table.Table (Spec_Scope).Scope_Num; |
9466892f AC |
1028 | end if; |
1029 | end; | |
1030 | end loop; | |
9466892f AC |
1031 | end; |
1032 | ||
06b599fd | 1033 | -- Generate SPARK cross-reference information |
56e94186 | 1034 | |
06b599fd YM |
1035 | Add_SPARK_Xrefs; |
1036 | end Collect_SPARK_Xrefs; | |
56e94186 | 1037 | |
06b599fd YM |
1038 | -------------------------------- |
1039 | -- Detect_And_Add_SPARK_Scope -- | |
1040 | -------------------------------- | |
2c1b72d7 | 1041 | |
06b599fd | 1042 | procedure Detect_And_Add_SPARK_Scope (N : Node_Id) is |
2c1b72d7 | 1043 | begin |
7b52257c AC |
1044 | if Nkind_In (N, N_Entry_Body, -- entries |
1045 | N_Entry_Declaration) | |
1046 | or else | |
1047 | Nkind_In (N, N_Package_Body, -- packages | |
ca7e6c26 | 1048 | N_Package_Body_Stub, |
7b52257c AC |
1049 | N_Package_Declaration) |
1050 | or else | |
4871a41d AC |
1051 | Nkind_In (N, N_Protected_Body, -- protected objects |
1052 | N_Protected_Body_Stub, | |
1053 | N_Protected_Type_Declaration) | |
1054 | or else | |
7b52257c | 1055 | Nkind_In (N, N_Subprogram_Body, -- subprograms |
dedac3eb | 1056 | N_Subprogram_Body_Stub, |
ca7e6c26 | 1057 | N_Subprogram_Declaration) |
7b52257c AC |
1058 | or else |
1059 | Nkind_In (N, N_Task_Body, -- tasks | |
eff69022 AC |
1060 | N_Task_Body_Stub, |
1061 | N_Task_Type_Declaration) | |
2c1b72d7 | 1062 | then |
06b599fd | 1063 | Add_SPARK_Scope (N); |
2c1b72d7 | 1064 | end if; |
06b599fd | 1065 | end Detect_And_Add_SPARK_Scope; |
2c1b72d7 | 1066 | |
226a7fa4 AC |
1067 | ------------------------------------- |
1068 | -- Enclosing_Subprogram_Or_Package -- | |
1069 | ------------------------------------- | |
1070 | ||
63b5225b YM |
1071 | function Enclosing_Subprogram_Or_Library_Package |
1072 | (N : Node_Id) return Entity_Id | |
1073 | is | |
4871a41d | 1074 | Context : Entity_Id; |
226a7fa4 AC |
1075 | |
1076 | begin | |
1077 | -- If N is the defining identifier for a subprogram, then return the | |
1078 | -- enclosing subprogram or package, not this subprogram. | |
1079 | ||
1080 | if Nkind_In (N, N_Defining_Identifier, N_Defining_Operator_Symbol) | |
4871a41d | 1081 | and then (Ekind (N) in Entry_Kind |
2c94bbe3 AC |
1082 | or else Ekind (N) = E_Subprogram_Body |
1083 | or else Ekind (N) in Generic_Subprogram_Kind | |
1084 | or else Ekind (N) in Subprogram_Kind) | |
226a7fa4 | 1085 | then |
4871a41d | 1086 | Context := Parent (Unit_Declaration_Node (N)); |
f6f40114 | 1087 | |
4871a41d | 1088 | -- If this was a library-level subprogram then replace Context with |
f6f40114 | 1089 | -- its Unit, which points to N_Subprogram_* node. |
cdabbb52 | 1090 | |
4871a41d AC |
1091 | if Nkind (Context) = N_Compilation_Unit then |
1092 | Context := Unit (Context); | |
f6f40114 | 1093 | end if; |
226a7fa4 | 1094 | else |
4871a41d | 1095 | Context := N; |
226a7fa4 AC |
1096 | end if; |
1097 | ||
4871a41d AC |
1098 | while Present (Context) loop |
1099 | case Nkind (Context) is | |
1100 | when N_Package_Body | | |
1101 | N_Package_Specification => | |
63b5225b YM |
1102 | |
1103 | -- Only return a library-level package | |
1104 | ||
4871a41d AC |
1105 | if Is_Library_Level_Entity (Defining_Entity (Context)) then |
1106 | Context := Defining_Entity (Context); | |
63b5225b YM |
1107 | exit; |
1108 | else | |
4871a41d | 1109 | Context := Parent (Context); |
63b5225b | 1110 | end if; |
226a7fa4 | 1111 | |
226a7fa4 | 1112 | when N_Pragma => |
9e92ad49 | 1113 | |
15918371 | 1114 | -- The enclosing subprogram for a precondition, postcondition, |
ab986406 AC |
1115 | -- or contract case should be the declaration preceding the |
1116 | -- pragma (skipping any other pragmas between this pragma and | |
1117 | -- this declaration. | |
1118 | ||
4871a41d AC |
1119 | while Nkind (Context) = N_Pragma |
1120 | and then Is_List_Member (Context) | |
1121 | and then Present (Prev (Context)) | |
ab986406 | 1122 | loop |
4871a41d | 1123 | Context := Prev (Context); |
ab986406 AC |
1124 | end loop; |
1125 | ||
4871a41d AC |
1126 | if Nkind (Context) = N_Pragma then |
1127 | Context := Parent (Context); | |
226a7fa4 AC |
1128 | end if; |
1129 | ||
4871a41d AC |
1130 | when N_Entry_Body | |
1131 | N_Entry_Declaration | | |
1132 | N_Protected_Type_Declaration | | |
1133 | N_Subprogram_Body | | |
1134 | N_Subprogram_Declaration | | |
1135 | N_Subprogram_Specification | | |
1136 | N_Task_Body | | |
1137 | N_Task_Type_Declaration => | |
1138 | Context := Defining_Entity (Context); | |
eff69022 AC |
1139 | exit; |
1140 | ||
226a7fa4 | 1141 | when others => |
4871a41d | 1142 | Context := Parent (Context); |
226a7fa4 AC |
1143 | end case; |
1144 | end loop; | |
1145 | ||
4871a41d AC |
1146 | if Nkind (Context) = N_Defining_Program_Unit_Name then |
1147 | Context := Defining_Identifier (Context); | |
226a7fa4 AC |
1148 | end if; |
1149 | ||
5b0113d6 | 1150 | -- Do not return a scope without a proper location |
226a7fa4 | 1151 | |
4871a41d AC |
1152 | if Present (Context) |
1153 | and then Sloc (Context) = No_Location | |
226a7fa4 AC |
1154 | then |
1155 | return Empty; | |
1156 | end if; | |
1157 | ||
4871a41d | 1158 | return Context; |
63b5225b | 1159 | end Enclosing_Subprogram_Or_Library_Package; |
226a7fa4 | 1160 | |
9466892f AC |
1161 | ----------------- |
1162 | -- Entity_Hash -- | |
1163 | ----------------- | |
1164 | ||
1165 | function Entity_Hash (E : Entity_Id) return Entity_Hashed_Range is | |
1166 | begin | |
9fde638d RD |
1167 | return |
1168 | Entity_Hashed_Range (E mod (Entity_Id (Entity_Hashed_Range'Last) + 1)); | |
9466892f AC |
1169 | end Entity_Hash; |
1170 | ||
226a7fa4 AC |
1171 | -------------------------- |
1172 | -- Generate_Dereference -- | |
1173 | -------------------------- | |
1174 | ||
1175 | procedure Generate_Dereference | |
1176 | (N : Node_Id; | |
1177 | Typ : Character := 'r') | |
1178 | is | |
cdc96e3e AC |
1179 | procedure Create_Heap; |
1180 | -- Create and decorate the special entity which denotes the heap | |
1181 | ||
1182 | ----------------- | |
1183 | -- Create_Heap -- | |
1184 | ----------------- | |
1185 | ||
1186 | procedure Create_Heap is | |
1187 | begin | |
1188 | Name_Len := Name_Of_Heap_Variable'Length; | |
1189 | Name_Buffer (1 .. Name_Len) := Name_Of_Heap_Variable; | |
1190 | ||
1191 | Heap := Make_Defining_Identifier (Standard_Location, Name_Enter); | |
1192 | ||
1193 | Set_Ekind (Heap, E_Variable); | |
1194 | Set_Is_Internal (Heap, True); | |
1195 | Set_Has_Fully_Qualified_Name (Heap); | |
1196 | end Create_Heap; | |
1197 | ||
1198 | -- Local variables | |
1199 | ||
b48a45e3 | 1200 | Loc : constant Source_Ptr := Sloc (N); |
226a7fa4 | 1201 | |
cdc96e3e AC |
1202 | -- Start of processing for Generate_Dereference |
1203 | ||
226a7fa4 | 1204 | begin |
226a7fa4 | 1205 | |
23e7bf6a | 1206 | if Loc > No_Location then |
226a7fa4 | 1207 | Drefs.Increment_Last; |
cdc96e3e AC |
1208 | |
1209 | declare | |
b48a45e3 | 1210 | Deref_Entry : Xref_Entry renames Drefs.Table (Drefs.Last); |
cdc96e3e AC |
1211 | Deref : Xref_Key renames Deref_Entry.Key; |
1212 | ||
1213 | begin | |
1214 | if No (Heap) then | |
1215 | Create_Heap; | |
1216 | end if; | |
226a7fa4 | 1217 | |
cdc96e3e | 1218 | Deref.Ent := Heap; |
23e7bf6a | 1219 | Deref.Loc := Loc; |
cdc96e3e | 1220 | Deref.Typ := Typ; |
226a7fa4 | 1221 | |
a5150cb1 AC |
1222 | -- It is as if the special "Heap" was defined in the main unit, |
1223 | -- in the scope of the entity for the main unit. This single | |
1224 | -- definition point is required to ensure that sorting cross | |
1225 | -- references works for "Heap" references as well. | |
226a7fa4 | 1226 | |
a5150cb1 AC |
1227 | Deref.Eun := Main_Unit; |
1228 | Deref.Lun := Get_Top_Level_Code_Unit (Loc); | |
226a7fa4 | 1229 | |
b48a45e3 | 1230 | Deref.Ref_Scope := Enclosing_Subprogram_Or_Library_Package (N); |
a5150cb1 | 1231 | Deref.Ent_Scope := Cunit_Entity (Main_Unit); |
226a7fa4 | 1232 | |
cdc96e3e | 1233 | Deref_Entry.Def := No_Location; |
226a7fa4 | 1234 | |
a5150cb1 | 1235 | Deref_Entry.Ent_Scope_File := Main_Unit; |
cdc96e3e | 1236 | end; |
226a7fa4 AC |
1237 | end if; |
1238 | end Generate_Dereference; | |
1239 | ||
2c1b72d7 AC |
1240 | ------------------------------- |
1241 | -- Traverse_Compilation_Unit -- | |
1242 | ------------------------------- | |
1243 | ||
1244 | procedure Traverse_Compilation_Unit | |
60370fb1 AC |
1245 | (CU : Node_Id; |
1246 | Process : Node_Processing; | |
1247 | Inside_Stubs : Boolean) | |
2c1b72d7 AC |
1248 | is |
1249 | Lu : Node_Id; | |
1250 | ||
1251 | begin | |
1252 | -- Get Unit (checking case of subunit) | |
1253 | ||
1254 | Lu := Unit (CU); | |
1255 | ||
1256 | if Nkind (Lu) = N_Subunit then | |
1257 | Lu := Proper_Body (Lu); | |
1258 | end if; | |
1259 | ||
23e7bf6a YM |
1260 | -- Do not add scopes for generic units |
1261 | ||
1262 | if Nkind (Lu) = N_Package_Body | |
1263 | and then Ekind (Corresponding_Spec (Lu)) in Generic_Unit_Kind | |
1264 | then | |
1265 | return; | |
1266 | end if; | |
1267 | ||
2c1b72d7 AC |
1268 | -- Call Process on all declarations |
1269 | ||
1270 | if Nkind (Lu) in N_Declaration | |
1271 | or else Nkind (Lu) in N_Later_Decl_Item | |
1272 | then | |
1273 | Process (Lu); | |
1274 | end if; | |
1275 | ||
1276 | -- Traverse the unit | |
1277 | ||
ca7e6c26 | 1278 | Traverse_Declaration_Or_Statement (Lu, Process, Inside_Stubs); |
2c1b72d7 AC |
1279 | end Traverse_Compilation_Unit; |
1280 | ||
ca7e6c26 AC |
1281 | --------------------------------------- |
1282 | -- Traverse_Declaration_Or_Statement -- | |
1283 | --------------------------------------- | |
56e94186 | 1284 | |
ca7e6c26 AC |
1285 | procedure Traverse_Declaration_Or_Statement |
1286 | (N : Node_Id; | |
60370fb1 AC |
1287 | Process : Node_Processing; |
1288 | Inside_Stubs : Boolean) | |
2c1b72d7 | 1289 | is |
56e94186 | 1290 | begin |
ca7e6c26 AC |
1291 | case Nkind (N) is |
1292 | when N_Package_Declaration => | |
363f2c58 AC |
1293 | declare |
1294 | Spec : constant Node_Id := Specification (N); | |
1295 | begin | |
1296 | Traverse_Declarations_Or_Statements | |
1297 | (Visible_Declarations (Spec), Process, Inside_Stubs); | |
1298 | Traverse_Declarations_Or_Statements | |
1299 | (Private_Declarations (Spec), Process, Inside_Stubs); | |
1300 | end; | |
56e94186 | 1301 | |
ca7e6c26 AC |
1302 | when N_Package_Body => |
1303 | if Ekind (Defining_Entity (N)) /= E_Generic_Package then | |
1304 | Traverse_Package_Body (N, Process, Inside_Stubs); | |
1305 | end if; | |
56e94186 | 1306 | |
ca7e6c26 AC |
1307 | when N_Package_Body_Stub => |
1308 | if Present (Library_Unit (N)) then | |
1309 | declare | |
1310 | Body_N : constant Node_Id := Get_Body_From_Stub (N); | |
1311 | begin | |
1312 | if Inside_Stubs | |
1313 | and then | |
1314 | Ekind (Defining_Entity (Body_N)) /= E_Generic_Package | |
1315 | then | |
1316 | Traverse_Package_Body (Body_N, Process, Inside_Stubs); | |
1317 | end if; | |
1318 | end; | |
1319 | end if; | |
56e94186 | 1320 | |
ca7e6c26 AC |
1321 | when N_Subprogram_Declaration => |
1322 | null; | |
56e94186 | 1323 | |
24fd21c3 | 1324 | when N_Entry_Body | N_Subprogram_Body => |
ca7e6c26 AC |
1325 | if not Is_Generic_Subprogram (Defining_Entity (N)) then |
1326 | Traverse_Subprogram_Body (N, Process, Inside_Stubs); | |
1327 | end if; | |
56e94186 | 1328 | |
ca7e6c26 AC |
1329 | when N_Subprogram_Body_Stub => |
1330 | if Present (Library_Unit (N)) then | |
1331 | declare | |
1332 | Body_N : constant Node_Id := Get_Body_From_Stub (N); | |
1333 | begin | |
1334 | if Inside_Stubs | |
1335 | and then | |
1336 | not Is_Generic_Subprogram (Defining_Entity (Body_N)) | |
1337 | then | |
1338 | Traverse_Subprogram_Body (Body_N, Process, Inside_Stubs); | |
1339 | end if; | |
1340 | end; | |
1341 | end if; | |
60370fb1 | 1342 | |
ca7e6c26 AC |
1343 | when N_Protected_Body => |
1344 | Traverse_Protected_Body (N, Process, Inside_Stubs); | |
704228bd | 1345 | |
ca7e6c26 AC |
1346 | when N_Protected_Body_Stub => |
1347 | if Present (Library_Unit (N)) then | |
1348 | declare | |
1349 | Body_N : constant Node_Id := Get_Body_From_Stub (N); | |
1350 | begin | |
1351 | if Inside_Stubs then | |
1352 | Traverse_Declarations_Or_Statements | |
1353 | (Declarations (Body_N), Process, Inside_Stubs); | |
1354 | end if; | |
1355 | end; | |
1356 | end if; | |
704228bd | 1357 | |
363f2c58 AC |
1358 | when N_Protected_Type_Declaration | N_Single_Protected_Declaration => |
1359 | declare | |
1360 | Def : constant Node_Id := Protected_Definition (N); | |
1361 | begin | |
1362 | Traverse_Declarations_Or_Statements | |
1363 | (Visible_Declarations (Def), Process, Inside_Stubs); | |
1364 | Traverse_Declarations_Or_Statements | |
1365 | (Private_Declarations (Def), Process, Inside_Stubs); | |
1366 | end; | |
1367 | ||
ca7e6c26 AC |
1368 | when N_Task_Definition => |
1369 | Traverse_Declarations_Or_Statements | |
1370 | (Visible_Declarations (N), Process, Inside_Stubs); | |
1371 | Traverse_Declarations_Or_Statements | |
1372 | (Private_Declarations (N), Process, Inside_Stubs); | |
704228bd | 1373 | |
ca7e6c26 AC |
1374 | when N_Task_Body => |
1375 | Traverse_Declarations_Or_Statements | |
1376 | (Declarations (N), Process, Inside_Stubs); | |
1377 | Traverse_Handled_Statement_Sequence | |
1378 | (Handled_Statement_Sequence (N), Process, Inside_Stubs); | |
704228bd | 1379 | |
ca7e6c26 AC |
1380 | when N_Task_Body_Stub => |
1381 | if Present (Library_Unit (N)) then | |
1382 | declare | |
1383 | Body_N : constant Node_Id := Get_Body_From_Stub (N); | |
1384 | begin | |
1385 | if Inside_Stubs then | |
1386 | Traverse_Declarations_Or_Statements | |
1387 | (Declarations (Body_N), Process, Inside_Stubs); | |
1388 | Traverse_Handled_Statement_Sequence | |
1389 | (Handled_Statement_Sequence (Body_N), Process, | |
1390 | Inside_Stubs); | |
1391 | end if; | |
1392 | end; | |
1393 | end if; | |
704228bd | 1394 | |
ca7e6c26 AC |
1395 | when N_Block_Statement => |
1396 | Traverse_Declarations_Or_Statements | |
1397 | (Declarations (N), Process, Inside_Stubs); | |
1398 | Traverse_Handled_Statement_Sequence | |
1399 | (Handled_Statement_Sequence (N), Process, Inside_Stubs); | |
704228bd | 1400 | |
ca7e6c26 | 1401 | when N_If_Statement => |
704228bd | 1402 | |
ca7e6c26 | 1403 | -- Traverse the statements in the THEN part |
56e94186 | 1404 | |
ca7e6c26 AC |
1405 | Traverse_Declarations_Or_Statements |
1406 | (Then_Statements (N), Process, Inside_Stubs); | |
56e94186 | 1407 | |
ca7e6c26 | 1408 | -- Loop through ELSIF parts if present |
56e94186 | 1409 | |
ca7e6c26 AC |
1410 | if Present (Elsif_Parts (N)) then |
1411 | declare | |
1412 | Elif : Node_Id := First (Elsif_Parts (N)); | |
56e94186 | 1413 | |
ca7e6c26 AC |
1414 | begin |
1415 | while Present (Elif) loop | |
1416 | Traverse_Declarations_Or_Statements | |
1417 | (Then_Statements (Elif), Process, Inside_Stubs); | |
1418 | Next (Elif); | |
1419 | end loop; | |
1420 | end; | |
1421 | end if; | |
56e94186 | 1422 | |
ca7e6c26 | 1423 | -- Finally traverse the ELSE statements if present |
56e94186 | 1424 | |
ca7e6c26 AC |
1425 | Traverse_Declarations_Or_Statements |
1426 | (Else_Statements (N), Process, Inside_Stubs); | |
56e94186 | 1427 | |
ca7e6c26 | 1428 | when N_Case_Statement => |
56e94186 | 1429 | |
ca7e6c26 | 1430 | -- Process case branches |
56e94186 | 1431 | |
ca7e6c26 AC |
1432 | declare |
1433 | Alt : Node_Id; | |
1434 | begin | |
1435 | Alt := First (Alternatives (N)); | |
1436 | while Present (Alt) loop | |
1437 | Traverse_Declarations_Or_Statements | |
1438 | (Statements (Alt), Process, Inside_Stubs); | |
1439 | Next (Alt); | |
1440 | end loop; | |
1441 | end; | |
56e94186 | 1442 | |
ca7e6c26 AC |
1443 | when N_Extended_Return_Statement => |
1444 | Traverse_Handled_Statement_Sequence | |
1445 | (Handled_Statement_Sequence (N), Process, Inside_Stubs); | |
56e94186 | 1446 | |
ca7e6c26 AC |
1447 | when N_Loop_Statement => |
1448 | Traverse_Declarations_Or_Statements | |
1449 | (Statements (N), Process, Inside_Stubs); | |
56e94186 | 1450 | |
ca7e6c26 | 1451 | -- Generic declarations are ignored |
56e94186 | 1452 | |
ca7e6c26 AC |
1453 | when others => |
1454 | null; | |
1455 | end case; | |
1456 | end Traverse_Declaration_Or_Statement; | |
56e94186 | 1457 | |
ca7e6c26 AC |
1458 | ----------------------------------------- |
1459 | -- Traverse_Declarations_Or_Statements -- | |
1460 | ----------------------------------------- | |
56e94186 | 1461 | |
ca7e6c26 AC |
1462 | procedure Traverse_Declarations_Or_Statements |
1463 | (L : List_Id; | |
1464 | Process : Node_Processing; | |
1465 | Inside_Stubs : Boolean) | |
1466 | is | |
1467 | N : Node_Id; | |
56e94186 | 1468 | |
ca7e6c26 AC |
1469 | begin |
1470 | -- Loop through statements or declarations | |
56e94186 | 1471 | |
ca7e6c26 AC |
1472 | N := First (L); |
1473 | while Present (N) loop | |
1474 | -- Call Process on all declarations | |
56e94186 | 1475 | |
ca7e6c26 AC |
1476 | if Nkind (N) in N_Declaration |
1477 | or else | |
1478 | Nkind (N) in N_Later_Decl_Item | |
f6f40114 AC |
1479 | or else |
1480 | Nkind (N) = N_Entry_Body | |
ca7e6c26 AC |
1481 | then |
1482 | Process (N); | |
1483 | end if; | |
ce5c2061 | 1484 | |
ca7e6c26 | 1485 | Traverse_Declaration_Or_Statement (N, Process, Inside_Stubs); |
56e94186 AC |
1486 | |
1487 | Next (N); | |
1488 | end loop; | |
1489 | end Traverse_Declarations_Or_Statements; | |
1490 | ||
1491 | ----------------------------------------- | |
1492 | -- Traverse_Handled_Statement_Sequence -- | |
1493 | ----------------------------------------- | |
1494 | ||
2c1b72d7 | 1495 | procedure Traverse_Handled_Statement_Sequence |
60370fb1 AC |
1496 | (N : Node_Id; |
1497 | Process : Node_Processing; | |
1498 | Inside_Stubs : Boolean) | |
2c1b72d7 | 1499 | is |
56e94186 AC |
1500 | Handler : Node_Id; |
1501 | ||
1502 | begin | |
1503 | if Present (N) then | |
60370fb1 AC |
1504 | Traverse_Declarations_Or_Statements |
1505 | (Statements (N), Process, Inside_Stubs); | |
56e94186 AC |
1506 | |
1507 | if Present (Exception_Handlers (N)) then | |
1508 | Handler := First (Exception_Handlers (N)); | |
1509 | while Present (Handler) loop | |
2c1b72d7 | 1510 | Traverse_Declarations_Or_Statements |
60370fb1 | 1511 | (Statements (Handler), Process, Inside_Stubs); |
56e94186 AC |
1512 | Next (Handler); |
1513 | end loop; | |
1514 | end if; | |
1515 | end if; | |
1516 | end Traverse_Handled_Statement_Sequence; | |
1517 | ||
1518 | --------------------------- | |
1519 | -- Traverse_Package_Body -- | |
1520 | --------------------------- | |
1521 | ||
2c1b72d7 | 1522 | procedure Traverse_Package_Body |
60370fb1 AC |
1523 | (N : Node_Id; |
1524 | Process : Node_Processing; | |
1525 | Inside_Stubs : Boolean) is | |
56e94186 | 1526 | begin |
60370fb1 AC |
1527 | Traverse_Declarations_Or_Statements |
1528 | (Declarations (N), Process, Inside_Stubs); | |
2c1b72d7 | 1529 | Traverse_Handled_Statement_Sequence |
60370fb1 | 1530 | (Handled_Statement_Sequence (N), Process, Inside_Stubs); |
56e94186 AC |
1531 | end Traverse_Package_Body; |
1532 | ||
265ca04a AC |
1533 | ----------------------------- |
1534 | -- Traverse_Protected_Body -- | |
1535 | ----------------------------- | |
1536 | ||
1537 | procedure Traverse_Protected_Body | |
1538 | (N : Node_Id; | |
1539 | Process : Node_Processing; | |
1540 | Inside_Stubs : Boolean) is | |
1541 | begin | |
1542 | Traverse_Declarations_Or_Statements | |
1543 | (Declarations (N), Process, Inside_Stubs); | |
1544 | end Traverse_Protected_Body; | |
1545 | ||
56e94186 AC |
1546 | ------------------------------ |
1547 | -- Traverse_Subprogram_Body -- | |
1548 | ------------------------------ | |
1549 | ||
2c1b72d7 | 1550 | procedure Traverse_Subprogram_Body |
60370fb1 AC |
1551 | (N : Node_Id; |
1552 | Process : Node_Processing; | |
5b0113d6 RD |
1553 | Inside_Stubs : Boolean) |
1554 | is | |
56e94186 | 1555 | begin |
60370fb1 AC |
1556 | Traverse_Declarations_Or_Statements |
1557 | (Declarations (N), Process, Inside_Stubs); | |
2c1b72d7 | 1558 | Traverse_Handled_Statement_Sequence |
60370fb1 | 1559 | (Handled_Statement_Sequence (N), Process, Inside_Stubs); |
56e94186 AC |
1560 | end Traverse_Subprogram_Body; |
1561 | ||
06b599fd | 1562 | end SPARK_Specific; |