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