OSDN Git Service

Fix aliasing bug that also caused memory usage problems.
[pf3gnuchains/gcc-fork.git] / gcc / ada / bcheck.adb
1 ------------------------------------------------------------------------------
2 --                                                                          --
3 --                         GNAT COMPILER COMPONENTS                         --
4 --                                                                          --
5 --                               B C H E C K                                --
6 --                                                                          --
7 --                                 B o d y                                  --
8 --                                                                          --
9 --          Copyright (C) 1992-2004 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,  59 Temple Place - Suite 330,  Boston, --
20 -- MA 02111-1307, 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 ALI;      use ALI;
28 with ALI.Util; use ALI.Util;
29 with Binderr;  use Binderr;
30 with Butil;    use Butil;
31 with Casing;   use Casing;
32 with Fname;    use Fname;
33 with Namet;    use Namet;
34 with Opt;      use Opt;
35 with Osint;
36 with Output;   use Output;
37 with Rident;   use Rident;
38 with Types;    use Types;
39
40 package body Bcheck is
41
42    -----------------------
43    -- Local Subprograms --
44    -----------------------
45
46    --  The following checking subprograms make up the parts of the
47    --  configuration consistency check.
48
49    procedure Check_Consistent_Dynamic_Elaboration_Checking;
50    procedure Check_Consistent_Floating_Point_Format;
51    procedure Check_Consistent_Interrupt_States;
52    procedure Check_Consistent_Locking_Policy;
53    procedure Check_Consistent_Normalize_Scalars;
54    procedure Check_Consistent_Queuing_Policy;
55    procedure Check_Consistent_Restrictions;
56    procedure Check_Consistent_Zero_Cost_Exception_Handling;
57
58    procedure Consistency_Error_Msg (Msg : String);
59    --  Produce an error or a warning message, depending on whether
60    --  an inconsistent configuration is permitted or not.
61
62    ------------------------------------
63    -- Check_Consistent_Configuration --
64    ------------------------------------
65
66    procedure Check_Configuration_Consistency is
67    begin
68       if Float_Format_Specified /= ' ' then
69          Check_Consistent_Floating_Point_Format;
70       end if;
71
72       if Queuing_Policy_Specified /= ' ' then
73          Check_Consistent_Queuing_Policy;
74       end if;
75
76       if Locking_Policy_Specified /= ' ' then
77          Check_Consistent_Locking_Policy;
78       end if;
79
80       if Zero_Cost_Exceptions_Specified then
81          Check_Consistent_Zero_Cost_Exception_Handling;
82       end if;
83
84       Check_Consistent_Normalize_Scalars;
85       Check_Consistent_Dynamic_Elaboration_Checking;
86
87       Check_Consistent_Restrictions;
88       Check_Consistent_Interrupt_States;
89    end Check_Configuration_Consistency;
90
91    ---------------------------------------------------
92    -- Check_Consistent_Dynamic_Elaboration_Checking --
93    ---------------------------------------------------
94
95    --  The rule here is that if a unit has dynamic elaboration checks,
96    --  then any unit it withs must meeting one of the following criteria:
97
98    --    1. There is a pragma Elaborate_All for the with'ed unit
99    --    2. The with'ed unit was compiled with dynamic elaboration checks
100    --    3. The with'ed unit has pragma Preelaborate or Pure
101    --    4. It is an internal GNAT unit (including children of GNAT)
102
103    procedure Check_Consistent_Dynamic_Elaboration_Checking is
104    begin
105       if Dynamic_Elaboration_Checks_Specified then
106          for U in First_Unit_Entry .. Units.Last loop
107             declare
108                UR : Unit_Record renames Units.Table (U);
109
110             begin
111                if UR.Dynamic_Elab then
112                   for W in UR.First_With .. UR.Last_With loop
113                      declare
114                         WR : With_Record renames Withs.Table (W);
115
116                      begin
117                         if Get_Name_Table_Info (WR.Uname) /= 0 then
118                            declare
119                               WU : Unit_Record renames
120                                      Units.Table
121                                        (Unit_Id
122                                          (Get_Name_Table_Info (WR.Uname)));
123
124                            begin
125                               --  Case 1. Elaborate_All for with'ed unit
126
127                               if WR.Elaborate_All then
128                                  null;
129
130                               --  Case 2. With'ed unit has dynamic elab checks
131
132                               elsif WU.Dynamic_Elab then
133                                  null;
134
135                               --  Case 3. With'ed unit is Preelaborate or Pure
136
137                               elsif WU.Preelab or WU.Pure then
138                                  null;
139
140                               --  Case 4. With'ed unit is internal file
141
142                               elsif Is_Internal_File_Name (WU.Sfile) then
143                                  null;
144
145                               --  Issue warning, not one of the safe cases
146
147                               else
148                                  Error_Msg_Name_1 := UR.Sfile;
149                                  Error_Msg
150                                    ("?% has dynamic elaboration checks " &
151                                                                  "and with's");
152
153                                  Error_Msg_Name_1 := WU.Sfile;
154                                  Error_Msg
155                                    ("?  % which has static elaboration " &
156                                                                      "checks");
157
158                                  Warnings_Detected := Warnings_Detected - 1;
159                               end if;
160                            end;
161                         end if;
162                      end;
163                   end loop;
164                end if;
165             end;
166          end loop;
167       end if;
168    end Check_Consistent_Dynamic_Elaboration_Checking;
169
170    --------------------------------------------
171    -- Check_Consistent_Floating_Point_Format --
172    --------------------------------------------
173
174    --  The rule is that all files must be compiled with the same setting
175    --  for the floating-point format.
176
177    procedure Check_Consistent_Floating_Point_Format is
178    begin
179       --  First search for a unit specifying a floating-point format and then
180       --  check all remaining units against it.
181
182       Find_Format : for A1 in ALIs.First .. ALIs.Last loop
183          if ALIs.Table (A1).Float_Format /= ' ' then
184             Check_Format : declare
185                Format : constant Character := ALIs.Table (A1).Float_Format;
186             begin
187                for A2 in A1 + 1 .. ALIs.Last loop
188                   if ALIs.Table (A2).Float_Format /= Format then
189                      Error_Msg_Name_1 := ALIs.Table (A1).Sfile;
190                      Error_Msg_Name_2 := ALIs.Table (A2).Sfile;
191
192                      Consistency_Error_Msg
193                        ("% and % compiled with different " &
194                         "floating-point representations");
195                      exit Find_Format;
196                   end if;
197                end loop;
198             end Check_Format;
199
200             exit Find_Format;
201          end if;
202       end loop Find_Format;
203    end Check_Consistent_Floating_Point_Format;
204
205    ---------------------------------------
206    -- Check_Consistent_Interrupt_States --
207    ---------------------------------------
208
209    --  The rule is that if the state of a given interrupt is specified
210    --  in more than one unit, it must be specified with a consistent state.
211
212    procedure Check_Consistent_Interrupt_States is
213       Max_Intrup : Nat;
214
215    begin
216       --  If no Interrupt_State entries, nothing to do
217
218       if Interrupt_States.Last < Interrupt_States.First then
219          return;
220       end if;
221
222       --  First find out the maximum interrupt value
223
224       Max_Intrup := 0;
225       for J in Interrupt_States.First .. Interrupt_States.Last loop
226          if Interrupt_States.Table (J).Interrupt_Id > Max_Intrup then
227             Max_Intrup := Interrupt_States.Table (J).Interrupt_Id;
228          end if;
229       end loop;
230
231       --  Now establish tables to be used for consistency checking
232
233       declare
234          Istate : array (0 .. Max_Intrup) of Character := (others => 'n');
235          --  Interrupt state entries, 'u'/'s'/'r' or 'n' to indicate an
236          --  entry that has not been set.
237
238          Afile : array (0 .. Max_Intrup) of ALI_Id;
239          --  ALI file that generated Istate entry for consistency message
240
241          Loc : array (0 .. Max_Intrup) of Nat;
242          --  Line numbers from IS pragma generating Istate entry
243
244          Inum : Nat;
245          --  Interrupt number from entry being tested
246
247          Stat : Character;
248          --  Interrupt state from entry being tested
249
250          Lnum : Nat;
251          --  Line number from entry being tested
252
253       begin
254          for F in ALIs.First .. ALIs.Last loop
255             for K in ALIs.Table (F).First_Interrupt_State ..
256                      ALIs.Table (F).Last_Interrupt_State
257             loop
258                Inum := Interrupt_States.Table (K).Interrupt_Id;
259                Stat := Interrupt_States.Table (K).Interrupt_State;
260                Lnum := Interrupt_States.Table (K).IS_Pragma_Line;
261
262                if Istate (Inum) = 'n' then
263                   Istate (Inum) := Stat;
264                   Afile  (Inum) := F;
265                   Loc    (Inum) := Lnum;
266
267                elsif Istate (Inum) /= Stat then
268                   Error_Msg_Name_1 := ALIs.Table (Afile (Inum)).Sfile;
269                   Error_Msg_Name_2 := ALIs.Table (F).Sfile;
270                   Error_Msg_Nat_1  := Loc (Inum);
271                   Error_Msg_Nat_2  := Lnum;
272
273                   Consistency_Error_Msg
274                     ("inconsistent interrupt states at %:# and %:#");
275                end if;
276             end loop;
277          end loop;
278       end;
279    end Check_Consistent_Interrupt_States;
280
281    -------------------------------------
282    -- Check_Consistent_Locking_Policy --
283    -------------------------------------
284
285    --  The rule is that all files for which the locking policy is
286    --  significant must be compiled with the same setting.
287
288    procedure Check_Consistent_Locking_Policy is
289    begin
290       --  First search for a unit specifying a policy and then
291       --  check all remaining units against it.
292
293       Find_Policy : for A1 in ALIs.First .. ALIs.Last loop
294          if ALIs.Table (A1).Locking_Policy /= ' ' then
295             Check_Policy : declare
296                Policy : constant Character := ALIs.Table (A1).Locking_Policy;
297
298             begin
299                for A2 in A1 + 1 .. ALIs.Last loop
300                   if ALIs.Table (A2).Locking_Policy /= ' ' and
301                      ALIs.Table (A2).Locking_Policy /= Policy
302                   then
303                      Error_Msg_Name_1 := ALIs.Table (A1).Sfile;
304                      Error_Msg_Name_2 := ALIs.Table (A2).Sfile;
305
306                      Consistency_Error_Msg
307                        ("% and % compiled with different locking policies");
308                      exit Find_Policy;
309                   end if;
310                end loop;
311             end Check_Policy;
312
313             exit Find_Policy;
314          end if;
315       end loop Find_Policy;
316    end Check_Consistent_Locking_Policy;
317
318    ----------------------------------------
319    -- Check_Consistent_Normalize_Scalars --
320    ----------------------------------------
321
322    --  The rule is that if any unit is compiled with Normalized_Scalars,
323    --  then all other units in the partition must also be compiled with
324    --  Normalized_Scalars in effect.
325
326    --  There is some issue as to whether this consistency check is
327    --  desirable, it is certainly required at the moment by the RM.
328    --  We should keep a watch on the ARG and HRG deliberations here.
329    --  GNAT no longer depends on this consistency (it used to do so,
330    --  but that has been corrected in the latest version, since the
331    --  Initialize_Scalars pragma does not require consistency.
332
333    procedure Check_Consistent_Normalize_Scalars is
334    begin
335       if Normalize_Scalars_Specified and No_Normalize_Scalars_Specified then
336          Consistency_Error_Msg
337               ("some but not all files compiled with Normalize_Scalars");
338
339          Write_Eol;
340          Write_Str ("files compiled with Normalize_Scalars");
341          Write_Eol;
342
343          for A1 in ALIs.First .. ALIs.Last loop
344             if ALIs.Table (A1).Normalize_Scalars then
345                Write_Str ("  ");
346                Write_Name (ALIs.Table (A1).Sfile);
347                Write_Eol;
348             end if;
349          end loop;
350
351          Write_Eol;
352          Write_Str ("files compiled without Normalize_Scalars");
353          Write_Eol;
354
355          for A1 in ALIs.First .. ALIs.Last loop
356             if not ALIs.Table (A1).Normalize_Scalars then
357                Write_Str ("  ");
358                Write_Name (ALIs.Table (A1).Sfile);
359                Write_Eol;
360             end if;
361          end loop;
362       end if;
363    end Check_Consistent_Normalize_Scalars;
364
365    -------------------------------------
366    -- Check_Consistent_Queuing_Policy --
367    -------------------------------------
368
369    --  The rule is that all files for which the queuing policy is
370    --  significant must be compiled with the same setting.
371
372    procedure Check_Consistent_Queuing_Policy is
373    begin
374       --  First search for a unit specifying a policy and then
375       --  check all remaining units against it.
376
377       Find_Policy : for A1 in ALIs.First .. ALIs.Last loop
378          if ALIs.Table (A1).Queuing_Policy /= ' ' then
379             Check_Policy : declare
380                Policy : constant Character := ALIs.Table (A1).Queuing_Policy;
381             begin
382                for A2 in A1 + 1 .. ALIs.Last loop
383                   if ALIs.Table (A2).Queuing_Policy /= ' '
384                        and then
385                      ALIs.Table (A2).Queuing_Policy /= Policy
386                   then
387                      Error_Msg_Name_1 := ALIs.Table (A1).Sfile;
388                      Error_Msg_Name_2 := ALIs.Table (A2).Sfile;
389
390                      Consistency_Error_Msg
391                        ("% and % compiled with different queuing policies");
392                      exit Find_Policy;
393                   end if;
394                end loop;
395             end Check_Policy;
396
397             exit Find_Policy;
398          end if;
399       end loop Find_Policy;
400    end Check_Consistent_Queuing_Policy;
401
402    -----------------------------------
403    -- Check_Consistent_Restrictions --
404    -----------------------------------
405
406    --  The rule is that if a restriction is specified in any unit,
407    --  then all units must obey the restriction. The check applies
408    --  only to restrictions which require partition wide consistency,
409    --  and not to internal units.
410
411    procedure Check_Consistent_Restrictions is
412       Restriction_File_Output : Boolean;
413       --  Shows if we have output header messages for restriction violation
414
415       procedure Print_Restriction_File (R : All_Restrictions);
416       --  Print header line for R if not printed yet
417
418       ----------------------------
419       -- Print_Restriction_File --
420       ----------------------------
421
422       procedure Print_Restriction_File (R : All_Restrictions) is
423       begin
424          if not Restriction_File_Output then
425             Restriction_File_Output := True;
426
427             --  Find an ali file specifying the restriction
428
429             for A in ALIs.First .. ALIs.Last loop
430                if ALIs.Table (A).Restrictions.Set (R)
431                  and then (R in All_Boolean_Restrictions
432                              or else ALIs.Table (A).Restrictions.Value (R) =
433                                      Cumulative_Restrictions.Value (R))
434                then
435                   --  We have found that ALI file A specifies the restriction
436                   --  that is being violated (the minimum value is specified
437                   --  in the case of a parameter restriction).
438
439                   declare
440                      M1 : constant String := "% has restriction ";
441                      S  : constant String := Restriction_Id'Image (R);
442                      M2 : String (1 .. 200); -- big enough!
443                      P  : Integer;
444
445                   begin
446                      Name_Buffer (1 .. S'Length) := S;
447                      Name_Len := S'Length;
448                      Set_Casing (Mixed_Case);
449
450                      M2 (M1'Range) := M1;
451                      P := M1'Length + 1;
452                      M2 (P .. P + S'Length - 1) := Name_Buffer (1 .. S'Length);
453                      P := P + S'Length;
454
455                      if R in All_Parameter_Restrictions then
456                         M2 (P .. P + 4) := " => #";
457                         Error_Msg_Nat_1 :=
458                           Int (Cumulative_Restrictions.Value (R));
459                         P := P + 5;
460                      end if;
461
462                      Error_Msg_Name_1 := ALIs.Table (A).Sfile;
463                      Consistency_Error_Msg (M2 (1 .. P - 1));
464                      Consistency_Error_Msg
465                        ("but the following files violate this restriction:");
466                      return;
467                   end;
468                end if;
469             end loop;
470          end if;
471       end Print_Restriction_File;
472
473    --  Start of processing for Check_Consistent_Restrictions
474
475    begin
476       --  Loop through all restriction violations
477
478       for R in All_Restrictions loop
479
480          --  Check for violation of this restriction
481
482          if Cumulative_Restrictions.Set (R)
483            and then Cumulative_Restrictions.Violated (R)
484            and then (R in Partition_Boolean_Restrictions
485                        or else (R in All_Parameter_Restrictions
486                                    and then
487                                      Cumulative_Restrictions.Count (R) >
488                                      Cumulative_Restrictions.Value (R)))
489          then
490             Restriction_File_Output := False;
491
492             --  Loop through files looking for violators
493
494             for A2 in ALIs.First .. ALIs.Last loop
495                declare
496                   T : ALIs_Record renames ALIs.Table (A2);
497
498                begin
499                   if T.Restrictions.Violated (R) then
500
501                      --  We exclude predefined files from the list of
502                      --  violators. This should be rethought. It is not
503                      --  clear that this is the right thing to do, that
504                      --  is particularly the case for restricted runtimes.
505
506                      if not Is_Internal_File_Name (T.Sfile) then
507
508                         --  Case of Boolean restriction, just print file name
509
510                         if R in All_Boolean_Restrictions then
511                            Print_Restriction_File (R);
512                            Error_Msg_Name_1 := T.Sfile;
513                            Consistency_Error_Msg ("  %");
514
515                         --  Case of Parameter restriction where violation
516                         --  count exceeds restriction value, print file
517                         --  name and count, adding "at least" if the
518                         --  exact count is not known.
519
520                         elsif R in Checked_Add_Parameter_Restrictions
521                           or else T.Restrictions.Count (R) >
522                           Cumulative_Restrictions.Value (R)
523                         then
524                            Print_Restriction_File (R);
525                            Error_Msg_Name_1 := T.Sfile;
526                            Error_Msg_Nat_1 := Int (T.Restrictions.Count (R));
527
528                            if T.Restrictions.Unknown (R) then
529                               Consistency_Error_Msg
530                                 ("  % (count = at least #)");
531                            else
532                               Consistency_Error_Msg
533                                 ("  % (count = #)");
534                            end if;
535                         end if;
536                      end if;
537                   end if;
538                end;
539             end loop;
540          end if;
541       end loop;
542    end Check_Consistent_Restrictions;
543
544    ---------------------------------------------------
545    -- Check_Consistent_Zero_Cost_Exception_Handling --
546    ---------------------------------------------------
547
548    --  Check consistent zero cost exception handling. The rule is that
549    --  all units must have the same exception handling mechanism.
550
551    procedure Check_Consistent_Zero_Cost_Exception_Handling is
552    begin
553       Check_Mechanism : for A1 in ALIs.First + 1 .. ALIs.Last loop
554          if ALIs.Table (A1).Zero_Cost_Exceptions /=
555             ALIs.Table (ALIs.First).Zero_Cost_Exceptions
556
557          then
558             Error_Msg_Name_1 := ALIs.Table (A1).Sfile;
559             Error_Msg_Name_2 := ALIs.Table (ALIs.First).Sfile;
560
561             Consistency_Error_Msg ("% and % compiled with different "
562                                             & "exception handling mechanisms");
563          end if;
564       end loop Check_Mechanism;
565    end Check_Consistent_Zero_Cost_Exception_Handling;
566
567    -----------------------
568    -- Check_Consistency --
569    -----------------------
570
571    procedure Check_Consistency is
572       Src : Source_Id;
573       --  Source file Id for this Sdep entry
574
575       ALI_Path_Id : Name_Id;
576
577    begin
578       --  First, we go through the source table to see if there are any cases
579       --  in which we should go after source files and compute checksums of
580       --  the source files. We need to do this for any file for which we have
581       --  mismatching time stamps and (so far) matching checksums.
582
583       for S in Source.First .. Source.Last loop
584
585          --  If all time stamps for a file match, then there is nothing to
586          --  do, since we will not be checking checksums in that case anyway
587
588          if Source.Table (S).All_Timestamps_Match then
589             null;
590
591          --  If we did not find the source file, then we can't compute its
592          --  checksum anyway. Note that when we have a time stamp mismatch,
593          --  we try to find the source file unconditionally (i.e. if
594          --  Check_Source_Files is False).
595
596          elsif not Source.Table (S).Source_Found then
597             null;
598
599          --  If we already have non-matching or missing checksums, then no
600          --  need to try going after source file, since we won't trust the
601          --  checksums in any case.
602
603          elsif not Source.Table (S).All_Checksums_Match then
604             null;
605
606          --  Now we have the case where we have time stamp mismatches, and
607          --  the source file is around, but so far all checksums match. This
608          --  is the case where we need to compute the checksum from the source
609          --  file, since otherwise we would ignore the time stamp mismatches,
610          --  and that is wrong if the checksum of the source does not agree
611          --  with the checksums in the ALI files.
612
613          elsif Check_Source_Files then
614             if not Checksums_Match
615               (Source.Table (S).Checksum,
616                Get_File_Checksum (Source.Table (S).Sfile))
617             then
618                Source.Table (S).All_Checksums_Match := False;
619             end if;
620          end if;
621       end loop;
622
623       --  Loop through ALI files
624
625       ALIs_Loop : for A in ALIs.First .. ALIs.Last loop
626
627          --  Loop through Sdep entries in one ALI file
628
629          Sdep_Loop : for D in
630            ALIs.Table (A).First_Sdep .. ALIs.Table (A).Last_Sdep
631          loop
632             if Sdep.Table (D).Dummy_Entry then
633                goto Continue;
634             end if;
635
636             Src := Source_Id (Get_Name_Table_Info (Sdep.Table (D).Sfile));
637
638             --  If the time stamps match, or all checksums match, then we
639             --  are OK, otherwise we have a definite error.
640
641             if Sdep.Table (D).Stamp /= Source.Table (Src).Stamp
642               and then not Source.Table (Src).All_Checksums_Match
643             then
644                Error_Msg_Name_1 := ALIs.Table (A).Sfile;
645                Error_Msg_Name_2 := Sdep.Table (D).Sfile;
646
647                --  Two styles of message, depending on whether or not
648                --  the updated file is the one that must be recompiled
649
650                if Error_Msg_Name_1 = Error_Msg_Name_2 then
651                   if Tolerate_Consistency_Errors then
652                      Error_Msg
653                         ("?% has been modified and should be recompiled");
654                   else
655                      Error_Msg
656                        ("% has been modified and must be recompiled");
657                   end if;
658
659                else
660                   ALI_Path_Id :=
661                     Osint.Find_File ((ALIs.Table (A).Afile), Osint.Library);
662                   if Osint.Is_Readonly_Library (ALI_Path_Id) then
663                      if Tolerate_Consistency_Errors then
664                         Error_Msg ("?% should be recompiled");
665                         Error_Msg_Name_1 := ALI_Path_Id;
666                         Error_Msg ("?(% is obsolete and read-only)");
667
668                      else
669                         Error_Msg ("% must be compiled");
670                         Error_Msg_Name_1 := ALI_Path_Id;
671                         Error_Msg ("(% is obsolete and read-only)");
672                      end if;
673
674                   elsif Tolerate_Consistency_Errors then
675                      Error_Msg
676                        ("?% should be recompiled (% has been modified)");
677
678                   else
679                      Error_Msg ("% must be recompiled (% has been modified)");
680                   end if;
681                end if;
682
683                if (not Tolerate_Consistency_Errors) and Verbose_Mode then
684                   declare
685                      Msg : constant String := "% time stamp ";
686                      Buf : String (1 .. Msg'Length + Time_Stamp_Length);
687
688                   begin
689                      Buf (1 .. Msg'Length) := Msg;
690                      Buf (Msg'Length + 1 .. Buf'Length) :=
691                        String (Source.Table (Src).Stamp);
692                      Error_Msg_Name_1 := Sdep.Table (D).Sfile;
693                      Error_Msg (Buf);
694                   end;
695
696                   declare
697                      Msg : constant String := " conflicts with % timestamp ";
698                      Buf : String (1 .. Msg'Length + Time_Stamp_Length);
699
700                   begin
701                      Buf (1 .. Msg'Length) := Msg;
702                      Buf (Msg'Length + 1 .. Buf'Length) :=
703                        String (Sdep.Table (D).Stamp);
704                      Error_Msg_Name_1 := Sdep.Table (D).Sfile;
705                      Error_Msg (Buf);
706                   end;
707                end if;
708
709                --  Exit from the loop through Sdep entries once we find one
710                --  that does not match.
711
712                exit Sdep_Loop;
713             end if;
714
715          <<Continue>>
716             null;
717          end loop Sdep_Loop;
718       end loop ALIs_Loop;
719    end Check_Consistency;
720
721    -------------------------------
722    -- Check_Duplicated_Subunits --
723    -------------------------------
724
725    procedure Check_Duplicated_Subunits is
726    begin
727       for J in Sdep.First .. Sdep.Last loop
728          if Sdep.Table (J).Subunit_Name /= No_Name then
729             Get_Decoded_Name_String (Sdep.Table (J).Subunit_Name);
730             Name_Len := Name_Len + 2;
731             Name_Buffer (Name_Len - 1) := '%';
732
733             --  See if there is a body or spec with the same name
734
735             for K in Boolean loop
736                if K then
737                   Name_Buffer (Name_Len) := 'b';
738
739                else
740                   Name_Buffer (Name_Len) := 's';
741                end if;
742
743                declare
744                   Info : constant Int := Get_Name_Table_Info (Name_Find);
745
746                begin
747                   if Info /= 0 then
748                      Set_Standard_Error;
749                      Write_Str ("error: subunit """);
750                      Write_Name_Decoded (Sdep.Table (J).Subunit_Name);
751                      Write_Str (""" in file """);
752                      Write_Name_Decoded (Sdep.Table (J).Sfile);
753                      Write_Char ('"');
754                      Write_Eol;
755                      Write_Str ("       has same name as unit """);
756                      Write_Unit_Name (Units.Table (Unit_Id (Info)).Uname);
757                      Write_Str (""" found in file """);
758                      Write_Name_Decoded (Units.Table (Unit_Id (Info)).Sfile);
759                      Write_Char ('"');
760                      Write_Eol;
761                      Write_Str ("       this is not allowed within a single "
762                                 & "partition (RM 10.2(19))");
763                      Write_Eol;
764                      Osint.Exit_Program (Osint.E_Fatal);
765                   end if;
766                end;
767             end loop;
768          end if;
769       end loop;
770    end Check_Duplicated_Subunits;
771
772    --------------------
773    -- Check_Versions --
774    --------------------
775
776    procedure Check_Versions is
777       VL : constant Natural := ALIs.Table (ALIs.First).Ver_Len;
778
779    begin
780       for A in ALIs.First .. ALIs.Last loop
781          if ALIs.Table (A).Ver_Len /= VL
782            or else ALIs.Table (A).Ver          (1 .. VL) /=
783                    ALIs.Table (ALIs.First).Ver (1 .. VL)
784          then
785             Error_Msg_Name_1 := ALIs.Table (A).Sfile;
786             Error_Msg_Name_2 := ALIs.Table (ALIs.First).Sfile;
787
788             Consistency_Error_Msg
789                ("% and % compiled with different GNAT versions");
790          end if;
791       end loop;
792    end Check_Versions;
793
794    ---------------------------
795    -- Consistency_Error_Msg --
796    ---------------------------
797
798    procedure Consistency_Error_Msg (Msg : String) is
799    begin
800       if Tolerate_Consistency_Errors then
801
802          --  If consistency errors are tolerated,
803          --  output the message as a warning.
804
805          declare
806             Warning_Msg : String (1 .. Msg'Length + 1);
807
808          begin
809             Warning_Msg (1) := '?';
810             Warning_Msg (2 .. Warning_Msg'Last) := Msg;
811
812             Error_Msg (Warning_Msg);
813          end;
814
815       --  Otherwise the consistency error is a true error
816
817       else
818          Error_Msg (Msg);
819       end if;
820    end Consistency_Error_Msg;
821
822 end Bcheck;