OSDN Git Service

2007-04-20 Robert Dewar <dewar@adacore.com>
[pf3gnuchains/gcc-fork.git] / gcc / ada / lib-xref.adb
1 ------------------------------------------------------------------------------
2 --                                                                          --
3 --                         GNAT COMPILER COMPONENTS                         --
4 --                                                                          --
5 --                             L I B . X R E F                              --
6 --                                                                          --
7 --                                 B o d y                                  --
8 --                                                                          --
9 --          Copyright (C) 1998-2007, Free Software Foundation, Inc.         --
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 2,  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 COPYING.  If not, write --
19 -- to  the  Free Software Foundation,  51  Franklin  Street,  Fifth  Floor, --
20 -- Boston, MA 02110-1301, USA.                                              --
21 --                                                                          --
22 -- GNAT was originally developed  by the GNAT team at  New York University. --
23 -- Extensive contributions were provided by Ada Core Technologies Inc.      --
24 --                                                                          --
25 ------------------------------------------------------------------------------
26
27 with Atree;    use Atree;
28 with Csets;    use Csets;
29 with Elists;   use Elists;
30 with Errout;   use Errout;
31 with Lib.Util; use Lib.Util;
32 with Nlists;   use Nlists;
33 with Opt;      use Opt;
34 with Restrict; use Restrict;
35 with Rident;   use Rident;
36 with Sem;      use Sem;
37 with Sem_Prag; use Sem_Prag;
38 with Sem_Util; use Sem_Util;
39 with Sem_Warn; use Sem_Warn;
40 with Sinfo;    use Sinfo;
41 with Sinput;   use Sinput;
42 with Snames;   use Snames;
43 with Stringt;  use Stringt;
44 with Stand;    use Stand;
45 with Table;    use Table;
46 with Widechar; use Widechar;
47
48 with GNAT.Heap_Sort_A;
49
50 package body Lib.Xref is
51
52    ------------------
53    -- Declarations --
54    ------------------
55
56    --  The Xref table is used to record references. The Loc field is set
57    --  to No_Location for a definition entry.
58
59    subtype Xref_Entry_Number is Int;
60
61    type Xref_Entry is record
62       Ent : Entity_Id;
63       --  Entity referenced (E parameter to Generate_Reference)
64
65       Def : Source_Ptr;
66       --  Original source location for entity being referenced. Note that
67       --  these values are used only during the output process, they are
68       --  not set when the entries are originally built. This is because
69       --  private entities can be swapped when the initial call is made.
70
71       Loc : Source_Ptr;
72       --  Location of reference (Original_Location (Sloc field of N parameter
73       --  to Generate_Reference). Set to No_Location for the case of a
74       --  defining occurrence.
75
76       Typ : Character;
77       --  Reference type (Typ param to Generate_Reference)
78
79       Eun : Unit_Number_Type;
80       --  Unit number corresponding to Ent
81
82       Lun : Unit_Number_Type;
83       --  Unit number corresponding to Loc. Value is undefined and not
84       --  referenced if Loc is set to No_Location.
85
86    end record;
87
88    package Xrefs is new Table.Table (
89      Table_Component_Type => Xref_Entry,
90      Table_Index_Type     => Xref_Entry_Number,
91      Table_Low_Bound      => 1,
92      Table_Initial        => Alloc.Xrefs_Initial,
93      Table_Increment      => Alloc.Xrefs_Increment,
94      Table_Name           => "Xrefs");
95
96    -------------------------
97    -- Generate_Definition --
98    -------------------------
99
100    procedure Generate_Definition (E : Entity_Id) is
101       Loc  : Source_Ptr;
102       Indx : Nat;
103
104    begin
105       pragma Assert (Nkind (E) in N_Entity);
106
107       --  Note that we do not test Xref_Entity_Letters here. It is too
108       --  early to do so, since we are often called before the entity
109       --  is fully constructed, so that the Ekind is still E_Void.
110
111       if Opt.Xref_Active
112
113          --  Definition must come from source
114
115          --  We make an exception for subprogram child units that have no
116          --  spec. For these we generate a subprogram declaration for library
117          --  use, and the corresponding entity does not come from source.
118          --  Nevertheless, all references will be attached to it and we have
119          --  to treat is as coming from user code.
120
121          and then (Comes_From_Source (E) or else Is_Child_Unit (E))
122
123          --  And must have a reasonable source location that is not
124          --  within an instance (all entities in instances are ignored)
125
126          and then Sloc (E) > No_Location
127          and then Instantiation_Location (Sloc (E)) = No_Location
128
129          --  And must be a non-internal name from the main source unit
130
131          and then In_Extended_Main_Source_Unit (E)
132          and then not Is_Internal_Name (Chars (E))
133       then
134          Xrefs.Increment_Last;
135          Indx := Xrefs.Last;
136          Loc  := Original_Location (Sloc (E));
137
138          Xrefs.Table (Indx).Ent := E;
139          Xrefs.Table (Indx).Def := No_Location;
140          Xrefs.Table (Indx).Loc := No_Location;
141          Xrefs.Table (Indx).Typ := ' ';
142          Xrefs.Table (Indx).Eun := Get_Source_Unit (Loc);
143          Xrefs.Table (Indx).Lun := No_Unit;
144          Set_Has_Xref_Entry (E);
145
146          if In_Inlined_Body then
147             Set_Referenced (E);
148          end if;
149       end if;
150    end Generate_Definition;
151
152    ---------------------------------
153    -- Generate_Operator_Reference --
154    ---------------------------------
155
156    procedure Generate_Operator_Reference
157      (N : Node_Id;
158       T : Entity_Id)
159    is
160    begin
161       if not In_Extended_Main_Source_Unit (N) then
162          return;
163       end if;
164
165       --  If the operator is not a Standard operator, then we generate
166       --  a real reference to the user defined operator.
167
168       if Sloc (Entity (N)) /= Standard_Location then
169          Generate_Reference (Entity (N), N);
170
171          --  A reference to an implicit inequality operator is a also a
172          --  reference to the user-defined equality.
173
174          if Nkind (N) = N_Op_Ne
175            and then not Comes_From_Source (Entity (N))
176            and then Present (Corresponding_Equality (Entity (N)))
177          then
178             Generate_Reference (Corresponding_Equality (Entity (N)), N);
179          end if;
180
181       --  For the case of Standard operators, we mark the result type
182       --  as referenced. This ensures that in the case where we are
183       --  using a derived operator, we mark an entity of the unit that
184       --  implicitly defines this operator as used. Otherwise we may
185       --  think that no entity of the unit is used. The actual entity
186       --  marked as referenced is the first subtype, which is the user
187       --  defined entity that is relevant.
188
189       --  Note: we only do this for operators that come from source.
190       --  The generated code sometimes reaches for entities that do
191       --  not need to be explicitly visible (for example, when we
192       --  expand the code for comparing two record types, the fields
193       --  of the record may not be visible).
194
195       elsif Comes_From_Source (N) then
196          Set_Referenced (First_Subtype (T));
197       end if;
198    end Generate_Operator_Reference;
199
200    ------------------------
201    -- Generate_Reference --
202    ------------------------
203
204    procedure Generate_Reference
205      (E       : Entity_Id;
206       N       : Node_Id;
207       Typ     : Character := 'r';
208       Set_Ref : Boolean   := True;
209       Force   : Boolean   := False)
210    is
211       Indx : Nat;
212       Nod  : Node_Id;
213       Ref  : Source_Ptr;
214       Def  : Source_Ptr;
215       Ent  : Entity_Id;
216
217       function Is_On_LHS (Node : Node_Id) return Boolean;
218       --  Used to check if a node is on the left hand side of an assignment.
219       --  The following cases are handled:
220       --
221       --   Variable  Node is a direct descendant of an assignment statement.
222       --
223       --   Prefix    Of an indexed or selected component that is present in a
224       --             subtree rooted by an assignment statement. There is no
225       --             restriction of nesting of components, thus cases such as
226       --             A.B(C).D are handled properly.
227
228       ---------------
229       -- Is_On_LHS --
230       ---------------
231
232       --  Couldn't we use Is_Lvalue or whatever it is called ???
233
234       function Is_On_LHS (Node : Node_Id) return Boolean is
235          N : Node_Id := Node;
236
237       begin
238          --  Only identifiers are considered, is this necessary???
239
240          if Nkind (N) /= N_Identifier then
241             return False;
242          end if;
243
244          --  Reach the assignment statement subtree root. In the case of a
245          --  variable being a direct descendant of an assignment statement,
246          --  the loop is skiped.
247
248          while Nkind (Parent (N)) /= N_Assignment_Statement loop
249
250             --  Check whether the parent is a component and the
251             --  current node is its prefix.
252
253             if (Nkind (Parent (N)) = N_Selected_Component
254                   or else
255                 Nkind (Parent (N)) = N_Indexed_Component)
256               and then Prefix (Parent (N)) = N
257             then
258                N := Parent (N);
259             else
260                return False;
261             end if;
262          end loop;
263
264          --  Parent (N) is assignment statement, check whether N is its name
265
266          return Name (Parent (N)) = N;
267       end Is_On_LHS;
268
269    --  Start of processing for Generate_Reference
270
271    begin
272       pragma Assert (Nkind (E) in N_Entity);
273
274       --  Check for obsolescent reference to package ASCII. GNAT treats this
275       --  element of annex J specially since in practice, programs make a lot
276       --  of use of this feature, so we don't include it in the set of features
277       --  diagnosed when Warn_On_Obsolescent_Features mode is set. However we
278       --  are required to note it as a violation of the RM defined restriction.
279
280       if E = Standard_ASCII then
281          Check_Restriction (No_Obsolescent_Features, N);
282       end if;
283
284       --  Check for reference to entity marked with Is_Obsolescent
285
286       --  Note that we always allow obsolescent references in the compiler
287       --  itself and the run time, since we assume that we know what we are
288       --  doing in such cases. For example the calls in Ada.Characters.Handling
289       --  to its own obsolescent subprograms are just fine.
290
291       --  In any case we do not generate warnings within the extended source
292       --  unit of the entity in question, since we assume the source unit
293       --  itself knows what is going on (and for sure we do not want silly
294       --  warnings, e.g. on the end line of an obsolescent procedure body).
295
296       if Is_Obsolescent (E)
297         and then not GNAT_Mode
298         and then not In_Extended_Main_Source_Unit (E)
299       then
300          Check_Restriction (No_Obsolescent_Features, N);
301
302          if Warn_On_Obsolescent_Feature then
303             Output_Obsolescent_Entity_Warnings (N, E);
304          end if;
305       end if;
306
307       --  Warn if reference to Ada 2005 entity not in Ada 2005 mode. We only
308       --  detect real explicit references (modifications and references).
309
310       if Comes_From_Source (N)
311         and then Is_Ada_2005_Only (E)
312         and then Ada_Version < Ada_05
313         and then Warn_On_Ada_2005_Compatibility
314         and then (Typ = 'm' or else Typ = 'r')
315       then
316          Error_Msg_NE ("& is only defined in Ada 2005?", N, E);
317       end if;
318
319       --  Never collect references if not in main source unit. However, we omit
320       --  this test if Typ is 'e' or 'k', since these entries are structural,
321       --  and it is useful to have them in units that reference packages as
322       --  well as units that define packages. We also omit the test for the
323       --  case of 'p' since we want to include inherited primitive operations
324       --  from other packages.
325
326       --  We also omit this test is this is a body reference for a subprogram
327       --  instantiation. In this case the reference is to the generic body,
328       --  which clearly need not be in the main unit containing the instance.
329       --  For the same reason we accept an implicit reference generated for
330       --  a default in an instance.
331
332       if not In_Extended_Main_Source_Unit (N) then
333          if Typ = 'e'
334            or else Typ = 'p'
335            or else Typ = 'i'
336            or else Typ = 'k'
337            or else (Typ = 'b' and then Is_Generic_Instance (E))
338          then
339             null;
340          else
341             return;
342          end if;
343       end if;
344
345       --  For reference type p, the entity must be in main source unit
346
347       if Typ = 'p' and then not In_Extended_Main_Source_Unit (E) then
348          return;
349       end if;
350
351       --  Unless the reference is forced, we ignore references where the
352       --  reference itself does not come from Source.
353
354       if not Force and then not Comes_From_Source (N) then
355          return;
356       end if;
357
358       --  Deal with setting entity as referenced, unless suppressed. Note that
359       --  we still do Set_Referenced on entities that do not come from source.
360       --  This situation arises when we have a source reference to a derived
361       --  operation, where the derived operation itself does not come from
362       --  source, but we still want to mark it as referenced, since we really
363       --  are referencing an entity in the corresponding package (this avoids
364       --  wrong complaints that the package contains no referenced entities).
365
366       if Set_Ref then
367
368          --  For a variable that appears on the left side of an assignment
369          --  statement, we set the Referenced_As_LHS flag since this is indeed
370          --  a left hand side. We also set the Referenced_As_LHS flag of a
371          --  prefix of selected or indexed component.
372
373          if Ekind (E) = E_Variable
374            and then Is_On_LHS (N)
375          then
376             Set_Referenced_As_LHS (E);
377
378          --  Check for a reference in a pragma that should not count as a
379          --  making the variable referenced for warning purposes.
380
381          elsif Is_Non_Significant_Pragma_Reference (N) then
382             null;
383
384          --  A reference in an attribute definition clause does not count as a
385          --  reference except for the case of Address. The reason that 'Address
386          --  is an exception is that it creates an alias through which the
387          --  variable may be referenced.
388
389          elsif Nkind (Parent (N)) = N_Attribute_Definition_Clause
390            and then Chars (Parent (N)) /= Name_Address
391            and then N = Name (Parent (N))
392          then
393             null;
394
395          --  Constant completion does not count as a reference
396
397          elsif Typ = 'c'
398            and then Ekind (E) = E_Constant
399          then
400             null;
401
402          --  Record representation clause does not count as a reference
403
404          elsif Nkind (N) = N_Identifier
405            and then Nkind (Parent (N)) = N_Record_Representation_Clause
406          then
407             null;
408
409          --  Discriminants do not need to produce a reference to record type
410
411          elsif Typ = 'd'
412            and then Nkind (Parent (N)) = N_Discriminant_Specification
413          then
414             null;
415
416          --  Any other occurrence counts as referencing the entity
417
418          else
419             Set_Referenced (E);
420
421             if Ekind (E) = E_Variable then
422                Set_Last_Assignment (E, Empty);
423             end if;
424          end if;
425
426          --  Check for pragma Unreferenced given and reference is within
427          --  this source unit (occasion for possible warning to be issued)
428
429          if Has_Pragma_Unreferenced (E)
430            and then In_Same_Extended_Unit (E, N)
431          then
432             --  A reference as a named parameter in a call does not count
433             --  as a violation of pragma Unreferenced for this purpose.
434
435             if Nkind (N) = N_Identifier
436               and then Nkind (Parent (N)) = N_Parameter_Association
437               and then Selector_Name (Parent (N)) = N
438             then
439                null;
440
441             --  Neither does a reference to a variable on the left side
442             --  of an assignment.
443
444             elsif Is_On_LHS (N) then
445                null;
446
447             --  For entry formals, we want to place the warning message on the
448             --  corresponding entity in the accept statement. The current scope
449             --  is the body of the accept, so we find the formal whose name
450             --  matches that of the entry formal (there is no link between the
451             --  two entities, and the one in the accept statement is only used
452             --  for conformance checking).
453
454             elsif Ekind (Scope (E)) = E_Entry then
455                declare
456                   BE : Entity_Id;
457
458                begin
459                   BE := First_Entity (Current_Scope);
460                   while Present (BE) loop
461                      if Chars (BE) = Chars (E) then
462                         Error_Msg_NE
463                           ("?pragma Unreferenced given for&", N, BE);
464                         exit;
465                      end if;
466
467                      Next_Entity (BE);
468                   end loop;
469                end;
470
471             --  Here we issue the warning, since this is a real reference
472
473             else
474                Error_Msg_NE ("?pragma Unreferenced given for&", N, E);
475             end if;
476          end if;
477
478          --  If this is a subprogram instance, mark as well the internal
479          --  subprogram in the wrapper package, which may be a visible
480          --  compilation unit.
481
482          if Is_Overloadable (E)
483            and then Is_Generic_Instance (E)
484            and then Present (Alias (E))
485          then
486             Set_Referenced (Alias (E));
487          end if;
488       end if;
489
490       --  Generate reference if all conditions are met:
491
492       if
493          --  Cross referencing must be active
494
495          Opt.Xref_Active
496
497          --  The entity must be one for which we collect references
498
499          and then Xref_Entity_Letters (Ekind (E)) /= ' '
500
501          --  Both Sloc values must be set to something sensible
502
503          and then Sloc (E) > No_Location
504          and then Sloc (N) > No_Location
505
506          --  We ignore references from within an instance
507
508          and then Instantiation_Location (Sloc (N)) = No_Location
509
510          --  Ignore dummy references
511
512         and then Typ /= ' '
513       then
514          if Nkind (N) = N_Identifier
515               or else
516             Nkind (N) = N_Defining_Identifier
517               or else
518             Nkind (N) in N_Op
519               or else
520             Nkind (N) = N_Defining_Operator_Symbol
521               or else
522             Nkind (N) = N_Operator_Symbol
523               or else
524             (Nkind (N) = N_Character_Literal
525               and then Sloc (Entity (N)) /= Standard_Location)
526               or else
527             Nkind (N) = N_Defining_Character_Literal
528          then
529             Nod := N;
530
531          elsif Nkind (N) = N_Expanded_Name
532                  or else
533                Nkind (N) = N_Selected_Component
534          then
535             Nod := Selector_Name (N);
536
537          else
538             return;
539          end if;
540
541          --  Normal case of source entity comes from source
542
543          if Comes_From_Source (E) then
544             Ent := E;
545
546          --  Entity does not come from source, but is a derived subprogram
547          --  and the derived subprogram comes from source (after one or more
548          --  derivations) in which case the reference is to parent subprogram.
549
550          elsif Is_Overloadable (E)
551            and then Present (Alias (E))
552          then
553             Ent := Alias (E);
554             while not Comes_From_Source (Ent) loop
555                if No (Alias (Ent)) then
556                   return;
557                end if;
558
559                Ent := Alias (Ent);
560             end loop;
561
562          --  The internally created defining entity for a child subprogram
563          --  that has no previous spec has valid references.
564
565          elsif Is_Overloadable (E)
566            and then Is_Child_Unit (E)
567          then
568             Ent := E;
569
570          --  Record components of discriminated subtypes or derived types
571          --  must be treated as references to the original component.
572
573          elsif Ekind (E) = E_Component
574            and then Comes_From_Source (Original_Record_Component (E))
575          then
576             Ent := Original_Record_Component (E);
577
578          --  Ignore reference to any other entity that is not from source
579
580          else
581             return;
582          end if;
583
584          --  Record reference to entity
585
586          Ref := Original_Location (Sloc (Nod));
587          Def := Original_Location (Sloc (Ent));
588
589          Xrefs.Increment_Last;
590          Indx := Xrefs.Last;
591
592          Xrefs.Table (Indx).Loc := Ref;
593
594          --  Overriding operations are marked with 'P'
595
596          if Typ = 'p'
597            and then Is_Subprogram (N)
598            and then Is_Overriding_Operation (N)
599          then
600             Xrefs.Table (Indx).Typ := 'P';
601          else
602             Xrefs.Table (Indx).Typ := Typ;
603          end if;
604
605          Xrefs.Table (Indx).Eun := Get_Source_Unit (Def);
606          Xrefs.Table (Indx).Lun := Get_Source_Unit (Ref);
607          Xrefs.Table (Indx).Ent := Ent;
608          Set_Has_Xref_Entry (Ent);
609       end if;
610    end Generate_Reference;
611
612    -----------------------------------
613    -- Generate_Reference_To_Formals --
614    -----------------------------------
615
616    procedure Generate_Reference_To_Formals (E : Entity_Id) is
617       Formal : Entity_Id;
618
619    begin
620       if Is_Generic_Subprogram (E) then
621          Formal := First_Entity (E);
622
623          while Present (Formal)
624            and then not Is_Formal (Formal)
625          loop
626             Next_Entity (Formal);
627          end loop;
628
629       else
630          Formal := First_Formal (E);
631       end if;
632
633       while Present (Formal) loop
634          if Ekind (Formal) = E_In_Parameter then
635
636             if Nkind (Parameter_Type (Parent (Formal)))
637               = N_Access_Definition
638             then
639                Generate_Reference (E, Formal, '^', False);
640             else
641                Generate_Reference (E, Formal, '>', False);
642             end if;
643
644          elsif Ekind (Formal) = E_In_Out_Parameter then
645             Generate_Reference (E, Formal, '=', False);
646
647          else
648             Generate_Reference (E, Formal, '<', False);
649          end if;
650
651          Next_Formal (Formal);
652       end loop;
653    end Generate_Reference_To_Formals;
654
655    -------------------------------------------
656    -- Generate_Reference_To_Generic_Formals --
657    -------------------------------------------
658
659    procedure Generate_Reference_To_Generic_Formals (E : Entity_Id) is
660       Formal : Entity_Id;
661
662    begin
663       Formal := First_Entity (E);
664       while Present (Formal) loop
665          if Comes_From_Source (Formal) then
666             Generate_Reference (E, Formal, 'z', False);
667          end if;
668
669          Next_Entity (Formal);
670       end loop;
671    end Generate_Reference_To_Generic_Formals;
672
673    ----------------
674    -- Initialize --
675    ----------------
676
677    procedure Initialize is
678    begin
679       Xrefs.Init;
680    end Initialize;
681
682    -----------------------
683    -- Output_References --
684    -----------------------
685
686    procedure Output_References is
687
688       procedure Get_Type_Reference
689         (Ent   : Entity_Id;
690          Tref  : out Entity_Id;
691          Left  : out Character;
692          Right : out Character);
693       --  Given an entity id Ent, determines whether a type reference is
694       --  required. If so, Tref is set to the entity for the type reference
695       --  and Left and Right are set to the left/right brackets to be
696       --  output for the reference. If no type reference is required, then
697       --  Tref is set to Empty, and Left/Right are set to space.
698
699       procedure Output_Import_Export_Info (Ent : Entity_Id);
700       --  Ouput language and external name information for an interfaced
701       --  entity, using the format <language, external_name>,
702
703       ------------------------
704       -- Get_Type_Reference --
705       ------------------------
706
707       procedure Get_Type_Reference
708         (Ent   : Entity_Id;
709          Tref  : out Entity_Id;
710          Left  : out Character;
711          Right : out Character)
712       is
713          Sav : Entity_Id;
714
715       begin
716          --  See if we have a type reference
717
718          Tref := Ent;
719          Left := '{';
720          Right := '}';
721
722          loop
723             Sav := Tref;
724
725             --  Processing for types
726
727             if Is_Type (Tref) then
728
729                --  Case of base type
730
731                if Base_Type (Tref) = Tref then
732
733                   --  If derived, then get first subtype
734
735                   if Tref /= Etype (Tref) then
736                      Tref := First_Subtype (Etype (Tref));
737
738                      --  Set brackets for derived type, but don't
739                      --  override pointer case since the fact that
740                      --  something is a pointer is more important
741
742                      if Left /= '(' then
743                         Left := '<';
744                         Right := '>';
745                      end if;
746
747                   --  If non-derived ptr, get directly designated type.
748                   --  If the type has a full view, all references are
749                   --  on the partial view, that is seen first.
750
751                   elsif Is_Access_Type (Tref) then
752                      Tref := Directly_Designated_Type (Tref);
753                      Left := '(';
754                      Right := ')';
755
756                   elsif Is_Private_Type (Tref)
757                     and then Present (Full_View (Tref))
758                   then
759                      if Is_Access_Type (Full_View (Tref)) then
760                         Tref := Directly_Designated_Type (Full_View (Tref));
761                         Left := '(';
762                         Right := ')';
763
764                      --  If the full view is an array type, we also retrieve
765                      --  the corresponding component type, because the ali
766                      --  entry already indicates that this is an array.
767
768                      elsif Is_Array_Type (Full_View (Tref)) then
769                         Tref := Component_Type (Full_View (Tref));
770                         Left := '(';
771                         Right := ')';
772                      end if;
773
774                   --  If non-derived array, get component type. Skip component
775                   --  type for case of String or Wide_String, saves worthwhile
776                   --  space.
777
778                   elsif Is_Array_Type (Tref)
779                     and then Tref /= Standard_String
780                     and then Tref /= Standard_Wide_String
781                   then
782                      Tref := Component_Type (Tref);
783                      Left := '(';
784                      Right := ')';
785
786                   --  For other non-derived base types, nothing
787
788                   else
789                      exit;
790                   end if;
791
792                --  For a subtype, go to ancestor subtype
793
794                else
795                   Tref := Ancestor_Subtype (Tref);
796
797                   --  If no ancestor subtype, go to base type
798
799                   if No (Tref) then
800                      Tref := Base_Type (Sav);
801                   end if;
802                end if;
803
804             --  For objects, functions, enum literals,
805             --  just get type from Etype field.
806
807             elsif Is_Object (Tref)
808               or else Ekind (Tref) = E_Enumeration_Literal
809               or else Ekind (Tref) = E_Function
810               or else Ekind (Tref) = E_Operator
811             then
812                Tref := Etype (Tref);
813
814             --  For anything else, exit
815
816             else
817                exit;
818             end if;
819
820             --  Exit if no type reference, or we are stuck in
821             --  some loop trying to find the type reference, or
822             --  if the type is standard void type (the latter is
823             --  an implementation artifact that should not show
824             --  up in the generated cross-references).
825
826             exit when No (Tref)
827               or else Tref = Sav
828               or else Tref = Standard_Void_Type;
829
830             --  If we have a usable type reference, return, otherwise
831             --  keep looking for something useful (we are looking for
832             --  something that either comes from source or standard)
833
834             if Sloc (Tref) = Standard_Location
835               or else Comes_From_Source (Tref)
836             then
837                --  If the reference is a subtype created for a generic
838                --  actual, go to actual directly, the inner subtype is
839                --  not user visible.
840
841                if Nkind (Parent (Tref)) = N_Subtype_Declaration
842                  and then not Comes_From_Source (Parent (Tref))
843                  and then
844                   (Is_Wrapper_Package (Scope (Tref))
845                      or else Is_Generic_Instance (Scope (Tref)))
846                then
847                   Tref := First_Subtype (Base_Type (Tref));
848                end if;
849
850                return;
851             end if;
852          end loop;
853
854          --  If we fall through the loop, no type reference
855
856          Tref := Empty;
857          Left := ' ';
858          Right := ' ';
859       end Get_Type_Reference;
860
861       -------------------------------
862       -- Output_Import_Export_Info --
863       -------------------------------
864
865       procedure Output_Import_Export_Info (Ent : Entity_Id) is
866          Language_Name : Name_Id;
867          Conv          : constant Convention_Id := Convention (Ent);
868
869       begin
870          --  Generate language name from convention
871
872          if Conv  = Convention_C then
873             Language_Name := Name_C;
874
875          elsif Conv = Convention_CPP then
876             Language_Name := Name_CPP;
877
878          elsif Conv = Convention_Ada then
879             Language_Name := Name_Ada;
880
881          else
882             --  For the moment we ignore all other cases ???
883
884             return;
885          end if;
886
887          Write_Info_Char ('<');
888          Get_Unqualified_Name_String (Language_Name);
889
890          for J in 1 .. Name_Len loop
891             Write_Info_Char (Name_Buffer (J));
892          end loop;
893
894          if Present (Interface_Name (Ent)) then
895             Write_Info_Char (',');
896             String_To_Name_Buffer (Strval (Interface_Name (Ent)));
897
898             for J in 1 .. Name_Len loop
899                Write_Info_Char (Name_Buffer (J));
900             end loop;
901          end if;
902
903          Write_Info_Char ('>');
904       end Output_Import_Export_Info;
905
906    --  Start of processing for Output_References
907
908    begin
909       if not Opt.Xref_Active then
910          return;
911       end if;
912
913       --  Before we go ahead and output the references we have a problem
914       --  that needs dealing with. So far we have captured things that are
915       --  definitely referenced by the main unit, or defined in the main
916       --  unit. That's because we don't want to clutter up the ali file
917       --  for this unit with definition lines for entities in other units
918       --  that are not referenced.
919
920       --  But there is a glitch. We may reference an entity in another unit,
921       --  and it may have a type reference to an entity that is not directly
922       --  referenced in the main unit, which may mean that there is no xref
923       --  entry for this entity yet in the list of references.
924
925       --  If we don't do something about this, we will end with an orphan type
926       --  reference, i.e. it will point to an entity that does not appear
927       --  within the generated references in the ali file. That is not good for
928       --  tools using the xref information.
929
930       --  To fix this, we go through the references adding definition entries
931       --  for any unreferenced entities that can be referenced in a type
932       --  reference. There is a recursion problem here, and that is dealt with
933       --  by making sure that this traversal also traverses any entries that
934       --  get added by the traversal.
935
936       Handle_Orphan_Type_References : declare
937          J    : Nat;
938          Tref : Entity_Id;
939          L, R : Character;
940          Indx : Nat;
941          Ent  : Entity_Id;
942          Loc  : Source_Ptr;
943
944          procedure New_Entry (E : Entity_Id);
945          --  Make an additional entry into the Xref table for a type entity
946          --  that is related to the current entity (parent, type. ancestor,
947          --  progenitor, etc.).
948
949          ----------------
950          -- New_Entry --
951          ----------------
952
953          procedure New_Entry (E : Entity_Id) is
954          begin
955             if Present (E)
956               and then not Has_Xref_Entry (E)
957               and then Sloc (E) > No_Location
958             then
959                Xrefs.Increment_Last;
960                Indx := Xrefs.Last;
961                Loc  := Original_Location (Sloc (E));
962                Xrefs.Table (Indx).Ent := E;
963                Xrefs.Table (Indx).Loc := No_Location;
964                Xrefs.Table (Indx).Eun := Get_Source_Unit (Loc);
965                Xrefs.Table (Indx).Lun := No_Unit;
966                Set_Has_Xref_Entry (E);
967             end if;
968          end New_Entry;
969
970       --  Start of processing for Handle_Orphan_Type_References
971
972       begin
973          --  Note that this is not a for loop for a very good reason. The
974          --  processing of items in the table can add new items to the table,
975          --  and they must be processed as well
976
977          J := 1;
978          while J <= Xrefs.Last loop
979             Ent := Xrefs.Table (J).Ent;
980             Get_Type_Reference (Ent, Tref, L, R);
981
982             if Present (Tref)
983               and then not Has_Xref_Entry (Tref)
984               and then Sloc (Tref) > No_Location
985             then
986                New_Entry (Tref);
987
988                if Is_Record_Type (Ent)
989                  and then Present (Abstract_Interfaces (Ent))
990                then
991                   --  Add an entry for each one of the given interfaces
992                   --  implemented by type Ent.
993
994                   declare
995                      Elmt : Elmt_Id;
996
997                   begin
998                      Elmt := First_Elmt (Abstract_Interfaces (Ent));
999                      while Present (Elmt) loop
1000                         New_Entry (Node (Elmt));
1001                         Next_Elmt (Elmt);
1002                      end loop;
1003                   end;
1004                end if;
1005             end if;
1006
1007             --  Collect inherited primitive operations that may be
1008             --  declared in another unit and have no visible reference
1009             --  in the current one.
1010
1011             if Is_Type (Ent)
1012               and then Is_Tagged_Type (Ent)
1013               and then Is_Derived_Type (Ent)
1014               and then Ent = Base_Type (Ent)
1015               and then In_Extended_Main_Source_Unit (Ent)
1016             then
1017                declare
1018                   Op_List : constant Elist_Id := Primitive_Operations (Ent);
1019                   Op      : Elmt_Id;
1020                   Prim    : Entity_Id;
1021
1022                   function Parent_Op (E : Entity_Id) return Entity_Id;
1023                   --  Find original operation, which may be inherited
1024                   --  through several derivations.
1025
1026                   function Parent_Op (E : Entity_Id) return Entity_Id is
1027                      Orig_Op : constant Entity_Id := Alias (E);
1028                   begin
1029                      if No (Orig_Op) then
1030                         return Empty;
1031                      elsif not Comes_From_Source (E)
1032                        and then not Has_Xref_Entry (Orig_Op)
1033                        and then Comes_From_Source (Orig_Op)
1034                      then
1035                         return Orig_Op;
1036                      else
1037                         return Parent_Op (Orig_Op);
1038                      end if;
1039                   end Parent_Op;
1040
1041                begin
1042                   Op := First_Elmt (Op_List);
1043                   while Present (Op) loop
1044                      Prim := Parent_Op (Node (Op));
1045
1046                      if Present (Prim) then
1047                         Xrefs.Increment_Last;
1048                         Indx := Xrefs.Last;
1049                         Loc  := Original_Location (Sloc (Prim));
1050                         Xrefs.Table (Indx).Ent := Prim;
1051                         Xrefs.Table (Indx).Loc := No_Location;
1052                         Xrefs.Table (Indx).Eun :=
1053                           Get_Source_Unit (Sloc (Prim));
1054                         Xrefs.Table (Indx).Lun := No_Unit;
1055                         Set_Has_Xref_Entry (Prim);
1056                      end if;
1057
1058                      Next_Elmt (Op);
1059                   end loop;
1060                end;
1061             end if;
1062
1063             J := J + 1;
1064          end loop;
1065       end Handle_Orphan_Type_References;
1066
1067       --  Now we have all the references, including those for any embedded
1068       --  type references, so we can sort them, and output them.
1069
1070       Output_Refs : declare
1071
1072          Nrefs : Nat := Xrefs.Last;
1073          --  Number of references in table. This value may get reset
1074          --  (reduced) when we eliminate duplicate reference entries.
1075
1076          Rnums : array (0 .. Nrefs) of Nat;
1077          --  This array contains numbers of references in the Xrefs table.
1078          --  This list is sorted in output order. The extra 0'th entry is
1079          --  convenient for the call to sort. When we sort the table, we
1080          --  move the entries in Rnums around, but we do not move the
1081          --  original table entries.
1082
1083          Curxu : Unit_Number_Type;
1084          --  Current xref unit
1085
1086          Curru : Unit_Number_Type;
1087          --  Current reference unit for one entity
1088
1089          Cursrc : Source_Buffer_Ptr;
1090          --  Current xref unit source text
1091
1092          Curent : Entity_Id;
1093          --  Current entity
1094
1095          Curnam : String (1 .. Name_Buffer'Length);
1096          Curlen : Natural;
1097          --  Simple name and length of current entity
1098
1099          Curdef : Source_Ptr;
1100          --  Original source location for current entity
1101
1102          Crloc : Source_Ptr;
1103          --  Current reference location
1104
1105          Ctyp : Character;
1106          --  Entity type character
1107
1108          Tref : Entity_Id;
1109          --  Type reference
1110
1111          Rref : Node_Id;
1112          --  Renaming reference
1113
1114          Trunit : Unit_Number_Type;
1115          --  Unit number for type reference
1116
1117          function Lt (Op1, Op2 : Natural) return Boolean;
1118          --  Comparison function for Sort call
1119
1120          function Name_Change (X : Entity_Id) return Boolean;
1121          --  Determines if entity X has a different simple name from Curent
1122
1123          procedure Move (From : Natural; To : Natural);
1124          --  Move procedure for Sort call
1125
1126          --------
1127          -- Lt --
1128          --------
1129
1130          function Lt (Op1, Op2 : Natural) return Boolean is
1131             T1 : Xref_Entry renames Xrefs.Table (Rnums (Nat (Op1)));
1132             T2 : Xref_Entry renames Xrefs.Table (Rnums (Nat (Op2)));
1133
1134          begin
1135             --  First test. If entity is in different unit, sort by unit
1136
1137             if T1.Eun /= T2.Eun then
1138                return Dependency_Num (T1.Eun) < Dependency_Num (T2.Eun);
1139
1140             --  Second test, within same unit, sort by entity Sloc
1141
1142             elsif T1.Def /= T2.Def then
1143                return T1.Def < T2.Def;
1144
1145             --  Third test, sort definitions ahead of references
1146
1147             elsif T1.Loc = No_Location then
1148                return True;
1149
1150             elsif T2.Loc = No_Location then
1151                return False;
1152
1153             --  Fourth test, for same entity, sort by reference location unit
1154
1155             elsif T1.Lun /= T2.Lun then
1156                return Dependency_Num (T1.Lun) < Dependency_Num (T2.Lun);
1157
1158             --  Fifth test order of location within referencing unit
1159
1160             elsif T1.Loc /= T2.Loc then
1161                return T1.Loc < T2.Loc;
1162
1163             --  Finally, for two locations at the same address, we prefer
1164             --  the one that does NOT have the type 'r' so that a modification
1165             --  or extension takes preference, when there are more than one
1166             --  reference at the same location.
1167
1168             else
1169                return T2.Typ = 'r';
1170             end if;
1171          end Lt;
1172
1173          ----------
1174          -- Move --
1175          ----------
1176
1177          procedure Move (From : Natural; To : Natural) is
1178          begin
1179             Rnums (Nat (To)) := Rnums (Nat (From));
1180          end Move;
1181
1182          -----------------
1183          -- Name_Change --
1184          -----------------
1185
1186          --  Why a string comparison here??? Why not compare Name_Id values???
1187
1188          function Name_Change (X : Entity_Id) return Boolean is
1189          begin
1190             Get_Unqualified_Name_String (Chars (X));
1191
1192             if Name_Len /= Curlen then
1193                return True;
1194
1195             else
1196                return Name_Buffer (1 .. Curlen) /= Curnam (1 .. Curlen);
1197             end if;
1198          end Name_Change;
1199
1200       --  Start of processing for Output_Refs
1201
1202       begin
1203          --  Capture the definition Sloc values. We delay doing this till now,
1204          --  since at the time the reference or definition is made, private
1205          --  types may be swapped, and the Sloc value may be incorrect. We
1206          --  also set up the pointer vector for the sort.
1207
1208          for J in 1 .. Nrefs loop
1209             Rnums (J) := J;
1210             Xrefs.Table (J).Def :=
1211               Original_Location (Sloc (Xrefs.Table (J).Ent));
1212          end loop;
1213
1214          --  Sort the references
1215
1216          GNAT.Heap_Sort_A.Sort
1217            (Integer (Nrefs),
1218             Move'Unrestricted_Access,
1219             Lt'Unrestricted_Access);
1220
1221          --  Eliminate duplicate entries
1222
1223          declare
1224             NR : constant Nat := Nrefs;
1225
1226          begin
1227             --  We need this test for NR because if we force ALI file
1228             --  generation in case of errors detected, it may be the case
1229             --  that Nrefs is 0, so we should not reset it here
1230
1231             if NR >= 2 then
1232                Nrefs := 1;
1233
1234                for J in 2 .. NR loop
1235                   if Xrefs.Table (Rnums (J)) /=
1236                      Xrefs.Table (Rnums (Nrefs))
1237                   then
1238                      Nrefs := Nrefs + 1;
1239                      Rnums (Nrefs) := Rnums (J);
1240                   end if;
1241                end loop;
1242             end if;
1243          end;
1244
1245          --  Initialize loop through references
1246
1247          Curxu  := No_Unit;
1248          Curent := Empty;
1249          Curdef := No_Location;
1250          Curru  := No_Unit;
1251          Crloc  := No_Location;
1252
1253          --  Loop to output references
1254
1255          for Refno in 1 .. Nrefs loop
1256             Output_One_Ref : declare
1257                P2  : Source_Ptr;
1258                WC  : Char_Code;
1259                Err : Boolean;
1260                Ent : Entity_Id;
1261
1262                XE : Xref_Entry renames Xrefs.Table (Rnums (Refno));
1263                --  The current entry to be accessed
1264
1265                P : Source_Ptr;
1266                --  Used to index into source buffer to get entity name
1267
1268                Left  : Character;
1269                Right : Character;
1270                --  Used for {} or <> or () for type reference
1271
1272                procedure Check_Type_Reference
1273                  (Ent : Entity_Id;
1274                   List_Interface : Boolean);
1275                --  Find whether there is a meaningful type reference for
1276                --  Ent, and display it accordingly. If List_Interface is
1277                --  true, then Ent is a progenitor interface of the current
1278                --  type entity being listed. In that case list it as is,
1279                --  without looking for a type reference for it.
1280
1281                procedure Output_Instantiation_Refs (Loc : Source_Ptr);
1282                --  Recursive procedure to output instantiation references for
1283                --  the given source ptr in [file|line[...]] form. No output
1284                --  if the given location is not a generic template reference.
1285
1286                procedure Output_Overridden_Op (Old_E : Entity_Id);
1287                --  For a subprogram that is overriding, display information
1288                --  about the inherited operation that it overrides.
1289
1290                --------------------------
1291                -- Check_Type_Reference --
1292                --------------------------
1293
1294                procedure Check_Type_Reference
1295                  (Ent : Entity_Id;
1296                   List_Interface : Boolean)
1297                is
1298                begin
1299                   if List_Interface then
1300
1301                      --  This is a progenitor interface of the type for
1302                      --  which xref information is being generated.
1303
1304                      Tref  := Ent;
1305                      Left  := '<';
1306                      Right := '>';
1307
1308                   else
1309                      Get_Type_Reference (Ent, Tref, Left, Right);
1310                   end if;
1311
1312                   if Present (Tref) then
1313
1314                      --  Case of standard entity, output name
1315
1316                      if Sloc (Tref) = Standard_Location then
1317                         Write_Info_Char (Left);
1318                         Write_Info_Name (Chars (Tref));
1319                         Write_Info_Char (Right);
1320
1321                      --  Case of source entity, output location
1322
1323                      else
1324                         Write_Info_Char (Left);
1325                         Trunit := Get_Source_Unit (Sloc (Tref));
1326
1327                         if Trunit /= Curxu then
1328                            Write_Info_Nat (Dependency_Num (Trunit));
1329                            Write_Info_Char ('|');
1330                         end if;
1331
1332                         Write_Info_Nat
1333                           (Int (Get_Logical_Line_Number (Sloc (Tref))));
1334
1335                         declare
1336                            Ent  : Entity_Id := Tref;
1337                            Kind : constant Entity_Kind := Ekind (Ent);
1338                            Ctyp : Character := Xref_Entity_Letters (Kind);
1339
1340                         begin
1341                            if Ctyp = '+'
1342                              and then Present (Full_View (Ent))
1343                            then
1344                               Ent := Underlying_Type (Ent);
1345
1346                               if Present (Ent) then
1347                                  Ctyp := Xref_Entity_Letters (Ekind (Ent));
1348                               end if;
1349                            end if;
1350
1351                            Write_Info_Char (Ctyp);
1352                         end;
1353
1354                         Write_Info_Nat
1355                           (Int (Get_Column_Number (Sloc (Tref))));
1356
1357                         --  If the type comes from an instantiation,
1358                         --  add the corresponding info.
1359
1360                         Output_Instantiation_Refs (Sloc (Tref));
1361                         Write_Info_Char (Right);
1362                      end if;
1363                   end if;
1364                end Check_Type_Reference;
1365
1366                -------------------------------
1367                -- Output_Instantiation_Refs --
1368                -------------------------------
1369
1370                procedure Output_Instantiation_Refs (Loc : Source_Ptr) is
1371                   Iloc : constant Source_Ptr := Instantiation_Location (Loc);
1372                   Lun  : Unit_Number_Type;
1373                   Cu   : constant Unit_Number_Type := Curru;
1374
1375                begin
1376                   --  Nothing to do if this is not an instantiation
1377
1378                   if Iloc = No_Location then
1379                      return;
1380                   end if;
1381
1382                   --  Output instantiation reference
1383
1384                   Write_Info_Char ('[');
1385                   Lun := Get_Source_Unit (Iloc);
1386
1387                   if Lun /= Curru then
1388                      Curru := Lun;
1389                      Write_Info_Nat (Dependency_Num (Curru));
1390                      Write_Info_Char ('|');
1391                   end if;
1392
1393                   Write_Info_Nat (Int (Get_Logical_Line_Number (Iloc)));
1394
1395                   --  Recursive call to get nested instantiations
1396
1397                   Output_Instantiation_Refs (Iloc);
1398
1399                   --  Output final ] after call to get proper nesting
1400
1401                   Write_Info_Char (']');
1402                   Curru := Cu;
1403                   return;
1404                end Output_Instantiation_Refs;
1405
1406                --------------------------
1407                -- Output_Overridden_Op --
1408                --------------------------
1409
1410                procedure Output_Overridden_Op (Old_E : Entity_Id) is
1411                begin
1412                   if Present (Old_E)
1413                     and then Sloc (Old_E) /= Standard_Location
1414                   then
1415                      declare
1416                         Loc      : constant Source_Ptr := Sloc (Old_E);
1417                         Par_Unit : constant Unit_Number_Type :=
1418                                      Get_Source_Unit (Loc);
1419                      begin
1420                         Write_Info_Char ('<');
1421
1422                         if Par_Unit /= Curxu then
1423                            Write_Info_Nat (Dependency_Num (Par_Unit));
1424                            Write_Info_Char ('|');
1425                         end if;
1426
1427                         Write_Info_Nat (Int (Get_Logical_Line_Number (Loc)));
1428                         Write_Info_Char ('p');
1429                         Write_Info_Nat (Int (Get_Column_Number (Loc)));
1430                         Write_Info_Char ('>');
1431                      end;
1432                   end if;
1433                end Output_Overridden_Op;
1434
1435             --  Start of processing for Output_One_Ref
1436
1437             begin
1438                Ent := XE.Ent;
1439                Ctyp := Xref_Entity_Letters (Ekind (Ent));
1440
1441                --  Skip reference if it is the only reference to an entity,
1442                --  and it is an end-line reference, and the entity is not in
1443                --  the current extended source. This prevents junk entries
1444                --  consisting only of packages with end lines, where no
1445                --  entity from the package is actually referenced.
1446
1447                if XE.Typ = 'e'
1448                  and then Ent /= Curent
1449                  and then (Refno = Nrefs or else
1450                              Ent /= Xrefs.Table (Rnums (Refno + 1)).Ent)
1451                  and then
1452                    not In_Extended_Main_Source_Unit (Ent)
1453                then
1454                   goto Continue;
1455                end if;
1456
1457                --  For private type, get full view type
1458
1459                if Ctyp = '+'
1460                  and then Present (Full_View (XE.Ent))
1461                then
1462                   Ent := Underlying_Type (Ent);
1463
1464                   if Present (Ent) then
1465                      Ctyp := Xref_Entity_Letters (Ekind (Ent));
1466                   end if;
1467                end if;
1468
1469                --  Special exception for Boolean
1470
1471                if Ctyp = 'E' and then Is_Boolean_Type (Ent) then
1472                   Ctyp := 'B';
1473                end if;
1474
1475                --  For variable reference, get corresponding type
1476
1477                if Ctyp = '*' then
1478                   Ent := Etype (XE.Ent);
1479                   Ctyp := Fold_Lower (Xref_Entity_Letters (Ekind (Ent)));
1480
1481                   --  If variable is private type, get full view type
1482
1483                   if Ctyp = '+'
1484                     and then Present (Full_View (Etype (XE.Ent)))
1485                   then
1486                      Ent := Underlying_Type (Etype (XE.Ent));
1487
1488                      if Present (Ent) then
1489                         Ctyp := Fold_Lower (Xref_Entity_Letters (Ekind (Ent)));
1490                      end if;
1491
1492                   elsif Is_Generic_Type (Ent) then
1493
1494                      --  If the type of the entity is a  generic private type
1495                      --  there is no usable full view, so retain the indication
1496                      --  that this is an object.
1497
1498                      Ctyp := '*';
1499                   end if;
1500
1501                   --  Special handling for access parameter
1502
1503                   declare
1504                      K : constant Entity_Kind := Ekind (Etype (XE.Ent));
1505
1506                   begin
1507                      if (K = E_Anonymous_Access_Type
1508                            or else
1509                          K = E_Anonymous_Access_Subprogram_Type
1510                             or else K =
1511                          E_Anonymous_Access_Protected_Subprogram_Type)
1512                        and then Is_Formal (XE.Ent)
1513                      then
1514                         Ctyp := 'p';
1515
1516                         --  Special handling for Boolean
1517
1518                      elsif Ctyp = 'e' and then Is_Boolean_Type (Ent) then
1519                         Ctyp := 'b';
1520                      end if;
1521                   end;
1522                end if;
1523
1524                --  Special handling for abstract types and operations
1525
1526                if Is_Overloadable (XE.Ent)
1527                  and then Is_Abstract_Subprogram (XE.Ent)
1528                then
1529                   if Ctyp = 'U' then
1530                      Ctyp := 'x';            --  abstract procedure
1531
1532                   elsif Ctyp = 'V' then
1533                      Ctyp := 'y';            --  abstract function
1534                   end if;
1535
1536                elsif Is_Type (XE.Ent)
1537                  and then Is_Abstract_Type (XE.Ent)
1538                then
1539                   if Is_Interface (XE.Ent) then
1540                      Ctyp := 'h';
1541
1542                   elsif Ctyp = 'R' then
1543                      Ctyp := 'H';            --  abstract type
1544                   end if;
1545                end if;
1546
1547                --  Only output reference if interesting type of entity, and
1548                --  suppress self references, except for bodies that act as
1549                --  specs. Also suppress definitions of body formals (we only
1550                --  treat these as references, and the references were
1551                --  separately recorded).
1552
1553                if Ctyp = ' '
1554                  or else (XE.Loc = XE.Def
1555                             and then
1556                               (XE.Typ /= 'b'
1557                                 or else not Is_Subprogram (XE.Ent)))
1558                  or else (Is_Formal (XE.Ent)
1559                             and then Present (Spec_Entity (XE.Ent)))
1560                then
1561                   null;
1562
1563                else
1564                   --  Start new Xref section if new xref unit
1565
1566                   if XE.Eun /= Curxu then
1567                      if Write_Info_Col > 1 then
1568                         Write_Info_EOL;
1569                      end if;
1570
1571                      Curxu := XE.Eun;
1572                      Cursrc := Source_Text (Source_Index (Curxu));
1573
1574                      Write_Info_Initiate ('X');
1575                      Write_Info_Char (' ');
1576                      Write_Info_Nat (Dependency_Num (XE.Eun));
1577                      Write_Info_Char (' ');
1578                      Write_Info_Name (Reference_Name (Source_Index (XE.Eun)));
1579                   end if;
1580
1581                   --  Start new Entity line if new entity. Note that we
1582                   --  consider two entities the same if they have the same
1583                   --  name and source location. This causes entities in
1584                   --  instantiations to be treated as though they referred
1585                   --  to the template.
1586
1587                   if No (Curent)
1588                     or else
1589                       (XE.Ent /= Curent
1590                          and then
1591                            (Name_Change (XE.Ent) or else XE.Def /= Curdef))
1592                   then
1593                      Curent := XE.Ent;
1594                      Curdef := XE.Def;
1595
1596                      Get_Unqualified_Name_String (Chars (XE.Ent));
1597                      Curlen := Name_Len;
1598                      Curnam (1 .. Curlen) := Name_Buffer (1 .. Curlen);
1599
1600                      if Write_Info_Col > 1 then
1601                         Write_Info_EOL;
1602                      end if;
1603
1604                      --  Write column number information
1605
1606                      Write_Info_Nat (Int (Get_Logical_Line_Number (XE.Def)));
1607                      Write_Info_Char (Ctyp);
1608                      Write_Info_Nat (Int (Get_Column_Number (XE.Def)));
1609
1610                      --  Write level information
1611
1612                      Write_Level_Info : declare
1613                         function Is_Visible_Generic_Entity
1614                           (E : Entity_Id) return Boolean;
1615                         --  Check whether E is declared in the visible part
1616                         --  of a generic package. For source navigation
1617                         --  purposes, treat this as a visible entity.
1618
1619                         function Is_Private_Record_Component
1620                           (E : Entity_Id) return Boolean;
1621                         --  Check whether E is a non-inherited component of a
1622                         --  private extension. Even if the enclosing record is
1623                         --  public, we want to treat the component as private
1624                         --  for navigation purposes.
1625
1626                         ---------------------------------
1627                         -- Is_Private_Record_Component --
1628                         ---------------------------------
1629
1630                         function Is_Private_Record_Component
1631                           (E : Entity_Id) return Boolean
1632                         is
1633                            S : constant Entity_Id := Scope (E);
1634                         begin
1635                            return
1636                              Ekind (E) = E_Component
1637                                and then Nkind (Declaration_Node (S)) =
1638                                  N_Private_Extension_Declaration
1639                                and then Original_Record_Component (E) = E;
1640                         end Is_Private_Record_Component;
1641
1642                         -------------------------------
1643                         -- Is_Visible_Generic_Entity --
1644                         -------------------------------
1645
1646                         function Is_Visible_Generic_Entity
1647                           (E : Entity_Id) return Boolean
1648                         is
1649                            Par : Node_Id;
1650
1651                         begin
1652                            if Ekind (Scope (E)) /= E_Generic_Package then
1653                               return False;
1654                            end if;
1655
1656                            Par := Parent (E);
1657                            while Present (Par) loop
1658                               if
1659                                 Nkind (Par) = N_Generic_Package_Declaration
1660                               then
1661                                  --  Entity is a generic formal
1662
1663                                  return False;
1664
1665                               elsif
1666                                 Nkind (Parent (Par)) = N_Package_Specification
1667                               then
1668                                  return
1669                                    Is_List_Member (Par)
1670                                      and then List_Containing (Par) =
1671                                        Visible_Declarations (Parent (Par));
1672                               else
1673                                  Par := Parent (Par);
1674                               end if;
1675                            end loop;
1676
1677                            return False;
1678                         end Is_Visible_Generic_Entity;
1679
1680                      --  Start of processing for Write_Level_Info
1681
1682                      begin
1683                         if Is_Hidden (Curent)
1684                           or else Is_Private_Record_Component (Curent)
1685                         then
1686                            Write_Info_Char (' ');
1687
1688                         elsif
1689                            Is_Public (Curent)
1690                              or else Is_Visible_Generic_Entity (Curent)
1691                         then
1692                            Write_Info_Char ('*');
1693
1694                         else
1695                            Write_Info_Char (' ');
1696                         end if;
1697                      end Write_Level_Info;
1698
1699                      --  Output entity name. We use the occurrence from the
1700                      --  actual source program at the definition point
1701
1702                      P := Original_Location (Sloc (XE.Ent));
1703
1704                      --  Entity is character literal
1705
1706                      if Cursrc (P) = ''' then
1707                         Write_Info_Char (Cursrc (P));
1708                         Write_Info_Char (Cursrc (P + 1));
1709                         Write_Info_Char (Cursrc (P + 2));
1710
1711                      --  Entity is operator symbol
1712
1713                      elsif Cursrc (P) = '"' or else Cursrc (P) = '%' then
1714                         Write_Info_Char (Cursrc (P));
1715
1716                         P2 := P;
1717                         loop
1718                            P2 := P2 + 1;
1719                            Write_Info_Char (Cursrc (P2));
1720                            exit when Cursrc (P2) = Cursrc (P);
1721                         end loop;
1722
1723                      --  Entity is identifier
1724
1725                      else
1726                         loop
1727                            if Is_Start_Of_Wide_Char (Cursrc, P) then
1728                               Scan_Wide (Cursrc, P, WC, Err);
1729                            elsif not Identifier_Char (Cursrc (P)) then
1730                               exit;
1731                            else
1732                               P := P + 1;
1733                            end if;
1734                         end loop;
1735
1736                         --  Write out the identifier by copying the exact
1737                         --  source characters used in its declaration. Note
1738                         --  that this means wide characters will be in their
1739                         --  original encoded form.
1740
1741                         for J in
1742                           Original_Location (Sloc (XE.Ent)) .. P - 1
1743                         loop
1744                            Write_Info_Char (Cursrc (J));
1745                         end loop;
1746                      end if;
1747
1748                      --  See if we have a renaming reference
1749
1750                      if Is_Object (XE.Ent)
1751                        and then Present (Renamed_Object (XE.Ent))
1752                      then
1753                         Rref := Renamed_Object (XE.Ent);
1754
1755                      elsif Is_Overloadable (XE.Ent)
1756                        and then Nkind (Parent (Declaration_Node (XE.Ent))) =
1757                                             N_Subprogram_Renaming_Declaration
1758                      then
1759                         Rref := Name (Parent (Declaration_Node (XE.Ent)));
1760
1761                      elsif Ekind (XE.Ent) = E_Package
1762                        and then Nkind (Declaration_Node (XE.Ent)) =
1763                                          N_Package_Renaming_Declaration
1764                      then
1765                         Rref := Name (Declaration_Node (XE.Ent));
1766
1767                      else
1768                         Rref := Empty;
1769                      end if;
1770
1771                      if Present (Rref) then
1772                         if Nkind (Rref) = N_Expanded_Name then
1773                            Rref := Selector_Name (Rref);
1774                         end if;
1775
1776                         if Nkind (Rref) = N_Identifier
1777                           or else Nkind (Rref) = N_Operator_Symbol
1778                         then
1779                            null;
1780
1781                         --  For renamed array components, use the array name
1782                         --  for the renamed entity, which reflect the fact that
1783                         --  in general the whole array is aliased.
1784
1785                         elsif Nkind (Rref) = N_Indexed_Component then
1786                            if Nkind (Prefix (Rref)) = N_Identifier then
1787                               Rref := Prefix (Rref);
1788                            elsif Nkind (Prefix (Rref)) = N_Expanded_Name then
1789                               Rref := Selector_Name (Prefix (Rref));
1790                            else
1791                               Rref := Empty;
1792                            end if;
1793
1794                         else
1795                            Rref := Empty;
1796                         end if;
1797                      end if;
1798
1799                      --  Write out renaming reference if we have one
1800
1801                      if Present (Rref) then
1802                         Write_Info_Char ('=');
1803                         Write_Info_Nat
1804                           (Int (Get_Logical_Line_Number (Sloc (Rref))));
1805                         Write_Info_Char (':');
1806                         Write_Info_Nat
1807                           (Int (Get_Column_Number (Sloc (Rref))));
1808                      end if;
1809
1810                      --  Indicate that the entity is in the unit of the current
1811                      --  xref xection.
1812
1813                      Curru := Curxu;
1814
1815                      --  Write out information about generic parent, if entity
1816                      --  is an instance.
1817
1818                      if  Is_Generic_Instance (XE.Ent) then
1819                         declare
1820                            Gen_Par : constant Entity_Id :=
1821                                        Generic_Parent
1822                                          (Specification
1823                                             (Unit_Declaration_Node (XE.Ent)));
1824                            Loc     : constant Source_Ptr := Sloc (Gen_Par);
1825                            Gen_U   : constant Unit_Number_Type :=
1826                                        Get_Source_Unit (Loc);
1827
1828                         begin
1829                            Write_Info_Char ('[');
1830                            if Curru /= Gen_U then
1831                               Write_Info_Nat (Dependency_Num (Gen_U));
1832                               Write_Info_Char ('|');
1833                            end if;
1834
1835                            Write_Info_Nat
1836                              (Int (Get_Logical_Line_Number (Loc)));
1837                            Write_Info_Char (']');
1838                         end;
1839                      end if;
1840
1841                      --  See if we have a type reference and if so output
1842
1843                      Check_Type_Reference (XE.Ent, False);
1844
1845                      if Is_Record_Type (XE.Ent)
1846                        and then Present (Abstract_Interfaces (XE.Ent))
1847                      then
1848                         declare
1849                            Elmt : Elmt_Id;
1850
1851                         begin
1852                            Elmt := First_Elmt (Abstract_Interfaces (XE.Ent));
1853                            while Present (Elmt) loop
1854                               Check_Type_Reference (Node (Elmt), True);
1855                               Next_Elmt (Elmt);
1856                            end loop;
1857                         end;
1858                      end if;
1859
1860                      --  If the entity is an overriding operation, write
1861                      --  info on operation that was overridden.
1862
1863                      if Is_Subprogram (XE.Ent)
1864                        and then Is_Overriding_Operation (XE.Ent)
1865                      then
1866                         Output_Overridden_Op (Overridden_Operation (XE.Ent));
1867                      end if;
1868
1869                      --  End of processing for entity output
1870
1871                      Crloc := No_Location;
1872                   end if;
1873
1874                   --  Output the reference
1875
1876                   if XE.Loc /= No_Location
1877                      and then XE.Loc /= Crloc
1878                   then
1879                      Crloc := XE.Loc;
1880
1881                      --  Start continuation if line full, else blank
1882
1883                      if Write_Info_Col > 72 then
1884                         Write_Info_EOL;
1885                         Write_Info_Initiate ('.');
1886                      end if;
1887
1888                      Write_Info_Char (' ');
1889
1890                      --  Output file number if changed
1891
1892                      if XE.Lun /= Curru then
1893                         Curru := XE.Lun;
1894                         Write_Info_Nat (Dependency_Num (Curru));
1895                         Write_Info_Char ('|');
1896                      end if;
1897
1898                      Write_Info_Nat  (Int (Get_Logical_Line_Number (XE.Loc)));
1899                      Write_Info_Char (XE.Typ);
1900
1901                      if Is_Overloadable (XE.Ent)
1902                        and then Is_Imported (XE.Ent)
1903                        and then XE.Typ = 'b'
1904                      then
1905                         Output_Import_Export_Info (XE.Ent);
1906                      end if;
1907
1908                      Write_Info_Nat  (Int (Get_Column_Number (XE.Loc)));
1909
1910                      Output_Instantiation_Refs (Sloc (XE.Ent));
1911                   end if;
1912                end if;
1913             end Output_One_Ref;
1914
1915          <<Continue>>
1916             null;
1917          end loop;
1918
1919          Write_Info_EOL;
1920       end Output_Refs;
1921    end Output_References;
1922
1923 end Lib.Xref;