1 ------------------------------------------------------------------------------
3 -- GNAT COMPILER COMPONENTS --
5 -- L I B . X R E F . A L F A --
9 -- Copyright (C) 2011, Free Software Foundation, Inc. --
11 -- GNAT is free software; you can redistribute it and/or modify it under --
12 -- terms of the GNU General Public License as published by the Free Soft- --
13 -- ware Foundation; either version 3, or (at your option) any later ver- --
14 -- sion. GNAT is distributed in the hope that it will be useful, but WITH- --
15 -- OUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY --
16 -- or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License --
17 -- for more details. You should have received a copy of the GNU General --
18 -- Public License distributed with GNAT; see file COPYING3. If not, go to --
19 -- http://www.gnu.org/licenses for a complete copy of the license. --
21 -- GNAT was originally developed by the GNAT team at New York University. --
22 -- Extensive contributions were provided by Ada Core Technologies Inc. --
24 ------------------------------------------------------------------------------
27 with Einfo; use Einfo;
28 with Nmake; use Nmake;
40 -- Table of Alfa_Entities, True for each entity kind used in Alfa
42 Alfa_Entities : constant array (Entity_Kind) of Boolean :=
47 E_Discriminant => False,
49 E_Loop_Parameter => True,
50 E_In_Parameter => True,
51 E_Out_Parameter => True,
52 E_In_Out_Parameter => True,
53 E_Generic_In_Out_Parameter => False,
55 E_Generic_In_Parameter => False,
56 E_Named_Integer => False,
57 E_Named_Real => False,
58 E_Enumeration_Type => False,
59 E_Enumeration_Subtype => False,
61 E_Signed_Integer_Type => False,
62 E_Signed_Integer_Subtype => False,
63 E_Modular_Integer_Type => False,
64 E_Modular_Integer_Subtype => False,
65 E_Ordinary_Fixed_Point_Type => False,
67 E_Ordinary_Fixed_Point_Subtype => False,
68 E_Decimal_Fixed_Point_Type => False,
69 E_Decimal_Fixed_Point_Subtype => False,
70 E_Floating_Point_Type => False,
71 E_Floating_Point_Subtype => False,
73 E_Access_Type => False,
74 E_Access_Subtype => False,
75 E_Access_Attribute_Type => False,
76 E_Allocator_Type => False,
77 E_General_Access_Type => False,
79 E_Access_Subprogram_Type => False,
80 E_Access_Protected_Subprogram_Type => False,
81 E_Anonymous_Access_Subprogram_Type => False,
82 E_Anonymous_Access_Protected_Subprogram_Type => False,
83 E_Anonymous_Access_Type => False,
85 E_Array_Type => False,
86 E_Array_Subtype => False,
87 E_String_Type => False,
88 E_String_Subtype => False,
89 E_String_Literal_Subtype => False,
91 E_Class_Wide_Type => False,
92 E_Class_Wide_Subtype => False,
93 E_Record_Type => False,
94 E_Record_Subtype => False,
95 E_Record_Type_With_Private => False,
97 E_Record_Subtype_With_Private => False,
98 E_Private_Type => False,
99 E_Private_Subtype => False,
100 E_Limited_Private_Type => False,
101 E_Limited_Private_Subtype => False,
103 E_Incomplete_Type => False,
104 E_Incomplete_Subtype => False,
105 E_Task_Type => False,
106 E_Task_Subtype => False,
107 E_Protected_Type => False,
109 E_Protected_Subtype => False,
110 E_Exception_Type => False,
111 E_Subprogram_Type => False,
112 E_Enumeration_Literal => False,
118 E_Entry_Family => False,
121 E_Entry_Index_Parameter => False,
122 E_Exception => False,
123 E_Generic_Function => False,
124 E_Generic_Package => False,
125 E_Generic_Procedure => False,
129 E_Return_Statement => False,
132 E_Package_Body => False,
133 E_Protected_Object => False,
134 E_Protected_Body => False,
135 E_Task_Body => False,
136 E_Subprogram_Body => False);
138 -- True for each reference type used in Alfa
139 Alfa_References : constant array (Character) of Boolean :=
145 type Entity_Hashed_Range is range 0 .. 255;
146 -- Size of hash table headers
148 ---------------------
149 -- Local Variables --
150 ---------------------
152 package Drefs is new Table.Table (
153 Table_Component_Type => Xref_Entry,
154 Table_Index_Type => Xref_Entry_Number,
155 Table_Low_Bound => 1,
156 Table_Initial => Alloc.Xrefs_Initial,
157 Table_Increment => Alloc.Xrefs_Increment,
158 Table_Name => "Drefs");
159 -- Table of cross-references for reads and writes through explicit
160 -- dereferences, that are output as reads/writes to the special variable
161 -- "Heap". These references are added to the regular references when
162 -- computing Alfa cross-references.
164 -----------------------
165 -- Local Subprograms --
166 -----------------------
168 procedure Add_Alfa_File (U : Unit_Number_Type; D : Nat);
169 -- Add file U and all scopes in U to the tables Alfa_File_Table and
172 procedure Add_Alfa_Scope (N : Node_Id);
173 -- Add scope N to the table Alfa_Scope_Table
175 procedure Add_Alfa_Xrefs;
176 -- Filter table Xrefs to add all references used in Alfa to the table
179 procedure Detect_And_Add_Alfa_Scope (N : Node_Id);
180 -- Call Add_Alfa_Scope on scopes
182 function Entity_Hash (E : Entity_Id) return Entity_Hashed_Range;
183 -- Hash function for hash table
185 procedure Traverse_Declarations_Or_Statements
187 Process : Node_Processing;
188 Inside_Stubs : Boolean);
189 procedure Traverse_Handled_Statement_Sequence
191 Process : Node_Processing;
192 Inside_Stubs : Boolean);
193 procedure Traverse_Package_Body
195 Process : Node_Processing;
196 Inside_Stubs : Boolean);
197 procedure Traverse_Package_Declaration
199 Process : Node_Processing;
200 Inside_Stubs : Boolean);
201 procedure Traverse_Subprogram_Body
203 Process : Node_Processing;
204 Inside_Stubs : Boolean);
205 -- Traverse the corresponding constructs, calling Process on all
212 procedure Add_Alfa_File (U : Unit_Number_Type; D : Nat) is
215 S : constant Source_File_Index := Source_Index (U);
218 -- Source file could be inexistant as a result of an error, if option
221 if S = No_Source_File then
225 From := Alfa_Scope_Table.Last + 1;
227 Traverse_Compilation_Unit (Cunit (U), Detect_And_Add_Alfa_Scope'Access,
228 Inside_Stubs => False);
230 -- Update scope numbers
237 for S in From .. Alfa_Scope_Table.Last loop
239 E : Entity_Id renames Alfa_Scope_Table.Table (S).Scope_Entity;
242 if Lib.Get_Source_Unit (E) = U then
243 Alfa_Scope_Table.Table (S).Scope_Num := Count;
244 Alfa_Scope_Table.Table (S).File_Num := D;
248 -- Mark for removal a scope S which is not located in unit
249 -- U, for example for scope inside generics that get
252 Alfa_Scope_Table.Table (S).Scope_Num := 0;
263 for S in From .. Alfa_Scope_Table.Last loop
264 -- Remove those scopes previously marked for removal
266 if Alfa_Scope_Table.Table (S).Scope_Num /= 0 then
267 Alfa_Scope_Table.Table (Snew) := Alfa_Scope_Table.Table (S);
272 Alfa_Scope_Table.Set_Last (Snew - 1);
275 -- Make entry for new file in file table
277 Get_Name_String (Reference_Name (S));
279 Alfa_File_Table.Append (
280 (File_Name => new String'(Name_Buffer (1 .. Name_Len)),
283 To_Scope => Alfa_Scope_Table.Last));
290 procedure Add_Alfa_Scope (N : Node_Id) is
291 E : constant Entity_Id := Defining_Entity (N);
292 Loc : constant Source_Ptr := Sloc (E);
296 -- Ignore scopes without a proper location
298 if Sloc (N) = No_Location then
303 when E_Function | E_Generic_Function =>
306 when E_Procedure | E_Generic_Procedure =>
309 when E_Subprogram_Body =>
316 if Nkind (Spec) = N_Defining_Program_Unit_Name then
317 Spec := Parent (Spec);
320 if Nkind (Spec) = N_Function_Specification then
324 (Nkind (Spec) = N_Procedure_Specification);
329 when E_Package | E_Package_Body | E_Generic_Package =>
333 -- Compilation of prj-attr.adb with -gnatn creates a node with
334 -- entity E_Void for the package defined at a-charac.ads16:13
344 -- File_Num and Scope_Num are filled later. From_Xref and To_Xref are
345 -- filled even later, but are initialized to represent an empty range.
347 Alfa_Scope_Table.Append (
348 (Scope_Name => new String'(Unique_Name (E)),
353 Line => Nat (Get_Logical_Line_Number (Loc)),
355 Col => Nat (Get_Column_Number (Loc)),
365 procedure Add_Alfa_Xrefs is
366 Cur_Scope_Idx : Scope_Index;
367 From_Xref_Idx : Xref_Index;
368 Cur_Entity : Entity_Id;
369 Cur_Entity_Name : String_Ptr;
372 No_Scope : constant Nat := 0;
373 function Get_Scope_Num (N : Entity_Id) return Nat;
374 procedure Set_Scope_Num (N : Entity_Id; Num : Nat);
381 package body Scopes is
387 package Scopes is new GNAT.HTable.Simple_HTable
388 (Header_Num => Entity_Hashed_Range,
390 No_Element => (Num => No_Scope, Entity => Empty),
399 function Get_Scope_Num (N : Entity_Id) return Nat is
401 return Scopes.Get (N).Num;
408 procedure Set_Scope_Num (N : Entity_Id; Num : Nat) is
410 Scopes.Set (K => N, E => Scope'(Num => Num, Entity => N));
416 Nrefs : Nat := Xrefs.Last;
417 -- Number of references in table. This value may get reset (reduced)
418 -- when we eliminate duplicate reference entries as well as references
419 -- not suitable for local cross-references.
421 Nrefs_Add : constant Nat := Drefs.Last;
423 Rnums : array (0 .. Nrefs + Nrefs_Add) of Nat;
424 -- This array contains numbers of references in the Xrefs table. This
425 -- list is sorted in output order. The extra 0'th entry is convenient
426 -- for the call to sort. When we sort the table, we move the entries in
427 -- Rnums around, but we do not move the original table entries.
429 function Lt (Op1, Op2 : Natural) return Boolean;
430 -- Comparison function for Sort call
432 procedure Move (From : Natural; To : Natural);
433 -- Move procedure for Sort call
435 package Sorting is new GNAT.Heap_Sort_G (Move, Lt);
441 function Lt (Op1, Op2 : Natural) return Boolean is
442 T1 : constant Xref_Entry := Xrefs.Table (Rnums (Nat (Op1)));
443 T2 : constant Xref_Entry := Xrefs.Table (Rnums (Nat (Op2)));
446 -- First test: if entity is in different unit, sort by unit. Note:
447 -- that we use Ent_Scope_File rather than Eun, as Eun may refer to
448 -- the file where the generic scope is defined, which may differ from
449 -- the file where the enclosing scope is defined. It is the latter
450 -- which matters for a correct order here.
452 if T1.Ent_Scope_File /= T2.Ent_Scope_File then
453 return Dependency_Num (T1.Ent_Scope_File) <
454 Dependency_Num (T2.Ent_Scope_File);
456 -- Second test: within same unit, sort by location of the scope of
457 -- the entity definition.
459 elsif Get_Scope_Num (T1.Key.Ent_Scope) /=
460 Get_Scope_Num (T2.Key.Ent_Scope)
462 return Get_Scope_Num (T1.Key.Ent_Scope) <
463 Get_Scope_Num (T2.Key.Ent_Scope);
465 -- Third test: within same unit and scope, sort by location of
466 -- entity definition.
468 elsif T1.Def /= T2.Def then
469 return T1.Def < T2.Def;
471 -- Fourth test: if reference is in same unit as entity definition,
475 T1.Key.Lun /= T2.Key.Lun and then T1.Ent_Scope_File = T1.Key.Lun
480 T1.Key.Lun /= T2.Key.Lun and then T2.Ent_Scope_File = T2.Key.Lun
484 -- Fifth test: if reference is in same unit and same scope as entity
485 -- definition, sort first.
487 elsif T1.Ent_Scope_File = T1.Key.Lun
488 and then T1.Key.Ref_Scope /= T2.Key.Ref_Scope
489 and then T1.Key.Ent_Scope = T1.Key.Ref_Scope
492 elsif T1.Ent_Scope_File = T1.Key.Lun
493 and then T1.Key.Ref_Scope /= T2.Key.Ref_Scope
494 and then T2.Key.Ent_Scope = T2.Key.Ref_Scope
498 -- Sixth test: for same entity, sort by reference location unit
500 elsif T1.Key.Lun /= T2.Key.Lun then
501 return Dependency_Num (T1.Key.Lun) < Dependency_Num (T2.Key.Lun);
503 -- Seventh test: for same entity, sort by reference location scope
505 elsif Get_Scope_Num (T1.Key.Ref_Scope) /=
506 Get_Scope_Num (T2.Key.Ref_Scope)
508 return Get_Scope_Num (T1.Key.Ref_Scope) <
509 Get_Scope_Num (T2.Key.Ref_Scope);
511 -- Eighth test: order of location within referencing unit
513 elsif T1.Key.Loc /= T2.Key.Loc then
514 return T1.Key.Loc < T2.Key.Loc;
516 -- Finally, for two locations at the same address prefer the one that
517 -- does NOT have the type 'r', so that a modification or extension
518 -- takes preference, when there are more than one reference at the
519 -- same location. As a result, in the case of entities that are
520 -- in-out actuals, the read reference follows the modify reference.
523 return T2.Key.Typ = 'r';
531 procedure Move (From : Natural; To : Natural) is
533 Rnums (Nat (To)) := Rnums (Nat (From));
538 -- Start of processing for Add_Alfa_Xrefs
541 for J in Alfa_Scope_Table.First .. Alfa_Scope_Table.Last loop
542 Set_Scope_Num (N => Alfa_Scope_Table.Table (J).Scope_Entity,
543 Num => Alfa_Scope_Table.Table (J).Scope_Num);
546 -- Set up the pointer vector for the sort
548 for J in 1 .. Nrefs loop
552 -- Add dereferences to the set of regular references, by creating a
553 -- special "Heap" variable for these special references.
555 Name_Len := Name_Of_Heap_Variable'Length;
556 Name_Buffer (1 .. Name_Len) := Name_Of_Heap_Variable;
560 Heap := Make_Defining_Identifier (Standard_Location, Name_Enter);
564 Set_Ekind (Heap, E_Variable);
565 Set_Is_Internal (Heap, True);
566 Set_Has_Fully_Qualified_Name (Heap);
568 for J in Drefs.First .. Drefs.Last loop
569 Xrefs.Append (Drefs.Table (J));
571 -- Set entity at this point with newly created "Heap" variable
573 Xrefs.Table (Xrefs.Last).Key.Ent := Heap;
576 Rnums (Nrefs) := Xrefs.Last;
579 -- Eliminate entries not appropriate for Alfa. Done prior to sorting
580 -- cross-references, as it discards useless references which do not have
581 -- a proper format for the comparison function (like no location).
583 Eliminate_Before_Sort : declare
586 function Is_Alfa_Reference
588 Typ : Character) return Boolean;
589 -- Return whether entity reference E meets Alfa requirements. Typ
590 -- is the reference type.
592 function Is_Alfa_Scope (E : Entity_Id) return Boolean;
593 -- Return whether the entity or reference scope meets requirements
594 -- for being an Alfa scope.
596 function Is_Global_Constant (E : Entity_Id) return Boolean;
597 -- Return True if E is a global constant for which we should ignore
600 -----------------------
601 -- Is_Alfa_Reference --
602 -----------------------
604 function Is_Alfa_Reference
606 Typ : Character) return Boolean
609 -- The only references of interest on callable entities are calls.
610 -- On non-callable entities, the only references of interest are
613 if Ekind (E) in Overloadable_Kind then
616 -- References to constant objects are not considered in Alfa
617 -- section, as these will be translated as constants in the
618 -- intermediate language for formal verification, and should
619 -- therefore never appear in frame conditions.
621 elsif Is_Constant_Object (E) then
624 -- Objects of Task type or protected type are not Alfa references
626 elsif Present (Etype (E))
627 and then Ekind (Etype (E)) in Concurrent_Kind
631 -- In all other cases, result is true for reference/modify cases,
632 -- and false for all other cases.
635 return Typ = 'r' or else Typ = 'm';
637 end Is_Alfa_Reference;
643 function Is_Alfa_Scope (E : Entity_Id) return Boolean is
646 and then not Is_Generic_Unit (E)
647 and then Renamed_Entity (E) = Empty
648 and then Get_Scope_Num (E) /= No_Scope;
651 ------------------------
652 -- Is_Global_Constant --
653 ------------------------
655 function Is_Global_Constant (E : Entity_Id) return Boolean is
657 return Ekind (E) = E_Constant
658 and then Ekind_In (Scope (E), E_Package, E_Package_Body);
659 end Is_Global_Constant;
661 -- Start of processing for Eliminate_Before_Sort
667 for J in 1 .. NR loop
668 if Alfa_Entities (Ekind (Xrefs.Table (Rnums (J)).Key.Ent))
669 and then Alfa_References (Xrefs.Table (Rnums (J)).Key.Typ)
670 and then Is_Alfa_Scope (Xrefs.Table (Rnums (J)).Key.Ent_Scope)
671 and then Is_Alfa_Scope (Xrefs.Table (Rnums (J)).Key.Ref_Scope)
672 and then not Is_Global_Constant (Xrefs.Table (Rnums (J)).Key.Ent)
673 and then Is_Alfa_Reference (Xrefs.Table (Rnums (J)).Key.Ent,
674 Xrefs.Table (Rnums (J)).Key.Typ)
677 Rnums (Nrefs) := Rnums (J);
680 end Eliminate_Before_Sort;
682 -- Sort the references
684 Sorting.Sort (Integer (Nrefs));
686 Eliminate_After_Sort : declare
690 -- Current reference location
693 -- reference kind of previous reference
696 -- Eliminate duplicate entries
698 -- We need this test for NR because if we force ALI file generation
699 -- in case of errors detected, it may be the case that Nrefs is 0, so
700 -- we should not reset it here
706 for J in 2 .. NR loop
707 if Xrefs.Table (Rnums (J)) /=
708 Xrefs.Table (Rnums (Nrefs))
711 Rnums (Nrefs) := Rnums (J);
716 -- Eliminate the reference if it is at the same location as the
717 -- previous one, unless it is a read-reference indicating that the
718 -- entity is an in-out actual in a call.
722 Crloc := No_Location;
725 for J in 1 .. NR loop
726 if Xrefs.Table (Rnums (J)).Key.Loc /= Crloc
728 and then Xrefs.Table (Rnums (J)).Key.Typ = 'r')
730 Crloc := Xrefs.Table (Rnums (J)).Key.Loc;
731 Prevt := Xrefs.Table (Rnums (J)).Key.Typ;
733 Rnums (Nrefs) := Rnums (J);
736 end Eliminate_After_Sort;
744 if Alfa_Scope_Table.Last = 0 then
748 -- Loop to output references
750 for Refno in 1 .. Nrefs loop
751 Add_One_Xref : declare
753 -----------------------
754 -- Local Subprograms --
755 -----------------------
757 function Cur_Scope return Node_Id;
758 -- Return scope entity which corresponds to index Cur_Scope_Idx in
759 -- table Alfa_Scope_Table.
761 function Get_Entity_Type (E : Entity_Id) return Character;
762 -- Return a character representing the type of entity
764 function Is_Future_Scope_Entity (E : Entity_Id) return Boolean;
765 -- Check whether entity E is in Alfa_Scope_Table at index
766 -- Cur_Scope_Idx or higher.
768 function Is_Past_Scope_Entity (E : Entity_Id) return Boolean;
769 -- Check whether entity E is in Alfa_Scope_Table at index strictly
770 -- lower than Cur_Scope_Idx.
776 function Cur_Scope return Node_Id is
778 return Alfa_Scope_Table.Table (Cur_Scope_Idx).Scope_Entity;
781 ---------------------
782 -- Get_Entity_Type --
783 ---------------------
785 function Get_Entity_Type (E : Entity_Id) return Character is
789 when E_Out_Parameter => C := '<';
790 when E_In_Out_Parameter => C := '=';
791 when E_In_Parameter => C := '>';
792 when others => C := '*';
797 ----------------------------
798 -- Is_Future_Scope_Entity --
799 ----------------------------
801 function Is_Future_Scope_Entity (E : Entity_Id) return Boolean is
803 for J in Cur_Scope_Idx .. Alfa_Scope_Table.Last loop
804 if E = Alfa_Scope_Table.Table (J).Scope_Entity then
809 -- If this assertion fails, this means that the scope which we
810 -- are looking for has been treated already, which reveals a
811 -- problem in the order of cross-references.
813 pragma Assert (not Is_Past_Scope_Entity (E));
816 end Is_Future_Scope_Entity;
818 --------------------------
819 -- Is_Past_Scope_Entity --
820 --------------------------
822 function Is_Past_Scope_Entity (E : Entity_Id) return Boolean is
824 for J in Alfa_Scope_Table.First .. Cur_Scope_Idx - 1 loop
825 if E = Alfa_Scope_Table.Table (J).Scope_Entity then
831 end Is_Past_Scope_Entity;
833 ---------------------
834 -- Local Variables --
835 ---------------------
837 XE : Xref_Entry renames Xrefs.Table (Rnums (Refno));
840 -- If this assertion fails, the scope which we are looking for is
841 -- not in Alfa scope table, which reveals either a problem in the
842 -- construction of the scope table, or an erroneous scope for the
843 -- current cross-reference.
845 pragma Assert (Is_Future_Scope_Entity (XE.Key.Ent_Scope));
847 -- Update the range of cross references to which the current scope
848 -- refers to. This may be the empty range only for the first scope
851 if XE.Key.Ent_Scope /= Cur_Scope then
852 Alfa_Scope_Table.Table (Cur_Scope_Idx).From_Xref :=
854 Alfa_Scope_Table.Table (Cur_Scope_Idx).To_Xref :=
855 Alfa_Xref_Table.Last;
856 From_Xref_Idx := Alfa_Xref_Table.Last + 1;
859 while XE.Key.Ent_Scope /= Cur_Scope loop
860 Cur_Scope_Idx := Cur_Scope_Idx + 1;
861 pragma Assert (Cur_Scope_Idx <= Alfa_Scope_Table.Last);
864 if XE.Key.Ent /= Cur_Entity then
866 new String'(Unique_Name (XE.Key.Ent));
869 if XE.Key.Ent = Heap then
870 Alfa_Xref_Table.Append (
871 (Entity_Name => Cur_Entity_Name,
873 Etype => Get_Entity_Type (XE.Key.Ent),
875 File_Num => Dependency_Num (XE.Key.Lun),
876 Scope_Num => Get_Scope_Num (XE.Key.Ref_Scope),
877 Line => Int (Get_Logical_Line_Number (XE.Key.Loc)),
879 Col => Int (Get_Column_Number (XE.Key.Loc))));
882 Alfa_Xref_Table.Append (
883 (Entity_Name => Cur_Entity_Name,
884 Entity_Line => Int (Get_Logical_Line_Number (XE.Def)),
885 Etype => Get_Entity_Type (XE.Key.Ent),
886 Entity_Col => Int (Get_Column_Number (XE.Def)),
887 File_Num => Dependency_Num (XE.Key.Lun),
888 Scope_Num => Get_Scope_Num (XE.Key.Ref_Scope),
889 Line => Int (Get_Logical_Line_Number (XE.Key.Loc)),
891 Col => Int (Get_Column_Number (XE.Key.Loc))));
896 -- Update the range of cross references to which the scope refers to
898 Alfa_Scope_Table.Table (Cur_Scope_Idx).From_Xref := From_Xref_Idx;
899 Alfa_Scope_Table.Table (Cur_Scope_Idx).To_Xref := Alfa_Xref_Table.Last;
906 procedure Collect_Alfa (Sdep_Table : Unit_Ref_Table; Num_Sdep : Nat) is
908 -- Cross-references should have been computed first
910 pragma Assert (Xrefs.Last /= 0);
912 Initialize_Alfa_Tables;
914 -- Generate file and scope Alfa information
916 for D in 1 .. Num_Sdep loop
917 Add_Alfa_File (U => Sdep_Table (D), D => D);
920 -- Fill in the spec information when relevant
923 package Entity_Hash_Table is new
924 GNAT.HTable.Simple_HTable
925 (Header_Num => Entity_Hashed_Range,
926 Element => Scope_Index,
933 -- Fill in the hash-table
935 for S in Alfa_Scope_Table.First .. Alfa_Scope_Table.Last loop
937 Srec : Alfa_Scope_Record renames Alfa_Scope_Table.Table (S);
939 Entity_Hash_Table.Set (Srec.Scope_Entity, S);
943 -- Use the hash-table to locate spec entities
945 for S in Alfa_Scope_Table.First .. Alfa_Scope_Table.Last loop
947 Srec : Alfa_Scope_Record renames Alfa_Scope_Table.Table (S);
949 Spec_Entity : constant Entity_Id :=
950 Unique_Entity (Srec.Scope_Entity);
951 Spec_Scope : constant Scope_Index :=
952 Entity_Hash_Table.Get (Spec_Entity);
955 -- Spec of generic may be missing, in which case Spec_Scope is
958 if Spec_Entity /= Srec.Scope_Entity
959 and then Spec_Scope /= 0
961 Srec.Spec_File_Num :=
962 Alfa_Scope_Table.Table (Spec_Scope).File_Num;
963 Srec.Spec_Scope_Num :=
964 Alfa_Scope_Table.Table (Spec_Scope).Scope_Num;
970 -- Generate cross reference Alfa information
975 -------------------------------
976 -- Detect_And_Add_Alfa_Scope --
977 -------------------------------
979 procedure Detect_And_Add_Alfa_Scope (N : Node_Id) is
981 if Nkind_In (N, N_Subprogram_Declaration,
983 N_Subprogram_Body_Stub,
984 N_Package_Declaration,
989 end Detect_And_Add_Alfa_Scope;
991 -------------------------------------
992 -- Enclosing_Subprogram_Or_Package --
993 -------------------------------------
995 function Enclosing_Subprogram_Or_Package (N : Node_Id) return Entity_Id is
999 -- If N is the defining identifier for a subprogram, then return the
1000 -- enclosing subprogram or package, not this subprogram.
1002 if Nkind_In (N, N_Defining_Identifier, N_Defining_Operator_Symbol)
1003 and then Nkind (Parent (N)) in N_Subprogram_Specification
1005 Result := Parent (Parent (Parent (N)));
1011 exit when No (Result);
1013 case Nkind (Result) is
1014 when N_Package_Specification =>
1015 Result := Defining_Unit_Name (Result);
1018 when N_Package_Body =>
1019 Result := Defining_Unit_Name (Result);
1022 when N_Subprogram_Specification =>
1023 Result := Defining_Unit_Name (Result);
1026 when N_Subprogram_Declaration =>
1027 Result := Defining_Unit_Name (Specification (Result));
1030 when N_Subprogram_Body =>
1031 Result := Defining_Unit_Name (Specification (Result));
1034 -- The enclosing subprogram for a pre- or postconditions should be
1035 -- the subprogram to which the pragma is attached. This is not
1036 -- always the case in the AST, as the pragma may be declared after
1037 -- the declaration of the subprogram. Return Empty in this case.
1040 if Get_Pragma_Id (Result) = Pragma_Precondition
1042 Get_Pragma_Id (Result) = Pragma_Postcondition
1046 Result := Parent (Result);
1050 Result := Parent (Result);
1054 if Nkind (Result) = N_Defining_Program_Unit_Name then
1055 Result := Defining_Identifier (Result);
1058 -- Do no return a scope without a proper location
1061 and then Sloc (Result) = No_Location
1067 end Enclosing_Subprogram_Or_Package;
1073 function Entity_Hash (E : Entity_Id) return Entity_Hashed_Range is
1076 Entity_Hashed_Range (E mod (Entity_Id (Entity_Hashed_Range'Last) + 1));
1079 --------------------------
1080 -- Generate_Dereference --
1081 --------------------------
1083 procedure Generate_Dereference
1085 Typ : Character := 'r')
1089 Ref_Scope : Entity_Id;
1092 Ref := Original_Location (Sloc (N));
1094 if Ref > No_Location then
1095 Drefs.Increment_Last;
1098 Ref_Scope := Enclosing_Subprogram_Or_Package (N);
1100 -- Entity is filled later on with the special "Heap" variable
1102 Drefs.Table (Indx).Key.Ent := Empty;
1104 Drefs.Table (Indx).Def := No_Location;
1105 Drefs.Table (Indx).Key.Loc := Ref;
1106 Drefs.Table (Indx).Key.Typ := Typ;
1108 -- It is as if the special "Heap" was defined in every scope where it
1111 Drefs.Table (Indx).Key.Eun := Get_Source_Unit (Ref);
1112 Drefs.Table (Indx).Key.Lun := Get_Source_Unit (Ref);
1114 Drefs.Table (Indx).Key.Ref_Scope := Ref_Scope;
1115 Drefs.Table (Indx).Key.Ent_Scope := Ref_Scope;
1116 Drefs.Table (Indx).Ent_Scope_File := Get_Source_Unit (Ref_Scope);
1118 end Generate_Dereference;
1120 ------------------------------------
1121 -- Traverse_All_Compilation_Units --
1122 ------------------------------------
1124 procedure Traverse_All_Compilation_Units (Process : Node_Processing) is
1126 for U in Units.First .. Last_Unit loop
1127 Traverse_Compilation_Unit (Cunit (U), Process, Inside_Stubs => False);
1129 end Traverse_All_Compilation_Units;
1131 -------------------------------
1132 -- Traverse_Compilation_Unit --
1133 -------------------------------
1135 procedure Traverse_Compilation_Unit
1137 Process : Node_Processing;
1138 Inside_Stubs : Boolean)
1143 -- Get Unit (checking case of subunit)
1147 if Nkind (Lu) = N_Subunit then
1148 Lu := Proper_Body (Lu);
1151 -- Call Process on all declarations
1153 if Nkind (Lu) in N_Declaration
1154 or else Nkind (Lu) in N_Later_Decl_Item
1159 -- Traverse the unit
1161 if Nkind (Lu) = N_Subprogram_Body then
1162 Traverse_Subprogram_Body (Lu, Process, Inside_Stubs);
1164 elsif Nkind (Lu) = N_Subprogram_Declaration then
1167 elsif Nkind (Lu) = N_Package_Declaration then
1168 Traverse_Package_Declaration (Lu, Process, Inside_Stubs);
1170 elsif Nkind (Lu) = N_Package_Body then
1171 Traverse_Package_Body (Lu, Process, Inside_Stubs);
1175 elsif Nkind (Lu) = N_Generic_Package_Declaration then
1180 elsif Nkind (Lu) in N_Generic_Instantiation then
1183 -- All other cases of compilation units (e.g. renamings), are not
1189 end Traverse_Compilation_Unit;
1191 -----------------------------------------
1192 -- Traverse_Declarations_Or_Statements --
1193 -----------------------------------------
1195 procedure Traverse_Declarations_Or_Statements
1197 Process : Node_Processing;
1198 Inside_Stubs : Boolean)
1203 -- Loop through statements or declarations
1206 while Present (N) loop
1207 -- Call Process on all declarations
1209 if Nkind (N) in N_Declaration
1211 Nkind (N) in N_Later_Decl_Item
1218 -- Package declaration
1220 when N_Package_Declaration =>
1221 Traverse_Package_Declaration (N, Process, Inside_Stubs);
1223 -- Generic package declaration ??? TBD
1225 when N_Generic_Package_Declaration =>
1230 when N_Package_Body =>
1231 if Ekind (Defining_Entity (N)) /= E_Generic_Package then
1232 Traverse_Package_Body (N, Process, Inside_Stubs);
1235 when N_Package_Body_Stub =>
1236 if Present (Library_Unit (N)) then
1238 Body_N : constant Node_Id := Get_Body_From_Stub (N);
1242 Ekind (Defining_Entity (Body_N)) /= E_Generic_Package
1244 Traverse_Package_Body (Body_N, Process, Inside_Stubs);
1249 -- Subprogram declaration
1251 when N_Subprogram_Declaration =>
1254 -- Generic subprogram declaration ??? TBD
1256 when N_Generic_Subprogram_Declaration =>
1261 when N_Subprogram_Body =>
1262 if not Is_Generic_Subprogram (Defining_Entity (N)) then
1263 Traverse_Subprogram_Body (N, Process, Inside_Stubs);
1266 when N_Subprogram_Body_Stub =>
1267 if Present (Library_Unit (N)) then
1269 Body_N : constant Node_Id := Get_Body_From_Stub (N);
1273 not Is_Generic_Subprogram (Defining_Entity (Body_N))
1275 Traverse_Subprogram_Body
1276 (Body_N, Process, Inside_Stubs);
1283 when N_Block_Statement =>
1284 Traverse_Declarations_Or_Statements
1285 (Declarations (N), Process, Inside_Stubs);
1286 Traverse_Handled_Statement_Sequence
1287 (Handled_Statement_Sequence (N), Process, Inside_Stubs);
1289 when N_If_Statement =>
1291 -- Traverse the statements in the THEN part
1293 Traverse_Declarations_Or_Statements
1294 (Then_Statements (N), Process, Inside_Stubs);
1296 -- Loop through ELSIF parts if present
1298 if Present (Elsif_Parts (N)) then
1300 Elif : Node_Id := First (Elsif_Parts (N));
1303 while Present (Elif) loop
1304 Traverse_Declarations_Or_Statements
1305 (Then_Statements (Elif), Process, Inside_Stubs);
1311 -- Finally traverse the ELSE statements if present
1313 Traverse_Declarations_Or_Statements
1314 (Else_Statements (N), Process, Inside_Stubs);
1318 when N_Case_Statement =>
1320 -- Process case branches
1325 Alt := First (Alternatives (N));
1326 while Present (Alt) loop
1327 Traverse_Declarations_Or_Statements
1328 (Statements (Alt), Process, Inside_Stubs);
1333 -- Extended return statement
1335 when N_Extended_Return_Statement =>
1336 Traverse_Handled_Statement_Sequence
1337 (Handled_Statement_Sequence (N), Process, Inside_Stubs);
1341 when N_Loop_Statement =>
1342 Traverse_Declarations_Or_Statements
1343 (Statements (N), Process, Inside_Stubs);
1351 end Traverse_Declarations_Or_Statements;
1353 -----------------------------------------
1354 -- Traverse_Handled_Statement_Sequence --
1355 -----------------------------------------
1357 procedure Traverse_Handled_Statement_Sequence
1359 Process : Node_Processing;
1360 Inside_Stubs : Boolean)
1366 Traverse_Declarations_Or_Statements
1367 (Statements (N), Process, Inside_Stubs);
1369 if Present (Exception_Handlers (N)) then
1370 Handler := First (Exception_Handlers (N));
1371 while Present (Handler) loop
1372 Traverse_Declarations_Or_Statements
1373 (Statements (Handler), Process, Inside_Stubs);
1378 end Traverse_Handled_Statement_Sequence;
1380 ---------------------------
1381 -- Traverse_Package_Body --
1382 ---------------------------
1384 procedure Traverse_Package_Body
1386 Process : Node_Processing;
1387 Inside_Stubs : Boolean) is
1389 Traverse_Declarations_Or_Statements
1390 (Declarations (N), Process, Inside_Stubs);
1391 Traverse_Handled_Statement_Sequence
1392 (Handled_Statement_Sequence (N), Process, Inside_Stubs);
1393 end Traverse_Package_Body;
1395 ----------------------------------
1396 -- Traverse_Package_Declaration --
1397 ----------------------------------
1399 procedure Traverse_Package_Declaration
1401 Process : Node_Processing;
1402 Inside_Stubs : Boolean)
1404 Spec : constant Node_Id := Specification (N);
1406 Traverse_Declarations_Or_Statements
1407 (Visible_Declarations (Spec), Process, Inside_Stubs);
1408 Traverse_Declarations_Or_Statements
1409 (Private_Declarations (Spec), Process, Inside_Stubs);
1410 end Traverse_Package_Declaration;
1412 ------------------------------
1413 -- Traverse_Subprogram_Body --
1414 ------------------------------
1416 procedure Traverse_Subprogram_Body
1418 Process : Node_Processing;
1419 Inside_Stubs : Boolean) is
1421 Traverse_Declarations_Or_Statements
1422 (Declarations (N), Process, Inside_Stubs);
1423 Traverse_Handled_Statement_Sequence
1424 (Handled_Statement_Sequence (N), Process, Inside_Stubs);
1425 end Traverse_Subprogram_Body;