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