OSDN Git Service

* Makefile.in (reload1.o-warn): Remove.
[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-2007, 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 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_Dispatching_Policy;
50    procedure Check_Consistent_Dynamic_Elaboration_Checking;
51    procedure Check_Consistent_Floating_Point_Format;
52    procedure Check_Consistent_Interrupt_States;
53    procedure Check_Consistent_Locking_Policy;
54    procedure Check_Consistent_Normalize_Scalars;
55    procedure Check_Consistent_Queuing_Policy;
56    procedure Check_Consistent_Restrictions;
57    procedure Check_Consistent_Zero_Cost_Exception_Handling;
58
59    procedure Consistency_Error_Msg (Msg : String);
60    --  Produce an error or a warning message, depending on whether an
61    --  inconsistent configuration is permitted or not.
62
63    function Same_Unit (U1 : Unit_Name_Type; U2 : Name_Id) return Boolean;
64    --  Used to compare two unit names for No_Dependence checks. U1 is in
65    --  standard unit name format, and U2 is in literal form with periods.
66
67    -------------------------------------
68    -- Check_Configuration_Consistency --
69    -------------------------------------
70
71    procedure Check_Configuration_Consistency is
72    begin
73       if Float_Format_Specified /= ' ' then
74          Check_Consistent_Floating_Point_Format;
75       end if;
76
77       if Queuing_Policy_Specified /= ' ' then
78          Check_Consistent_Queuing_Policy;
79       end if;
80
81       if Locking_Policy_Specified /= ' ' then
82          Check_Consistent_Locking_Policy;
83       end if;
84
85       if Zero_Cost_Exceptions_Specified then
86          Check_Consistent_Zero_Cost_Exception_Handling;
87       end if;
88
89       Check_Consistent_Normalize_Scalars;
90       Check_Consistent_Dynamic_Elaboration_Checking;
91
92       Check_Consistent_Restrictions;
93       Check_Consistent_Interrupt_States;
94       Check_Consistent_Dispatching_Policy;
95    end Check_Configuration_Consistency;
96
97    -----------------------
98    -- Check_Consistency --
99    -----------------------
100
101    procedure Check_Consistency is
102       Src : Source_Id;
103       --  Source file Id for this Sdep entry
104
105       ALI_Path_Id : File_Name_Type;
106
107    begin
108       --  First, we go through the source table to see if there are any cases
109       --  in which we should go after source files and compute checksums of
110       --  the source files. We need to do this for any file for which we have
111       --  mismatching time stamps and (so far) matching checksums.
112
113       for S in Source.First .. Source.Last loop
114
115          --  If all time stamps for a file match, then there is nothing to
116          --  do, since we will not be checking checksums in that case anyway
117
118          if Source.Table (S).All_Timestamps_Match then
119             null;
120
121          --  If we did not find the source file, then we can't compute its
122          --  checksum anyway. Note that when we have a time stamp mismatch,
123          --  we try to find the source file unconditionally (i.e. if
124          --  Check_Source_Files is False).
125
126          elsif not Source.Table (S).Source_Found then
127             null;
128
129          --  If we already have non-matching or missing checksums, then no
130          --  need to try going after source file, since we won't trust the
131          --  checksums in any case.
132
133          elsif not Source.Table (S).All_Checksums_Match then
134             null;
135
136          --  Now we have the case where we have time stamp mismatches, and
137          --  the source file is around, but so far all checksums match. This
138          --  is the case where we need to compute the checksum from the source
139          --  file, since otherwise we would ignore the time stamp mismatches,
140          --  and that is wrong if the checksum of the source does not agree
141          --  with the checksums in the ALI files.
142
143          elsif Check_Source_Files then
144             if not Checksums_Match
145               (Source.Table (S).Checksum,
146                Get_File_Checksum (Source.Table (S).Sfile))
147             then
148                Source.Table (S).All_Checksums_Match := False;
149             end if;
150          end if;
151       end loop;
152
153       --  Loop through ALI files
154
155       ALIs_Loop : for A in ALIs.First .. ALIs.Last loop
156
157          --  Loop through Sdep entries in one ALI file
158
159          Sdep_Loop : for D in
160            ALIs.Table (A).First_Sdep .. ALIs.Table (A).Last_Sdep
161          loop
162             if Sdep.Table (D).Dummy_Entry then
163                goto Continue;
164             end if;
165
166             Src := Source_Id (Get_Name_Table_Info (Sdep.Table (D).Sfile));
167
168             --  If the time stamps match, or all checksums match, then we
169             --  are OK, otherwise we have a definite error.
170
171             if Sdep.Table (D).Stamp /= Source.Table (Src).Stamp
172               and then not Source.Table (Src).All_Checksums_Match
173             then
174                Error_Msg_File_1 := ALIs.Table (A).Sfile;
175                Error_Msg_File_2 := Sdep.Table (D).Sfile;
176
177                --  Two styles of message, depending on whether or not
178                --  the updated file is the one that must be recompiled
179
180                if Error_Msg_File_1 = Error_Msg_File_2 then
181                   if Tolerate_Consistency_Errors then
182                      Error_Msg
183                         ("?{ has been modified and should be recompiled");
184                   else
185                      Error_Msg
186                        ("{ has been modified and must be recompiled");
187                   end if;
188
189                else
190                   ALI_Path_Id :=
191                     Osint.Find_File ((ALIs.Table (A).Afile), Osint.Library);
192                   if Osint.Is_Readonly_Library (ALI_Path_Id) then
193                      if Tolerate_Consistency_Errors then
194                         Error_Msg ("?{ should be recompiled");
195                         Error_Msg_File_1 := ALI_Path_Id;
196                         Error_Msg ("?({ is obsolete and read-only)");
197                      else
198                         Error_Msg ("{ must be compiled");
199                         Error_Msg_File_1 := ALI_Path_Id;
200                         Error_Msg ("({ is obsolete and read-only)");
201                      end if;
202
203                   elsif Tolerate_Consistency_Errors then
204                      Error_Msg
205                        ("?% should be recompiled (% has been modified)");
206
207                   else
208                      Error_Msg ("{ must be recompiled ({ has been modified)");
209                   end if;
210                end if;
211
212                if (not Tolerate_Consistency_Errors) and Verbose_Mode then
213                   Error_Msg_File_1 := Sdep.Table (D).Sfile;
214                   Error_Msg
215                     ("{ time stamp " & String (Source.Table (Src).Stamp));
216
217                   Error_Msg_File_1 := Sdep.Table (D).Sfile;
218                   --  Something wrong here, should be different file ???
219
220                   Error_Msg
221                     (" conflicts with { timestamp " &
222                      String (Sdep.Table (D).Stamp));
223                end if;
224
225                --  Exit from the loop through Sdep entries once we find one
226                --  that does not match.
227
228                exit Sdep_Loop;
229             end if;
230
231          <<Continue>>
232             null;
233          end loop Sdep_Loop;
234       end loop ALIs_Loop;
235    end Check_Consistency;
236
237    -----------------------------------------
238    -- Check_Consistent_Dispatching_Policy --
239    -----------------------------------------
240
241    --  The rule is that all files for which the dispatching policy is
242    --  significant must meet the following rules:
243
244    --    1. All files for which a task dispatching policy is significant must
245    --    be compiled with the same setting.
246
247    --    2. If a partition contains one or more Priority_Specific_Dispatching
248    --    pragmas it cannot contain a Task_Dispatching_Policy pragma.
249
250    --    3. No overlap is allowed in the priority ranges specified in
251    --    Priority_Specific_Dispatching pragmas within the same partition.
252
253    --    4. If a partition contains one or more Priority_Specific_Dispatching
254    --    pragmas then the Ceiling_Locking policy is the only one allowed for
255    --    the partition.
256
257    procedure Check_Consistent_Dispatching_Policy is
258       Max_Prio : Nat := 0;
259       --  Maximum priority value for which a Priority_Specific_Dispatching
260       --  pragma has been specified.
261
262       TDP_Pragma_Afile : ALI_Id := No_ALI_Id;
263       --  ALI file where a Task_Dispatching_Policy pragma appears
264
265    begin
266       --  Consistency checks in units specifying a Task_Dispatching_Policy
267
268       if Task_Dispatching_Policy_Specified /= ' ' then
269          Find_Policy : for A1 in ALIs.First .. ALIs.Last loop
270             if ALIs.Table (A1).Task_Dispatching_Policy /= ' ' then
271
272                --  Store the place where the first task dispatching pragma
273                --  appears. We may need this value for issuing consistency
274                --  errors if Priority_Specific_Dispatching pragmas are used.
275
276                TDP_Pragma_Afile := A1;
277
278                Check_Policy : declare
279                   Policy : constant Character :=
280                              ALIs.Table (A1).Task_Dispatching_Policy;
281
282                begin
283                   for A2 in A1 + 1 .. ALIs.Last loop
284                      if ALIs.Table (A2).Task_Dispatching_Policy /= ' '
285                           and then
286                         ALIs.Table (A2).Task_Dispatching_Policy /= Policy
287                      then
288                         Error_Msg_File_1 := ALIs.Table (A1).Sfile;
289                         Error_Msg_File_2 := ALIs.Table (A2).Sfile;
290
291                         Consistency_Error_Msg
292                           ("{ and { compiled with different task" &
293                            " dispatching policies");
294                         exit Find_Policy;
295                      end if;
296                   end loop;
297                end Check_Policy;
298
299                exit Find_Policy;
300             end if;
301          end loop Find_Policy;
302       end if;
303
304       --  If no Priority_Specific_Dispatching entries, nothing else to do
305
306       if Specific_Dispatching.Last >= Specific_Dispatching.First then
307
308          --  Find out the maximum priority value for which one of the
309          --  Priority_Specific_Dispatching pragmas applies.
310
311          Max_Prio := 0;
312          for J in Specific_Dispatching.First .. Specific_Dispatching.Last loop
313             if Specific_Dispatching.Table (J).Last_Priority > Max_Prio then
314                Max_Prio := Specific_Dispatching.Table (J).Last_Priority;
315             end if;
316          end loop;
317
318          --  Now establish tables to be used for consistency checking
319
320          declare
321             --  The following record type is used to record locations of the
322             --  Priority_Specific_Dispatching pragmas applying to the Priority.
323
324             type Specific_Dispatching_Entry is record
325                Dispatching_Policy : Character := ' ';
326                --  First character (upper case) of corresponding policy name
327
328                Afile : ALI_Id := No_ALI_Id;
329                --  ALI file that generated Priority Specific Dispatching
330                --  entry for consistency message.
331
332                Loc : Nat := 0;
333                --  Line numbers from Priority_Specific_Dispatching pragma
334             end record;
335
336             PSD_Table  : array (0 .. Max_Prio) of Specific_Dispatching_Entry :=
337                            (others => Specific_Dispatching_Entry'
338                               (Dispatching_Policy => ' ',
339                                Afile              => No_ALI_Id,
340                                Loc                => 0));
341             --  Array containing an entry per priority containing the location
342             --  where there is a Priority_Specific_Dispatching pragma that
343             --  applies to the priority.
344
345          begin
346             for F in ALIs.First .. ALIs.Last loop
347                for K in ALIs.Table (F).First_Specific_Dispatching ..
348                         ALIs.Table (F).Last_Specific_Dispatching
349                loop
350                   declare
351                      DTK : Specific_Dispatching_Record
352                              renames Specific_Dispatching.Table (K);
353                   begin
354                      --  Check whether pragma Task_Dispatching_Policy and
355                      --  pragma Priority_Specific_Dispatching are used in the
356                      --  same partition.
357
358                      if Task_Dispatching_Policy_Specified /= ' ' then
359                         Error_Msg_File_1 := ALIs.Table (F).Sfile;
360                         Error_Msg_File_2 :=
361                           ALIs.Table (TDP_Pragma_Afile).Sfile;
362
363                         Error_Msg_Nat_1 := DTK.PSD_Pragma_Line;
364
365                         Consistency_Error_Msg
366                           ("Priority_Specific_Dispatching at {:#" &
367                            " incompatible with Task_Dispatching_Policy at {");
368                      end if;
369
370                      --  Ceiling_Locking must also be specified for a partition
371                      --  with at least one Priority_Specific_Dispatching
372                      --  pragma.
373
374                      if Locking_Policy_Specified /= ' '
375                        and then Locking_Policy_Specified /= 'C'
376                      then
377                         for A in ALIs.First .. ALIs.Last loop
378                            if ALIs.Table (A).Locking_Policy /= ' '
379                              and then ALIs.Table (A).Locking_Policy /= 'C'
380                            then
381                               Error_Msg_File_1 := ALIs.Table (F).Sfile;
382                               Error_Msg_File_2 := ALIs.Table (A).Sfile;
383
384                               Error_Msg_Nat_1  := DTK.PSD_Pragma_Line;
385
386                               Consistency_Error_Msg
387                                 ("Priority_Specific_Dispatching at {:#" &
388                                  " incompatible with Locking_Policy at {");
389                            end if;
390                         end loop;
391                      end if;
392
393                      --  Check overlapping priority ranges
394
395                      Find_Overlapping : for Prio in
396                        DTK.First_Priority .. DTK.Last_Priority
397                      loop
398                         if PSD_Table (Prio).Afile = No_ALI_Id then
399                            PSD_Table (Prio) :=
400                              (Dispatching_Policy => DTK.Dispatching_Policy,
401                               Afile => F, Loc => DTK.PSD_Pragma_Line);
402
403                         elsif PSD_Table (Prio).Dispatching_Policy /=
404                               DTK.Dispatching_Policy
405
406                         then
407                            Error_Msg_File_1 :=
408                              ALIs.Table (PSD_Table (Prio).Afile).Sfile;
409                            Error_Msg_File_2 := ALIs.Table (F).Sfile;
410                            Error_Msg_Nat_1  := PSD_Table (Prio).Loc;
411                            Error_Msg_Nat_2  := DTK.PSD_Pragma_Line;
412
413                            Consistency_Error_Msg
414                              ("overlapping priority ranges at {:# and {:#");
415
416                            exit Find_Overlapping;
417                         end if;
418                      end loop Find_Overlapping;
419                   end;
420                end loop;
421             end loop;
422          end;
423       end if;
424    end Check_Consistent_Dispatching_Policy;
425
426    ---------------------------------------------------
427    -- Check_Consistent_Dynamic_Elaboration_Checking --
428    ---------------------------------------------------
429
430    --  The rule here is that if a unit has dynamic elaboration checks,
431    --  then any unit it withs must meeting one of the following criteria:
432
433    --    1. There is a pragma Elaborate_All for the with'ed unit
434    --    2. The with'ed unit was compiled with dynamic elaboration checks
435    --    3. The with'ed unit has pragma Preelaborate or Pure
436    --    4. It is an internal GNAT unit (including children of GNAT)
437
438    procedure Check_Consistent_Dynamic_Elaboration_Checking is
439    begin
440       if Dynamic_Elaboration_Checks_Specified then
441          for U in First_Unit_Entry .. Units.Last loop
442             declare
443                UR : Unit_Record renames Units.Table (U);
444
445             begin
446                if UR.Dynamic_Elab then
447                   for W in UR.First_With .. UR.Last_With loop
448                      declare
449                         WR : With_Record renames Withs.Table (W);
450
451                      begin
452                         if Get_Name_Table_Info (WR.Uname) /= 0 then
453                            declare
454                               WU : Unit_Record renames
455                                      Units.Table
456                                        (Unit_Id
457                                          (Get_Name_Table_Info (WR.Uname)));
458
459                            begin
460                               --  Case 1. Elaborate_All for with'ed unit
461
462                               if WR.Elaborate_All then
463                                  null;
464
465                               --  Case 2. With'ed unit has dynamic elab checks
466
467                               elsif WU.Dynamic_Elab then
468                                  null;
469
470                               --  Case 3. With'ed unit is Preelaborate or Pure
471
472                               elsif WU.Preelab or WU.Pure then
473                                  null;
474
475                               --  Case 4. With'ed unit is internal file
476
477                               elsif Is_Internal_File_Name (WU.Sfile) then
478                                  null;
479
480                               --  Issue warning, not one of the safe cases
481
482                               else
483                                  Error_Msg_File_1 := UR.Sfile;
484                                  Error_Msg
485                                    ("?{ has dynamic elaboration checks " &
486                                                                  "and with's");
487
488                                  Error_Msg_File_1 := WU.Sfile;
489                                  Error_Msg
490                                    ("?  { which has static elaboration " &
491                                                                      "checks");
492
493                                  Warnings_Detected := Warnings_Detected - 1;
494                               end if;
495                            end;
496                         end if;
497                      end;
498                   end loop;
499                end if;
500             end;
501          end loop;
502       end if;
503    end Check_Consistent_Dynamic_Elaboration_Checking;
504
505    --------------------------------------------
506    -- Check_Consistent_Floating_Point_Format --
507    --------------------------------------------
508
509    --  The rule is that all files must be compiled with the same setting
510    --  for the floating-point format.
511
512    procedure Check_Consistent_Floating_Point_Format is
513    begin
514       --  First search for a unit specifying a floating-point format and then
515       --  check all remaining units against it.
516
517       Find_Format : for A1 in ALIs.First .. ALIs.Last loop
518          if ALIs.Table (A1).Float_Format /= ' ' then
519             Check_Format : declare
520                Format : constant Character := ALIs.Table (A1).Float_Format;
521             begin
522                for A2 in A1 + 1 .. ALIs.Last loop
523                   if ALIs.Table (A2).Float_Format /= Format then
524                      Error_Msg_File_1 := ALIs.Table (A1).Sfile;
525                      Error_Msg_File_2 := ALIs.Table (A2).Sfile;
526
527                      Consistency_Error_Msg
528                        ("{ and { compiled with different " &
529                         "floating-point representations");
530                      exit Find_Format;
531                   end if;
532                end loop;
533             end Check_Format;
534
535             exit Find_Format;
536          end if;
537       end loop Find_Format;
538    end Check_Consistent_Floating_Point_Format;
539
540    ---------------------------------------
541    -- Check_Consistent_Interrupt_States --
542    ---------------------------------------
543
544    --  The rule is that if the state of a given interrupt is specified
545    --  in more than one unit, it must be specified with a consistent state.
546
547    procedure Check_Consistent_Interrupt_States is
548       Max_Intrup : Nat;
549
550    begin
551       --  If no Interrupt_State entries, nothing to do
552
553       if Interrupt_States.Last < Interrupt_States.First then
554          return;
555       end if;
556
557       --  First find out the maximum interrupt value
558
559       Max_Intrup := 0;
560       for J in Interrupt_States.First .. Interrupt_States.Last loop
561          if Interrupt_States.Table (J).Interrupt_Id > Max_Intrup then
562             Max_Intrup := Interrupt_States.Table (J).Interrupt_Id;
563          end if;
564       end loop;
565
566       --  Now establish tables to be used for consistency checking
567
568       declare
569          Istate : array (0 .. Max_Intrup) of Character := (others => 'n');
570          --  Interrupt state entries, 'u'/'s'/'r' or 'n' to indicate an
571          --  entry that has not been set.
572
573          Afile : array (0 .. Max_Intrup) of ALI_Id;
574          --  ALI file that generated Istate entry for consistency message
575
576          Loc : array (0 .. Max_Intrup) of Nat;
577          --  Line numbers from IS pragma generating Istate entry
578
579          Inum : Nat;
580          --  Interrupt number from entry being tested
581
582          Stat : Character;
583          --  Interrupt state from entry being tested
584
585          Lnum : Nat;
586          --  Line number from entry being tested
587
588       begin
589          for F in ALIs.First .. ALIs.Last loop
590             for K in ALIs.Table (F).First_Interrupt_State ..
591                      ALIs.Table (F).Last_Interrupt_State
592             loop
593                Inum := Interrupt_States.Table (K).Interrupt_Id;
594                Stat := Interrupt_States.Table (K).Interrupt_State;
595                Lnum := Interrupt_States.Table (K).IS_Pragma_Line;
596
597                if Istate (Inum) = 'n' then
598                   Istate (Inum) := Stat;
599                   Afile  (Inum) := F;
600                   Loc    (Inum) := Lnum;
601
602                elsif Istate (Inum) /= Stat then
603                   Error_Msg_File_1 := ALIs.Table (Afile (Inum)).Sfile;
604                   Error_Msg_File_2 := ALIs.Table (F).Sfile;
605                   Error_Msg_Nat_1  := Loc (Inum);
606                   Error_Msg_Nat_2  := Lnum;
607
608                   Consistency_Error_Msg
609                     ("inconsistent interrupt states at {:# and {:#");
610                end if;
611             end loop;
612          end loop;
613       end;
614    end Check_Consistent_Interrupt_States;
615
616    -------------------------------------
617    -- Check_Consistent_Locking_Policy --
618    -------------------------------------
619
620    --  The rule is that all files for which the locking policy is
621    --  significant must be compiled with the same setting.
622
623    procedure Check_Consistent_Locking_Policy is
624    begin
625       --  First search for a unit specifying a policy and then
626       --  check all remaining units against it.
627
628       Find_Policy : for A1 in ALIs.First .. ALIs.Last loop
629          if ALIs.Table (A1).Locking_Policy /= ' ' then
630             Check_Policy : declare
631                Policy : constant Character := ALIs.Table (A1).Locking_Policy;
632
633             begin
634                for A2 in A1 + 1 .. ALIs.Last loop
635                   if ALIs.Table (A2).Locking_Policy /= ' ' and
636                      ALIs.Table (A2).Locking_Policy /= Policy
637                   then
638                      Error_Msg_File_1 := ALIs.Table (A1).Sfile;
639                      Error_Msg_File_2 := ALIs.Table (A2).Sfile;
640
641                      Consistency_Error_Msg
642                        ("{ and { compiled with different locking policies");
643                      exit Find_Policy;
644                   end if;
645                end loop;
646             end Check_Policy;
647
648             exit Find_Policy;
649          end if;
650       end loop Find_Policy;
651    end Check_Consistent_Locking_Policy;
652
653    ----------------------------------------
654    -- Check_Consistent_Normalize_Scalars --
655    ----------------------------------------
656
657    --  The rule is that if any unit is compiled with Normalized_Scalars,
658    --  then all other units in the partition must also be compiled with
659    --  Normalized_Scalars in effect.
660
661    --  There is some issue as to whether this consistency check is
662    --  desirable, it is certainly required at the moment by the RM.
663    --  We should keep a watch on the ARG and HRG deliberations here.
664    --  GNAT no longer depends on this consistency (it used to do so,
665    --  but that has been corrected in the latest version, since the
666    --  Initialize_Scalars pragma does not require consistency.
667
668    procedure Check_Consistent_Normalize_Scalars is
669    begin
670       if Normalize_Scalars_Specified and No_Normalize_Scalars_Specified then
671          Consistency_Error_Msg
672               ("some but not all files compiled with Normalize_Scalars");
673
674          Write_Eol;
675          Write_Str ("files compiled with Normalize_Scalars");
676          Write_Eol;
677
678          for A1 in ALIs.First .. ALIs.Last loop
679             if ALIs.Table (A1).Normalize_Scalars then
680                Write_Str ("  ");
681                Write_Name (ALIs.Table (A1).Sfile);
682                Write_Eol;
683             end if;
684          end loop;
685
686          Write_Eol;
687          Write_Str ("files compiled without Normalize_Scalars");
688          Write_Eol;
689
690          for A1 in ALIs.First .. ALIs.Last loop
691             if not ALIs.Table (A1).Normalize_Scalars then
692                Write_Str ("  ");
693                Write_Name (ALIs.Table (A1).Sfile);
694                Write_Eol;
695             end if;
696          end loop;
697       end if;
698    end Check_Consistent_Normalize_Scalars;
699
700    -------------------------------------
701    -- Check_Consistent_Queuing_Policy --
702    -------------------------------------
703
704    --  The rule is that all files for which the queuing policy is
705    --  significant must be compiled with the same setting.
706
707    procedure Check_Consistent_Queuing_Policy is
708    begin
709       --  First search for a unit specifying a policy and then
710       --  check all remaining units against it.
711
712       Find_Policy : for A1 in ALIs.First .. ALIs.Last loop
713          if ALIs.Table (A1).Queuing_Policy /= ' ' then
714             Check_Policy : declare
715                Policy : constant Character := ALIs.Table (A1).Queuing_Policy;
716             begin
717                for A2 in A1 + 1 .. ALIs.Last loop
718                   if ALIs.Table (A2).Queuing_Policy /= ' '
719                        and then
720                      ALIs.Table (A2).Queuing_Policy /= Policy
721                   then
722                      Error_Msg_File_1 := ALIs.Table (A1).Sfile;
723                      Error_Msg_File_2 := ALIs.Table (A2).Sfile;
724
725                      Consistency_Error_Msg
726                        ("{ and { compiled with different queuing policies");
727                      exit Find_Policy;
728                   end if;
729                end loop;
730             end Check_Policy;
731
732             exit Find_Policy;
733          end if;
734       end loop Find_Policy;
735    end Check_Consistent_Queuing_Policy;
736
737    -----------------------------------
738    -- Check_Consistent_Restrictions --
739    -----------------------------------
740
741    --  The rule is that if a restriction is specified in any unit,
742    --  then all units must obey the restriction. The check applies
743    --  only to restrictions which require partition wide consistency,
744    --  and not to internal units.
745
746    procedure Check_Consistent_Restrictions is
747       Restriction_File_Output : Boolean;
748       --  Shows if we have output header messages for restriction violation
749
750       procedure Print_Restriction_File (R : All_Restrictions);
751       --  Print header line for R if not printed yet
752
753       ----------------------------
754       -- Print_Restriction_File --
755       ----------------------------
756
757       procedure Print_Restriction_File (R : All_Restrictions) is
758       begin
759          if not Restriction_File_Output then
760             Restriction_File_Output := True;
761
762             --  Find an ali file specifying the restriction
763
764             for A in ALIs.First .. ALIs.Last loop
765                if ALIs.Table (A).Restrictions.Set (R)
766                  and then (R in All_Boolean_Restrictions
767                              or else ALIs.Table (A).Restrictions.Value (R) =
768                                      Cumulative_Restrictions.Value (R))
769                then
770                   --  We have found that ALI file A specifies the restriction
771                   --  that is being violated (the minimum value is specified
772                   --  in the case of a parameter restriction).
773
774                   declare
775                      M1 : constant String := "{ has restriction ";
776                      S  : constant String := Restriction_Id'Image (R);
777                      M2 : String (1 .. 200); -- big enough!
778                      P  : Integer;
779
780                   begin
781                      Name_Buffer (1 .. S'Length) := S;
782                      Name_Len := S'Length;
783                      Set_Casing (Mixed_Case);
784
785                      M2 (M1'Range) := M1;
786                      P := M1'Length + 1;
787                      M2 (P .. P + S'Length - 1) := Name_Buffer (1 .. S'Length);
788                      P := P + S'Length;
789
790                      if R in All_Parameter_Restrictions then
791                         M2 (P .. P + 4) := " => #";
792                         Error_Msg_Nat_1 :=
793                           Int (Cumulative_Restrictions.Value (R));
794                         P := P + 5;
795                      end if;
796
797                      Error_Msg_File_1 := ALIs.Table (A).Sfile;
798                      Consistency_Error_Msg (M2 (1 .. P - 1));
799                      Consistency_Error_Msg
800                        ("but the following files violate this restriction:");
801                      return;
802                   end;
803                end if;
804             end loop;
805          end if;
806       end Print_Restriction_File;
807
808    --  Start of processing for Check_Consistent_Restrictions
809
810    begin
811       --  Loop through all restriction violations
812
813       for R in All_Restrictions loop
814
815          --  Check for violation of this restriction
816
817          if Cumulative_Restrictions.Set (R)
818            and then Cumulative_Restrictions.Violated (R)
819            and then (R in Partition_Boolean_Restrictions
820                        or else (R in All_Parameter_Restrictions
821                                    and then
822                                      Cumulative_Restrictions.Count (R) >
823                                      Cumulative_Restrictions.Value (R)))
824          then
825             Restriction_File_Output := False;
826
827             --  Loop through files looking for violators
828
829             for A2 in ALIs.First .. ALIs.Last loop
830                declare
831                   T : ALIs_Record renames ALIs.Table (A2);
832
833                begin
834                   if T.Restrictions.Violated (R) then
835
836                      --  We exclude predefined files from the list of
837                      --  violators. This should be rethought. It is not
838                      --  clear that this is the right thing to do, that
839                      --  is particularly the case for restricted runtimes.
840
841                      if not Is_Internal_File_Name (T.Sfile) then
842
843                         --  Case of Boolean restriction, just print file name
844
845                         if R in All_Boolean_Restrictions then
846                            Print_Restriction_File (R);
847                            Error_Msg_File_1 := T.Sfile;
848                            Consistency_Error_Msg ("  {");
849
850                         --  Case of Parameter restriction where violation
851                         --  count exceeds restriction value, print file
852                         --  name and count, adding "at least" if the
853                         --  exact count is not known.
854
855                         elsif R in Checked_Add_Parameter_Restrictions
856                           or else T.Restrictions.Count (R) >
857                           Cumulative_Restrictions.Value (R)
858                         then
859                            Print_Restriction_File (R);
860                            Error_Msg_File_1 := T.Sfile;
861                            Error_Msg_Nat_1 := Int (T.Restrictions.Count (R));
862
863                            if T.Restrictions.Unknown (R) then
864                               Consistency_Error_Msg
865                                 ("  { (count = at least #)");
866                            else
867                               Consistency_Error_Msg
868                                 ("  % (count = #)");
869                            end if;
870                         end if;
871                      end if;
872                   end if;
873                end;
874             end loop;
875          end if;
876       end loop;
877
878       --  Now deal with No_Dependence indications. Note that we put the loop
879       --  through entries in the no dependency table first, since this loop
880       --  is most often empty (no such pragma Restrictions in use).
881
882       for ND in No_Deps.First .. No_Deps.Last loop
883          declare
884             ND_Unit : constant Name_Id :=
885                         No_Deps.Table (ND).No_Dep_Unit;
886
887          begin
888             for J in ALIs.First .. ALIs.Last loop
889                declare
890                   A : ALIs_Record renames ALIs.Table (J);
891
892                begin
893                   for K in A.First_Unit .. A.Last_Unit loop
894                      declare
895                         U : Unit_Record renames Units.Table (K);
896                      begin
897                         for L in U.First_With .. U.Last_With loop
898                            if Same_Unit
899                              (Withs.Table (L).Uname, ND_Unit)
900                            then
901                               Error_Msg_File_1 := U.Sfile;
902                               Error_Msg_Name_1 := ND_Unit;
903                               Consistency_Error_Msg
904                                 ("file { violates restriction " &
905                                  "No_Dependence => %");
906                            end if;
907                         end loop;
908                      end;
909                   end loop;
910                end;
911             end loop;
912          end;
913       end loop;
914    end Check_Consistent_Restrictions;
915
916    ---------------------------------------------------
917    -- Check_Consistent_Zero_Cost_Exception_Handling --
918    ---------------------------------------------------
919
920    --  Check consistent zero cost exception handling. The rule is that
921    --  all units must have the same exception handling mechanism.
922
923    procedure Check_Consistent_Zero_Cost_Exception_Handling is
924    begin
925       Check_Mechanism : for A1 in ALIs.First + 1 .. ALIs.Last loop
926          if ALIs.Table (A1).Zero_Cost_Exceptions /=
927             ALIs.Table (ALIs.First).Zero_Cost_Exceptions
928          then
929             Error_Msg_File_1 := ALIs.Table (A1).Sfile;
930             Error_Msg_File_2 := ALIs.Table (ALIs.First).Sfile;
931
932             Consistency_Error_Msg ("{ and { compiled with different "
933                                             & "exception handling mechanisms");
934          end if;
935       end loop Check_Mechanism;
936    end Check_Consistent_Zero_Cost_Exception_Handling;
937
938    -------------------------------
939    -- Check_Duplicated_Subunits --
940    -------------------------------
941
942    procedure Check_Duplicated_Subunits is
943    begin
944       for J in Sdep.First .. Sdep.Last loop
945          if Sdep.Table (J).Subunit_Name /= No_Name then
946             Get_Decoded_Name_String (Sdep.Table (J).Subunit_Name);
947             Name_Len := Name_Len + 2;
948             Name_Buffer (Name_Len - 1) := '%';
949
950             --  See if there is a body or spec with the same name
951
952             for K in Boolean loop
953                if K then
954                   Name_Buffer (Name_Len) := 'b';
955                else
956                   Name_Buffer (Name_Len) := 's';
957                end if;
958
959                declare
960                   Unit : constant Unit_Name_Type := Name_Find;
961                   Info : constant Int := Get_Name_Table_Info (Unit);
962
963                begin
964                   if Info /= 0 then
965                      Set_Standard_Error;
966                      Write_Str ("error: subunit """);
967                      Write_Name_Decoded (Sdep.Table (J).Subunit_Name);
968                      Write_Str (""" in file """);
969                      Write_Name_Decoded (Sdep.Table (J).Sfile);
970                      Write_Char ('"');
971                      Write_Eol;
972                      Write_Str ("       has same name as unit """);
973                      Write_Unit_Name (Units.Table (Unit_Id (Info)).Uname);
974                      Write_Str (""" found in file """);
975                      Write_Name_Decoded (Units.Table (Unit_Id (Info)).Sfile);
976                      Write_Char ('"');
977                      Write_Eol;
978                      Write_Str ("       this is not allowed within a single "
979                                 & "partition (RM 10.2(19))");
980                      Write_Eol;
981                      Osint.Exit_Program (Osint.E_Fatal);
982                   end if;
983                end;
984             end loop;
985          end if;
986       end loop;
987    end Check_Duplicated_Subunits;
988
989    --------------------
990    -- Check_Versions --
991    --------------------
992
993    procedure Check_Versions is
994       VL : constant Natural := ALIs.Table (ALIs.First).Ver_Len;
995
996    begin
997       for A in ALIs.First .. ALIs.Last loop
998          if ALIs.Table (A).Ver_Len /= VL
999            or else ALIs.Table (A).Ver          (1 .. VL) /=
1000                    ALIs.Table (ALIs.First).Ver (1 .. VL)
1001          then
1002             Error_Msg_File_1 := ALIs.Table (A).Sfile;
1003             Error_Msg_File_2 := ALIs.Table (ALIs.First).Sfile;
1004
1005             Consistency_Error_Msg
1006                ("{ and { compiled with different GNAT versions");
1007          end if;
1008       end loop;
1009    end Check_Versions;
1010
1011    ---------------------------
1012    -- Consistency_Error_Msg --
1013    ---------------------------
1014
1015    procedure Consistency_Error_Msg (Msg : String) is
1016    begin
1017       if Tolerate_Consistency_Errors then
1018
1019          --  If consistency errors are tolerated,
1020          --  output the message as a warning.
1021
1022          declare
1023             Warning_Msg : String (1 .. Msg'Length + 1);
1024
1025          begin
1026             Warning_Msg (1) := '?';
1027             Warning_Msg (2 .. Warning_Msg'Last) := Msg;
1028
1029             Error_Msg (Warning_Msg);
1030          end;
1031
1032       --  Otherwise the consistency error is a true error
1033
1034       else
1035          Error_Msg (Msg);
1036       end if;
1037    end Consistency_Error_Msg;
1038
1039    ---------------
1040    -- Same_Unit --
1041    ---------------
1042
1043    function Same_Unit (U1 : Unit_Name_Type; U2 : Name_Id) return Boolean is
1044    begin
1045       --  Note, the string U1 has a terminating %s or %b, U2 does not
1046
1047       if Length_Of_Name (U1) - 2 = Length_Of_Name (U2) then
1048          Get_Name_String (U1);
1049
1050          declare
1051             U1_Str : constant String := Name_Buffer (1 .. Name_Len - 2);
1052          begin
1053             Get_Name_String (U2);
1054             return U1_Str = Name_Buffer (1 .. Name_Len);
1055          end;
1056
1057       else
1058          return False;
1059       end if;
1060    end Same_Unit;
1061
1062 end Bcheck;