OSDN Git Service

* common.opt (Wmudflap): New option.
[pf3gnuchains/gcc-fork.git] / gcc / ada / bcheck.adb
index 7d23d27..adab958 100644 (file)
@@ -6,23 +6,20 @@
 --                                                                          --
 --                                 B o d y                                  --
 --                                                                          --
---                            $Revision$
---                                                                          --
---          Copyright (C) 1992-2002 Free Software Foundation, Inc.          --
+--          Copyright (C) 1992-2007, Free Software Foundation, Inc.         --
 --                                                                          --
 -- GNAT is free software;  you can  redistribute it  and/or modify it under --
 -- terms of the  GNU General Public License as published  by the Free Soft- --
--- ware  Foundation;  either version 2,  or (at your option) any later ver- --
+-- ware  Foundation;  either version 3,  or (at your option) any later ver- --
 -- sion.  GNAT is distributed in the hope that it will be useful, but WITH- --
 -- OUT ANY WARRANTY;  without even the  implied warranty of MERCHANTABILITY --
 -- or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License --
 -- for  more details.  You should have  received  a copy of the GNU General --
--- Public License  distributed with GNAT;  see file COPYING.  If not, write --
--- to  the Free Software Foundation,  59 Temple Place - Suite 330,  Boston, --
--- MA 02111-1307, USA.                                                      --
+-- Public License  distributed with GNAT; see file COPYING3.  If not, go to --
+-- http://www.gnu.org/licenses for a complete copy of the license.          --
 --                                                                          --
 -- GNAT was originally developed  by the GNAT team at  New York University. --
--- It is now maintained by Ada Core Technologies Inc (http://www.gnat.com). --
+-- Extensive contributions were provided by Ada Core Technologies Inc.      --
 --                                                                          --
 ------------------------------------------------------------------------------
 
@@ -41,26 +38,34 @@ with Types;    use Types;
 
 package body Bcheck is
 
-   --  Local subprograms
+   -----------------------
+   -- Local Subprograms --
+   -----------------------
 
-   --  The following checking subprograms make up the parts
-   --  of the configuration consistency check.
+   --  The following checking subprograms make up the parts of the
+   --  configuration consistency check.
 
+   procedure Check_Consistent_Dispatching_Policy;
    procedure Check_Consistent_Dynamic_Elaboration_Checking;
    procedure Check_Consistent_Floating_Point_Format;
+   procedure Check_Consistent_Interrupt_States;
    procedure Check_Consistent_Locking_Policy;
    procedure Check_Consistent_Normalize_Scalars;
    procedure Check_Consistent_Queuing_Policy;
+   procedure Check_Consistent_Restrictions;
    procedure Check_Consistent_Zero_Cost_Exception_Handling;
-   procedure Check_Partition_Restrictions;
 
    procedure Consistency_Error_Msg (Msg : String);
-   --  Produce an error or a warning message, depending on whether
-   --  an inconsistent configuration is permitted or not.
+   --  Produce an error or a warning message, depending on whether an
+   --  inconsistent configuration is permitted or not.
 
-   ------------------------------------
-   -- Check_Consistent_Configuration --
-   ------------------------------------
+   function Same_Unit (U1 : Unit_Name_Type; U2 : Name_Id) return Boolean;
+   --  Used to compare two unit names for No_Dependence checks. U1 is in
+   --  standard unit name format, and U2 is in literal form with periods.
+
+   -------------------------------------
+   -- Check_Configuration_Consistency --
+   -------------------------------------
 
    procedure Check_Configuration_Consistency is
    begin
@@ -83,9 +88,340 @@ package body Bcheck is
       Check_Consistent_Normalize_Scalars;
       Check_Consistent_Dynamic_Elaboration_Checking;
 
-      Check_Partition_Restrictions;
+      Check_Consistent_Restrictions;
+      Check_Consistent_Interrupt_States;
+      Check_Consistent_Dispatching_Policy;
    end Check_Configuration_Consistency;
 
+   -----------------------
+   -- Check_Consistency --
+   -----------------------
+
+   procedure Check_Consistency is
+      Src : Source_Id;
+      --  Source file Id for this Sdep entry
+
+      ALI_Path_Id : File_Name_Type;
+
+   begin
+      --  First, we go through the source table to see if there are any cases
+      --  in which we should go after source files and compute checksums of
+      --  the source files. We need to do this for any file for which we have
+      --  mismatching time stamps and (so far) matching checksums.
+
+      for S in Source.First .. Source.Last loop
+
+         --  If all time stamps for a file match, then there is nothing to
+         --  do, since we will not be checking checksums in that case anyway
+
+         if Source.Table (S).All_Timestamps_Match then
+            null;
+
+         --  If we did not find the source file, then we can't compute its
+         --  checksum anyway. Note that when we have a time stamp mismatch,
+         --  we try to find the source file unconditionally (i.e. if
+         --  Check_Source_Files is False).
+
+         elsif not Source.Table (S).Source_Found then
+            null;
+
+         --  If we already have non-matching or missing checksums, then no
+         --  need to try going after source file, since we won't trust the
+         --  checksums in any case.
+
+         elsif not Source.Table (S).All_Checksums_Match then
+            null;
+
+         --  Now we have the case where we have time stamp mismatches, and
+         --  the source file is around, but so far all checksums match. This
+         --  is the case where we need to compute the checksum from the source
+         --  file, since otherwise we would ignore the time stamp mismatches,
+         --  and that is wrong if the checksum of the source does not agree
+         --  with the checksums in the ALI files.
+
+         elsif Check_Source_Files then
+            if not Checksums_Match
+              (Source.Table (S).Checksum,
+               Get_File_Checksum (Source.Table (S).Sfile))
+            then
+               Source.Table (S).All_Checksums_Match := False;
+            end if;
+         end if;
+      end loop;
+
+      --  Loop through ALI files
+
+      ALIs_Loop : for A in ALIs.First .. ALIs.Last loop
+
+         --  Loop through Sdep entries in one ALI file
+
+         Sdep_Loop : for D in
+           ALIs.Table (A).First_Sdep .. ALIs.Table (A).Last_Sdep
+         loop
+            if Sdep.Table (D).Dummy_Entry then
+               goto Continue;
+            end if;
+
+            Src := Source_Id (Get_Name_Table_Info (Sdep.Table (D).Sfile));
+
+            --  If the time stamps match, or all checksums match, then we
+            --  are OK, otherwise we have a definite error.
+
+            if Sdep.Table (D).Stamp /= Source.Table (Src).Stamp
+              and then not Source.Table (Src).All_Checksums_Match
+            then
+               Error_Msg_File_1 := ALIs.Table (A).Sfile;
+               Error_Msg_File_2 := Sdep.Table (D).Sfile;
+
+               --  Two styles of message, depending on whether or not
+               --  the updated file is the one that must be recompiled
+
+               if Error_Msg_File_1 = Error_Msg_File_2 then
+                  if Tolerate_Consistency_Errors then
+                     Error_Msg
+                        ("?{ has been modified and should be recompiled");
+                  else
+                     Error_Msg
+                       ("{ has been modified and must be recompiled");
+                  end if;
+
+               else
+                  ALI_Path_Id :=
+                    Osint.Find_File ((ALIs.Table (A).Afile), Osint.Library);
+                  if Osint.Is_Readonly_Library (ALI_Path_Id) then
+                     if Tolerate_Consistency_Errors then
+                        Error_Msg ("?{ should be recompiled");
+                        Error_Msg_File_1 := ALI_Path_Id;
+                        Error_Msg ("?({ is obsolete and read-only)");
+                     else
+                        Error_Msg ("{ must be compiled");
+                        Error_Msg_File_1 := ALI_Path_Id;
+                        Error_Msg ("({ is obsolete and read-only)");
+                     end if;
+
+                  elsif Tolerate_Consistency_Errors then
+                     Error_Msg
+                       ("?{ should be recompiled ({ has been modified)");
+
+                  else
+                     Error_Msg ("{ must be recompiled ({ has been modified)");
+                  end if;
+               end if;
+
+               if (not Tolerate_Consistency_Errors) and Verbose_Mode then
+                  Error_Msg_File_1 := Sdep.Table (D).Sfile;
+                  Error_Msg
+                    ("{ time stamp " & String (Source.Table (Src).Stamp));
+
+                  Error_Msg_File_1 := Sdep.Table (D).Sfile;
+                  --  Something wrong here, should be different file ???
+
+                  Error_Msg
+                    (" conflicts with { timestamp " &
+                     String (Sdep.Table (D).Stamp));
+               end if;
+
+               --  Exit from the loop through Sdep entries once we find one
+               --  that does not match.
+
+               exit Sdep_Loop;
+            end if;
+
+         <<Continue>>
+            null;
+         end loop Sdep_Loop;
+      end loop ALIs_Loop;
+   end Check_Consistency;
+
+   -----------------------------------------
+   -- Check_Consistent_Dispatching_Policy --
+   -----------------------------------------
+
+   --  The rule is that all files for which the dispatching policy is
+   --  significant must meet the following rules:
+
+   --    1. All files for which a task dispatching policy is significant must
+   --    be compiled with the same setting.
+
+   --    2. If a partition contains one or more Priority_Specific_Dispatching
+   --    pragmas it cannot contain a Task_Dispatching_Policy pragma.
+
+   --    3. No overlap is allowed in the priority ranges specified in
+   --    Priority_Specific_Dispatching pragmas within the same partition.
+
+   --    4. If a partition contains one or more Priority_Specific_Dispatching
+   --    pragmas then the Ceiling_Locking policy is the only one allowed for
+   --    the partition.
+
+   procedure Check_Consistent_Dispatching_Policy is
+      Max_Prio : Nat := 0;
+      --  Maximum priority value for which a Priority_Specific_Dispatching
+      --  pragma has been specified.
+
+      TDP_Pragma_Afile : ALI_Id := No_ALI_Id;
+      --  ALI file where a Task_Dispatching_Policy pragma appears
+
+   begin
+      --  Consistency checks in units specifying a Task_Dispatching_Policy
+
+      if Task_Dispatching_Policy_Specified /= ' ' then
+         Find_Policy : for A1 in ALIs.First .. ALIs.Last loop
+            if ALIs.Table (A1).Task_Dispatching_Policy /= ' ' then
+
+               --  Store the place where the first task dispatching pragma
+               --  appears. We may need this value for issuing consistency
+               --  errors if Priority_Specific_Dispatching pragmas are used.
+
+               TDP_Pragma_Afile := A1;
+
+               Check_Policy : declare
+                  Policy : constant Character :=
+                             ALIs.Table (A1).Task_Dispatching_Policy;
+
+               begin
+                  for A2 in A1 + 1 .. ALIs.Last loop
+                     if ALIs.Table (A2).Task_Dispatching_Policy /= ' '
+                          and then
+                        ALIs.Table (A2).Task_Dispatching_Policy /= Policy
+                     then
+                        Error_Msg_File_1 := ALIs.Table (A1).Sfile;
+                        Error_Msg_File_2 := ALIs.Table (A2).Sfile;
+
+                        Consistency_Error_Msg
+                          ("{ and { compiled with different task" &
+                           " dispatching policies");
+                        exit Find_Policy;
+                     end if;
+                  end loop;
+               end Check_Policy;
+
+               exit Find_Policy;
+            end if;
+         end loop Find_Policy;
+      end if;
+
+      --  If no Priority_Specific_Dispatching entries, nothing else to do
+
+      if Specific_Dispatching.Last >= Specific_Dispatching.First then
+
+         --  Find out the maximum priority value for which one of the
+         --  Priority_Specific_Dispatching pragmas applies.
+
+         Max_Prio := 0;
+         for J in Specific_Dispatching.First .. Specific_Dispatching.Last loop
+            if Specific_Dispatching.Table (J).Last_Priority > Max_Prio then
+               Max_Prio := Specific_Dispatching.Table (J).Last_Priority;
+            end if;
+         end loop;
+
+         --  Now establish tables to be used for consistency checking
+
+         declare
+            --  The following record type is used to record locations of the
+            --  Priority_Specific_Dispatching pragmas applying to the Priority.
+
+            type Specific_Dispatching_Entry is record
+               Dispatching_Policy : Character := ' ';
+               --  First character (upper case) of corresponding policy name
+
+               Afile : ALI_Id := No_ALI_Id;
+               --  ALI file that generated Priority Specific Dispatching
+               --  entry for consistency message.
+
+               Loc : Nat := 0;
+               --  Line numbers from Priority_Specific_Dispatching pragma
+            end record;
+
+            PSD_Table  : array (0 .. Max_Prio) of Specific_Dispatching_Entry :=
+                           (others => Specific_Dispatching_Entry'
+                              (Dispatching_Policy => ' ',
+                               Afile              => No_ALI_Id,
+                               Loc                => 0));
+            --  Array containing an entry per priority containing the location
+            --  where there is a Priority_Specific_Dispatching pragma that
+            --  applies to the priority.
+
+         begin
+            for F in ALIs.First .. ALIs.Last loop
+               for K in ALIs.Table (F).First_Specific_Dispatching ..
+                        ALIs.Table (F).Last_Specific_Dispatching
+               loop
+                  declare
+                     DTK : Specific_Dispatching_Record
+                             renames Specific_Dispatching.Table (K);
+                  begin
+                     --  Check whether pragma Task_Dispatching_Policy and
+                     --  pragma Priority_Specific_Dispatching are used in the
+                     --  same partition.
+
+                     if Task_Dispatching_Policy_Specified /= ' ' then
+                        Error_Msg_File_1 := ALIs.Table (F).Sfile;
+                        Error_Msg_File_2 :=
+                          ALIs.Table (TDP_Pragma_Afile).Sfile;
+
+                        Error_Msg_Nat_1 := DTK.PSD_Pragma_Line;
+
+                        Consistency_Error_Msg
+                          ("Priority_Specific_Dispatching at {:#" &
+                           " incompatible with Task_Dispatching_Policy at {");
+                     end if;
+
+                     --  Ceiling_Locking must also be specified for a partition
+                     --  with at least one Priority_Specific_Dispatching
+                     --  pragma.
+
+                     if Locking_Policy_Specified /= ' '
+                       and then Locking_Policy_Specified /= 'C'
+                     then
+                        for A in ALIs.First .. ALIs.Last loop
+                           if ALIs.Table (A).Locking_Policy /= ' '
+                             and then ALIs.Table (A).Locking_Policy /= 'C'
+                           then
+                              Error_Msg_File_1 := ALIs.Table (F).Sfile;
+                              Error_Msg_File_2 := ALIs.Table (A).Sfile;
+
+                              Error_Msg_Nat_1  := DTK.PSD_Pragma_Line;
+
+                              Consistency_Error_Msg
+                                ("Priority_Specific_Dispatching at {:#" &
+                                 " incompatible with Locking_Policy at {");
+                           end if;
+                        end loop;
+                     end if;
+
+                     --  Check overlapping priority ranges
+
+                     Find_Overlapping : for Prio in
+                       DTK.First_Priority .. DTK.Last_Priority
+                     loop
+                        if PSD_Table (Prio).Afile = No_ALI_Id then
+                           PSD_Table (Prio) :=
+                             (Dispatching_Policy => DTK.Dispatching_Policy,
+                              Afile => F, Loc => DTK.PSD_Pragma_Line);
+
+                        elsif PSD_Table (Prio).Dispatching_Policy /=
+                              DTK.Dispatching_Policy
+
+                        then
+                           Error_Msg_File_1 :=
+                             ALIs.Table (PSD_Table (Prio).Afile).Sfile;
+                           Error_Msg_File_2 := ALIs.Table (F).Sfile;
+                           Error_Msg_Nat_1  := PSD_Table (Prio).Loc;
+                           Error_Msg_Nat_2  := DTK.PSD_Pragma_Line;
+
+                           Consistency_Error_Msg
+                             ("overlapping priority ranges at {:# and {:#");
+
+                           exit Find_Overlapping;
+                        end if;
+                     end loop Find_Overlapping;
+                  end;
+               end loop;
+            end loop;
+         end;
+      end if;
+   end Check_Consistent_Dispatching_Policy;
+
    ---------------------------------------------------
    -- Check_Consistent_Dynamic_Elaboration_Checking --
    ---------------------------------------------------
@@ -143,14 +479,14 @@ package body Bcheck is
                               --  Issue warning, not one of the safe cases
 
                               else
-                                 Error_Msg_Name_1 := UR.Sfile;
+                                 Error_Msg_File_1 := UR.Sfile;
                                  Error_Msg
-                                   ("?% has dynamic elaboration checks " &
+                                   ("?{ has dynamic elaboration checks " &
                                                                  "and with's");
 
-                                 Error_Msg_Name_1 := WU.Sfile;
+                                 Error_Msg_File_1 := WU.Sfile;
                                  Error_Msg
-                                   ("?  % which has static elaboration " &
+                                   ("?  { which has static elaboration " &
                                                                      "checks");
 
                                  Warnings_Detected := Warnings_Detected - 1;
@@ -184,11 +520,11 @@ package body Bcheck is
             begin
                for A2 in A1 + 1 .. ALIs.Last loop
                   if ALIs.Table (A2).Float_Format /= Format then
-                     Error_Msg_Name_1 := ALIs.Table (A1).Sfile;
-                     Error_Msg_Name_2 := ALIs.Table (A2).Sfile;
+                     Error_Msg_File_1 := ALIs.Table (A1).Sfile;
+                     Error_Msg_File_2 := ALIs.Table (A2).Sfile;
 
                      Consistency_Error_Msg
-                       ("% and % compiled with different " &
+                       ("{ and { compiled with different " &
                         "floating-point representations");
                      exit Find_Format;
                   end if;
@@ -200,6 +536,82 @@ package body Bcheck is
       end loop Find_Format;
    end Check_Consistent_Floating_Point_Format;
 
+   ---------------------------------------
+   -- Check_Consistent_Interrupt_States --
+   ---------------------------------------
+
+   --  The rule is that if the state of a given interrupt is specified
+   --  in more than one unit, it must be specified with a consistent state.
+
+   procedure Check_Consistent_Interrupt_States is
+      Max_Intrup : Nat;
+
+   begin
+      --  If no Interrupt_State entries, nothing to do
+
+      if Interrupt_States.Last < Interrupt_States.First then
+         return;
+      end if;
+
+      --  First find out the maximum interrupt value
+
+      Max_Intrup := 0;
+      for J in Interrupt_States.First .. Interrupt_States.Last loop
+         if Interrupt_States.Table (J).Interrupt_Id > Max_Intrup then
+            Max_Intrup := Interrupt_States.Table (J).Interrupt_Id;
+         end if;
+      end loop;
+
+      --  Now establish tables to be used for consistency checking
+
+      declare
+         Istate : array (0 .. Max_Intrup) of Character := (others => 'n');
+         --  Interrupt state entries, 'u'/'s'/'r' or 'n' to indicate an
+         --  entry that has not been set.
+
+         Afile : array (0 .. Max_Intrup) of ALI_Id;
+         --  ALI file that generated Istate entry for consistency message
+
+         Loc : array (0 .. Max_Intrup) of Nat;
+         --  Line numbers from IS pragma generating Istate entry
+
+         Inum : Nat;
+         --  Interrupt number from entry being tested
+
+         Stat : Character;
+         --  Interrupt state from entry being tested
+
+         Lnum : Nat;
+         --  Line number from entry being tested
+
+      begin
+         for F in ALIs.First .. ALIs.Last loop
+            for K in ALIs.Table (F).First_Interrupt_State ..
+                     ALIs.Table (F).Last_Interrupt_State
+            loop
+               Inum := Interrupt_States.Table (K).Interrupt_Id;
+               Stat := Interrupt_States.Table (K).Interrupt_State;
+               Lnum := Interrupt_States.Table (K).IS_Pragma_Line;
+
+               if Istate (Inum) = 'n' then
+                  Istate (Inum) := Stat;
+                  Afile  (Inum) := F;
+                  Loc    (Inum) := Lnum;
+
+               elsif Istate (Inum) /= Stat then
+                  Error_Msg_File_1 := ALIs.Table (Afile (Inum)).Sfile;
+                  Error_Msg_File_2 := ALIs.Table (F).Sfile;
+                  Error_Msg_Nat_1  := Loc (Inum);
+                  Error_Msg_Nat_2  := Lnum;
+
+                  Consistency_Error_Msg
+                    ("inconsistent interrupt states at {:# and {:#");
+               end if;
+            end loop;
+         end loop;
+      end;
+   end Check_Consistent_Interrupt_States;
+
    -------------------------------------
    -- Check_Consistent_Locking_Policy --
    -------------------------------------
@@ -222,11 +634,11 @@ package body Bcheck is
                   if ALIs.Table (A2).Locking_Policy /= ' ' and
                      ALIs.Table (A2).Locking_Policy /= Policy
                   then
-                     Error_Msg_Name_1 := ALIs.Table (A1).Sfile;
-                     Error_Msg_Name_2 := ALIs.Table (A2).Sfile;
+                     Error_Msg_File_1 := ALIs.Table (A1).Sfile;
+                     Error_Msg_File_2 := ALIs.Table (A2).Sfile;
 
                      Consistency_Error_Msg
-                       ("% and % compiled with different locking policies");
+                       ("{ and { compiled with different locking policies");
                      exit Find_Policy;
                   end if;
                end loop;
@@ -306,11 +718,11 @@ package body Bcheck is
                        and then
                      ALIs.Table (A2).Queuing_Policy /= Policy
                   then
-                     Error_Msg_Name_1 := ALIs.Table (A1).Sfile;
-                     Error_Msg_Name_2 := ALIs.Table (A2).Sfile;
+                     Error_Msg_File_1 := ALIs.Table (A1).Sfile;
+                     Error_Msg_File_2 := ALIs.Table (A2).Sfile;
 
                      Consistency_Error_Msg
-                       ("% and % compiled with different queuing policies");
+                       ("{ and { compiled with different queuing policies");
                      exit Find_Policy;
                   end if;
                end loop;
@@ -321,302 +733,206 @@ package body Bcheck is
       end loop Find_Policy;
    end Check_Consistent_Queuing_Policy;
 
-   ---------------------------------------------------
-   -- Check_Consistent_Zero_Cost_Exception_Handling --
-   ---------------------------------------------------
-
-   --  Check consistent zero cost exception handling. The rule is that
-   --  all units must have the same exception handling mechanism.
-
-   procedure Check_Consistent_Zero_Cost_Exception_Handling is
-   begin
-      Check_Mechanism : for A1 in ALIs.First + 1 .. ALIs.Last loop
-         if ALIs.Table (A1).Zero_Cost_Exceptions /=
-            ALIs.Table (ALIs.First).Zero_Cost_Exceptions
-
-         then
-            Error_Msg_Name_1 := ALIs.Table (A1).Sfile;
-            Error_Msg_Name_2 := ALIs.Table (ALIs.First).Sfile;
-
-            Consistency_Error_Msg ("% and % compiled with different "
-                                            & "exception handling mechanisms");
-         end if;
-      end loop Check_Mechanism;
-   end Check_Consistent_Zero_Cost_Exception_Handling;
-
-   ----------------------------------
-   -- Check_Partition_Restrictions --
-   ----------------------------------
+   -----------------------------------
+   -- Check_Consistent_Restrictions --
+   -----------------------------------
 
    --  The rule is that if a restriction is specified in any unit,
    --  then all units must obey the restriction. The check applies
    --  only to restrictions which require partition wide consistency,
    --  and not to internal units.
 
-   --  The check is done in two steps. First for every restriction
-   --  a unit specifying that restriction is found, if any.
-   --  Second, all units are verified against the specified restrictions.
-
-   procedure Check_Partition_Restrictions is
-      No_Restriction_List : array (All_Restrictions) of Boolean :=
-        (No_Implicit_Conditionals => True,
-         --  This could modify and pessimize generated code
-
-         No_Implicit_Dynamic_Code => True,
-         --  This could modify and pessimize generated code
-
-         No_Implicit_Loops        => True,
-         --  This could modify and pessimize generated code
-
-         No_Recursion             => True,
-         --  Not checkable at compile time
-
-         No_Reentrancy            => True,
-         --  Not checkable at compile time
-
-         others                   => False);
-      --  Define those restrictions that should be output if the gnatbind -r
-      --  switch is used. Not all restrictions are output for the reasons given
-      --  above in the list, and this array is used to test whether the
-      --  corresponding pragma should be listed. True means that it should not
-      --  be listed.
-
-      R : array (All_Restrictions) of ALI_Id := (others => No_ALI_Id);
-      --  Record the first unit specifying each compilation unit restriction
-
-      V : array (All_Restrictions) of ALI_Id := (others => No_ALI_Id);
-      --  Record the last unit violating each partition restriction. Note
-      --  that entries in this array that do not correspond to partition
-      --  restrictions can never be modified.
-
-      Additional_Restrictions_Listed : Boolean := False;
-      --  Set True if we have listed header for restrictions
-
-   begin
-      --  Loop to find restrictions
-
-      for A in ALIs.First .. ALIs.Last loop
-         for J in All_Restrictions loop
-            if R (J) = No_ALI_Id and ALIs.Table (A).Restrictions (J) = 'r' then
-               R (J) := A;
-            end if;
-         end loop;
-      end loop;
+   procedure Check_Consistent_Restrictions is
+      Restriction_File_Output : Boolean;
+      --  Shows if we have output header messages for restriction violation
 
-      --  Loop to find violations
+      procedure Print_Restriction_File (R : All_Restrictions);
+      --  Print header line for R if not printed yet
 
-      for A in ALIs.First .. ALIs.Last loop
-         for J in All_Restrictions loop
-            if ALIs.Table (A).Restrictions (J) = 'v'
-               and then not Is_Internal_File_Name (ALIs.Table (A).Sfile)
-            then
-               --  A violation of a restriction was found
+      ----------------------------
+      -- Print_Restriction_File --
+      ----------------------------
 
-               V (J) := A;
+      procedure Print_Restriction_File (R : All_Restrictions) is
+      begin
+         if not Restriction_File_Output then
+            Restriction_File_Output := True;
 
-               --  If this is a paritition restriction, and the restriction
-               --  was specified in some unit in the partition, then this
-               --  is a violation of the consistency requirement, so we
-               --  generate an appropriate error message.
+            --  Find an ali file specifying the restriction
 
-               if R (J) /= No_ALI_Id
-                 and then J in Partition_Restrictions
+            for A in ALIs.First .. ALIs.Last loop
+               if ALIs.Table (A).Restrictions.Set (R)
+                 and then (R in All_Boolean_Restrictions
+                             or else ALIs.Table (A).Restrictions.Value (R) =
+                                     Cumulative_Restrictions.Value (R))
                then
+                  --  We have found that ALI file A specifies the restriction
+                  --  that is being violated (the minimum value is specified
+                  --  in the case of a parameter restriction).
+
                   declare
-                     M1 : constant String := "% has Restriction (";
-                     S  : constant String := Restriction_Id'Image (J);
-                     M2 : String (1 .. M1'Length + S'Length + 1);
+                     M1 : constant String := "{ has restriction ";
+                     S  : constant String := Restriction_Id'Image (R);
+                     M2 : String (1 .. 200); -- big enough!
+                     P  : Integer;
 
                   begin
                      Name_Buffer (1 .. S'Length) := S;
                      Name_Len := S'Length;
-                     Set_Casing
-                       (Units.Table (ALIs.Table (R (J)).First_Unit).Icasing);
+                     Set_Casing (Mixed_Case);
 
                      M2 (M1'Range) := M1;
-                     M2 (M1'Length + 1 .. M2'Last - 1) :=
-                                                   Name_Buffer (1 .. S'Length);
-                     M2 (M2'Last) := ')';
-
-                     Error_Msg_Name_1 := ALIs.Table (R (J)).Sfile;
-                     Consistency_Error_Msg (M2);
-                     Error_Msg_Name_1 := ALIs.Table (A).Sfile;
+                     P := M1'Length + 1;
+                     M2 (P .. P + S'Length - 1) := Name_Buffer (1 .. S'Length);
+                     P := P + S'Length;
+
+                     if R in All_Parameter_Restrictions then
+                        M2 (P .. P + 4) := " => #";
+                        Error_Msg_Nat_1 :=
+                          Int (Cumulative_Restrictions.Value (R));
+                        P := P + 5;
+                     end if;
+
+                     Error_Msg_File_1 := ALIs.Table (A).Sfile;
+                     Consistency_Error_Msg (M2 (1 .. P - 1));
                      Consistency_Error_Msg
-                       ("but file % violates this restriction");
+                       ("but the following files violate this restriction:");
+                     return;
                   end;
                end if;
-            end if;
-         end loop;
-      end loop;
+            end loop;
+         end if;
+      end Print_Restriction_File;
+
+   --  Start of processing for Check_Consistent_Restrictions
 
-      --  List applicable restrictions if option set
+   begin
+      --  Loop through all restriction violations
 
-      if List_Restrictions then
+      for R in All_Restrictions loop
 
-         --  List any restrictions which were not violated and not specified
+         --  Check for violation of this restriction
 
-         for J in All_Restrictions loop
-            if V (J) = No_ALI_Id
-              and then R (J) = No_ALI_Id
-              and then not No_Restriction_List (J)
-            then
-               if not Additional_Restrictions_Listed then
-                  Write_Eol;
-                  Write_Line
-                    ("The following additional restrictions may be" &
-                     " applied to this partition:");
-                  Additional_Restrictions_Listed := True;
-               end if;
+         if Cumulative_Restrictions.Set (R)
+           and then Cumulative_Restrictions.Violated (R)
+           and then (R in Partition_Boolean_Restrictions
+                       or else (R in All_Parameter_Restrictions
+                                   and then
+                                     Cumulative_Restrictions.Count (R) >
+                                     Cumulative_Restrictions.Value (R)))
+         then
+            Restriction_File_Output := False;
 
-               Write_Str ("pragma Restrictions (");
+            --  Loop through files looking for violators
 
+            for A2 in ALIs.First .. ALIs.Last loop
                declare
-                  S : constant String := Restriction_Id'Image (J);
+                  T : ALIs_Record renames ALIs.Table (A2);
 
                begin
-                  Name_Len := S'Length;
-                  Name_Buffer (1 .. Name_Len) := S;
+                  if T.Restrictions.Violated (R) then
+
+                     --  We exclude predefined files from the list of
+                     --  violators. This should be rethought. It is not
+                     --  clear that this is the right thing to do, that
+                     --  is particularly the case for restricted runtimes.
+
+                     if not Is_Internal_File_Name (T.Sfile) then
+
+                        --  Case of Boolean restriction, just print file name
+
+                        if R in All_Boolean_Restrictions then
+                           Print_Restriction_File (R);
+                           Error_Msg_File_1 := T.Sfile;
+                           Consistency_Error_Msg ("  {");
+
+                        --  Case of Parameter restriction where violation
+                        --  count exceeds restriction value, print file
+                        --  name and count, adding "at least" if the
+                        --  exact count is not known.
+
+                        elsif R in Checked_Add_Parameter_Restrictions
+                          or else T.Restrictions.Count (R) >
+                          Cumulative_Restrictions.Value (R)
+                        then
+                           Print_Restriction_File (R);
+                           Error_Msg_File_1 := T.Sfile;
+                           Error_Msg_Nat_1 := Int (T.Restrictions.Count (R));
+
+                           if T.Restrictions.Unknown (R) then
+                              Consistency_Error_Msg
+                                ("  { (count = at least #)");
+                           else
+                              Consistency_Error_Msg
+                                ("  % (count = #)");
+                           end if;
+                        end if;
+                     end if;
+                  end if;
                end;
-
-               Set_Casing (Mixed_Case);
-               Write_Str (Name_Buffer (1 .. Name_Len));
-               Write_Str (");");
-               Write_Eol;
-            end if;
-         end loop;
-      end if;
-   end Check_Partition_Restrictions;
-
-   -----------------------
-   -- Check_Consistency --
-   -----------------------
-
-   procedure Check_Consistency is
-      Src : Source_Id;
-      --  Source file Id for this Sdep entry
-
-   begin
-      --  First, we go through the source table to see if there are any cases
-      --  in which we should go after source files and compute checksums of
-      --  the source files. We need to do this for any file for which we have
-      --  mismatching time stamps and (so far) matching checksums.
-
-      for S in Source.First .. Source.Last loop
-
-         --  If all time stamps for a file match, then there is nothing to
-         --  do, since we will not be checking checksums in that case anyway
-
-         if Source.Table (S).All_Timestamps_Match then
-            null;
-
-         --  If we did not find the source file, then we can't compute its
-         --  checksum anyway. Note that when we have a time stamp mismatch,
-         --  we try to find the source file unconditionally (i.e. if
-         --  Check_Source_Files is False).
-
-         elsif not Source.Table (S).Source_Found then
-            null;
-
-         --  If we already have non-matching or missing checksums, then no
-         --  need to try going after source file, since we won't trust the
-         --  checksums in any case.
-
-         elsif not Source.Table (S).All_Checksums_Match then
-            null;
-
-         --  Now we have the case where we have time stamp mismatches, and
-         --  the source file is around, but so far all checksums match. This
-         --  is the case where we need to compute the checksum from the source
-         --  file, since otherwise we would ignore the time stamp mismatches,
-         --  and that is wrong if the checksum of the source does not agree
-         --  with the checksums in the ALI files.
-
-         elsif Check_Source_Files then
-            if not Checksums_Match
-              (Source.Table (S).Checksum,
-               Get_File_Checksum (Source.Table (S).Sfile))
-            then
-               Source.Table (S).All_Checksums_Match := False;
-            end if;
+            end loop;
          end if;
       end loop;
 
-      --  Loop through ALI files
-
-      ALIs_Loop : for A in ALIs.First .. ALIs.Last loop
-
-         --  Loop through Sdep entries in one ALI file
-
-         Sdep_Loop : for D in
-           ALIs.Table (A).First_Sdep .. ALIs.Table (A).Last_Sdep
-         loop
-            if Sdep.Table (D).Dummy_Entry then
-               goto Continue;
-            end if;
-
-            Src := Source_Id (Get_Name_Table_Info (Sdep.Table (D).Sfile));
-
-            --  If the time stamps match, or all checksums match, then we
-            --  are OK, otherwise we have a definite error.
+      --  Now deal with No_Dependence indications. Note that we put the loop
+      --  through entries in the no dependency table first, since this loop
+      --  is most often empty (no such pragma Restrictions in use).
 
-            if Sdep.Table (D).Stamp /= Source.Table (Src).Stamp
-              and then not Source.Table (Src).All_Checksums_Match
-            then
-               Error_Msg_Name_1 := ALIs.Table (A).Sfile;
-               Error_Msg_Name_2 := Sdep.Table (D).Sfile;
-
-               --  Two styles of message, depending on whether or not
-               --  the updated file is the one that must be recompiled
-
-               if Error_Msg_Name_1 = Error_Msg_Name_2 then
-                  if Tolerate_Consistency_Errors then
-                     Error_Msg
-                        ("?% has been modified and should be recompiled");
-                  else
-                     Error_Msg
-                       ("% has been modified and must be recompiled");
-                  end if;
-
-               else
-                  if Tolerate_Consistency_Errors then
-                     Error_Msg
-                       ("?% should be recompiled (% has been modified)");
+      for ND in No_Deps.First .. No_Deps.Last loop
+         declare
+            ND_Unit : constant Name_Id :=
+                        No_Deps.Table (ND).No_Dep_Unit;
 
-                  else
-                     Error_Msg ("% must be recompiled (% has been modified)");
-                  end if;
-               end if;
+         begin
+            for J in ALIs.First .. ALIs.Last loop
+               declare
+                  A : ALIs_Record renames ALIs.Table (J);
 
-               if (not Tolerate_Consistency_Errors) and Verbose_Mode then
-                  declare
-                     Msg : constant String := "file % has time stamp ";
-                     Buf : String (1 .. Msg'Length + Time_Stamp_Length);
+               begin
+                  for K in A.First_Unit .. A.Last_Unit loop
+                     declare
+                        U : Unit_Record renames Units.Table (K);
+                     begin
+                        for L in U.First_With .. U.Last_With loop
+                           if Same_Unit
+                             (Withs.Table (L).Uname, ND_Unit)
+                           then
+                              Error_Msg_File_1 := U.Sfile;
+                              Error_Msg_Name_1 := ND_Unit;
+                              Consistency_Error_Msg
+                                ("file { violates restriction " &
+                                 "No_Dependence => %");
+                           end if;
+                        end loop;
+                     end;
+                  end loop;
+               end;
+            end loop;
+         end;
+      end loop;
+   end Check_Consistent_Restrictions;
 
-                  begin
-                     Buf (1 .. Msg'Length) := Msg;
-                     Buf (Msg'Length + 1 .. Buf'Length) :=
-                       String (Source.Table (Src).Stamp);
-                     Error_Msg_Name_1 := ALIs.Table (A).Sfile;
-                     Error_Msg (Buf);
-
-                     Buf (Msg'Length + 1 .. Buf'Length) :=
-                       String (Sdep.Table (D).Stamp);
-                     Error_Msg_Name_1 := Sdep.Table (D).Sfile;
-                     Error_Msg (Buf);
-                  end;
-               end if;
+   ---------------------------------------------------
+   -- Check_Consistent_Zero_Cost_Exception_Handling --
+   ---------------------------------------------------
 
-               --  Exit from the loop through Sdep entries once we find one
-               --  that does not match.
+   --  Check consistent zero cost exception handling. The rule is that
+   --  all units must have the same exception handling mechanism.
 
-               exit Sdep_Loop;
-            end if;
+   procedure Check_Consistent_Zero_Cost_Exception_Handling is
+   begin
+      Check_Mechanism : for A1 in ALIs.First + 1 .. ALIs.Last loop
+         if ALIs.Table (A1).Zero_Cost_Exceptions /=
+            ALIs.Table (ALIs.First).Zero_Cost_Exceptions
+         then
+            Error_Msg_File_1 := ALIs.Table (A1).Sfile;
+            Error_Msg_File_2 := ALIs.Table (ALIs.First).Sfile;
 
-         <<Continue>>
-            null;
-         end loop Sdep_Loop;
-      end loop ALIs_Loop;
-   end Check_Consistency;
+            Consistency_Error_Msg ("{ and { compiled with different "
+                                            & "exception handling mechanisms");
+         end if;
+      end loop Check_Mechanism;
+   end Check_Consistent_Zero_Cost_Exception_Handling;
 
    -------------------------------
    -- Check_Duplicated_Subunits --
@@ -635,13 +951,13 @@ package body Bcheck is
             for K in Boolean loop
                if K then
                   Name_Buffer (Name_Len) := 'b';
-
                else
                   Name_Buffer (Name_Len) := 's';
                end if;
 
                declare
-                  Info : constant Int := Get_Name_Table_Info (Name_Find);
+                  Unit : constant Unit_Name_Type := Name_Find;
+                  Info : constant Int := Get_Name_Table_Info (Unit);
 
                begin
                   if Info /= 0 then
@@ -682,11 +998,11 @@ package body Bcheck is
            or else ALIs.Table (A).Ver          (1 .. VL) /=
                    ALIs.Table (ALIs.First).Ver (1 .. VL)
          then
-            Error_Msg_Name_1 := ALIs.Table (A).Sfile;
-            Error_Msg_Name_2 := ALIs.Table (ALIs.First).Sfile;
+            Error_Msg_File_1 := ALIs.Table (A).Sfile;
+            Error_Msg_File_2 := ALIs.Table (ALIs.First).Sfile;
 
             Consistency_Error_Msg
-               ("% and % compiled with different GNAT versions");
+               ("{ and { compiled with different GNAT versions");
          end if;
       end loop;
    end Check_Versions;
@@ -719,4 +1035,27 @@ package body Bcheck is
       end if;
    end Consistency_Error_Msg;
 
+   ---------------
+   -- Same_Unit --
+   ---------------
+
+   function Same_Unit (U1 : Unit_Name_Type; U2 : Name_Id) return Boolean is
+   begin
+      --  Note, the string U1 has a terminating %s or %b, U2 does not
+
+      if Length_Of_Name (U1) - 2 = Length_Of_Name (U2) then
+         Get_Name_String (U1);
+
+         declare
+            U1_Str : constant String := Name_Buffer (1 .. Name_Len - 2);
+         begin
+            Get_Name_String (U2);
+            return U1_Str = Name_Buffer (1 .. Name_Len);
+         end;
+
+      else
+         return False;
+      end if;
+   end Same_Unit;
+
 end Bcheck;