diff options
author | Arnaud Charlet <charlet@gcc.gnu.org> | 2011-08-03 10:22:52 +0200 |
---|---|---|
committer | Arnaud Charlet <charlet@gcc.gnu.org> | 2011-08-03 10:22:52 +0200 |
commit | 56e941863ba558a7a3426c686d6e5c08eefca90e (patch) | |
tree | eeabf64a1a78064507c612cff6b0b9e20b698374 /gcc/ada/lib-xref-alfa.adb | |
parent | 4317e442b4eced893bf40c552deb37c303d81102 (diff) | |
download | gcc-56e941863ba558a7a3426c686d6e5c08eefca90e.zip gcc-56e941863ba558a7a3426c686d6e5c08eefca90e.tar.gz gcc-56e941863ba558a7a3426c686d6e5c08eefca90e.tar.bz2 |
[multiple changes]
2011-08-03 Eric Botcazou <ebotcazou@adacore.com>
* gnat_ugn.texi: Document -Wstack-usage.
* gcc-interface/misc.c (enumerate_modes): Add guard for ghost FP modes.
2011-08-03 Thomas Quinot <quinot@adacore.com>
* sem_prag.adb Issue an error (not a warning) when a C++ type does not
have keyword LIMITED.
2011-08-03 Yannick Moy <moy@adacore.com>
* alfa.adb, alfa.ads, alfa_test.adb: New files.
* ali.adb (Known_ALI_Lines): add 'C' lines (SCO) and 'F' lines (ALFA)
(Scan_ALI): do not issue a fatal error if parsing known lines after Xref
section (does not happen in compiler, only if code directly calls
Scan_ALI).
* get_alfa.adb, get_alfa.ads: New files.
* lib-writ.adb, lib-writ.ads (Write_ALI): output ALFA information if
needed.
* lib-xref-alfa.adb: New file.
* lib-xref.adb, lib-xref.ads
(Xref_Entry): redefine information needed in cross-references for ALFA.
Push ALFA treatments in separated local package.
(Enclosing_Subpragram_Or_Package): treat specially subprogram
identifiers. Return entity of package body instead of spec. Return
Empty for a scope with no location.
(Generate_Reference): adapt to new components for ALFA information.
Remove the need for D references on definitions.
(Is_Local_Reference): moved to ALFA local package
(Output_References): extract subfunction as Extract_Source_Name
(Output_Local_References): remove procedure, replaced by filtering of
cross-references in package ALFA and printing in Put_ALFA.
(Write_Entity_Name): remove procedure
* lib.adb, lib.ads (Extract_Source_Name): extract here function to
print exact name of entity as it appears in source file
(Unit_Ref_Table): make type public for use in Lib.Xref.ALFA
* put_alfa.adb, put_alfa.ads: New files.
* xref_lib.adb (Search_Xref): protect read of cross-references against
reading other sections of the ALI file, in gnatxref
(Search): protect read of cross-references against reading other
sections of the ALI file, in gnatfind.
* gcc-interface/Make-lang.in: Update dependencies.
2011-08-03 Thomas Quinot <quinot@adacore.com>
* sem_ch3.adb: Minor reformatting.
2011-08-03 Jose Ruiz <ruiz@adacore.com>
* s-inmaop-vxworks.adb (Setup_Interrupt_Mask): Do nothing instead of
raising an exception.
2011-08-03 Ed Schonberg <schonberg@adacore.com>
* sem_res.adb (Set_String_Literal_Subtype): if index type is an integer
type, always use 1 as the lower bound or string, even if lower bound of
context is not static, to handle properly null strings in a non-static
context.
2011-08-03 Bob Duff <duff@adacore.com>
* sem_prag.adb (Resolve_Aggregate): An array aggregate with 'others' is
always legal on the right-hand side of an assignment statement; there
is always an applicable index constraint in this case. Therefore, the
check for Pkind = N_Assignment_Statement is now unconditional -- it
doesn't depend on whether Is_Constrained (Typ).
From-SVN: r177239
Diffstat (limited to 'gcc/ada/lib-xref-alfa.adb')
-rw-r--r-- | gcc/ada/lib-xref-alfa.adb | 938 |
1 files changed, 938 insertions, 0 deletions
diff --git a/gcc/ada/lib-xref-alfa.adb b/gcc/ada/lib-xref-alfa.adb new file mode 100644 index 0000000..a5dca53 --- /dev/null +++ b/gcc/ada/lib-xref-alfa.adb @@ -0,0 +1,938 @@ +------------------------------------------------------------------------------ +-- -- +-- GNAT COMPILER COMPONENTS -- +-- -- +-- L I B . X R E F . A L F A -- +-- -- +-- B o d y -- +-- -- +-- Copyright (C) 2011, Free Software Foundation, Inc. -- +-- -- +-- GNAT is free software; you can redistribute it and/or modify it under -- +-- terms of the GNU General Public License as published by the Free Soft- -- +-- ware Foundation; either version 3, or (at your option) any later ver- -- +-- sion. GNAT is distributed in the hope that it will be useful, but WITH- -- +-- OUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY -- +-- or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License -- +-- for more details. You should have received a copy of the GNU General -- +-- Public License distributed with GNAT; see file COPYING3. If not, go to -- +-- http://www.gnu.org/licenses for a complete copy of the license. -- +-- -- +-- GNAT was originally developed by the GNAT team at New York University. -- +-- Extensive contributions were provided by Ada Core Technologies Inc. -- +-- -- +------------------------------------------------------------------------------ + +with ALFA; use ALFA; +with Einfo; use Einfo; +with Put_ALFA; +with GNAT.HTable; + +separate (Lib.Xref) +package body ALFA is + + --------------------- + -- Local Constants -- + --------------------- + + -- True for each entity kind used in ALFA + ALFA_Entities : constant array (Entity_Kind) of Boolean := + (E_Void => False, + E_Variable => True, + E_Component => False, + E_Constant => True, + E_Discriminant => False, + + E_Loop_Parameter => True, + E_In_Parameter => True, + E_Out_Parameter => True, + E_In_Out_Parameter => True, + E_Generic_In_Out_Parameter => False, + + E_Generic_In_Parameter => False, + E_Named_Integer => False, + E_Named_Real => False, + E_Enumeration_Type => False, + E_Enumeration_Subtype => False, + + E_Signed_Integer_Type => False, + E_Signed_Integer_Subtype => False, + E_Modular_Integer_Type => False, + E_Modular_Integer_Subtype => False, + E_Ordinary_Fixed_Point_Type => False, + + E_Ordinary_Fixed_Point_Subtype => False, + E_Decimal_Fixed_Point_Type => False, + E_Decimal_Fixed_Point_Subtype => False, + E_Floating_Point_Type => False, + E_Floating_Point_Subtype => False, + + E_Access_Type => False, + E_Access_Subtype => False, + E_Access_Attribute_Type => False, + E_Allocator_Type => False, + E_General_Access_Type => False, + + E_Access_Subprogram_Type => False, + E_Access_Protected_Subprogram_Type => False, + E_Anonymous_Access_Subprogram_Type => False, + E_Anonymous_Access_Protected_Subprogram_Type => False, + E_Anonymous_Access_Type => False, + + E_Array_Type => False, + E_Array_Subtype => False, + E_String_Type => False, + E_String_Subtype => False, + E_String_Literal_Subtype => False, + + E_Class_Wide_Type => False, + E_Class_Wide_Subtype => False, + E_Record_Type => False, + E_Record_Subtype => False, + E_Record_Type_With_Private => False, + + E_Record_Subtype_With_Private => False, + E_Private_Type => False, + E_Private_Subtype => False, + E_Limited_Private_Type => False, + E_Limited_Private_Subtype => False, + + E_Incomplete_Type => False, + E_Incomplete_Subtype => False, + E_Task_Type => False, + E_Task_Subtype => False, + E_Protected_Type => False, + + E_Protected_Subtype => False, + E_Exception_Type => False, + E_Subprogram_Type => False, + E_Enumeration_Literal => False, + E_Function => True, + + E_Operator => True, + E_Procedure => True, + E_Entry => False, + E_Entry_Family => False, + E_Block => False, + + E_Entry_Index_Parameter => False, + E_Exception => False, + E_Generic_Function => False, + E_Generic_Package => False, + E_Generic_Procedure => False, + + E_Label => False, + E_Loop => False, + E_Return_Statement => False, + E_Package => False, + + E_Package_Body => False, + E_Protected_Object => False, + E_Protected_Body => False, + E_Task_Body => False, + E_Subprogram_Body => False); + + -- True for each reference type used in ALFA + ALFA_References : constant array (Character) of Boolean := + ('m' => True, + 'r' => True, + 's' => True, + others => False); + + ----------------------- + -- Local Subprograms -- + ----------------------- + + procedure Add_ALFA_File (U : Unit_Number_Type; D : Nat); + -- Add file U and all scopes in U to the tables ALFA_File_Table and + -- ALFA_Scope_Table. + + procedure Add_ALFA_Scope (N : Node_Id); + -- Add scope N to the table ALFA_Scope_Table + + procedure Add_ALFA_Xrefs; + -- Filter table Xrefs to add all references used in ALFA to the table + -- ALFA_Xref_Table. + + procedure Traverse_Declarations_Or_Statements (L : List_Id); + procedure Traverse_Handled_Statement_Sequence (N : Node_Id); + procedure Traverse_Package_Body (N : Node_Id); + procedure Traverse_Package_Declaration (N : Node_Id); + procedure Traverse_Subprogram_Body (N : Node_Id); + -- Traverse the corresponding construct, generating ALFA scope table + -- entries. + + ------------------- + -- Add_ALFA_File -- + ------------------- + + procedure Add_ALFA_File (U : Unit_Number_Type; D : Nat) is + Lu : Node_Id; + From : Scope_Index; + + S : constant Source_File_Index := Source_Index (U); + begin + -- Source file could be inexistant as a result of an error, if option + -- gnatQ is used. + + if S = No_Source_File then + return; + end if; + + From := ALFA_Scope_Table.Last + 1; + + -- Get Unit (checking case of subunit) + + Lu := Unit (Cunit (U)); + + if Nkind (Lu) = N_Subunit then + Lu := Proper_Body (Lu); + end if; + + -- Traverse the unit + + if Nkind (Lu) = N_Subprogram_Body then + Traverse_Subprogram_Body (Lu); + + elsif Nkind (Lu) = N_Subprogram_Declaration then + Add_ALFA_Scope (Lu); + + elsif Nkind (Lu) = N_Package_Declaration then + Traverse_Package_Declaration (Lu); + + elsif Nkind (Lu) = N_Package_Body then + Traverse_Package_Body (Lu); + + -- ??? TBD + + elsif Nkind (Lu) = N_Generic_Package_Declaration then + null; + + -- ??? TBD + + elsif Nkind (Lu) in N_Generic_Instantiation then + null; + + -- All other cases of compilation units (e.g. renamings), generate + -- no ALFA information. + + else + null; + end if; + + -- Update scope numbers + + for S in From .. ALFA_Scope_Table.Last loop + declare + E : Entity_Id renames ALFA_Scope_Table.Table (S).Scope_Entity; + begin + if Lib.Get_Source_Unit (E) = U then + ALFA_Scope_Table.Table (S).Scope_Num := Int (S - From) + 1; + ALFA_Scope_Table.Table (S).File_Num := D; + + else + -- Remove scope S which is not located in unit U, for example + -- for scope inside generics that get instantiated. + + for J in S .. ALFA_Scope_Table.Last - 1 loop + ALFA_Scope_Table.Table (J) := ALFA_Scope_Table.Table (J + 1); + end loop; + ALFA_Scope_Table.Set_Last (ALFA_Scope_Table.Last - 1); + end if; + end; + end loop; + + -- Make entry for new file in file table + + Get_Name_String (Reference_Name (S)); + + ALFA_File_Table.Append ( + (File_Name => new String'(Name_Buffer (1 .. Name_Len)), + File_Num => D, + From_Scope => From, + To_Scope => ALFA_Scope_Table.Last)); + end Add_ALFA_File; + + -------------------- + -- Add_ALFA_Scope -- + -------------------- + + procedure Add_ALFA_Scope (N : Node_Id) is + E : constant Entity_Id := Defining_Entity (N); + Loc : constant Source_Ptr := Sloc (E); + Typ : Character; + + begin + -- Ignore scopes without a proper location + + if Sloc (N) = No_Location then + return; + end if; + + case Ekind (E) is + when E_Function => + Typ := 'V'; + + when E_Procedure => + Typ := 'U'; + + when E_Subprogram_Body => + declare + Spec : Node_Id; + + begin + Spec := Parent (E); + + if Nkind (Spec) = N_Defining_Program_Unit_Name then + Spec := Parent (Spec); + end if; + + if Nkind (Spec) = N_Function_Specification then + Typ := 'V'; + else + pragma Assert + (Nkind (Spec) = N_Procedure_Specification); + Typ := 'U'; + end if; + end; + + when E_Package | E_Package_Body => + Typ := 'K'; + + when E_Void => + -- Compilation of prj-attr.adb with -gnatn creates a node with + -- entity E_Void for the package defined at a-charac.ads16:13 + + -- ??? TBD + + return; + + when others => + raise Program_Error; + end case; + + -- File_Num and Scope_Num are filled later. From_Xref and To_Xref are + -- filled even later, but are initialized to represent an empty range. + + ALFA_Scope_Table.Append ( + (Scope_Name => new String'(Exact_Source_Name (Sloc (E))), + File_Num => 0, + Scope_Num => 0, + Line => Nat (Get_Logical_Line_Number (Loc)), + Stype => Typ, + Col => Nat (Get_Column_Number (Loc)), + From_Xref => 1, + To_Xref => 0, + Scope_Entity => E)); + end Add_ALFA_Scope; + + -------------------- + -- Add_ALFA_Xrefs -- + -------------------- + + procedure Add_ALFA_Xrefs is + Prev_Scope_Idx : Scope_Index; + Cur_Scope_Idx : Scope_Index; + From_Xref_Idx : Xref_Index; + Cur_Entity : Entity_Id; + Cur_Entity_Name : String_Ptr; + + package Scopes is + No_Scope : constant Nat := 0; + function Get_Scope_Num (N : Entity_Id) return Nat; + procedure Set_Scope_Num (N : Entity_Id; Num : Nat); + end Scopes; + + package body Scopes is + type Scope is record + Num : Nat; + Entity : Entity_Id; + end record; + + type Scope_Hashed is range 0 .. 255; + + function Scope_Hash (E : Entity_Id) return Scope_Hashed; + + function Scope_Hash (E : Entity_Id) return Scope_Hashed is + Value : constant Int := Int (E); + Modulo : constant Int := Int (Scope_Hashed'Last) + 1; + begin + return Scope_Hashed (Value - (Value / Modulo) * Modulo); + end Scope_Hash; + + package Scopes is new GNAT.HTable.Simple_HTable + (Header_Num => Scope_Hashed, + Element => Scope, + No_Element => (Num => No_Scope, Entity => Empty), + Key => Entity_Id, + Hash => Scope_Hash, + Equal => "="); + + function Get_Scope_Num (N : Entity_Id) return Nat is + begin + return Scopes.Get (N).Num; + end Get_Scope_Num; + + procedure Set_Scope_Num (N : Entity_Id; Num : Nat) is + begin + Scopes.Set (K => N, E => Scope'(Num => Num, Entity => N)); + end Set_Scope_Num; + end Scopes; + + use Scopes; + + Nrefs : Nat := Xrefs.Last; + -- Number of references in table. This value may get reset (reduced) + -- when we eliminate duplicate reference entries as well as references + -- not suitable for local cross-references. + + Rnums : array (0 .. Nrefs) of Nat; + -- This array contains numbers of references in the Xrefs table. This + -- list is sorted in output order. The extra 0'th entry is convenient + -- for the call to sort. When we sort the table, we move the entries in + -- Rnums around, but we do not move the original table entries. + + function Lt (Op1, Op2 : Natural) return Boolean; + -- Comparison function for Sort call + + procedure Move (From : Natural; To : Natural); + -- Move procedure for Sort call + + package Sorting is new GNAT.Heap_Sort_G (Move, Lt); + + -------- + -- Lt -- + -------- + + function Lt (Op1, Op2 : Natural) return Boolean is + T1 : constant Xref_Entry := Xrefs.Table (Rnums (Nat (Op1))); + T2 : constant Xref_Entry := Xrefs.Table (Rnums (Nat (Op2))); + + begin + -- First test: if entity is in different unit, sort by unit. Notice + -- that we use Ent_Scope_File rather than Eun, as Eun may refer to + -- the file where the generic scope is defined, and it may be + -- different from the file where the enclosing scope is defined. It + -- is the latter which matters for a correct order here. + + if T1.Ent_Scope_File /= T2.Ent_Scope_File then + return Dependency_Num (T1.Ent_Scope_File) < + Dependency_Num (T2.Ent_Scope_File); + + -- Second test: within same unit, sort by location of the scope of + -- the entity definition. + + elsif Get_Scope_Num (T1.Ent_Scope) /= + Get_Scope_Num (T2.Ent_Scope) + then + return Get_Scope_Num (T1.Ent_Scope) < Get_Scope_Num (T2.Ent_Scope); + + -- Third test: within same unit and scope, sort by location of + -- entity definition. + + elsif T1.Def /= T2.Def then + return T1.Def < T2.Def; + + -- Fourth test: if reference is in same unit as entity definition, + -- sort first. + + elsif T1.Lun /= T2.Lun and then T1.Ent_Scope_File = T1.Lun then + return True; + elsif T1.Lun /= T2.Lun and then T2.Ent_Scope_File = T2.Lun then + return False; + + -- Fifth test: if reference is in same unit and same scope as entity + -- definition, sort first. + + elsif T1.Ent_Scope_File = T1.Lun + and then T1.Ref_Scope /= T2.Ref_Scope + and then T1.Ent_Scope = T1.Ref_Scope + then + return True; + elsif T1.Ent_Scope_File = T1.Lun + and then T1.Ref_Scope /= T2.Ref_Scope + and then T2.Ent_Scope = T2.Ref_Scope + then + return False; + + -- Sixth test: for same entity, sort by reference location unit + + elsif T1.Lun /= T2.Lun then + return Dependency_Num (T1.Lun) < Dependency_Num (T2.Lun); + + -- Seventh test: for same entity, sort by reference location scope + + elsif Get_Scope_Num (T1.Ref_Scope) /= + Get_Scope_Num (T2.Ref_Scope) + then + return Get_Scope_Num (T1.Ref_Scope) < Get_Scope_Num (T2.Ref_Scope); + + -- Eighth test: order of location within referencing unit + + elsif T1.Loc /= T2.Loc then + return T1.Loc < T2.Loc; + + -- Finally, for two locations at the same address, we prefer the one + -- that does NOT have the type 'r' so that a modification or + -- extension takes preference, when there are more than one reference + -- at the same location. As a result, in the case of entities that + -- are in-out actuals, the read reference follows the modify + -- reference. + + else + return T2.Typ = 'r'; + end if; + end Lt; + + ---------- + -- Move -- + ---------- + + procedure Move (From : Natural; To : Natural) is + begin + Rnums (Nat (To)) := Rnums (Nat (From)); + end Move; + + -- Start of processing for Add_ALFA_Xrefs + begin + + for J in ALFA_Scope_Table.First .. ALFA_Scope_Table.Last loop + Set_Scope_Num (N => ALFA_Scope_Table.Table (J).Scope_Entity, + Num => ALFA_Scope_Table.Table (J).Scope_Num); + end loop; + + -- Set up the pointer vector for the sort + + for J in 1 .. Nrefs loop + Rnums (J) := J; + end loop; + + -- Eliminate entries not appropriate for ALFA. Should be prior to + -- sorting cross-references, as it discards useless references which do + -- not have a proper format for the comparison function (like no + -- location). + + Eliminate_Before_Sort : declare + NR : Nat; + + function Is_ALFA_Scope (E : Entity_Id) return Boolean; + -- Return whether the entity or reference scope is adequate + + ------------------- + -- Is_ALFA_Scope -- + ------------------- + + function Is_ALFA_Scope (E : Entity_Id) return Boolean is + begin + return Present (E) + and then not Is_Generic_Unit (E) + and then Renamed_Entity (E) = Empty + and then Get_Scope_Num (E) /= No_Scope; + end Is_ALFA_Scope; + + -- Start of processing for Eliminate_Before_Sort + begin + + NR := Nrefs; + Nrefs := 0; + + for J in 1 .. NR loop + if ALFA_Entities (Ekind (Xrefs.Table (Rnums (J)).Ent)) + and then ALFA_References (Xrefs.Table (Rnums (J)).Typ) + and then Is_ALFA_Scope (Xrefs.Table (Rnums (J)).Ent_Scope) + and then Is_ALFA_Scope (Xrefs.Table (Rnums (J)).Ref_Scope) + then + Nrefs := Nrefs + 1; + Rnums (Nrefs) := Rnums (J); + end if; + end loop; + end Eliminate_Before_Sort; + + -- Sort the references + + Sorting.Sort (Integer (Nrefs)); + + Eliminate_After_Sort : declare + NR : Nat; + + Crloc : Source_Ptr; + -- Current reference location + + Prevt : Character; + -- reference kind of previous reference + + begin + -- Eliminate duplicate entries + + -- We need this test for NR because if we force ALI file generation + -- in case of errors detected, it may be the case that Nrefs is 0, so + -- we should not reset it here + + if Nrefs >= 2 then + NR := Nrefs; + Nrefs := 1; + + for J in 2 .. NR loop + if Xrefs.Table (Rnums (J)) /= + Xrefs.Table (Rnums (Nrefs)) + then + Nrefs := Nrefs + 1; + Rnums (Nrefs) := Rnums (J); + end if; + end loop; + end if; + + -- Eliminate the reference if it is at the same location as the + -- previous one, unless it is a read-reference that indicates that + -- the entity is an in-out actual in a call. + + NR := Nrefs; + Nrefs := 0; + Crloc := No_Location; + Prevt := 'm'; + + for J in 1 .. NR loop + if Xrefs.Table (Rnums (J)).Loc /= Crloc + or else (Prevt = 'm' + and then Xrefs.Table (Rnums (J)).Typ = 'r') + then + Crloc := Xrefs.Table (Rnums (J)).Loc; + Prevt := Xrefs.Table (Rnums (J)).Typ; + Nrefs := Nrefs + 1; + Rnums (Nrefs) := Rnums (J); + end if; + end loop; + end Eliminate_After_Sort; + + -- Initialize loop + + Prev_Scope_Idx := 1; + Cur_Scope_Idx := 1; + From_Xref_Idx := 1; + Cur_Entity := Empty; + + if ALFA_Scope_Table.Last /= 0 then + ALFA_Scope_Table.Table (1).From_Xref := 1; + end if; + + -- Loop to output references + + for Refno in 1 .. Nrefs loop + Add_One_Xref : declare + + ----------------------- + -- Local Subprograms -- + ----------------------- + + function Cur_Scope return Node_Id; + -- Return the scope entity which corresponds to index + -- Cur_Scope_Idx in table ALFA_Scope_Table. + + function Is_Future_Scope_Entity (E : Entity_Id) return Boolean; + -- Check whether entity E is in ALFA_Scope_Table at index + -- Cur_Scope_Idx or higher. + + function Is_Past_Scope_Entity (E : Entity_Id) return Boolean; + -- Check whether entity E is in ALFA_Scope_Table at index strictly + -- lower than Cur_Scope_Idx. + + --------------- + -- Cur_Scope -- + --------------- + + function Cur_Scope return Node_Id is + begin + return ALFA_Scope_Table.Table (Cur_Scope_Idx).Scope_Entity; + end Cur_Scope; + + ---------------------------- + -- Is_Future_Scope_Entity -- + ---------------------------- + + function Is_Future_Scope_Entity (E : Entity_Id) return Boolean is + begin + for J in Cur_Scope_Idx .. ALFA_Scope_Table.Last loop + if E = ALFA_Scope_Table.Table (J).Scope_Entity then + return True; + end if; + end loop; + + -- If this assertion fails, this means that the scope which we + -- are looking for has been treated already, which reveals a + -- problem in the order of cross-references. + + pragma Assert (not Is_Past_Scope_Entity (E)); + + return False; + end Is_Future_Scope_Entity; + + -------------------------- + -- Is_Past_Scope_Entity -- + -------------------------- + + function Is_Past_Scope_Entity (E : Entity_Id) return Boolean is + begin + for J in ALFA_Scope_Table.First .. Cur_Scope_Idx - 1 loop + if E = ALFA_Scope_Table.Table (J).Scope_Entity then + return True; + end if; + end loop; + + return False; + end Is_Past_Scope_Entity; + + --------------------- + -- Local Variables -- + --------------------- + + XE : Xref_Entry renames Xrefs.Table (Rnums (Refno)); + + begin + -- If this assertion fails, this means that the scope which we + -- are looking for is not in ALFA scope table, which reveals + -- either a problem in the construction of the scope table, or an + -- erroneous scope for the current cross-reference. + + pragma Assert (Is_Future_Scope_Entity (XE.Ent_Scope)); + + if XE.Ent_Scope /= Cur_Scope then + ALFA_Scope_Table.Table (Cur_Scope_Idx).From_Xref := + From_Xref_Idx; + From_Xref_Idx := ALFA_Xref_Table.Last + 1; + end if; + + while XE.Ent_Scope /= Cur_Scope loop + Cur_Scope_Idx := Cur_Scope_Idx + 1; + pragma Assert (Cur_Scope_Idx <= ALFA_Scope_Table.Last); + end loop; + + if Prev_Scope_Idx /= Cur_Scope_Idx + and then ALFA_Xref_Table.Last /= 0 + then + ALFA_Scope_Table.Table (Prev_Scope_Idx).To_Xref := + ALFA_Xref_Table.Last; + Prev_Scope_Idx := Cur_Scope_Idx; + end if; + + if XE.Ent /= Cur_Entity then + Cur_Entity_Name := + new String'(Exact_Source_Name (Sloc (XE.Ent))); + end if; + + ALFA_Xref_Table.Append ( + (Entity_Name => Cur_Entity_Name, + Entity_Line => Int (Get_Logical_Line_Number (XE.Def)), + Entity_Col => Int (Get_Column_Number (XE.Def)), + File_Num => Dependency_Num (XE.Lun), + Scope_Num => Get_Scope_Num (XE.Ref_Scope), + Line => Int (Get_Logical_Line_Number (XE.Loc)), + Rtype => XE.Typ, + Col => Int (Get_Column_Number (XE.Loc)))); + end Add_One_Xref; + end loop; + + ALFA_Scope_Table.Table (Cur_Scope_Idx).From_Xref := From_Xref_Idx; + ALFA_Scope_Table.Table (Cur_Scope_Idx).To_Xref := ALFA_Xref_Table.Last; + end Add_ALFA_Xrefs; + + ------------------ + -- Collect_ALFA -- + ------------------ + + procedure Collect_ALFA (Sdep_Table : Unit_Ref_Table; Num_Sdep : Nat) is + begin + -- Cross-references should have been computed first + + pragma Assert (Xrefs.Last /= 0); + + Initialize_ALFA_Tables; + + -- Generate file and scope ALFA information + + for D in 1 .. Num_Sdep loop + + -- Ignore file for System + + if Units.Table (Sdep_Table (D)).Source_Index /= + System_Source_File_Index + then + Add_ALFA_File (U => Sdep_Table (D), D => D); + end if; + end loop; + + -- Generate cross reference ALFA information + + Add_ALFA_Xrefs; + end Collect_ALFA; + + ----------------------------------------- + -- Traverse_Declarations_Or_Statements -- + ----------------------------------------- + + procedure Traverse_Declarations_Or_Statements (L : List_Id) is + N : Node_Id; + + begin + -- Loop through statements or declarations + + N := First (L); + while Present (N) loop + case Nkind (N) is + + -- Package declaration + + when N_Package_Declaration => + Traverse_Package_Declaration (N); + + -- Generic package declaration ??? TBD + + when N_Generic_Package_Declaration => + null; + + -- Package body + + when N_Package_Body => + if Ekind (Defining_Entity (N)) /= E_Generic_Package then + Traverse_Package_Body (N); + end if; + + -- Subprogram declaration + + when N_Subprogram_Declaration => + Add_ALFA_Scope (N); + + -- Generic subprogram declaration ??? TBD + + when N_Generic_Subprogram_Declaration => + null; + + -- Subprogram body + + when N_Subprogram_Body => + if not Is_Generic_Subprogram (Defining_Entity (N)) then + Traverse_Subprogram_Body (N); + end if; + + -- Block statement + + when N_Block_Statement => + Traverse_Declarations_Or_Statements (Declarations (N)); + Traverse_Handled_Statement_Sequence + (Handled_Statement_Sequence (N)); + + when N_If_Statement => + + -- Traverse the statements in the THEN part + + Traverse_Declarations_Or_Statements (Then_Statements (N)); + + -- Loop through ELSIF parts if present + + if Present (Elsif_Parts (N)) then + declare + Elif : Node_Id := First (Elsif_Parts (N)); + + begin + while Present (Elif) loop + Traverse_Declarations_Or_Statements + (Then_Statements (Elif)); + Next (Elif); + end loop; + end; + end if; + + -- Finally traverse the ELSE statements if present + + Traverse_Declarations_Or_Statements (Else_Statements (N)); + + -- Case statement + + when N_Case_Statement => + + -- Process case branches + + declare + Alt : Node_Id; + begin + Alt := First (Alternatives (N)); + while Present (Alt) loop + Traverse_Declarations_Or_Statements (Statements (Alt)); + Next (Alt); + end loop; + end; + + -- Extended return statement + + when N_Extended_Return_Statement => + Traverse_Handled_Statement_Sequence + (Handled_Statement_Sequence (N)); + + -- Loop + + when N_Loop_Statement => + Traverse_Declarations_Or_Statements (Statements (N)); + + when others => + null; + end case; + + Next (N); + end loop; + end Traverse_Declarations_Or_Statements; + + ----------------------------------------- + -- Traverse_Handled_Statement_Sequence -- + ----------------------------------------- + + procedure Traverse_Handled_Statement_Sequence (N : Node_Id) is + Handler : Node_Id; + + begin + if Present (N) then + Traverse_Declarations_Or_Statements (Statements (N)); + + if Present (Exception_Handlers (N)) then + Handler := First (Exception_Handlers (N)); + while Present (Handler) loop + Traverse_Declarations_Or_Statements (Statements (Handler)); + Next (Handler); + end loop; + end if; + end if; + end Traverse_Handled_Statement_Sequence; + + --------------------------- + -- Traverse_Package_Body -- + --------------------------- + + procedure Traverse_Package_Body (N : Node_Id) is + begin + Add_ALFA_Scope (N); + Traverse_Declarations_Or_Statements (Declarations (N)); + Traverse_Handled_Statement_Sequence (Handled_Statement_Sequence (N)); + end Traverse_Package_Body; + + ---------------------------------- + -- Traverse_Package_Declaration -- + ---------------------------------- + + procedure Traverse_Package_Declaration (N : Node_Id) is + Spec : constant Node_Id := Specification (N); + begin + Add_ALFA_Scope (N); + Traverse_Declarations_Or_Statements (Visible_Declarations (Spec)); + Traverse_Declarations_Or_Statements (Private_Declarations (Spec)); + end Traverse_Package_Declaration; + + ------------------------------ + -- Traverse_Subprogram_Body -- + ------------------------------ + + procedure Traverse_Subprogram_Body (N : Node_Id) is + begin + Add_ALFA_Scope (N); + Traverse_Declarations_Or_Statements (Declarations (N)); + Traverse_Handled_Statement_Sequence (Handled_Statement_Sequence (N)); + end Traverse_Subprogram_Body; + +end ALFA; |