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;
38 -- Table of ALFA_Entities, True for each entity kind used in ALFA
40 ALFA_Entities : constant array (Entity_Kind) of Boolean :=
45 E_Discriminant => False,
47 E_Loop_Parameter => True,
48 E_In_Parameter => True,
49 E_Out_Parameter => True,
50 E_In_Out_Parameter => True,
51 E_Generic_In_Out_Parameter => False,
53 E_Generic_In_Parameter => False,
54 E_Named_Integer => False,
55 E_Named_Real => False,
56 E_Enumeration_Type => False,
57 E_Enumeration_Subtype => False,
59 E_Signed_Integer_Type => False,
60 E_Signed_Integer_Subtype => False,
61 E_Modular_Integer_Type => False,
62 E_Modular_Integer_Subtype => False,
63 E_Ordinary_Fixed_Point_Type => False,
65 E_Ordinary_Fixed_Point_Subtype => False,
66 E_Decimal_Fixed_Point_Type => False,
67 E_Decimal_Fixed_Point_Subtype => False,
68 E_Floating_Point_Type => False,
69 E_Floating_Point_Subtype => False,
71 E_Access_Type => False,
72 E_Access_Subtype => False,
73 E_Access_Attribute_Type => False,
74 E_Allocator_Type => False,
75 E_General_Access_Type => False,
77 E_Access_Subprogram_Type => False,
78 E_Access_Protected_Subprogram_Type => False,
79 E_Anonymous_Access_Subprogram_Type => False,
80 E_Anonymous_Access_Protected_Subprogram_Type => False,
81 E_Anonymous_Access_Type => False,
83 E_Array_Type => False,
84 E_Array_Subtype => False,
85 E_String_Type => False,
86 E_String_Subtype => False,
87 E_String_Literal_Subtype => False,
89 E_Class_Wide_Type => False,
90 E_Class_Wide_Subtype => False,
91 E_Record_Type => False,
92 E_Record_Subtype => False,
93 E_Record_Type_With_Private => False,
95 E_Record_Subtype_With_Private => False,
96 E_Private_Type => False,
97 E_Private_Subtype => False,
98 E_Limited_Private_Type => False,
99 E_Limited_Private_Subtype => False,
101 E_Incomplete_Type => False,
102 E_Incomplete_Subtype => False,
103 E_Task_Type => False,
104 E_Task_Subtype => False,
105 E_Protected_Type => False,
107 E_Protected_Subtype => False,
108 E_Exception_Type => False,
109 E_Subprogram_Type => False,
110 E_Enumeration_Literal => False,
116 E_Entry_Family => False,
119 E_Entry_Index_Parameter => False,
120 E_Exception => False,
121 E_Generic_Function => False,
122 E_Generic_Package => False,
123 E_Generic_Procedure => False,
127 E_Return_Statement => False,
130 E_Package_Body => False,
131 E_Protected_Object => False,
132 E_Protected_Body => False,
133 E_Task_Body => False,
134 E_Subprogram_Body => False);
136 -- True for each reference type used in ALFA
137 ALFA_References : constant array (Character) of Boolean :=
143 type Entity_Hashed_Range is range 0 .. 255;
144 -- Size of hash table headers
146 -----------------------
147 -- Local Subprograms --
148 -----------------------
150 procedure Add_ALFA_File (U : Unit_Number_Type; D : Nat);
151 -- Add file U and all scopes in U to the tables ALFA_File_Table and
154 procedure Add_ALFA_Scope (N : Node_Id);
155 -- Add scope N to the table ALFA_Scope_Table
157 procedure Add_ALFA_Xrefs;
158 -- Filter table Xrefs to add all references used in ALFA to the table
161 procedure Detect_And_Add_ALFA_Scope (N : Node_Id);
162 -- Call Add_ALFA_Scope on scopes
164 function Entity_Hash (E : Entity_Id) return Entity_Hashed_Range;
165 -- Hash function for hash table
167 procedure Traverse_Declarations_Or_Statements
169 Process : Node_Processing);
170 procedure Traverse_Handled_Statement_Sequence
172 Process : Node_Processing);
173 procedure Traverse_Package_Body
175 Process : Node_Processing);
176 procedure Traverse_Package_Declaration
178 Process : Node_Processing);
179 procedure Traverse_Subprogram_Body
181 Process : Node_Processing);
182 -- Traverse the corresponding constructs, calling Process on all
189 procedure Add_ALFA_File (U : Unit_Number_Type; D : Nat) is
192 S : constant Source_File_Index := Source_Index (U);
195 -- Source file could be inexistant as a result of an error, if option
198 if S = No_Source_File then
202 From := ALFA_Scope_Table.Last + 1;
204 Traverse_Compilation_Unit (Cunit (U), Detect_And_Add_ALFA_Scope'Access);
206 -- Update scope numbers
213 for S in From .. ALFA_Scope_Table.Last loop
215 E : Entity_Id renames ALFA_Scope_Table.Table (S).Scope_Entity;
218 if Lib.Get_Source_Unit (E) = U then
219 ALFA_Scope_Table.Table (S).Scope_Num := Count;
220 ALFA_Scope_Table.Table (S).File_Num := D;
224 -- Mark for removal a scope S which is not located in unit
225 -- U, for example for scope inside generics that get
228 ALFA_Scope_Table.Table (S).Scope_Num := 0;
239 for S in From .. ALFA_Scope_Table.Last loop
240 -- Remove those scopes previously marked for removal
242 if ALFA_Scope_Table.Table (S).Scope_Num /= 0 then
243 ALFA_Scope_Table.Table (Snew) := ALFA_Scope_Table.Table (S);
248 ALFA_Scope_Table.Set_Last (Snew - 1);
251 -- Make entry for new file in file table
253 Get_Name_String (Reference_Name (S));
255 ALFA_File_Table.Append (
256 (File_Name => new String'(Name_Buffer (1 .. Name_Len)),
259 To_Scope => ALFA_Scope_Table.Last));
266 procedure Add_ALFA_Scope (N : Node_Id) is
267 E : constant Entity_Id := Defining_Entity (N);
268 Loc : constant Source_Ptr := Sloc (E);
272 -- Ignore scopes without a proper location
274 if Sloc (N) = No_Location then
285 when E_Subprogram_Body =>
292 if Nkind (Spec) = N_Defining_Program_Unit_Name then
293 Spec := Parent (Spec);
296 if Nkind (Spec) = N_Function_Specification then
300 (Nkind (Spec) = N_Procedure_Specification);
305 when E_Package | E_Package_Body =>
309 -- Compilation of prj-attr.adb with -gnatn creates a node with
310 -- entity E_Void for the package defined at a-charac.ads16:13
320 -- File_Num and Scope_Num are filled later. From_Xref and To_Xref are
321 -- filled even later, but are initialized to represent an empty range.
323 ALFA_Scope_Table.Append (
324 (Scope_Name => new String'(Unique_Name (E)),
329 Line => Nat (Get_Logical_Line_Number (Loc)),
331 Col => Nat (Get_Column_Number (Loc)),
341 procedure Add_ALFA_Xrefs is
342 Cur_Scope_Idx : Scope_Index;
343 From_Xref_Idx : Xref_Index;
344 Cur_Entity : Entity_Id;
345 Cur_Entity_Name : String_Ptr;
348 No_Scope : constant Nat := 0;
349 function Get_Scope_Num (N : Entity_Id) return Nat;
350 procedure Set_Scope_Num (N : Entity_Id; Num : Nat);
357 package body Scopes is
363 package Scopes is new GNAT.HTable.Simple_HTable
364 (Header_Num => Entity_Hashed_Range,
366 No_Element => (Num => No_Scope, Entity => Empty),
375 function Get_Scope_Num (N : Entity_Id) return Nat is
377 return Scopes.Get (N).Num;
384 procedure Set_Scope_Num (N : Entity_Id; Num : Nat) is
386 Scopes.Set (K => N, E => Scope'(Num => Num, Entity => N));
392 Nrefs : Nat := Xrefs.Last;
393 -- Number of references in table. This value may get reset (reduced)
394 -- when we eliminate duplicate reference entries as well as references
395 -- not suitable for local cross-references.
397 Rnums : array (0 .. Nrefs) of Nat;
398 -- This array contains numbers of references in the Xrefs table. This
399 -- list is sorted in output order. The extra 0'th entry is convenient
400 -- for the call to sort. When we sort the table, we move the entries in
401 -- Rnums around, but we do not move the original table entries.
403 function Lt (Op1, Op2 : Natural) return Boolean;
404 -- Comparison function for Sort call
406 procedure Move (From : Natural; To : Natural);
407 -- Move procedure for Sort call
409 package Sorting is new GNAT.Heap_Sort_G (Move, Lt);
415 function Lt (Op1, Op2 : Natural) return Boolean is
416 T1 : constant Xref_Entry := Xrefs.Table (Rnums (Nat (Op1)));
417 T2 : constant Xref_Entry := Xrefs.Table (Rnums (Nat (Op2)));
420 -- First test: if entity is in different unit, sort by unit. Note:
421 -- that we use Ent_Scope_File rather than Eun, as Eun may refer to
422 -- the file where the generic scope is defined, which may differ from
423 -- the file where the enclosing scope is defined. It is the latter
424 -- which matters for a correct order here.
426 if T1.Ent_Scope_File /= T2.Ent_Scope_File then
427 return Dependency_Num (T1.Ent_Scope_File) <
428 Dependency_Num (T2.Ent_Scope_File);
430 -- Second test: within same unit, sort by location of the scope of
431 -- the entity definition.
433 elsif Get_Scope_Num (T1.Ent_Scope) /=
434 Get_Scope_Num (T2.Ent_Scope)
436 return Get_Scope_Num (T1.Ent_Scope) < Get_Scope_Num (T2.Ent_Scope);
438 -- Third test: within same unit and scope, sort by location of
439 -- entity definition.
441 elsif T1.Def /= T2.Def then
442 return T1.Def < T2.Def;
444 -- Fourth test: if reference is in same unit as entity definition,
447 elsif T1.Lun /= T2.Lun and then T1.Ent_Scope_File = T1.Lun then
449 elsif T1.Lun /= T2.Lun and then T2.Ent_Scope_File = T2.Lun then
452 -- Fifth test: if reference is in same unit and same scope as entity
453 -- definition, sort first.
455 elsif T1.Ent_Scope_File = T1.Lun
456 and then T1.Ref_Scope /= T2.Ref_Scope
457 and then T1.Ent_Scope = T1.Ref_Scope
460 elsif T1.Ent_Scope_File = T1.Lun
461 and then T1.Ref_Scope /= T2.Ref_Scope
462 and then T2.Ent_Scope = T2.Ref_Scope
466 -- Sixth test: for same entity, sort by reference location unit
468 elsif T1.Lun /= T2.Lun then
469 return Dependency_Num (T1.Lun) < Dependency_Num (T2.Lun);
471 -- Seventh test: for same entity, sort by reference location scope
473 elsif Get_Scope_Num (T1.Ref_Scope) /=
474 Get_Scope_Num (T2.Ref_Scope)
476 return Get_Scope_Num (T1.Ref_Scope) < Get_Scope_Num (T2.Ref_Scope);
478 -- Eighth test: order of location within referencing unit
480 elsif T1.Loc /= T2.Loc then
481 return T1.Loc < T2.Loc;
483 -- Finally, for two locations at the same address prefer the one that
484 -- does NOT have the type 'r', so that a modification or extension
485 -- takes preference, when there are more than one reference at the
486 -- same location. As a result, in the case of entities that are
487 -- in-out actuals, the read reference follows the modify reference.
498 procedure Move (From : Natural; To : Natural) is
500 Rnums (Nat (To)) := Rnums (Nat (From));
503 -- Start of processing for Add_ALFA_Xrefs
506 for J in ALFA_Scope_Table.First .. ALFA_Scope_Table.Last loop
507 Set_Scope_Num (N => ALFA_Scope_Table.Table (J).Scope_Entity,
508 Num => ALFA_Scope_Table.Table (J).Scope_Num);
511 -- Set up the pointer vector for the sort
513 for J in 1 .. Nrefs loop
517 -- Eliminate entries not appropriate for ALFA. Done prior to sorting
518 -- cross-references, as it discards useless references which do not have
519 -- a proper format for the comparison function (like no location).
521 Eliminate_Before_Sort : declare
524 function Is_ALFA_Scope (E : Entity_Id) return Boolean;
525 -- Return whether the entity or reference scope is adequate
527 function Is_Global_Constant (E : Entity_Id) return Boolean;
528 -- Return True if E is a global constant for which we should ignore
535 function Is_ALFA_Scope (E : Entity_Id) return Boolean is
538 and then not Is_Generic_Unit (E)
539 and then Renamed_Entity (E) = Empty
540 and then Get_Scope_Num (E) /= No_Scope;
543 ------------------------
544 -- Is_Global_Constant --
545 ------------------------
547 function Is_Global_Constant (E : Entity_Id) return Boolean is
549 return Ekind (E) = E_Constant
550 and then Ekind_In (Scope (E), E_Package, E_Package_Body);
551 end Is_Global_Constant;
553 -- Start of processing for Eliminate_Before_Sort
559 for J in 1 .. NR loop
560 if ALFA_Entities (Ekind (Xrefs.Table (Rnums (J)).Ent))
561 and then ALFA_References (Xrefs.Table (Rnums (J)).Typ)
562 and then Is_ALFA_Scope (Xrefs.Table (Rnums (J)).Ent_Scope)
563 and then Is_ALFA_Scope (Xrefs.Table (Rnums (J)).Ref_Scope)
564 and then not Is_Global_Constant (Xrefs.Table (Rnums (J)).Ent)
567 Rnums (Nrefs) := Rnums (J);
570 end Eliminate_Before_Sort;
572 -- Sort the references
574 Sorting.Sort (Integer (Nrefs));
576 Eliminate_After_Sort : declare
580 -- Current reference location
583 -- reference kind of previous reference
586 -- Eliminate duplicate entries
588 -- We need this test for NR because if we force ALI file generation
589 -- in case of errors detected, it may be the case that Nrefs is 0, so
590 -- we should not reset it here
596 for J in 2 .. NR loop
597 if Xrefs.Table (Rnums (J)) /=
598 Xrefs.Table (Rnums (Nrefs))
601 Rnums (Nrefs) := Rnums (J);
606 -- Eliminate the reference if it is at the same location as the
607 -- previous one, unless it is a read-reference indicating that the
608 -- entity is an in-out actual in a call.
612 Crloc := No_Location;
615 for J in 1 .. NR loop
616 if Xrefs.Table (Rnums (J)).Loc /= Crloc
618 and then Xrefs.Table (Rnums (J)).Typ = 'r')
620 Crloc := Xrefs.Table (Rnums (J)).Loc;
621 Prevt := Xrefs.Table (Rnums (J)).Typ;
623 Rnums (Nrefs) := Rnums (J);
626 end Eliminate_After_Sort;
634 if ALFA_Scope_Table.Last = 0 then
638 -- Loop to output references
640 for Refno in 1 .. Nrefs loop
641 Add_One_Xref : declare
643 -----------------------
644 -- Local Subprograms --
645 -----------------------
647 function Cur_Scope return Node_Id;
648 -- Return scope entity which corresponds to index Cur_Scope_Idx in
649 -- table ALFA_Scope_Table.
651 function Get_Entity_Type (E : Entity_Id) return Character;
652 -- Return a character representing the type of entity
654 function Is_Future_Scope_Entity (E : Entity_Id) return Boolean;
655 -- Check whether entity E is in ALFA_Scope_Table at index
656 -- Cur_Scope_Idx or higher.
658 function Is_Past_Scope_Entity (E : Entity_Id) return Boolean;
659 -- Check whether entity E is in ALFA_Scope_Table at index strictly
660 -- lower than Cur_Scope_Idx.
666 function Cur_Scope return Node_Id is
668 return ALFA_Scope_Table.Table (Cur_Scope_Idx).Scope_Entity;
671 ---------------------
672 -- Get_Entity_Type --
673 ---------------------
675 function Get_Entity_Type (E : Entity_Id) return Character is
679 when E_Out_Parameter => C := '<';
680 when E_In_Out_Parameter => C := '=';
681 when E_In_Parameter => C := '>';
682 when others => C := '*';
687 ----------------------------
688 -- Is_Future_Scope_Entity --
689 ----------------------------
691 function Is_Future_Scope_Entity (E : Entity_Id) return Boolean is
693 for J in Cur_Scope_Idx .. ALFA_Scope_Table.Last loop
694 if E = ALFA_Scope_Table.Table (J).Scope_Entity then
699 -- If this assertion fails, this means that the scope which we
700 -- are looking for has been treated already, which reveals a
701 -- problem in the order of cross-references.
703 pragma Assert (not Is_Past_Scope_Entity (E));
706 end Is_Future_Scope_Entity;
708 --------------------------
709 -- Is_Past_Scope_Entity --
710 --------------------------
712 function Is_Past_Scope_Entity (E : Entity_Id) return Boolean is
714 for J in ALFA_Scope_Table.First .. Cur_Scope_Idx - 1 loop
715 if E = ALFA_Scope_Table.Table (J).Scope_Entity then
721 end Is_Past_Scope_Entity;
723 ---------------------
724 -- Local Variables --
725 ---------------------
727 XE : Xref_Entry renames Xrefs.Table (Rnums (Refno));
730 -- If this assertion fails, the scope which we are looking for is
731 -- not in ALFA scope table, which reveals either a problem in the
732 -- construction of the scope table, or an erroneous scope for the
733 -- current cross-reference.
735 pragma Assert (Is_Future_Scope_Entity (XE.Ent_Scope));
737 -- Update the range of cross references to which the current scope
738 -- refers to. This may be the empty range only for the first scope
741 if XE.Ent_Scope /= Cur_Scope then
742 ALFA_Scope_Table.Table (Cur_Scope_Idx).From_Xref :=
744 ALFA_Scope_Table.Table (Cur_Scope_Idx).To_Xref :=
745 ALFA_Xref_Table.Last;
746 From_Xref_Idx := ALFA_Xref_Table.Last + 1;
749 while XE.Ent_Scope /= Cur_Scope loop
750 Cur_Scope_Idx := Cur_Scope_Idx + 1;
751 pragma Assert (Cur_Scope_Idx <= ALFA_Scope_Table.Last);
754 if XE.Ent /= Cur_Entity then
756 new String'(Unique_Name (XE.Ent));
759 ALFA_Xref_Table.Append (
760 (Entity_Name => Cur_Entity_Name,
761 Entity_Line => Int (Get_Logical_Line_Number (XE.Def)),
762 Etype => Get_Entity_Type (XE.Ent),
763 Entity_Col => Int (Get_Column_Number (XE.Def)),
764 File_Num => Dependency_Num (XE.Lun),
765 Scope_Num => Get_Scope_Num (XE.Ref_Scope),
766 Line => Int (Get_Logical_Line_Number (XE.Loc)),
768 Col => Int (Get_Column_Number (XE.Loc))));
772 -- Update the range of cross references to which the scope refers to
774 ALFA_Scope_Table.Table (Cur_Scope_Idx).From_Xref := From_Xref_Idx;
775 ALFA_Scope_Table.Table (Cur_Scope_Idx).To_Xref := ALFA_Xref_Table.Last;
782 procedure Collect_ALFA (Sdep_Table : Unit_Ref_Table; Num_Sdep : Nat) is
784 -- Cross-references should have been computed first
786 pragma Assert (Xrefs.Last /= 0);
788 Initialize_ALFA_Tables;
790 -- Generate file and scope ALFA information
792 for D in 1 .. Num_Sdep loop
794 -- Ignore file for System
796 if Units.Table (Sdep_Table (D)).Source_Index /=
797 System_Source_File_Index
799 Add_ALFA_File (U => Sdep_Table (D), D => D);
803 -- Fill in the spec information when relevant
806 package Entity_Hash_Table is new
807 GNAT.HTable.Simple_HTable
808 (Header_Num => Entity_Hashed_Range,
809 Element => Scope_Index,
816 -- Fill in the hash-table
818 for S in ALFA_Scope_Table.First .. ALFA_Scope_Table.Last loop
820 Srec : ALFA_Scope_Record renames ALFA_Scope_Table.Table (S);
822 Entity_Hash_Table.Set (Srec.Scope_Entity, S);
826 -- Use the hash-table to locate spec entities
828 for S in ALFA_Scope_Table.First .. ALFA_Scope_Table.Last loop
830 Srec : ALFA_Scope_Record renames ALFA_Scope_Table.Table (S);
832 Body_Entity : Entity_Id;
833 Spec_Entity : Entity_Id;
834 Spec_Scope : Scope_Index;
837 if Ekind (Srec.Scope_Entity) = E_Subprogram_Body then
838 Body_Entity := Parent (Parent (Srec.Scope_Entity));
839 elsif Ekind (Srec.Scope_Entity) = E_Package_Body then
840 Body_Entity := Parent (Srec.Scope_Entity);
842 Body_Entity := Empty;
845 if Present (Body_Entity) then
846 if Nkind (Body_Entity) = N_Defining_Program_Unit_Name then
847 Body_Entity := Parent (Body_Entity);
850 Spec_Entity := Corresponding_Spec (Body_Entity);
851 Spec_Scope := Entity_Hash_Table.Get (Spec_Entity);
853 -- Spec of generic may be missing
855 if Spec_Scope /= 0 then
856 Srec.Spec_File_Num :=
857 ALFA_Scope_Table.Table (Spec_Scope).File_Num;
858 Srec.Spec_Scope_Num :=
859 ALFA_Scope_Table.Table (Spec_Scope).Scope_Num;
866 -- Generate cross reference ALFA information
871 -------------------------------
872 -- Detect_And_Add_ALFA_Scope --
873 -------------------------------
875 procedure Detect_And_Add_ALFA_Scope (N : Node_Id) is
877 if Nkind_In (N, N_Subprogram_Declaration,
879 N_Package_Declaration,
884 end Detect_And_Add_ALFA_Scope;
890 function Entity_Hash (E : Entity_Id) return Entity_Hashed_Range is
893 Entity_Hashed_Range (E mod (Entity_Id (Entity_Hashed_Range'Last) + 1));
896 ------------------------------------
897 -- Traverse_All_Compilation_Units --
898 ------------------------------------
900 procedure Traverse_All_Compilation_Units (Process : Node_Processing) is
902 for U in Units.First .. Last_Unit loop
903 Traverse_Compilation_Unit (Cunit (U), Process);
905 end Traverse_All_Compilation_Units;
907 -------------------------------
908 -- Traverse_Compilation_Unit --
909 -------------------------------
911 procedure Traverse_Compilation_Unit
913 Process : Node_Processing)
918 -- Get Unit (checking case of subunit)
922 if Nkind (Lu) = N_Subunit then
923 Lu := Proper_Body (Lu);
926 -- Call Process on all declarations
928 if Nkind (Lu) in N_Declaration
929 or else Nkind (Lu) in N_Later_Decl_Item
936 if Nkind (Lu) = N_Subprogram_Body then
937 Traverse_Subprogram_Body (Lu, Process);
939 elsif Nkind (Lu) = N_Subprogram_Declaration then
942 elsif Nkind (Lu) = N_Package_Declaration then
943 Traverse_Package_Declaration (Lu, Process);
945 elsif Nkind (Lu) = N_Package_Body then
946 Traverse_Package_Body (Lu, Process);
950 elsif Nkind (Lu) = N_Generic_Package_Declaration then
955 elsif Nkind (Lu) in N_Generic_Instantiation then
958 -- All other cases of compilation units (e.g. renamings), are not
964 end Traverse_Compilation_Unit;
966 -----------------------------------------
967 -- Traverse_Declarations_Or_Statements --
968 -----------------------------------------
970 procedure Traverse_Declarations_Or_Statements
972 Process : Node_Processing)
977 -- Loop through statements or declarations
980 while Present (N) loop
981 -- Call Process on all declarations
983 if Nkind (N) in N_Declaration
985 Nkind (N) in N_Later_Decl_Item
992 -- Package declaration
994 when N_Package_Declaration =>
995 Traverse_Package_Declaration (N, Process);
997 -- Generic package declaration ??? TBD
999 when N_Generic_Package_Declaration =>
1004 when N_Package_Body =>
1005 if Ekind (Defining_Entity (N)) /= E_Generic_Package then
1006 Traverse_Package_Body (N, Process);
1009 -- Subprogram declaration
1011 when N_Subprogram_Declaration =>
1014 -- Generic subprogram declaration ??? TBD
1016 when N_Generic_Subprogram_Declaration =>
1021 when N_Subprogram_Body =>
1022 if not Is_Generic_Subprogram (Defining_Entity (N)) then
1023 Traverse_Subprogram_Body (N, Process);
1028 when N_Block_Statement =>
1029 Traverse_Declarations_Or_Statements (Declarations (N), Process);
1030 Traverse_Handled_Statement_Sequence
1031 (Handled_Statement_Sequence (N), Process);
1033 when N_If_Statement =>
1035 -- Traverse the statements in the THEN part
1037 Traverse_Declarations_Or_Statements
1038 (Then_Statements (N), Process);
1040 -- Loop through ELSIF parts if present
1042 if Present (Elsif_Parts (N)) then
1044 Elif : Node_Id := First (Elsif_Parts (N));
1047 while Present (Elif) loop
1048 Traverse_Declarations_Or_Statements
1049 (Then_Statements (Elif), Process);
1055 -- Finally traverse the ELSE statements if present
1057 Traverse_Declarations_Or_Statements
1058 (Else_Statements (N), Process);
1062 when N_Case_Statement =>
1064 -- Process case branches
1069 Alt := First (Alternatives (N));
1070 while Present (Alt) loop
1071 Traverse_Declarations_Or_Statements
1072 (Statements (Alt), Process);
1077 -- Extended return statement
1079 when N_Extended_Return_Statement =>
1080 Traverse_Handled_Statement_Sequence
1081 (Handled_Statement_Sequence (N), Process);
1085 when N_Loop_Statement =>
1086 Traverse_Declarations_Or_Statements (Statements (N), Process);
1094 end Traverse_Declarations_Or_Statements;
1096 -----------------------------------------
1097 -- Traverse_Handled_Statement_Sequence --
1098 -----------------------------------------
1100 procedure Traverse_Handled_Statement_Sequence
1102 Process : Node_Processing)
1108 Traverse_Declarations_Or_Statements (Statements (N), Process);
1110 if Present (Exception_Handlers (N)) then
1111 Handler := First (Exception_Handlers (N));
1112 while Present (Handler) loop
1113 Traverse_Declarations_Or_Statements
1114 (Statements (Handler), Process);
1119 end Traverse_Handled_Statement_Sequence;
1121 ---------------------------
1122 -- Traverse_Package_Body --
1123 ---------------------------
1125 procedure Traverse_Package_Body
1127 Process : Node_Processing) is
1129 Traverse_Declarations_Or_Statements (Declarations (N), Process);
1130 Traverse_Handled_Statement_Sequence
1131 (Handled_Statement_Sequence (N), Process);
1132 end Traverse_Package_Body;
1134 ----------------------------------
1135 -- Traverse_Package_Declaration --
1136 ----------------------------------
1138 procedure Traverse_Package_Declaration
1140 Process : Node_Processing)
1142 Spec : constant Node_Id := Specification (N);
1144 Traverse_Declarations_Or_Statements
1145 (Visible_Declarations (Spec), Process);
1146 Traverse_Declarations_Or_Statements
1147 (Private_Declarations (Spec), Process);
1148 end Traverse_Package_Declaration;
1150 ------------------------------
1151 -- Traverse_Subprogram_Body --
1152 ------------------------------
1154 procedure Traverse_Subprogram_Body
1156 Process : Node_Processing) is
1158 Traverse_Declarations_Or_Statements (Declarations (N), Process);
1159 Traverse_Handled_Statement_Sequence
1160 (Handled_Statement_Sequence (N), Process);
1161 end Traverse_Subprogram_Body;