1------------------------------------------------------------------------------
2--                                                                          --
3--                         GNAT COMPILER COMPONENTS                         --
4--                                                                          --
5--                             L I B . L O A D                              --
6--                                                                          --
7--                                 B o d y                                  --
8--                                                                          --
9--          Copyright (C) 1992-2021, 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.  See the GNU General Public License --
17-- for  more details.  You should have  received  a copy of the GNU General --
18-- Public License  distributed with GNAT; see file COPYING3.  If not, go to --
19-- http://www.gnu.org/licenses for a complete copy of the license.          --
20--                                                                          --
21-- GNAT was originally developed  by the GNAT team at  New York University. --
22-- Extensive contributions were provided by Ada Core Technologies Inc.      --
23--                                                                          --
24------------------------------------------------------------------------------
25
26with Atree;          use Atree;
27with Debug;          use Debug;
28with Einfo;          use Einfo;
29with Einfo.Entities; use Einfo.Entities;
30with Errout;         use Errout;
31with Fname;          use Fname;
32with Fname.UF;       use Fname.UF;
33with Nlists;         use Nlists;
34with Nmake;          use Nmake;
35with Opt;            use Opt;
36with Osint;          use Osint;
37with Osint.C;        use Osint.C;
38with Output;         use Output;
39with Par;
40with Restrict;       use Restrict;
41with Scn;            use Scn;
42with Sinfo;          use Sinfo;
43with Sinfo.Nodes;    use Sinfo.Nodes;
44with Sinfo.Utils;    use Sinfo.Utils;
45with Sinput;         use Sinput;
46with Sinput.L;       use Sinput.L;
47with Stand;          use Stand;
48with Tbuild;         use Tbuild;
49with Uname;          use Uname;
50
51package body Lib.Load is
52
53   -----------------------
54   -- Local Subprograms --
55   -----------------------
56
57   function From_Limited_With_Chain return Boolean;
58   --  Check whether a possible circular dependence includes units that
59   --  have been loaded through limited_with clauses, in which case there
60   --  is no real circularity.
61
62   function Spec_Is_Irrelevant
63     (Spec_Unit : Unit_Number_Type;
64      Body_Unit : Unit_Number_Type) return Boolean;
65   --  The Spec_Unit and Body_Unit parameters are the unit numbers of the
66   --  spec file that corresponds to the main unit which is a body. This
67   --  function determines if the spec file is irrelevant and will be
68   --  overridden by the body as described in RM 10.1.4(4). See description
69   --  in "Special Handling of Subprogram Bodies" for further details.
70
71   procedure Write_Dependency_Chain;
72   --  This procedure is used to generate error message info lines that
73   --  trace the current dependency chain when a load error occurs.
74
75   ------------------------------
76   -- Change_Main_Unit_To_Spec --
77   ------------------------------
78
79   procedure Change_Main_Unit_To_Spec is
80      U : Unit_Record renames Units.Table (Main_Unit);
81      N : File_Name_Type;
82      X : Source_File_Index;
83
84   begin
85      --  Get name of unit body
86
87      Get_Name_String (U.Unit_File_Name);
88
89      --  Note: for the following we should really generalize and consult the
90      --  file name pattern data, but for now we just deal with the common
91      --  naming cases, which is good enough in practice.
92
93      --  Change .adb to .ads
94
95      if Name_Len >= 5
96        and then Name_Buffer (Name_Len - 3 .. Name_Len) = ".adb"
97      then
98         Name_Buffer (Name_Len) := 's';
99
100      --  Change .2.ada to .1.ada (Rational convention)
101
102      elsif Name_Len >= 7
103        and then Name_Buffer (Name_Len - 5 .. Name_Len) = ".2.ada"
104      then
105         Name_Buffer (Name_Len - 4) := '1';
106
107      --  Change .ada to _.ada (DEC convention)
108
109      elsif Name_Len >= 5
110        and then Name_Buffer (Name_Len - 3 .. Name_Len) = ".ada"
111      then
112         Name_Buffer (Name_Len - 3 .. Name_Len + 1) := "_.ada";
113         Name_Len := Name_Len + 1;
114
115      --  No match, don't make the change
116
117      else
118         return;
119      end if;
120
121      --  Try loading the spec
122
123      N := Name_Find;
124      X := Load_Source_File (N);
125
126      --  No change if we did not find the spec
127
128      if X <= No_Source_File then
129         return;
130      end if;
131
132      --  Otherwise modify Main_Unit entry to point to spec
133
134      U.Unit_File_Name := N;
135      U.Source_Index := X;
136   end Change_Main_Unit_To_Spec;
137
138   -------------------------------
139   -- Create_Dummy_Package_Unit --
140   -------------------------------
141
142   function Create_Dummy_Package_Unit
143     (With_Node : Node_Id;
144      Spec_Name : Unit_Name_Type) return Unit_Number_Type
145   is
146      Unum         : Unit_Number_Type;
147      Cunit_Entity : Entity_Id;
148      Cunit        : Node_Id;
149      Du_Name      : Node_Or_Entity_Id;
150      End_Lab      : Node_Id;
151      Fname        : constant File_Name_Type :=
152        Get_File_Name (Spec_Name, Subunit => False);
153      Pre_Name : constant Boolean :=
154        Is_Predefined_File_Name (Fname, Renamings_Included => False);
155      Ren_Name : constant Boolean :=
156        Is_Predefined_Renaming_File_Name (Fname);
157      GNAT_Name : constant Boolean :=
158        Is_GNAT_File_Name (Fname);
159      Save_CS : constant Boolean := Get_Comes_From_Source_Default;
160
161   begin
162      --  The created dummy package unit does not come from source
163
164      Set_Comes_From_Source_Default (False);
165
166      --  Normal package
167
168      if Nkind (Name (With_Node)) = N_Identifier then
169         Cunit_Entity :=
170           Make_Defining_Identifier (No_Location,
171             Chars => Chars (Name (With_Node)));
172         Du_Name := Cunit_Entity;
173         End_Lab := New_Occurrence_Of (Cunit_Entity, No_Location);
174
175      --  Child package
176
177      else
178         Cunit_Entity :=
179           Make_Defining_Identifier (No_Location,
180             Chars => Chars (Selector_Name (Name (With_Node))));
181         Du_Name :=
182           Make_Defining_Program_Unit_Name (No_Location,
183             Name => Copy_Separate_Tree (Prefix (Name (With_Node))),
184             Defining_Identifier => Cunit_Entity);
185
186         Set_Is_Child_Unit (Cunit_Entity);
187
188         End_Lab :=
189           Make_Designator (No_Location,
190             Name => Copy_Separate_Tree (Prefix (Name (With_Node))),
191             Identifier => New_Occurrence_Of (Cunit_Entity, No_Location));
192      end if;
193
194      Set_Scope (Cunit_Entity, Standard_Standard);
195
196      Cunit :=
197        Make_Compilation_Unit (No_Location,
198          Context_Items => Empty_List,
199          Unit =>
200            Make_Package_Declaration (No_Location,
201              Specification =>
202                Make_Package_Specification (No_Location,
203                  Defining_Unit_Name   => Du_Name,
204                  Visible_Declarations => Empty_List,
205                  End_Label            => End_Lab)),
206          Aux_Decls_Node =>
207            Make_Compilation_Unit_Aux (No_Location));
208
209      --  Mark the dummy package as analyzed to prevent analysis of this
210      --  (non-existent) unit in -gnatQ mode because at the moment the
211      --  structure and attributes of this dummy package does not allow
212      --  a normal analysis of this unit
213
214      Set_Analyzed (Cunit);
215
216      Units.Increment_Last;
217      Unum := Units.Last;
218
219      Units.Table (Unum) :=
220        (Cunit                  => Cunit,
221         Cunit_Entity           => Cunit_Entity,
222         Dependency_Num         => 0,
223         Dynamic_Elab           => False,
224         Error_Location         => Sloc (With_Node),
225         Expected_Unit          => Spec_Name,
226         Fatal_Error            => Error_Detected,
227         Generate_Code          => False,
228         Has_RACW               => False,
229         Filler                 => False,
230         Ident_String           => Empty,
231
232         Is_Predefined_Renaming => Ren_Name,
233         Is_Predefined_Unit     => Pre_Name or Ren_Name,
234         Is_Internal_Unit       => Pre_Name or Ren_Name or GNAT_Name,
235         Filler2                => False,
236
237         Loading                => False,
238         Main_Priority          => Default_Main_Priority,
239         Main_CPU               => Default_Main_CPU,
240         Primary_Stack_Count    => 0,
241         Sec_Stack_Count        => 0,
242         Munit_Index            => 0,
243         No_Elab_Code_All       => False,
244         Serial_Number          => 0,
245         Source_Index           => No_Source_File,
246         Unit_File_Name         => Fname,
247         Unit_Name              => Spec_Name,
248         Version                => 0,
249         OA_Setting             => 'O');
250
251      Init_Unit_Name (Unum, Spec_Name);
252
253      Set_Comes_From_Source_Default (Save_CS);
254      Set_Error_Posted (Cunit_Entity);
255      Set_Error_Posted (Cunit);
256      return Unum;
257   end Create_Dummy_Package_Unit;
258
259   -----------------------------
260   -- From_Limited_With_Chain --
261   -----------------------------
262
263   function From_Limited_With_Chain return Boolean is
264      Curr_Num : constant Unit_Number_Type :=
265                   Load_Stack.Table (Load_Stack.Last).Unit_Number;
266
267   begin
268      --  True if the current load operation is through a limited_with clause
269      --  and we are not within a loop of regular with_clauses.
270
271      for U in reverse Load_Stack.First .. Load_Stack.Last - 1 loop
272         if Load_Stack.Table (U).Unit_Number = Curr_Num then
273            return False;
274
275         elsif Present (Load_Stack.Table (U).With_Node)
276           and then Limited_Present (Load_Stack.Table (U).With_Node)
277         then
278            return True;
279         end if;
280      end loop;
281
282      return False;
283   end From_Limited_With_Chain;
284
285   ----------------
286   -- Initialize --
287   ----------------
288
289   procedure Initialize is
290   begin
291      Units.Init;
292      Load_Stack.Init;
293   end Initialize;
294
295   ------------------------
296   -- Initialize_Version --
297   ------------------------
298
299   procedure Initialize_Version (U : Unit_Number_Type) is
300   begin
301      Units.Table (U).Version := Source_Checksum (Source_Index (U));
302   end Initialize_Version;
303
304   ----------------------
305   -- Load_Main_Source --
306   ----------------------
307
308   procedure Load_Main_Source is
309      Fname : constant File_Name_Type := Next_Main_Source;
310      Pre_Name : constant Boolean :=
311        Is_Predefined_File_Name (Fname, Renamings_Included => False);
312      Ren_Name : constant Boolean :=
313        Is_Predefined_Renaming_File_Name (Fname);
314      GNAT_Name : constant Boolean :=
315        Is_GNAT_File_Name (Fname);
316      Version : Word := 0;
317
318   begin
319      Load_Stack.Increment_Last;
320      Load_Stack.Table (Load_Stack.Last) := (Main_Unit, Empty);
321
322      --  Initialize unit table entry for Main_Unit. Note that we don't know
323      --  the unit name yet, that gets filled in when the parser parses the
324      --  main unit, at which time a check is made that it matches the main
325      --  file name, and then the Unit_Name field is set. The Cunit and
326      --  Cunit_Entity fields also get filled in later by the parser.
327
328      Units.Increment_Last;
329
330      Units.Table (Main_Unit).Unit_File_Name := Fname;
331
332      if Fname /= No_File then
333         Main_Source_File := Load_Source_File (Fname);
334         Current_Error_Source_File := Main_Source_File;
335
336         if Main_Source_File > No_Source_File then
337            Version := Source_Checksum (Main_Source_File);
338
339         else
340            --  To avoid emitting a source location (since there is no file),
341            --  we write a custom error message instead of using the machinery
342            --  in errout.adb.
343
344            Set_Standard_Error;
345
346            if Main_Source_File = No_Access_To_Source_File then
347               Write_Str
348                 ("no read access for file """ & Get_Name_String (Fname)
349                  & """");
350            else
351               Write_Str
352                 ("file """ & Get_Name_String (Fname) & """ not found");
353            end if;
354
355            Write_Eol;
356            Set_Standard_Output;
357         end if;
358
359         Units.Table (Main_Unit) :=
360           (Cunit                  => Empty,
361            Cunit_Entity           => Empty,
362            Dependency_Num         => 0,
363            Dynamic_Elab           => False,
364            Error_Location         => No_Location,
365            Expected_Unit          => No_Unit_Name,
366            Fatal_Error            => None,
367            Generate_Code          => True,
368            Has_RACW               => False,
369            Filler                 => False,
370            Ident_String           => Empty,
371
372            Is_Predefined_Renaming => Ren_Name,
373            Is_Predefined_Unit     => Pre_Name or Ren_Name,
374            Is_Internal_Unit       => Pre_Name or Ren_Name or GNAT_Name,
375            Filler2                => False,
376
377            Loading                => True,
378            Main_Priority          => Default_Main_Priority,
379            Main_CPU               => Default_Main_CPU,
380            Primary_Stack_Count    => 0,
381            Sec_Stack_Count        => 0,
382
383            Munit_Index            => 0,
384            No_Elab_Code_All       => False,
385            Serial_Number          => 0,
386            Source_Index           => Main_Source_File,
387            Unit_File_Name         => Fname,
388            Unit_Name              => No_Unit_Name,
389            Version                => Version,
390            OA_Setting             => 'O');
391      end if;
392   end Load_Main_Source;
393
394   ---------------
395   -- Load_Unit --
396   ---------------
397
398   function Load_Unit
399     (Load_Name  : Unit_Name_Type;
400      Required   : Boolean;
401      Error_Node : Node_Id;
402      Subunit    : Boolean;
403      Corr_Body  : Unit_Number_Type := No_Unit;
404      Renamings  : Boolean          := False;
405      With_Node  : Node_Id          := Empty;
406      PMES       : Boolean          := False) return Unit_Number_Type
407   is
408      Calling_Unit : Unit_Number_Type;
409      Uname_Actual : Unit_Name_Type;
410      Unum         : Unit_Number_Type;
411      Unump        : Unit_Number_Type;
412      Fname        : File_Name_Type;
413      Pre_Name     : Boolean;
414      Ren_Name     : Boolean;
415      GNAT_Name    : Boolean;
416      Src_Ind      : Source_File_Index;
417      Save_PMES    : constant Boolean := Parsing_Main_Extended_Source;
418
419      Save_Cunit_Restrictions : constant Save_Cunit_Boolean_Restrictions :=
420                                  Cunit_Boolean_Restrictions_Save;
421      --  Save current restrictions for restore at end
422
423   begin
424      Parsing_Main_Extended_Source := PMES;
425
426      --  Initialize restrictions to config restrictions for unit to load if
427      --  it is part of the main extended source, otherwise reset them.
428
429      --  Note: it's a bit odd but PMES is False for subunits, which is why
430      --  we have the OR here.
431
432      if PMES or Subunit then
433         Restore_Config_Cunit_Boolean_Restrictions;
434      else
435         Reset_Cunit_Boolean_Restrictions;
436      end if;
437
438      --  If renamings are allowed and we have a child unit name, then we
439      --  must first load the parent to deal with finding the real name.
440      --  Retain the with_clause that names the child, so that if it is
441      --  limited, the parent is loaded under the same condition.
442
443      if Renamings and then Is_Child_Name (Load_Name) then
444         Unump :=
445           Load_Unit
446             (Load_Name  => Get_Parent_Spec_Name (Load_Name),
447              Required   => Required,
448              Subunit    => False,
449              Renamings  => True,
450              Error_Node => Error_Node,
451              With_Node  => With_Node);
452
453         if Unump = No_Unit then
454            Unum := No_Unit;
455            goto Done;
456         end if;
457
458         --  If parent is a renaming, then we use the renamed package as
459         --  the actual parent for the subsequent load operation.
460
461         if Nkind (Unit (Cunit (Unump))) = N_Package_Renaming_Declaration then
462            Uname_Actual :=
463              New_Child
464                (Load_Name, Get_Unit_Name (Name (Unit (Cunit (Unump)))));
465
466            --  If the load is for a with_clause, for visibility purposes both
467            --  the renamed entity and renaming one must be available in the
468            --  current unit: the renamed one in order to retrieve the child
469            --  unit, and the original one because it may be used as a prefix
470            --  in the body of the current unit. We add an explicit with_clause
471            --  for the original parent so that the renaming declaration is
472            --  properly loaded and analyzed.
473
474            if Present (With_Node) then
475               Insert_After (With_Node,
476                 Make_With_Clause (Sloc (With_Node),
477                   Name => Copy_Separate_Tree (Prefix (Name (With_Node)))));
478            end if;
479
480            --  Save the renaming entity, to establish its visibility when
481            --  installing the context. The implicit with is on this entity,
482            --  not on the package it renames. This is somewhat redundant given
483            --  the with_clause just created, but it simplifies subsequent
484            --  expansion of the current with_clause.
485
486            if Nkind (Error_Node) = N_With_Clause
487              and then Nkind (Name (Error_Node)) = N_Selected_Component
488            then
489               declare
490                  Par : Node_Id := Name (Error_Node);
491
492               begin
493                  while Nkind (Par) = N_Selected_Component
494                    and then Chars (Selector_Name (Par)) /=
495                             Chars (Cunit_Entity (Unump))
496                  loop
497                     Par := Prefix (Par);
498                  end loop;
499
500                  --  Case of some intermediate parent is a renaming
501
502                  if Nkind (Par) = N_Selected_Component then
503                     Set_Entity (Selector_Name (Par), Cunit_Entity (Unump));
504
505                  --  Case where the ultimate parent is a renaming
506
507                  else
508                     Set_Entity (Par, Cunit_Entity (Unump));
509                  end if;
510               end;
511            end if;
512
513         --  If the parent is not a renaming, then get its name (this may
514         --  be different from the parent spec name obtained above because
515         --  of renamings higher up in the hierarchy).
516
517         else
518            Uname_Actual := New_Child (Load_Name, Unit_Name (Unump));
519         end if;
520
521      --  Here if unit to be loaded is not a child unit
522
523      else
524         Uname_Actual := Load_Name;
525      end if;
526
527      Fname     := Get_File_Name (Uname_Actual, Subunit);
528      Pre_Name  :=
529        Is_Predefined_File_Name (Fname, Renamings_Included => False);
530      Ren_Name  := Is_Predefined_Renaming_File_Name (Fname);
531      GNAT_Name := Is_GNAT_File_Name (Fname);
532
533      if Debug_Flag_L then
534         Write_Eol;
535         Write_Str ("*** Load request for unit: ");
536         Write_Unit_Name (Load_Name);
537
538         if Required then
539            Write_Str (" (Required = True)");
540         else
541            Write_Str (" (Required = False)");
542         end if;
543
544         Write_Eol;
545
546         if Uname_Actual /= Load_Name then
547            Write_Str ("*** Actual unit loaded: ");
548            Write_Unit_Name (Uname_Actual);
549         end if;
550      end if;
551
552      --  Capture error location if it is for the main unit. The idea is to
553      --  post errors on the main unit location, not the most recent unit.
554      --  Note: Unit_Name (Main_Unit) is not set if we are parsing gnat.adc.
555
556      if Present (Error_Node)
557        and then Present (Unit_Name (Main_Unit))
558      then
559         --  It seems like In_Extended_Main_Source_Unit (Error_Node) would
560         --  do the trick here, but that's wrong, it is much too early to
561         --  call this routine. We are still in the parser, and the required
562         --  semantic information is not established yet. So we base the
563         --  judgment on unit names.
564
565         Get_External_Unit_Name_String (Unit_Name (Main_Unit));
566
567         declare
568            Main_Unit_Name : constant String := Name_Buffer (1 .. Name_Len);
569
570         begin
571            Get_External_Unit_Name_String
572              (Unit_Name (Get_Source_Unit (Error_Node)));
573
574            --  If the two names are identical, then for sure we are part
575            --  of the extended main unit
576
577            if Main_Unit_Name = Name_Buffer (1 .. Name_Len) then
578               Load_Msg_Sloc := Sloc (Error_Node);
579
580            --  If the load is called from a with_type clause, the error
581            --  node is correct.
582
583            --  Otherwise, check for the subunit case, and if so, consider
584            --  we have a match if one name is a prefix of the other name.
585
586            else
587               if Nkind (Unit (Cunit (Main_Unit))) = N_Subunit
588                    or else
589                  Nkind (Unit (Cunit (Get_Source_Unit (Error_Node)))) =
590                                                                N_Subunit
591               then
592                  Name_Len := Integer'Min (Name_Len, Main_Unit_Name'Length);
593
594                  if Name_Buffer (1 .. Name_Len)
595                        =
596                     Main_Unit_Name (1 .. Name_Len)
597                  then
598                     Load_Msg_Sloc := Sloc (Error_Node);
599                  end if;
600               end if;
601            end if;
602         end;
603      end if;
604
605      --  If we are generating error messages, then capture calling unit
606
607      if Present (Error_Node) then
608         Calling_Unit := Get_Source_Unit (Error_Node);
609      else
610         Calling_Unit := No_Unit;
611      end if;
612
613      --  See if we already have an entry for this unit
614
615      Unum := Unit_Names.Get (Uname_Actual);
616      if Unum = No_Unit then
617         Unum := Units.Last + 1;
618      end if;
619
620      --  Whether or not the entry was found, Unum is now the right value,
621      --  since it is one more than Units.Last (i.e. the index of the new
622      --  entry we will create) in the not found case.
623
624      --  A special check is necessary in the unit not found case. If the unit
625      --  is not found, but the file in which it lives has already been loaded,
626      --  then we have the problem that the file does not contain the unit that
627      --  is needed. We simply treat this as a file not found condition.
628
629      --  We skip this test in multiple unit per file mode since in this
630      --  case we can have multiple units from the same source file.
631
632      if Unum > Units.Last and then Get_Unit_Index (Uname_Actual) = 0 then
633         for J in Units.First .. Units.Last loop
634            if Fname = Units.Table (J).Unit_File_Name then
635               if Debug_Flag_L then
636                  Write_Str ("  file does not contain unit, Unit_Number = ");
637                  Write_Int (Int (Unum));
638                  Write_Eol;
639                  Write_Eol;
640               end if;
641
642               if Present (Error_Node) then
643                  Get_Name_String (Fname);
644
645                  if Is_Predefined_File_Name (Fname) then
646                     Error_Msg_Unit_1 := Uname_Actual;
647                     Error_Msg
648                       ("$$ is not a language defined unit", Load_Msg_Sloc);
649                  else
650                     Error_Msg_File_1 := Fname;
651                     Error_Msg_Unit_1 := Uname_Actual;
652                     Error_Msg ("file{ does not contain unit$", Load_Msg_Sloc);
653                  end if;
654
655                  Write_Dependency_Chain;
656                  Unum := No_Unit;
657                  goto Done;
658
659               else
660                  Unum := No_Unit;
661                  goto Done;
662               end if;
663            end if;
664         end loop;
665      end if;
666
667      --  If we are proceeding with load, then make load stack entry,
668      --  and indicate the kind of with_clause responsible for the load.
669
670      Load_Stack.Increment_Last;
671      Load_Stack.Table (Load_Stack.Last) := (Unum, With_Node);
672
673      --  Case of entry already in table
674
675      if Unum <= Units.Last then
676
677         --  Here is where we check for a circular dependency, which is
678         --  an attempt to load a unit which is currently in the process
679         --  of being loaded. We do *not* care about a circular chain that
680         --  leads back to a body, because this kind of circular dependence
681         --  legitimately occurs (e.g. two package bodies that contain
682         --  inlined subprogram referenced by the other).
683
684         --  Ada 2005 (AI-50217): We also ignore limited_with clauses, because
685         --  their purpose is precisely to create legal circular structures.
686
687         if Loading (Unum)
688           and then (Is_Spec_Name (Units.Table (Unum).Unit_Name)
689                       or else Acts_As_Spec (Units.Table (Unum).Cunit))
690           and then (Nkind (Error_Node) /= N_With_Clause
691                       or else not Limited_Present (Error_Node))
692           and then not From_Limited_With_Chain
693         then
694            if Debug_Flag_L then
695               Write_Str ("  circular dependency encountered");
696               Write_Eol;
697            end if;
698
699            if Present (Error_Node) then
700               Error_Msg ("circular unit dependency", Load_Msg_Sloc);
701               Write_Dependency_Chain;
702            else
703               Load_Stack.Decrement_Last;
704            end if;
705
706            Unum := No_Unit;
707            goto Done;
708         end if;
709
710         if Debug_Flag_L then
711            Write_Str ("  unit already in file table, Unit_Number = ");
712            Write_Int (Int (Unum));
713            Write_Eol;
714         end if;
715
716         Load_Stack.Decrement_Last;
717         goto Done;
718
719      --  Unit is not already in table, so try to open the file
720
721      else
722         if Debug_Flag_L then
723            Write_Str ("  attempt unit load, Unit_Number = ");
724            Write_Int (Int (Unum));
725            Write_Eol;
726         end if;
727
728         Src_Ind := Load_Source_File (Fname);
729
730         --  Make a partial entry in the file table, used even in the file not
731         --  found case to print the dependency chain including the last entry
732
733         Units.Increment_Last;
734         Init_Unit_Name (Unum, Uname_Actual);
735
736         --  File was found
737
738         if Src_Ind > No_Source_File then
739            Units.Table (Unum) :=
740              (Cunit                  => Empty,
741               Cunit_Entity           => Empty,
742               Dependency_Num         => 0,
743               Dynamic_Elab           => False,
744               Error_Location         => Sloc (Error_Node),
745               Expected_Unit          => Uname_Actual,
746               Fatal_Error            => None,
747               Generate_Code          => False,
748               Has_RACW               => False,
749               Filler                 => False,
750               Ident_String           => Empty,
751
752               Is_Predefined_Renaming => Ren_Name,
753               Is_Predefined_Unit     => Pre_Name or Ren_Name,
754               Is_Internal_Unit       => Pre_Name or Ren_Name or GNAT_Name,
755               Filler2                => False,
756
757               Loading                => True,
758               Main_Priority          => Default_Main_Priority,
759               Main_CPU               => Default_Main_CPU,
760               Primary_Stack_Count    => 0,
761               Sec_Stack_Count        => 0,
762               Munit_Index            => 0,
763               No_Elab_Code_All       => False,
764               Serial_Number          => 0,
765               Source_Index           => Src_Ind,
766               Unit_File_Name         => Fname,
767               Unit_Name              => Uname_Actual,
768               Version                => Source_Checksum (Src_Ind),
769               OA_Setting             => 'O');
770
771            --  Parse the new unit
772
773            declare
774               Save_Index : constant Nat     := Multiple_Unit_Index;
775               Save_PMES  : constant Boolean := Parsing_Main_Extended_Source;
776
777            begin
778               Multiple_Unit_Index := Get_Unit_Index (Uname_Actual);
779               Units.Table (Unum).Munit_Index := Multiple_Unit_Index;
780               Initialize_Scanner (Unum, Source_Index (Unum));
781
782               if Calling_Unit = Main_Unit and then Subunit then
783                  Parsing_Main_Extended_Source := True;
784               end if;
785
786               Discard_List (Par (Configuration_Pragmas => False));
787
788               Parsing_Main_Extended_Source := Save_PMES;
789
790               Multiple_Unit_Index := Save_Index;
791               Set_Loading (Unum, False);
792            end;
793
794            --  If spec is irrelevant, then post errors and quit
795
796            if Corr_Body /= No_Unit
797              and then Spec_Is_Irrelevant (Unum, Corr_Body)
798            then
799               Error_Msg_File_1 := Unit_File_Name (Corr_Body);
800               Error_Msg
801                 ("cannot compile subprogram in file {!", Load_Msg_Sloc);
802               Error_Msg_File_1 := Unit_File_Name (Unum);
803               Error_Msg
804                 ("\incorrect spec in file { must be removed first!",
805                  Load_Msg_Sloc);
806               Unum := No_Unit;
807               goto Done;
808            end if;
809
810            --  If loaded unit had an error, then caller inherits setting
811
812            if Present (Error_Node) then
813               case Units.Table (Unum).Fatal_Error is
814
815                  --  Nothing to do if with'ed unit had no error
816
817                  when None =>
818                     null;
819
820                  --  If with'ed unit had a detected fatal error, propagate it
821
822                  when Error_Detected =>
823                     Units.Table (Calling_Unit).Fatal_Error := Error_Detected;
824
825                  --  If with'ed unit had an ignored error, then propagate it
826                  --  but do not overide an existing setting.
827
828                  when Error_Ignored =>
829                     if Units.Table (Calling_Unit).Fatal_Error = None then
830                        Units.Table (Calling_Unit).Fatal_Error :=
831                                                               Error_Ignored;
832                     end if;
833               end case;
834            end if;
835
836            --  Remove load stack entry and return the entry in the file table
837
838            Load_Stack.Decrement_Last;
839
840            --  All done, return unit number
841
842            goto Done;
843
844         --  Case of file not found
845
846         else
847            if Debug_Flag_L then
848               if Src_Ind = No_Access_To_Source_File then
849                  Write_Str ("  no read access to file, load failed");
850               else
851                  Write_Str ("  file was not found, load failed");
852               end if;
853
854               Write_Eol;
855            end if;
856
857            --  Generate message if unit required
858
859            if Required then
860               Get_Name_String (Fname);
861
862               if Is_Predefined_File_Name (Fname) then
863
864                  --  This is a predefined library unit which is not present
865                  --  in the run time. If a predefined unit is not available
866                  --  it may very likely be the case that there is also pragma
867                  --  Restriction forbidding its usage. This is typically the
868                  --  case when building a configurable run time, where the
869                  --  usage of certain run-time units is restricted by means
870                  --  of both the corresponding pragma Restriction (such as
871                  --  No_Calendar), and by not including the unit. Hence, we
872                  --  check whether this predefined unit is forbidden, so that
873                  --  the message about the restriction violation is generated,
874                  --  if needed.
875
876                  if Present (Error_Node) then
877                     Check_Restricted_Unit (Load_Name, Error_Node);
878                  end if;
879
880                  Error_Msg_Unit_1 := Uname_Actual;
881                  Error_Msg -- CODEFIX
882                    ("$$ is not a predefined library unit", Load_Msg_Sloc);
883
884               else
885                  Error_Msg_File_1 := Fname;
886
887                  if Src_Ind = No_Access_To_Source_File then
888                     Error_Msg ("no read access to file{", Load_Msg_Sloc);
889                  else
890                     Error_Msg ("file{ not found", Load_Msg_Sloc);
891                  end if;
892               end if;
893
894               Write_Dependency_Chain;
895
896               --  Remove unit from stack, to avoid cascaded errors on
897               --  subsequent missing files.
898
899               Load_Stack.Decrement_Last;
900               Remove_Unit (Unum);
901
902            --  If unit not required, remove load stack entry and the junk
903            --  file table entry, and return No_Unit to indicate not found.
904
905            else
906               Load_Stack.Decrement_Last;
907               Remove_Unit (Unum);
908            end if;
909
910            Unum := No_Unit;
911            goto Done;
912         end if;
913      end if;
914
915      --  Here to exit, with result in Unum
916
917      <<Done>>
918      Parsing_Main_Extended_Source := Save_PMES;
919      Cunit_Boolean_Restrictions_Restore (Save_Cunit_Restrictions);
920      return Unum;
921   end Load_Unit;
922
923   --------------------------
924   -- Make_Child_Decl_Unit --
925   --------------------------
926
927   procedure Make_Child_Decl_Unit (N : Node_Id) is
928      Unit_Decl : constant Node_Id          := Library_Unit (N);
929      Unit_Num  : constant Unit_Number_Type := Get_Cunit_Unit_Number (N);
930
931   begin
932      Units.Increment_Last;
933      Units.Table (Units.Last) := Units.Table (Unit_Num);
934      Units.Table (Units.Last).Cunit := Unit_Decl;
935      Units.Table (Units.Last).Cunit_Entity  :=
936        Defining_Identifier
937          (Defining_Unit_Name (Specification (Unit (Unit_Decl))));
938      Init_Unit_Name (Units.Last, Get_Spec_Name (Unit_Name (Unit_Num)));
939
940      --  The library unit created for of a child subprogram unit plays no
941      --  role in code generation and binding, so label it accordingly.
942
943      Units.Table (Units.Last).Generate_Code := False;
944      Set_Has_No_Elaboration_Code (Unit_Decl);
945   end Make_Child_Decl_Unit;
946
947   ------------------------
948   -- Make_Instance_Unit --
949   ------------------------
950
951   --  If the unit is an instance, it appears as a package declaration, but
952   --  contains both declaration and body of the instance. The body becomes
953   --  the main unit of the compilation, and the declaration is inserted
954   --  at the end of the unit table. The main unit now has the name of a
955   --  body, which is constructed from the name of the original spec,
956   --  and is attached to the compilation node of the original unit. The
957   --  declaration has been attached to a new compilation unit node, and
958   --  code will have to be generated for it.
959
960   procedure Make_Instance_Unit (N : Node_Id; In_Main : Boolean) is
961      Sind  : constant Source_File_Index := Source_Index (Main_Unit);
962
963   begin
964      Units.Increment_Last;
965
966      if In_Main then
967         Units.Table (Units.Last)        := Units.Table (Main_Unit);
968         Units.Table (Units.Last).Cunit  := Library_Unit (N);
969         Init_Unit_Name (Units.Last, Unit_Name (Main_Unit));
970
971         Units.Table (Main_Unit).Cunit   := N;
972         Units.Table (Main_Unit).Version := Source_Checksum (Sind);
973         Init_Unit_Name (Main_Unit,
974           Get_Body_Name
975             (Unit_Name (Get_Cunit_Unit_Number (Library_Unit (N)))));
976
977      else
978         --  Duplicate information from instance unit, for the body. The unit
979         --  node N has been rewritten as a body, but it was placed in the
980         --  units table when first loaded as a declaration.
981
982         Units.Table (Units.Last) := Units.Table (Get_Cunit_Unit_Number (N));
983         Units.Table (Units.Last).Cunit := Library_Unit (N);
984      end if;
985   end Make_Instance_Unit;
986
987   ------------------------
988   -- Spec_Is_Irrelevant --
989   ------------------------
990
991   function Spec_Is_Irrelevant
992     (Spec_Unit : Unit_Number_Type;
993      Body_Unit : Unit_Number_Type) return Boolean
994   is
995      Sunit : constant Node_Id := Cunit (Spec_Unit);
996      Bunit : constant Node_Id := Cunit (Body_Unit);
997
998   begin
999      --  The spec is irrelevant if the body is a subprogram body, and the spec
1000      --  is other than a subprogram spec or generic subprogram spec. Note that
1001      --  the names must be the same, we don't need to check that, because we
1002      --  already know that from the fact that the file names are the same.
1003
1004      return
1005         Nkind (Unit (Bunit)) = N_Subprogram_Body
1006           and then Nkind (Unit (Sunit)) /= N_Subprogram_Declaration
1007           and then Nkind (Unit (Sunit)) /= N_Generic_Subprogram_Declaration;
1008   end Spec_Is_Irrelevant;
1009
1010   --------------------
1011   -- Version_Update --
1012   --------------------
1013
1014   procedure Version_Update (U : Node_Id; From : Node_Id) is
1015      Unum  : constant Unit_Number_Type := Get_Cunit_Unit_Number (U);
1016      Fnum  : constant Unit_Number_Type := Get_Cunit_Unit_Number (From);
1017   begin
1018      if Source_Index (Fnum) > No_Source_File then
1019         Units.Table (Unum).Version :=
1020           Units.Table (Unum).Version
1021             xor
1022              Source_Checksum (Source_Index (Fnum));
1023      end if;
1024   end Version_Update;
1025
1026   ----------------------------
1027   -- Write_Dependency_Chain --
1028   ----------------------------
1029
1030   procedure Write_Dependency_Chain is
1031   begin
1032      --  The dependency chain is only written if it is at least two entries
1033      --  deep, otherwise it is trivial (the main unit depending on a unit
1034      --  that it obviously directly depends on).
1035
1036      if Load_Stack.Last - 1 > Load_Stack.First then
1037         for U in Load_Stack.First .. Load_Stack.Last - 1 loop
1038            Error_Msg_Unit_1 :=
1039              Unit_Name (Load_Stack.Table (U).Unit_Number);
1040            Error_Msg_Unit_2 :=
1041              Unit_Name (Load_Stack.Table (U + 1).Unit_Number);
1042            Error_Msg ("$ depends on $!", Load_Msg_Sloc);
1043         end loop;
1044      end if;
1045   end Write_Dependency_Chain;
1046
1047end Lib.Load;
1048