1------------------------------------------------------------------------------
2--                                                                          --
3--                         GNAT COMPILER COMPONENTS                         --
4--                                                                          --
5--                                  L I B                                   --
6--                                                                          --
7--                                 B o d y                                  --
8--                                                                          --
9--          Copyright (C) 1992-2013, 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 3,  or (at your option) any later ver- --
14-- sion.  GNAT is distributed in the hope that it will be useful, but WITH- --
15-- OUT ANY WARRANTY;  without even the  implied warranty of MERCHANTABILITY --
16-- or FITNESS FOR A PARTICULAR PURPOSE.                                     --
17--                                                                          --
18-- As a special exception under Section 7 of GPL version 3, you are granted --
19-- additional permissions described in the GCC Runtime Library Exception,   --
20-- version 3.1, as published by the Free Software Foundation.               --
21--                                                                          --
22-- You should have received a copy of the GNU General Public License and    --
23-- a copy of the GCC Runtime Library Exception along with this program;     --
24-- see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see    --
25-- <http://www.gnu.org/licenses/>.                                          --
26--                                                                          --
27-- GNAT was originally developed  by the GNAT team at  New York University. --
28-- Extensive contributions were provided by Ada Core Technologies Inc.      --
29--                                                                          --
30------------------------------------------------------------------------------
31
32pragma Style_Checks (All_Checks);
33--  Subprogram ordering not enforced in this unit
34--  (because of some logical groupings).
35
36with Atree;    use Atree;
37with Csets;    use Csets;
38with Einfo;    use Einfo;
39with Fname;    use Fname;
40with Nlists;   use Nlists;
41with Output;   use Output;
42with Sinfo;    use Sinfo;
43with Sinput;   use Sinput;
44with Stand;    use Stand;
45with Stringt;  use Stringt;
46with Tree_IO;  use Tree_IO;
47with Uname;    use Uname;
48with Widechar; use Widechar;
49
50package body Lib is
51
52   Switch_Storing_Enabled : Boolean := True;
53   --  Controlled by Enable_Switch_Storing/Disable_Switch_Storing
54
55   -----------------------
56   -- Local Subprograms --
57   -----------------------
58
59   type SEU_Result is (
60      Yes_Before, -- S1 is in same extended unit as S2 and appears before it
61      Yes_Same,   -- S1 is in same extended unit as S2, Slocs are the same
62      Yes_After,  -- S1 is in same extended unit as S2, and appears after it
63      No);        -- S2 is not in same extended unit as S2
64
65   function Check_Same_Extended_Unit (S1, S2 : Source_Ptr) return SEU_Result;
66   --  Used by In_Same_Extended_Unit and Earlier_In_Extended_Unit. Returns
67   --  value as described above.
68
69   function Get_Code_Or_Source_Unit
70     (S                : Source_Ptr;
71      Unwind_Instances : Boolean) return Unit_Number_Type;
72   --  Common code for Get_Code_Unit (get unit of instantiation for location)
73   --  and Get_Source_Unit (get unit of template for location).
74
75   --------------------------------------------
76   -- Access Functions for Unit Table Fields --
77   --------------------------------------------
78
79   function Cunit (U : Unit_Number_Type) return Node_Id is
80   begin
81      return Units.Table (U).Cunit;
82   end Cunit;
83
84   function Cunit_Entity (U : Unit_Number_Type) return Entity_Id is
85   begin
86      return Units.Table (U).Cunit_Entity;
87   end Cunit_Entity;
88
89   function Dependency_Num (U : Unit_Number_Type) return Nat is
90   begin
91      return Units.Table (U).Dependency_Num;
92   end Dependency_Num;
93
94   function Dynamic_Elab (U : Unit_Number_Type) return Boolean is
95   begin
96      return Units.Table (U).Dynamic_Elab;
97   end Dynamic_Elab;
98
99   function Error_Location (U : Unit_Number_Type) return Source_Ptr is
100   begin
101      return Units.Table (U).Error_Location;
102   end Error_Location;
103
104   function Expected_Unit (U : Unit_Number_Type) return Unit_Name_Type is
105   begin
106      return Units.Table (U).Expected_Unit;
107   end Expected_Unit;
108
109   function Fatal_Error (U : Unit_Number_Type) return Boolean is
110   begin
111      return Units.Table (U).Fatal_Error;
112   end Fatal_Error;
113
114   function Generate_Code (U : Unit_Number_Type) return Boolean is
115   begin
116      return Units.Table (U).Generate_Code;
117   end Generate_Code;
118
119   function Has_Allocator (U : Unit_Number_Type) return Boolean is
120   begin
121      return Units.Table (U).Has_Allocator;
122   end Has_Allocator;
123
124   function Has_RACW (U : Unit_Number_Type) return Boolean is
125   begin
126      return Units.Table (U).Has_RACW;
127   end Has_RACW;
128
129   function Is_Compiler_Unit (U : Unit_Number_Type) return Boolean is
130   begin
131      return Units.Table (U).Is_Compiler_Unit;
132   end Is_Compiler_Unit;
133
134   function Ident_String (U : Unit_Number_Type) return Node_Id is
135   begin
136      return Units.Table (U).Ident_String;
137   end Ident_String;
138
139   function Loading (U : Unit_Number_Type) return Boolean is
140   begin
141      return Units.Table (U).Loading;
142   end Loading;
143
144   function Main_CPU (U : Unit_Number_Type) return Int is
145   begin
146      return Units.Table (U).Main_CPU;
147   end Main_CPU;
148
149   function Main_Priority (U : Unit_Number_Type) return Int is
150   begin
151      return Units.Table (U).Main_Priority;
152   end Main_Priority;
153
154   function Munit_Index (U : Unit_Number_Type) return Nat is
155   begin
156      return Units.Table (U).Munit_Index;
157   end Munit_Index;
158
159   function OA_Setting (U : Unit_Number_Type) return Character is
160   begin
161      return Units.Table (U).OA_Setting;
162   end OA_Setting;
163
164   function Source_Index (U : Unit_Number_Type) return Source_File_Index is
165   begin
166      return Units.Table (U).Source_Index;
167   end Source_Index;
168
169   function Unit_File_Name (U : Unit_Number_Type) return File_Name_Type is
170   begin
171      return Units.Table (U).Unit_File_Name;
172   end Unit_File_Name;
173
174   function Unit_Name (U : Unit_Number_Type) return Unit_Name_Type is
175   begin
176      return Units.Table (U).Unit_Name;
177   end Unit_Name;
178
179   ------------------------------------------
180   -- Subprograms to Set Unit Table Fields --
181   ------------------------------------------
182
183   procedure Set_Cunit (U : Unit_Number_Type; N : Node_Id) is
184   begin
185      Units.Table (U).Cunit := N;
186   end Set_Cunit;
187
188   procedure Set_Cunit_Entity (U : Unit_Number_Type; E : Entity_Id) is
189   begin
190      Units.Table (U).Cunit_Entity := E;
191      Set_Is_Compilation_Unit (E);
192   end Set_Cunit_Entity;
193
194   procedure Set_Dynamic_Elab (U : Unit_Number_Type; B : Boolean := True) is
195   begin
196      Units.Table (U).Dynamic_Elab := B;
197   end Set_Dynamic_Elab;
198
199   procedure Set_Error_Location (U : Unit_Number_Type; W : Source_Ptr) is
200   begin
201      Units.Table (U).Error_Location := W;
202   end Set_Error_Location;
203
204   procedure Set_Fatal_Error (U : Unit_Number_Type; B : Boolean := True) is
205   begin
206      Units.Table (U).Fatal_Error := B;
207   end Set_Fatal_Error;
208
209   procedure Set_Generate_Code (U : Unit_Number_Type; B : Boolean := True) is
210   begin
211      Units.Table (U).Generate_Code := B;
212   end Set_Generate_Code;
213
214   procedure Set_Has_Allocator (U : Unit_Number_Type; B : Boolean := True) is
215   begin
216      Units.Table (U).Has_Allocator := B;
217   end Set_Has_Allocator;
218
219   procedure Set_Has_RACW (U : Unit_Number_Type; B : Boolean := True) is
220   begin
221      Units.Table (U).Has_RACW := B;
222   end Set_Has_RACW;
223
224   procedure Set_Is_Compiler_Unit
225     (U : Unit_Number_Type;
226      B : Boolean := True)
227   is
228   begin
229      Units.Table (U).Is_Compiler_Unit := B;
230   end Set_Is_Compiler_Unit;
231
232   procedure Set_Ident_String (U : Unit_Number_Type; N : Node_Id) is
233   begin
234      Units.Table (U).Ident_String := N;
235   end Set_Ident_String;
236
237   procedure Set_Loading (U : Unit_Number_Type; B : Boolean := True) is
238   begin
239      Units.Table (U).Loading := B;
240   end Set_Loading;
241
242   procedure Set_Main_CPU (U : Unit_Number_Type; P : Int) is
243   begin
244      Units.Table (U).Main_CPU := P;
245   end Set_Main_CPU;
246
247   procedure Set_Main_Priority (U : Unit_Number_Type; P : Int) is
248   begin
249      Units.Table (U).Main_Priority := P;
250   end Set_Main_Priority;
251
252   procedure Set_OA_Setting (U : Unit_Number_Type; C : Character) is
253   begin
254      Units.Table (U).OA_Setting := C;
255   end Set_OA_Setting;
256
257   procedure Set_Unit_Name (U : Unit_Number_Type; N : Unit_Name_Type) is
258   begin
259      Units.Table (U).Unit_Name := N;
260   end Set_Unit_Name;
261
262   ------------------------------
263   -- Check_Same_Extended_Unit --
264   ------------------------------
265
266   function Check_Same_Extended_Unit (S1, S2 : Source_Ptr) return SEU_Result is
267      Sloc1  : Source_Ptr;
268      Sloc2  : Source_Ptr;
269      Sind1  : Source_File_Index;
270      Sind2  : Source_File_Index;
271      Inst1  : Source_Ptr;
272      Inst2  : Source_Ptr;
273      Unum1  : Unit_Number_Type;
274      Unum2  : Unit_Number_Type;
275      Unit1  : Node_Id;
276      Unit2  : Node_Id;
277      Depth1 : Nat;
278      Depth2 : Nat;
279
280   begin
281      if S1 = No_Location or else S2 = No_Location then
282         return No;
283
284      elsif S1 = Standard_Location then
285         if S2 = Standard_Location then
286            return Yes_Same;
287         else
288            return No;
289         end if;
290
291      elsif S2 = Standard_Location then
292         return No;
293      end if;
294
295      Sloc1 := S1;
296      Sloc2 := S2;
297
298      Unum1 := Get_Source_Unit (Sloc1);
299      Unum2 := Get_Source_Unit (Sloc2);
300
301      loop
302         --  Step 1: Check whether the two locations are in the same source
303         --  file.
304
305         Sind1 := Get_Source_File_Index (Sloc1);
306         Sind2 := Get_Source_File_Index (Sloc2);
307
308         if Sind1 = Sind2 then
309            if Sloc1 < Sloc2 then
310               return Yes_Before;
311            elsif Sloc1 > Sloc2 then
312               return Yes_After;
313            else
314               return Yes_Same;
315            end if;
316         end if;
317
318         --  Step 2: Check subunits. If a subunit is instantiated, follow the
319         --  instantiation chain rather than the stub chain.
320
321         Unit1 := Unit (Cunit (Unum1));
322         Unit2 := Unit (Cunit (Unum2));
323         Inst1 := Instantiation (Sind1);
324         Inst2 := Instantiation (Sind2);
325
326         if Nkind (Unit1) = N_Subunit
327           and then Present (Corresponding_Stub (Unit1))
328           and then Inst1 = No_Location
329         then
330            if Nkind (Unit2) = N_Subunit
331              and then Present (Corresponding_Stub (Unit2))
332              and then Inst2 = No_Location
333            then
334               --  Both locations refer to subunits which may have a common
335               --  ancestor. If they do, the deeper subunit must have a longer
336               --  unit name. Replace the deeper one with its corresponding
337               --  stub in order to find the nearest ancestor.
338
339               if Length_Of_Name (Unit_Name (Unum1)) <
340                  Length_Of_Name (Unit_Name (Unum2))
341               then
342                  Sloc2 := Sloc (Corresponding_Stub (Unit2));
343                  Unum2 := Get_Source_Unit (Sloc2);
344                  goto Continue;
345
346               else
347                  Sloc1 := Sloc (Corresponding_Stub (Unit1));
348                  Unum1 := Get_Source_Unit (Sloc1);
349                  goto Continue;
350               end if;
351
352            --  Sloc1 in subunit, Sloc2 not
353
354            else
355               Sloc1 := Sloc (Corresponding_Stub (Unit1));
356               Unum1 := Get_Source_Unit (Sloc1);
357               goto Continue;
358            end if;
359
360         --  Sloc2 in subunit, Sloc1 not
361
362         elsif Nkind (Unit2) = N_Subunit
363           and then Present (Corresponding_Stub (Unit2))
364           and then Inst2 = No_Location
365         then
366            Sloc2 := Sloc (Corresponding_Stub (Unit2));
367            Unum2 := Get_Source_Unit (Sloc2);
368            goto Continue;
369         end if;
370
371         --  Step 3: Check instances. The two locations may yield a common
372         --  ancestor.
373
374         if Inst1 /= No_Location then
375            if Inst2 /= No_Location then
376
377               --  Both locations denote instantiations
378
379               Depth1 := Instantiation_Depth (Sloc1);
380               Depth2 := Instantiation_Depth (Sloc2);
381
382               if Depth1 < Depth2 then
383                  Sloc2 := Inst2;
384                  Unum2 := Get_Source_Unit (Sloc2);
385                  goto Continue;
386
387               elsif Depth1 > Depth2 then
388                  Sloc1 := Inst1;
389                  Unum1 := Get_Source_Unit (Sloc1);
390                  goto Continue;
391
392               else
393                  Sloc1 := Inst1;
394                  Sloc2 := Inst2;
395                  Unum1 := Get_Source_Unit (Sloc1);
396                  Unum2 := Get_Source_Unit (Sloc2);
397                  goto Continue;
398               end if;
399
400            --  Sloc1 is an instantiation
401
402            else
403               Sloc1 := Inst1;
404               Unum1 := Get_Source_Unit (Sloc1);
405               goto Continue;
406            end if;
407
408         --  Sloc2 is an instantiation
409
410         elsif Inst2 /= No_Location then
411            Sloc2 := Inst2;
412            Unum2 := Get_Source_Unit (Sloc2);
413            goto Continue;
414         end if;
415
416         --  Step 4: One location in the spec, the other in the corresponding
417         --  body of the same unit. The location in the spec is considered
418         --  earlier.
419
420         if Nkind (Unit1) = N_Subprogram_Body
421              or else
422            Nkind (Unit1) = N_Package_Body
423         then
424            if Library_Unit (Cunit (Unum1)) = Cunit (Unum2) then
425               return Yes_After;
426            end if;
427
428         elsif Nkind (Unit2) = N_Subprogram_Body
429                 or else
430               Nkind (Unit2) = N_Package_Body
431         then
432            if Library_Unit (Cunit (Unum2)) = Cunit (Unum1) then
433               return Yes_Before;
434            end if;
435         end if;
436
437         --  At this point it is certain that the two locations denote two
438         --  entirely separate units.
439
440         return No;
441
442         <<Continue>>
443            null;
444      end loop;
445   end Check_Same_Extended_Unit;
446
447   -------------------------------
448   -- Compilation_Switches_Last --
449   -------------------------------
450
451   function Compilation_Switches_Last return Nat is
452   begin
453      return Compilation_Switches.Last;
454   end Compilation_Switches_Last;
455
456   ---------------------------
457   -- Enable_Switch_Storing --
458   ---------------------------
459
460   procedure Enable_Switch_Storing is
461   begin
462      Switch_Storing_Enabled := True;
463   end Enable_Switch_Storing;
464
465   ----------------------------
466   -- Disable_Switch_Storing --
467   ----------------------------
468
469   procedure Disable_Switch_Storing is
470   begin
471      Switch_Storing_Enabled := False;
472   end Disable_Switch_Storing;
473
474   ------------------------------
475   -- Earlier_In_Extended_Unit --
476   ------------------------------
477
478   function Earlier_In_Extended_Unit (S1, S2 : Source_Ptr) return Boolean is
479   begin
480      return Check_Same_Extended_Unit (S1, S2) = Yes_Before;
481   end Earlier_In_Extended_Unit;
482
483   -----------------------
484   -- Exact_Source_Name --
485   -----------------------
486
487   function Exact_Source_Name (Loc : Source_Ptr) return String is
488      U    : constant Unit_Number_Type  := Get_Source_Unit (Loc);
489      Buf  : constant Source_Buffer_Ptr := Source_Text (Source_Index (U));
490      Orig : constant Source_Ptr        := Original_Location (Loc);
491      P    : Source_Ptr;
492
493      WC   : Char_Code;
494      Err  : Boolean;
495      pragma Warnings (Off, WC);
496      pragma Warnings (Off, Err);
497
498   begin
499      --  Entity is character literal
500
501      if Buf (Orig) = ''' then
502         return String (Buf (Orig .. Orig + 2));
503
504      --  Entity is operator symbol
505
506      elsif Buf (Orig) = '"' or else Buf (Orig) = '%' then
507         P := Orig;
508
509         loop
510            P := P + 1;
511            exit when Buf (P) = Buf (Orig);
512         end loop;
513
514         return String (Buf (Orig .. P));
515
516      --  Entity is identifier
517
518      else
519         P := Orig;
520
521         loop
522            if Is_Start_Of_Wide_Char (Buf, P) then
523               Scan_Wide (Buf, P, WC, Err);
524            elsif not Identifier_Char (Buf (P)) then
525               exit;
526            else
527               P := P + 1;
528            end if;
529         end loop;
530
531         --  Write out the identifier by copying the exact source characters
532         --  used in its declaration. Note that this means wide characters will
533         --  be in their original encoded form.
534
535         return String (Buf (Orig .. P - 1));
536      end if;
537   end Exact_Source_Name;
538
539   ----------------------------
540   -- Entity_Is_In_Main_Unit --
541   ----------------------------
542
543   function Entity_Is_In_Main_Unit (E : Entity_Id) return Boolean is
544      S : Entity_Id;
545
546   begin
547      S := Scope (E);
548
549      while S /= Standard_Standard loop
550         if S = Main_Unit_Entity then
551            return True;
552         elsif Ekind (S) = E_Package and then Is_Child_Unit (S) then
553            return False;
554         else
555            S := Scope (S);
556         end if;
557      end loop;
558
559      return False;
560   end Entity_Is_In_Main_Unit;
561
562   --------------------------
563   -- Generic_May_Lack_ALI --
564   --------------------------
565
566   function Generic_May_Lack_ALI (Sfile : File_Name_Type) return Boolean is
567   begin
568      --  We allow internal generic units to be used without having a
569      --  corresponding ALI files to help bootstrapping with older compilers
570      --  that did not support generating ALIs for such generics. It is safe
571      --  to do so because the only thing the generated code would contain
572      --  is the elaboration boolean, and we are careful to elaborate all
573      --  predefined units first anyway.
574
575      return Is_Internal_File_Name
576               (Fname              => Sfile,
577                Renamings_Included => True);
578   end Generic_May_Lack_ALI;
579
580   -----------------------------
581   -- Get_Code_Or_Source_Unit --
582   -----------------------------
583
584   function Get_Code_Or_Source_Unit
585     (S                : Source_Ptr;
586      Unwind_Instances : Boolean) return Unit_Number_Type
587   is
588   begin
589      --  Search table unless we have No_Location, which can happen if the
590      --  relevant location has not been set yet. Happens for example when
591      --  we obtain Sloc (Cunit (Main_Unit)) before it is set.
592
593      if S /= No_Location then
594         declare
595            Source_File : Source_File_Index;
596            Source_Unit : Unit_Number_Type;
597
598         begin
599            Source_File := Get_Source_File_Index (S);
600
601            if Unwind_Instances then
602               while Template (Source_File) /= No_Source_File loop
603                  Source_File := Template (Source_File);
604               end loop;
605            end if;
606
607            Source_Unit := Unit (Source_File);
608
609            if Source_Unit /= No_Unit then
610               return Source_Unit;
611            end if;
612         end;
613      end if;
614
615      --  If S was No_Location, or was not in the table, we must be in the main
616      --  source unit (and the value has not been placed in the table yet),
617      --  or in one of the configuration pragma files.
618
619      return Main_Unit;
620   end Get_Code_Or_Source_Unit;
621
622   -------------------
623   -- Get_Code_Unit --
624   -------------------
625
626   function Get_Code_Unit (S : Source_Ptr) return Unit_Number_Type is
627   begin
628      return Get_Code_Or_Source_Unit (Top_Level_Location (S),
629        Unwind_Instances => False);
630   end Get_Code_Unit;
631
632   function Get_Code_Unit (N : Node_Or_Entity_Id) return Unit_Number_Type is
633   begin
634      return Get_Code_Unit (Sloc (N));
635   end Get_Code_Unit;
636
637   ----------------------------
638   -- Get_Compilation_Switch --
639   ----------------------------
640
641   function Get_Compilation_Switch (N : Pos) return String_Ptr is
642   begin
643      if N <= Compilation_Switches.Last then
644         return Compilation_Switches.Table (N);
645
646      else
647         return null;
648      end if;
649   end Get_Compilation_Switch;
650
651   ----------------------------------
652   -- Get_Cunit_Entity_Unit_Number --
653   ----------------------------------
654
655   function Get_Cunit_Entity_Unit_Number
656     (E : Entity_Id) return Unit_Number_Type
657   is
658   begin
659      for U in Units.First .. Units.Last loop
660         if Cunit_Entity (U) = E then
661            return U;
662         end if;
663      end loop;
664
665      --  If not in the table, must be the main source unit, and we just
666      --  have not got it put into the table yet.
667
668      return Main_Unit;
669   end Get_Cunit_Entity_Unit_Number;
670
671   ---------------------------
672   -- Get_Cunit_Unit_Number --
673   ---------------------------
674
675   function Get_Cunit_Unit_Number (N : Node_Id) return Unit_Number_Type is
676   begin
677      for U in Units.First .. Units.Last loop
678         if Cunit (U) = N then
679            return U;
680         end if;
681      end loop;
682
683      --  If not in the table, must be a spec created for a main unit that is a
684      --  child subprogram body which we have not inserted into the table yet.
685
686      if N = Library_Unit (Cunit (Main_Unit)) then
687         return Main_Unit;
688
689      --  If it is anything else, something is seriously wrong, and we really
690      --  don't want to proceed, even if assertions are off, so we explicitly
691      --  raise an exception in this case to terminate compilation.
692
693      else
694         raise Program_Error;
695      end if;
696   end Get_Cunit_Unit_Number;
697
698   ---------------------
699   -- Get_Source_Unit --
700   ---------------------
701
702   function Get_Source_Unit (S : Source_Ptr) return Unit_Number_Type is
703   begin
704      return Get_Code_Or_Source_Unit (S, Unwind_Instances => True);
705   end Get_Source_Unit;
706
707   function Get_Source_Unit (N : Node_Or_Entity_Id) return Unit_Number_Type is
708   begin
709      return Get_Source_Unit (Sloc (N));
710   end Get_Source_Unit;
711
712   --------------------------------
713   -- In_Extended_Main_Code_Unit --
714   --------------------------------
715
716   function In_Extended_Main_Code_Unit
717     (N : Node_Or_Entity_Id) return Boolean
718   is
719   begin
720      if Sloc (N) = Standard_Location then
721         return False;
722
723      elsif Sloc (N) = No_Location then
724         return False;
725
726      --  Special case Itypes to test the Sloc of the associated node. The
727      --  reason we do this is for possible calls from gigi after -gnatD
728      --  processing is complete in sprint. This processing updates the
729      --  sloc fields of all nodes in the tree, but itypes are not in the
730      --  tree so their slocs do not get updated.
731
732      elsif Nkind (N) = N_Defining_Identifier
733        and then Is_Itype (N)
734      then
735         return In_Extended_Main_Code_Unit (Associated_Node_For_Itype (N));
736
737      --  Otherwise see if we are in the main unit
738
739      elsif Get_Code_Unit (Sloc (N)) = Get_Code_Unit (Cunit (Main_Unit)) then
740         return True;
741
742      --  Node may be in spec (or subunit etc) of main unit
743
744      else
745         return
746           In_Same_Extended_Unit (N, Cunit (Main_Unit));
747      end if;
748   end In_Extended_Main_Code_Unit;
749
750   function In_Extended_Main_Code_Unit (Loc : Source_Ptr) return Boolean is
751   begin
752      if Loc = Standard_Location then
753         return False;
754
755      elsif Loc = No_Location then
756         return False;
757
758      --  Otherwise see if we are in the main unit
759
760      elsif Get_Code_Unit (Loc) = Get_Code_Unit (Cunit (Main_Unit)) then
761         return True;
762
763      --  Location may be in spec (or subunit etc) of main unit
764
765      else
766         return
767           In_Same_Extended_Unit (Loc, Sloc (Cunit (Main_Unit)));
768      end if;
769   end In_Extended_Main_Code_Unit;
770
771   ----------------------------------
772   -- In_Extended_Main_Source_Unit --
773   ----------------------------------
774
775   function In_Extended_Main_Source_Unit
776     (N : Node_Or_Entity_Id) return Boolean
777   is
778      Nloc : constant Source_Ptr := Sloc (N);
779      Mloc : constant Source_Ptr := Sloc (Cunit (Main_Unit));
780
781   begin
782      --  If parsing, then use the global flag to indicate result
783
784      if Compiler_State = Parsing then
785         return Parsing_Main_Extended_Source;
786
787      --  Special value cases
788
789      elsif Nloc = Standard_Location then
790         return False;
791
792      elsif Nloc = No_Location then
793         return False;
794
795      --  Special case Itypes to test the Sloc of the associated node. The
796      --  reason we do this is for possible calls from gigi after -gnatD
797      --  processing is complete in sprint. This processing updates the
798      --  sloc fields of all nodes in the tree, but itypes are not in the
799      --  tree so their slocs do not get updated.
800
801      elsif Nkind (N) = N_Defining_Identifier
802        and then Is_Itype (N)
803      then
804         return In_Extended_Main_Source_Unit (Associated_Node_For_Itype (N));
805
806      --  Otherwise compare original locations to see if in same unit
807
808      else
809         return
810           In_Same_Extended_Unit
811             (Original_Location (Nloc), Original_Location (Mloc));
812      end if;
813   end In_Extended_Main_Source_Unit;
814
815   function In_Extended_Main_Source_Unit
816     (Loc : Source_Ptr) return Boolean
817   is
818      Mloc : constant Source_Ptr := Sloc (Cunit (Main_Unit));
819
820   begin
821      --  If parsing, then use the global flag to indicate result
822
823      if Compiler_State = Parsing then
824         return Parsing_Main_Extended_Source;
825
826      --  Special value cases
827
828      elsif Loc = Standard_Location then
829         return False;
830
831      elsif Loc = No_Location then
832         return False;
833
834      --  Otherwise compare original locations to see if in same unit
835
836      else
837         return
838           In_Same_Extended_Unit
839             (Original_Location (Loc), Original_Location (Mloc));
840      end if;
841   end In_Extended_Main_Source_Unit;
842
843   ------------------------
844   -- In_Predefined_Unit --
845   ------------------------
846
847   function In_Predefined_Unit (N : Node_Or_Entity_Id) return Boolean is
848   begin
849      return In_Predefined_Unit (Sloc (N));
850   end In_Predefined_Unit;
851
852   function In_Predefined_Unit (S : Source_Ptr) return Boolean is
853      Unit : constant Unit_Number_Type := Get_Source_Unit (S);
854      File : constant File_Name_Type   := Unit_File_Name (Unit);
855   begin
856      return Is_Predefined_File_Name (File);
857   end In_Predefined_Unit;
858
859   -----------------------
860   -- In_Same_Code_Unit --
861   -----------------------
862
863   function In_Same_Code_Unit (N1, N2 : Node_Or_Entity_Id) return Boolean is
864      S1 : constant Source_Ptr := Sloc (N1);
865      S2 : constant Source_Ptr := Sloc (N2);
866
867   begin
868      if S1 = No_Location or else S2 = No_Location then
869         return False;
870
871      elsif S1 = Standard_Location then
872         return S2 = Standard_Location;
873
874      elsif S2 = Standard_Location then
875         return False;
876      end if;
877
878      return Get_Code_Unit (N1) = Get_Code_Unit (N2);
879   end In_Same_Code_Unit;
880
881   ---------------------------
882   -- In_Same_Extended_Unit --
883   ---------------------------
884
885   function In_Same_Extended_Unit
886     (N1, N2 : Node_Or_Entity_Id) return Boolean
887   is
888   begin
889      return Check_Same_Extended_Unit (Sloc (N1), Sloc (N2)) /= No;
890   end In_Same_Extended_Unit;
891
892   function In_Same_Extended_Unit (S1, S2 : Source_Ptr) return Boolean is
893   begin
894      return Check_Same_Extended_Unit (S1, S2) /= No;
895   end In_Same_Extended_Unit;
896
897   -------------------------
898   -- In_Same_Source_Unit --
899   -------------------------
900
901   function In_Same_Source_Unit (N1, N2 : Node_Or_Entity_Id) return Boolean is
902      S1 : constant Source_Ptr := Sloc (N1);
903      S2 : constant Source_Ptr := Sloc (N2);
904
905   begin
906      if S1 = No_Location or else S2 = No_Location then
907         return False;
908
909      elsif S1 = Standard_Location then
910         return S2 = Standard_Location;
911
912      elsif S2 = Standard_Location then
913         return False;
914      end if;
915
916      return Get_Source_Unit (N1) = Get_Source_Unit (N2);
917   end In_Same_Source_Unit;
918
919   -----------------------------
920   -- Increment_Serial_Number --
921   -----------------------------
922
923   function Increment_Serial_Number return Nat is
924      TSN : Int renames Units.Table (Current_Sem_Unit).Serial_Number;
925   begin
926      TSN := TSN + 1;
927      return TSN;
928   end Increment_Serial_Number;
929
930   ----------------
931   -- Initialize --
932   ----------------
933
934   procedure Initialize is
935   begin
936      Linker_Option_Lines.Init;
937      Notes.Init;
938      Load_Stack.Init;
939      Units.Init;
940      Compilation_Switches.Init;
941   end Initialize;
942
943   ---------------
944   -- Is_Loaded --
945   ---------------
946
947   function Is_Loaded (Uname : Unit_Name_Type) return Boolean is
948   begin
949      for Unum in Units.First .. Units.Last loop
950         if Uname = Unit_Name (Unum) then
951            return True;
952         end if;
953      end loop;
954
955      return False;
956   end Is_Loaded;
957
958   ---------------
959   -- Last_Unit --
960   ---------------
961
962   function Last_Unit return Unit_Number_Type is
963   begin
964      return Units.Last;
965   end Last_Unit;
966
967   ----------
968   -- List --
969   ----------
970
971   procedure List (File_Names_Only : Boolean := False) is separate;
972
973   ----------
974   -- Lock --
975   ----------
976
977   procedure Lock is
978   begin
979      Linker_Option_Lines.Locked := True;
980      Load_Stack.Locked := True;
981      Units.Locked := True;
982      Linker_Option_Lines.Release;
983      Load_Stack.Release;
984      Units.Release;
985   end Lock;
986
987   ---------------
988   -- Num_Units --
989   ---------------
990
991   function Num_Units return Nat is
992   begin
993      return Int (Units.Last) - Int (Main_Unit) + 1;
994   end Num_Units;
995
996   -----------------
997   -- Remove_Unit --
998   -----------------
999
1000   procedure Remove_Unit (U : Unit_Number_Type) is
1001   begin
1002      if U = Units.Last then
1003         Units.Decrement_Last;
1004      end if;
1005   end Remove_Unit;
1006
1007   ----------------------------------
1008   -- Replace_Linker_Option_String --
1009   ----------------------------------
1010
1011   procedure Replace_Linker_Option_String
1012     (S : String_Id; Match_String : String)
1013   is
1014   begin
1015      if Match_String'Length > 0 then
1016         for J in 1 .. Linker_Option_Lines.Last loop
1017            String_To_Name_Buffer (Linker_Option_Lines.Table (J).Option);
1018
1019            if Match_String = Name_Buffer (1 .. Match_String'Length) then
1020               Linker_Option_Lines.Table (J).Option := S;
1021               return;
1022            end if;
1023         end loop;
1024      end if;
1025
1026      Store_Linker_Option_String (S);
1027   end Replace_Linker_Option_String;
1028
1029   ----------
1030   -- Sort --
1031   ----------
1032
1033   procedure Sort (Tbl : in out Unit_Ref_Table) is separate;
1034
1035   ------------------------------
1036   -- Store_Compilation_Switch --
1037   ------------------------------
1038
1039   procedure Store_Compilation_Switch (Switch : String) is
1040   begin
1041      if Switch_Storing_Enabled then
1042         Compilation_Switches.Increment_Last;
1043         Compilation_Switches.Table (Compilation_Switches.Last) :=
1044           new String'(Switch);
1045
1046         --  Fix up --RTS flag which has been transformed by the gcc driver
1047         --  into -fRTS
1048
1049         if Switch'Last >= Switch'First + 4
1050           and then Switch (Switch'First .. Switch'First + 4) = "-fRTS"
1051         then
1052            Compilation_Switches.Table
1053              (Compilation_Switches.Last) (Switch'First + 1) := '-';
1054         end if;
1055      end if;
1056   end Store_Compilation_Switch;
1057
1058   --------------------------------
1059   -- Store_Linker_Option_String --
1060   --------------------------------
1061
1062   procedure Store_Linker_Option_String (S : String_Id) is
1063   begin
1064      Linker_Option_Lines.Append ((Option => S, Unit => Current_Sem_Unit));
1065   end Store_Linker_Option_String;
1066
1067   ----------------
1068   -- Store_Note --
1069   ----------------
1070
1071   procedure Store_Note (N : Node_Id) is
1072   begin
1073      Notes.Append ((Pragma_Node => N, Unit => Current_Sem_Unit));
1074   end Store_Note;
1075
1076   -------------------------------
1077   -- Synchronize_Serial_Number --
1078   -------------------------------
1079
1080   procedure Synchronize_Serial_Number is
1081      TSN : Int renames Units.Table (Current_Sem_Unit).Serial_Number;
1082   begin
1083      TSN := TSN + 1;
1084   end Synchronize_Serial_Number;
1085
1086   ---------------
1087   -- Tree_Read --
1088   ---------------
1089
1090   procedure Tree_Read is
1091      N : Nat;
1092      S : String_Ptr;
1093
1094   begin
1095      Units.Tree_Read;
1096
1097      --  Read Compilation_Switches table. First release the memory occupied
1098      --  by the previously loaded switches.
1099
1100      for J in Compilation_Switches.First .. Compilation_Switches.Last loop
1101         Free (Compilation_Switches.Table (J));
1102      end loop;
1103
1104      Tree_Read_Int (N);
1105      Compilation_Switches.Set_Last (N);
1106
1107      for J in 1 .. N loop
1108         Tree_Read_Str (S);
1109         Compilation_Switches.Table (J) := S;
1110      end loop;
1111   end Tree_Read;
1112
1113   ----------------
1114   -- Tree_Write --
1115   ----------------
1116
1117   procedure Tree_Write is
1118   begin
1119      Units.Tree_Write;
1120
1121      --  Write Compilation_Switches table
1122
1123      Tree_Write_Int (Compilation_Switches.Last);
1124
1125      for J in 1 .. Compilation_Switches.Last loop
1126         Tree_Write_Str (Compilation_Switches.Table (J));
1127      end loop;
1128   end Tree_Write;
1129
1130   ------------
1131   -- Unlock --
1132   ------------
1133
1134   procedure Unlock is
1135   begin
1136      Linker_Option_Lines.Locked := False;
1137      Load_Stack.Locked := False;
1138      Units.Locked := False;
1139   end Unlock;
1140
1141   -----------------
1142   -- Version_Get --
1143   -----------------
1144
1145   function Version_Get (U : Unit_Number_Type) return Word_Hex_String is
1146   begin
1147      return Get_Hex_String (Units.Table (U).Version);
1148   end Version_Get;
1149
1150   ------------------------
1151   -- Version_Referenced --
1152   ------------------------
1153
1154   procedure Version_Referenced (S : String_Id) is
1155   begin
1156      Version_Ref.Append (S);
1157   end Version_Referenced;
1158
1159   ---------------------
1160   -- Write_Unit_Info --
1161   ---------------------
1162
1163   procedure Write_Unit_Info
1164     (Unit_Num : Unit_Number_Type;
1165      Item     : Node_Id;
1166      Prefix   : String := "";
1167      Withs    : Boolean := False)
1168   is
1169   begin
1170      Write_Str (Prefix);
1171      Write_Unit_Name (Unit_Name (Unit_Num));
1172      Write_Str (", unit ");
1173      Write_Int (Int (Unit_Num));
1174      Write_Str (", ");
1175      Write_Int (Int (Item));
1176      Write_Str ("=");
1177      Write_Str (Node_Kind'Image (Nkind (Item)));
1178
1179      if Item /= Original_Node (Item) then
1180         Write_Str (", orig = ");
1181         Write_Int (Int (Original_Node (Item)));
1182         Write_Str ("=");
1183         Write_Str (Node_Kind'Image (Nkind (Original_Node (Item))));
1184      end if;
1185
1186      Write_Eol;
1187
1188      --  Skip the rest if we're not supposed to print the withs
1189
1190      if not Withs then
1191         return;
1192      end if;
1193
1194      declare
1195         Context_Item : Node_Id;
1196
1197      begin
1198         Context_Item := First (Context_Items (Cunit (Unit_Num)));
1199         while Present (Context_Item)
1200           and then (Nkind (Context_Item) /= N_With_Clause
1201                      or else Limited_Present (Context_Item))
1202         loop
1203            Context_Item := Next (Context_Item);
1204         end loop;
1205
1206         if Present (Context_Item) then
1207            Indent;
1208            Write_Line ("withs:");
1209            Indent;
1210
1211            while Present (Context_Item) loop
1212               if Nkind (Context_Item) = N_With_Clause
1213                 and then not Limited_Present (Context_Item)
1214               then
1215                  pragma Assert (Present (Library_Unit (Context_Item)));
1216                  Write_Unit_Name
1217                    (Unit_Name
1218                       (Get_Cunit_Unit_Number (Library_Unit (Context_Item))));
1219
1220                  if Implicit_With (Context_Item) then
1221                     Write_Str (" -- implicit");
1222                  end if;
1223
1224                  Write_Eol;
1225               end if;
1226
1227               Context_Item := Next (Context_Item);
1228            end loop;
1229
1230            Outdent;
1231            Write_Line ("end withs");
1232            Outdent;
1233         end if;
1234      end;
1235   end Write_Unit_Info;
1236
1237end Lib;
1238