OSDN Git Service

* gcc.dg/attr-weakref-1.c: Add exit (0) to avoid spurious
[pf3gnuchains/gcc-fork.git] / gcc / ada / lib-load.adb
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-2005 Free Software Foundation, Inc.          --
10 --                                                                          --
11 -- GNAT is free software;  you can  redistribute it  and/or modify it under --
12 -- terms of the  GNU General Public License as published  by the Free Soft- --
13 -- ware  Foundation;  either version 2,  or (at your option) any later ver- --
14 -- sion.  GNAT is distributed in the hope that it will be useful, but WITH- --
15 -- OUT ANY WARRANTY;  without even the  implied warranty of MERCHANTABILITY --
16 -- or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License --
17 -- for  more details.  You should have  received  a copy of the GNU General --
18 -- Public License  distributed with GNAT;  see file COPYING.  If not, write --
19 -- to  the  Free Software Foundation,  51  Franklin  Street,  Fifth  Floor, --
20 -- Boston, MA 02110-1301, USA.                                              --
21 --                                                                          --
22 -- GNAT was originally developed  by the GNAT team at  New York University. --
23 -- Extensive contributions were provided by Ada Core Technologies Inc.      --
24 --                                                                          --
25 ------------------------------------------------------------------------------
26
27 with Atree;    use Atree;
28 with Debug;    use Debug;
29 with Einfo;    use Einfo;
30 with Errout;   use Errout;
31 with Fname;    use Fname;
32 with Fname.UF; use Fname.UF;
33 with Namet;    use Namet;
34 with Nlists;   use Nlists;
35 with Nmake;    use Nmake;
36 with Opt;      use Opt;
37 with Osint;    use Osint;
38 with Osint.C;  use Osint.C;
39 with Output;   use Output;
40 with Par;
41 with Restrict; use Restrict;
42 with Scn;      use Scn;
43 with Sinfo;    use Sinfo;
44 with Sinput;   use Sinput;
45 with Sinput.L; use Sinput.L;
46 with Stand;    use Stand;
47 with Tbuild;   use Tbuild;
48 with Uname;    use Uname;
49
50 package body Lib.Load is
51
52    -----------------------
53    -- Local Subprograms --
54    -----------------------
55
56    function From_Limited_With_Chain (Lim : Boolean) return Boolean;
57    --  Check whether a possible circular dependence includes units that
58    --  have been loaded through limited_with clauses, in which case there
59    --  is no real circularity.
60
61    function Spec_Is_Irrelevant
62      (Spec_Unit : Unit_Number_Type;
63       Body_Unit : Unit_Number_Type) return Boolean;
64    --  The Spec_Unit and Body_Unit parameters are the unit numbers of the
65    --  spec file that corresponds to the main unit which is a body. This
66    --  function determines if the spec file is irrelevant and will be
67    --  overridden by the body as described in RM 10.1.4(4). See description
68    --  in "Special Handling of Subprogram Bodies" for further details.
69
70    procedure Write_Dependency_Chain;
71    --  This procedure is used to generate error message info lines that
72    --  trace the current dependency chain when a load error occurs.
73
74    -------------------------------
75    -- Create_Dummy_Package_Unit --
76    -------------------------------
77
78    function Create_Dummy_Package_Unit
79      (With_Node : Node_Id;
80       Spec_Name : Unit_Name_Type) return Unit_Number_Type
81    is
82       Unum         : Unit_Number_Type;
83       Cunit_Entity : Entity_Id;
84       Cunit        : Node_Id;
85       Du_Name      : Node_Or_Entity_Id;
86       End_Lab      : Node_Id;
87       Save_CS      : constant Boolean := Get_Comes_From_Source_Default;
88
89    begin
90       --  The created dummy package unit does not come from source
91
92       Set_Comes_From_Source_Default (False);
93
94       --  Normal package
95
96       if Nkind (Name (With_Node)) = N_Identifier then
97          Cunit_Entity :=
98            Make_Defining_Identifier (No_Location,
99              Chars => Chars (Name (With_Node)));
100          Du_Name := Cunit_Entity;
101          End_Lab := New_Occurrence_Of (Cunit_Entity, No_Location);
102
103       --  Child package
104
105       else
106          Cunit_Entity :=
107            Make_Defining_Identifier (No_Location,
108              Chars => Chars (Selector_Name (Name (With_Node))));
109          Du_Name :=
110            Make_Defining_Program_Unit_Name (No_Location,
111              Name => New_Copy_Tree (Prefix (Name (With_Node))),
112              Defining_Identifier => Cunit_Entity);
113
114          Set_Is_Child_Unit (Cunit_Entity);
115
116          End_Lab :=
117            Make_Designator (No_Location,
118              Name => New_Copy_Tree (Prefix (Name (With_Node))),
119              Identifier => New_Occurrence_Of (Cunit_Entity, No_Location));
120       end if;
121
122       Set_Scope (Cunit_Entity, Standard_Standard);
123
124       Cunit :=
125         Make_Compilation_Unit (No_Location,
126           Context_Items => Empty_List,
127           Unit =>
128             Make_Package_Declaration (No_Location,
129               Specification =>
130                 Make_Package_Specification (No_Location,
131                   Defining_Unit_Name   => Du_Name,
132                   Visible_Declarations => Empty_List,
133                   End_Label            => End_Lab)),
134           Aux_Decls_Node =>
135             Make_Compilation_Unit_Aux (No_Location));
136
137       --  Mark the dummy package as analyzed to prevent analysis of this
138       --  (non-existent) unit in -gnatQ mode because at the moment the
139       --  structure and attributes of this dummy package does not allow
140       --  a normal analysis of this unit
141
142       Set_Analyzed (Cunit);
143
144       Units.Increment_Last;
145       Unum := Units.Last;
146
147       Units.Table (Unum) := (
148         Cunit           => Cunit,
149         Cunit_Entity    => Cunit_Entity,
150         Dependency_Num  => 0,
151         Dynamic_Elab    => False,
152         Error_Location  => Sloc (With_Node),
153         Expected_Unit   => Spec_Name,
154         Fatal_Error     => True,
155         Generate_Code   => False,
156         Has_RACW        => False,
157         Ident_String    => Empty,
158         Loading         => False,
159         Main_Priority   => Default_Main_Priority,
160         Munit_Index     => 0,
161         Serial_Number   => 0,
162         Source_Index    => No_Source_File,
163         Unit_File_Name  => Get_File_Name (Spec_Name, Subunit => False),
164         Unit_Name       => Spec_Name,
165         Version         => 0);
166
167       Set_Comes_From_Source_Default (Save_CS);
168       Set_Error_Posted (Cunit_Entity);
169       Set_Error_Posted (Cunit);
170       return Unum;
171    end Create_Dummy_Package_Unit;
172
173    -----------------------------
174    -- From_Limited_With_Chain --
175    -----------------------------
176
177    function From_Limited_With_Chain (Lim : Boolean) return Boolean is
178    begin
179       --  True if the current load operation is through a limited_with clause
180
181       if Lim then
182          return True;
183
184       --  Examine the Load_Stack to locate any previous Limited_with clause
185
186       elsif Load_Stack.Last - 1 > Load_Stack.First then
187          for U in Load_Stack.First .. Load_Stack.Last - 1 loop
188             if Load_Stack.Table (U).From_Limited_With then
189                return True;
190             end if;
191          end loop;
192       end if;
193
194       return False;
195    end From_Limited_With_Chain;
196
197    ----------------
198    -- Initialize --
199    ----------------
200
201    procedure Initialize is
202    begin
203       Units.Init;
204       Load_Stack.Init;
205    end Initialize;
206
207    ------------------------
208    -- Initialize_Version --
209    ------------------------
210
211    procedure Initialize_Version (U : Unit_Number_Type) is
212    begin
213       Units.Table (U).Version := Source_Checksum (Source_Index (U));
214    end Initialize_Version;
215
216    ----------------------
217    -- Load_Main_Source --
218    ----------------------
219
220    procedure Load_Main_Source is
221       Fname : File_Name_Type;
222
223    begin
224       Load_Stack.Increment_Last;
225       Load_Stack.Table (Load_Stack.Last) := (Main_Unit, False);
226
227       --  Initialize unit table entry for Main_Unit. Note that we don't know
228       --  the unit name yet, that gets filled in when the parser parses the
229       --  main unit, at which time a check is made that it matches the main
230       --  file name, and then the Unit_Name field is set. The Cunit and
231       --  Cunit_Entity fields also get filled in later by the parser.
232
233       Units.Increment_Last;
234       Fname := Next_Main_Source;
235
236       Units.Table (Main_Unit).Unit_File_Name := Fname;
237
238       if Fname /= No_File then
239          Main_Source_File := Load_Source_File (Fname);
240          Current_Error_Source_File := Main_Source_File;
241
242          Units.Table (Main_Unit) := (
243            Cunit           => Empty,
244            Cunit_Entity    => Empty,
245            Dependency_Num  => 0,
246            Dynamic_Elab    => False,
247            Error_Location  => No_Location,
248            Expected_Unit   => No_Name,
249            Fatal_Error     => False,
250            Generate_Code   => False,
251            Has_RACW        => False,
252            Ident_String    => Empty,
253            Loading         => True,
254            Main_Priority   => Default_Main_Priority,
255            Munit_Index     => 0,
256            Serial_Number   => 0,
257            Source_Index    => Main_Source_File,
258            Unit_File_Name  => Fname,
259            Unit_Name       => No_Name,
260            Version         => Source_Checksum (Main_Source_File));
261       end if;
262    end Load_Main_Source;
263
264    ---------------
265    -- Load_Unit --
266    ---------------
267
268    function Load_Unit
269      (Load_Name         : Unit_Name_Type;
270       Required          : Boolean;
271       Error_Node        : Node_Id;
272       Subunit           : Boolean;
273       Corr_Body         : Unit_Number_Type := No_Unit;
274       Renamings         : Boolean          := False;
275       From_Limited_With : Boolean          := False) return Unit_Number_Type
276    is
277       Calling_Unit : Unit_Number_Type;
278       Uname_Actual : Unit_Name_Type;
279       Unum         : Unit_Number_Type;
280       Unump        : Unit_Number_Type;
281       Fname        : File_Name_Type;
282       Src_Ind      : Source_File_Index;
283
284    --  Start of processing for Load_Unit
285
286    begin
287       --  If renamings are allowed and we have a child unit name, then we
288       --  must first load the parent to deal with finding the real name.
289
290       if Renamings and then Is_Child_Name (Load_Name) then
291          Unump :=
292            Load_Unit
293              (Load_Name  => Get_Parent_Spec_Name (Load_Name),
294               Required   => Required,
295               Subunit    => False,
296               Renamings  => True,
297               Error_Node => Error_Node);
298
299          if Unump = No_Unit then
300             return No_Unit;
301          end if;
302
303          --  If parent is a renaming, then we use the renamed package as
304          --  the actual parent for the subsequent load operation.
305
306          if Nkind (Parent (Cunit_Entity (Unump))) =
307            N_Package_Renaming_Declaration
308          then
309             Uname_Actual :=
310               New_Child
311                 (Load_Name,
312                  Get_Unit_Name (Name (Parent (Cunit_Entity (Unump)))));
313
314             --  Save the renaming entity, to establish its visibility when
315             --  installing the context. The implicit with is on this entity,
316             --  not on the package it renames.
317
318             if Nkind (Error_Node) = N_With_Clause
319               and then Nkind (Name (Error_Node)) = N_Selected_Component
320             then
321                declare
322                   Par : Node_Id := Name (Error_Node);
323
324                begin
325                   while Nkind (Par) = N_Selected_Component
326                     and then Chars (Selector_Name (Par)) /=
327                       Chars (Cunit_Entity (Unump))
328                   loop
329                      Par := Prefix (Par);
330                   end loop;
331
332                   --  Case of some intermediate parent is a renaming
333
334                   if Nkind (Par) = N_Selected_Component then
335                      Set_Entity (Selector_Name (Par), Cunit_Entity (Unump));
336
337                   --  Case where the ultimate parent is a renaming
338
339                   else
340                      Set_Entity (Par, Cunit_Entity (Unump));
341                   end if;
342                end;
343             end if;
344
345          --  If the parent is not a renaming, then get its name (this may
346          --  be different from the parent spec name obtained above because
347          --  of renamings higher up in the hierarchy).
348
349          else
350             Uname_Actual := New_Child (Load_Name, Unit_Name (Unump));
351          end if;
352
353       --  Here if unit to be loaded is not a child unit
354
355       else
356          Uname_Actual := Load_Name;
357       end if;
358
359       Fname := Get_File_Name (Uname_Actual, Subunit);
360
361       if Debug_Flag_L then
362          Write_Eol;
363          Write_Str ("*** Load request for unit: ");
364          Write_Unit_Name (Load_Name);
365
366          if Required then
367             Write_Str (" (Required = True)");
368          else
369             Write_Str (" (Required = False)");
370          end if;
371
372          Write_Eol;
373
374          if Uname_Actual /= Load_Name then
375             Write_Str ("*** Actual unit loaded: ");
376             Write_Unit_Name (Uname_Actual);
377          end if;
378       end if;
379
380       --  Capture error location if it is for the main unit. The idea is to
381       --  post errors on the main unit location, not the most recent unit.
382       --  Note: Unit_Name (Main_Unit) is not set if we are parsing gnat.adc.
383
384       if Present (Error_Node)
385         and then Unit_Name (Main_Unit) /= No_Name
386       then
387          --  It seems like In_Extended_Main_Source_Unit (Error_Node) would
388          --  do the trick here, but that's wrong, it is much too early to
389          --  call this routine. We are still in the parser, and the required
390          --  semantic information is not established yet. So we base the
391          --  judgment on unit names.
392
393          Get_External_Unit_Name_String (Unit_Name (Main_Unit));
394
395          declare
396             Main_Unit_Name : constant String := Name_Buffer (1 .. Name_Len);
397
398          begin
399             Get_External_Unit_Name_String
400               (Unit_Name (Get_Source_Unit (Error_Node)));
401
402             --  If the two names are identical, then for sure we are part
403             --  of the extended main unit
404
405             if Main_Unit_Name = Name_Buffer (1 .. Name_Len) then
406                Load_Msg_Sloc := Sloc (Error_Node);
407
408             --  If the load is called from a with_type clause, the error
409             --  node is correct.
410
411             elsif Nkind (Parent (Error_Node)) = N_With_Type_Clause then
412                Load_Msg_Sloc := Sloc (Error_Node);
413
414             --  Otherwise, check for the subunit case, and if so, consider
415             --  we have a match if one name is a prefix of the other name.
416
417             else
418                if Nkind (Unit (Cunit (Main_Unit))) = N_Subunit
419                     or else
420                   Nkind (Unit (Cunit (Get_Source_Unit (Error_Node)))) =
421                                                                 N_Subunit
422                then
423                   Name_Len := Integer'Min (Name_Len, Main_Unit_Name'Length);
424
425                   if Name_Buffer (1 .. Name_Len)
426                         =
427                      Main_Unit_Name (1 .. Name_Len)
428                   then
429                      Load_Msg_Sloc := Sloc (Error_Node);
430                   end if;
431                end if;
432             end if;
433          end;
434       end if;
435
436       --  If we are generating error messages, then capture calling unit
437
438       if Present (Error_Node) then
439          Calling_Unit := Get_Source_Unit (Error_Node);
440       else
441          Calling_Unit := No_Unit;
442       end if;
443
444       --  See if we already have an entry for this unit
445
446       Unum := Main_Unit;
447
448       while Unum <= Units.Last loop
449          exit when Uname_Actual = Units.Table (Unum).Unit_Name;
450          Unum := Unum + 1;
451       end loop;
452
453       --  Whether or not the entry was found, Unum is now the right value,
454       --  since it is one more than Units.Last (i.e. the index of the new
455       --  entry we will create) in the not found case.
456
457       --  A special check is necessary in the unit not found case. If the unit
458       --  is not found, but the file in which it lives has already been loaded,
459       --  then we have the problem that the file does not contain the unit that
460       --  is needed. We simply treat this as a file not found condition.
461
462       --  We skip this test in multiple unit per file mode since in this
463       --  case we can have multiple units from the same source file.
464
465       if Unum > Units.Last and then Multiple_Unit_Index = 0 then
466          for J in Units.First .. Units.Last loop
467             if Fname = Units.Table (J).Unit_File_Name then
468                if Debug_Flag_L then
469                   Write_Str ("  file does not contain unit, Unit_Number = ");
470                   Write_Int (Int (Unum));
471                   Write_Eol;
472                   Write_Eol;
473                end if;
474
475                if Present (Error_Node) then
476                   if Is_Predefined_File_Name (Fname) then
477                      Error_Msg_Name_1 := Uname_Actual;
478                      Error_Msg
479                        ("% is not a language defined unit", Load_Msg_Sloc);
480                   else
481                      Error_Msg_Name_1 := Fname;
482                      Error_Msg_Unit_1 := Uname_Actual;
483                      Error_Msg
484                        ("File{ does not contain unit$", Load_Msg_Sloc);
485                   end if;
486
487                   Write_Dependency_Chain;
488                   return No_Unit;
489
490                else
491                   return No_Unit;
492                end if;
493             end if;
494          end loop;
495       end if;
496
497       --  If we are proceeding with load, then make load stack entry,
498       --  and indicate the kind of with_clause responsible for the load.
499
500       Load_Stack.Increment_Last;
501       Load_Stack.Table (Load_Stack.Last) := (Unum, From_Limited_With);
502
503       --  Case of entry already in table
504
505       if Unum <= Units.Last then
506
507          --  Here is where we check for a circular dependency, which is
508          --  an attempt to load a unit which is currently in the process
509          --  of being loaded. We do *not* care about a circular chain that
510          --  leads back to a body, because this kind of circular dependence
511          --  legitimately occurs (e.g. two package bodies that contain
512          --  inlined subprogram referenced by the other).
513
514          --  Ada 2005 (AI-50217): We also ignore limited_with clauses, because
515          --  their purpose is precisely to create legal circular structures.
516
517          if Loading (Unum)
518            and then (Is_Spec_Name (Units.Table (Unum).Unit_Name)
519                        or else Acts_As_Spec (Units.Table (Unum).Cunit))
520            and then (Nkind (Error_Node) /= N_With_Clause
521                        or else not Limited_Present (Error_Node))
522            and then not From_Limited_With_Chain (From_Limited_With)
523          then
524             if Debug_Flag_L then
525                Write_Str ("  circular dependency encountered");
526                Write_Eol;
527             end if;
528
529             if Present (Error_Node) then
530                Error_Msg ("circular unit dependency", Load_Msg_Sloc);
531                Write_Dependency_Chain;
532             else
533                Load_Stack.Decrement_Last;
534             end if;
535
536             return No_Unit;
537          end if;
538
539          if Debug_Flag_L then
540             Write_Str ("  unit already in file table, Unit_Number = ");
541             Write_Int (Int (Unum));
542             Write_Eol;
543          end if;
544
545          Load_Stack.Decrement_Last;
546          return Unum;
547
548       --  Unit is not already in table, so try to open the file
549
550       else
551          if Debug_Flag_L then
552             Write_Str ("  attempt unit load, Unit_Number = ");
553             Write_Int (Int (Unum));
554             Write_Eol;
555          end if;
556
557          Src_Ind := Load_Source_File (Fname);
558
559          --  Make a partial entry in the file table, used even in the file not
560          --  found case to print the dependency chain including the last entry
561
562          Units.Increment_Last;
563          Units.Table (Unum).Unit_Name := Uname_Actual;
564
565          --  File was found
566
567          if Src_Ind /= No_Source_File then
568             Units.Table (Unum) := (
569               Cunit           => Empty,
570               Cunit_Entity    => Empty,
571               Dependency_Num  => 0,
572               Dynamic_Elab    => False,
573               Error_Location  => Sloc (Error_Node),
574               Expected_Unit   => Uname_Actual,
575               Fatal_Error     => False,
576               Generate_Code   => False,
577               Has_RACW        => False,
578               Ident_String    => Empty,
579               Loading         => True,
580               Main_Priority   => Default_Main_Priority,
581               Munit_Index     => 0,
582               Serial_Number   => 0,
583               Source_Index    => Src_Ind,
584               Unit_File_Name  => Fname,
585               Unit_Name       => Uname_Actual,
586               Version         => Source_Checksum (Src_Ind));
587
588             --  Parse the new unit
589
590             declare
591                Save_Index : constant Nat := Multiple_Unit_Index;
592             begin
593                Multiple_Unit_Index := Get_Unit_Index (Uname_Actual);
594                Units.Table (Unum).Munit_Index := Multiple_Unit_Index;
595                Initialize_Scanner (Unum, Source_Index (Unum));
596                Discard_List (Par (Configuration_Pragmas => False,
597                                   From_Limited_With     => From_Limited_With));
598                Multiple_Unit_Index := Save_Index;
599                Set_Loading (Unum, False);
600             end;
601
602             --  If spec is irrelevant, then post errors and quit
603
604             if Corr_Body /= No_Unit
605               and then Spec_Is_Irrelevant (Unum, Corr_Body)
606             then
607                Error_Msg_Name_1 := Unit_File_Name (Corr_Body);
608                Error_Msg
609                  ("cannot compile subprogram in file {!",
610                   Load_Msg_Sloc);
611                Error_Msg_Name_1 := Unit_File_Name (Unum);
612                Error_Msg
613                  ("incorrect spec in file { must be removed first!",
614                   Load_Msg_Sloc);
615                return No_Unit;
616             end if;
617
618             --  If loaded unit had a fatal error, then caller inherits it!
619
620             if Units.Table (Unum).Fatal_Error
621               and then Present (Error_Node)
622             then
623                Units.Table (Calling_Unit).Fatal_Error := True;
624             end if;
625
626             --  Remove load stack entry and return the entry in the file table
627
628             Load_Stack.Decrement_Last;
629             return Unum;
630
631          --  Case of file not found
632
633          else
634             if Debug_Flag_L then
635                Write_Str ("  file was not found, load failed");
636                Write_Eol;
637             end if;
638
639             --  Generate message if unit required
640
641             if Required and then Present (Error_Node) then
642                if Is_Predefined_File_Name (Fname) then
643
644                   --  This is a predefined library unit which is not present
645                   --  in the run time. If a predefined unit is not available
646                   --  it may very likely be the case that there is also pragma
647                   --  Restriction forbidding its usage. This is typically the
648                   --  case when building a configurable run time, where the
649                   --  usage of certain run-time units units is restricted by
650                   --  means of both the corresponding pragma Restriction (such
651                   --  as No_Calendar), and by not including the unit. Hence,
652                   --  we check whether this predefined unit is forbidden, so
653                   --  that the message about the restriction violation is
654                   --  generated, if needed.
655
656                   Check_Restricted_Unit (Load_Name, Error_Node);
657
658                   Error_Msg_Name_1 := Uname_Actual;
659                   Error_Msg
660                     ("% is not a predefined library unit", Load_Msg_Sloc);
661
662                else
663                   Error_Msg_Name_1 := Fname;
664                   Error_Msg ("file{ not found", Load_Msg_Sloc);
665                end if;
666
667                Write_Dependency_Chain;
668
669                --  Remove unit from stack, to avoid cascaded errors on
670                --  subsequent missing files.
671
672                Load_Stack.Decrement_Last;
673                Units.Decrement_Last;
674
675             --  If unit not required, remove load stack entry and the junk
676             --  file table entry, and return No_Unit to indicate not found,
677
678             else
679                Load_Stack.Decrement_Last;
680                Units.Decrement_Last;
681             end if;
682
683             return No_Unit;
684          end if;
685       end if;
686    end Load_Unit;
687
688    ------------------------
689    -- Make_Instance_Unit --
690    ------------------------
691
692    --  If the unit is an instance, it appears as a package declaration, but
693    --  contains both declaration and body of the instance. The body becomes
694    --  the main unit of the compilation, and the declaration is inserted
695    --  at the end of the unit table. The main unit now has the name of a
696    --  body, which is constructed from the name of the original spec,
697    --  and is attached to the compilation node of the original unit. The
698    --  declaration has been attached to a new compilation unit node, and
699    --  code will have to be generated for it.
700
701    procedure Make_Instance_Unit (N : Node_Id) is
702       Sind : constant Source_File_Index := Source_Index (Main_Unit);
703    begin
704       Units.Increment_Last;
705       Units.Table (Units.Last)               := Units.Table (Main_Unit);
706       Units.Table (Units.Last).Cunit         := Library_Unit (N);
707       Units.Table (Units.Last).Generate_Code := True;
708       Units.Table (Main_Unit).Cunit          := N;
709       Units.Table (Main_Unit).Unit_Name      :=
710         Get_Body_Name (Unit_Name (Get_Cunit_Unit_Number (Library_Unit (N))));
711       Units.Table (Main_Unit).Version        := Source_Checksum (Sind);
712    end Make_Instance_Unit;
713
714    ------------------------
715    -- Spec_Is_Irrelevant --
716    ------------------------
717
718    function Spec_Is_Irrelevant
719      (Spec_Unit : Unit_Number_Type;
720       Body_Unit : Unit_Number_Type) return Boolean
721    is
722       Sunit : constant Node_Id := Cunit (Spec_Unit);
723       Bunit : constant Node_Id := Cunit (Body_Unit);
724
725    begin
726       --  The spec is irrelevant if the body is a subprogram body, and the
727       --  spec is other than a subprogram spec or generic subprogram spec.
728       --  Note that the names must be the same, we don't need to check that,
729       --  because we already know that from the fact that the file names are
730       --  the same.
731
732       return
733          Nkind (Unit (Bunit)) = N_Subprogram_Body
734            and then Nkind (Unit (Sunit)) /= N_Subprogram_Declaration
735            and then Nkind (Unit (Sunit)) /= N_Generic_Subprogram_Declaration;
736    end Spec_Is_Irrelevant;
737
738    --------------------
739    -- Version_Update --
740    --------------------
741
742    procedure Version_Update (U : Node_Id; From : Node_Id) is
743       Unum  : constant Unit_Number_Type := Get_Cunit_Unit_Number (U);
744       Fnum  : constant Unit_Number_Type := Get_Cunit_Unit_Number (From);
745    begin
746       if Source_Index (Fnum) /= No_Source_File then
747          Units.Table (Unum).Version :=
748            Units.Table (Unum).Version
749              xor
750               Source_Checksum (Source_Index (Fnum));
751       end if;
752    end Version_Update;
753
754    ----------------------------
755    -- Write_Dependency_Chain --
756    ----------------------------
757
758    procedure Write_Dependency_Chain is
759    begin
760       --  The dependency chain is only written if it is at least two entries
761       --  deep, otherwise it is trivial (the main unit depending on a unit
762       --  that it obviously directly depends on).
763
764       if Load_Stack.Last - 1 > Load_Stack.First then
765          for U in Load_Stack.First .. Load_Stack.Last - 1 loop
766             Error_Msg_Unit_1 :=
767               Unit_Name (Load_Stack.Table (U).Unit_Number);
768             Error_Msg_Unit_2 :=
769               Unit_Name (Load_Stack.Table (U + 1).Unit_Number);
770             Error_Msg ("$ depends on $!", Load_Msg_Sloc);
771          end loop;
772       end if;
773    end Write_Dependency_Chain;
774
775 end Lib.Load;