]> git.ipfire.org Git - thirdparty/gcc.git/blame - gcc/ada/lib-xref-spark_specific.adb
lib-xref-spark_specific.adb (Generate_Dereference): Assignment to not commented local...
[thirdparty/gcc.git] / gcc / ada / lib-xref-spark_specific.adb
CommitLineData
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
26with Einfo; use Einfo;
27with Nmake; use Nmake;
9db78a42 28with SPARK_Xrefs; use SPARK_Xrefs;
996c8821 29
56e94186
AC
30with GNAT.HTable;
31
32separate (Lib.Xref)
06b599fd 33package 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 1562end SPARK_Specific;