diff mbox

[Ada] More detailed exception messages

Message ID 20101019105627.GA8958@adacore.com
State New
Headers show

Commit Message

Arnaud Charlet Oct. 19, 2010, 10:56 a.m. UTC
This patch introduces extra info on access, range and index checks when
using the -gnateE switch by calling an alternate gnat_rcheck routine which
takes additional int params: column, value, first, last so that
extra info of the form: index 1 not in 2..10
is generated in the exception message.

It's not enabled by default for now since it generates bigger executables (about
4% increase), although that's still under discussion for the future.

Tested on x86_64-pc-linux-gnu, committed on trunk

2010-10-19  Arnaud Charlet  <charlet@adacore.com>

	* switch-c.adb (Scan_Front_End_Switches): Add handling of -gnateE.
	* fe.h (Exception_Extra_Info): Declare.
	* usage.adb (usage): Add -gnateE doc.
	* checks.adb (Install_Null_Excluding_Check): Use better sloc.
	* sem_util.adb (Insert_Explicit_Dereference): Ditto.
	* gnat_ugn.texi: Document -gnateE switch.
	* a-except.adb (Set_Exception_C_Msg): New parameter Column.
	* a-except-2005.adb (Set_Exception_C_Msg): New parameter Column.
	(Raise_Constraint_Error_Msg): Ditto.
	(Image): New helper function.
	(Rcheck_00_Ext, Rcheck_05_Ext, Rcheck_12_Ext): New procedure with more
	detailed exception information.
	Adjust calls to Set_Exception_C_Msg and Raise_Constraint_Error_Msg.
	* a-exexda.adb (Set_Exception_C_Msg): New parameter Column.
	* opt.ads (Exception_Extra_Info): New flag.
	* gcc-interface/utils.c (gnat_raise_decls_ext): New.
	* gcc-interface/utils2.c (build_call_raise_range,
	build_call_raise_column): New functions.
	* gcc-interface/gigi.h (exception_info_kind, gnat_raise_decls_ext,
	build_call_raise_range, build_call_raise_column): Declare.
	gcc-interface/trans.c (build_raise_check): New function.
	(gigi): Initialize gnat_raise_decls_ext.
	(gnat_to_gnu): Add initial support for -gnateE switch.
diff mbox

Patch

Index: switch-c.adb
===================================================================
--- switch-c.adb	(revision 165687)
+++ switch-c.adb	(working copy)
@@ -422,6 +422,12 @@ 
                        ("-gnateD" & Switch_Chars (Ptr .. Max));
                      Ptr := Max + 1;
 
+                  --  -gnateE (extra exception information)
+
+                  when 'E' =>
+                     Exception_Extra_Info := True;
+                     Ptr := Ptr + 1;
+
                   --  -gnatef (full source path for brief error messages)
 
                   when 'f' =>
Index: fe.h
===================================================================
--- fe.h	(revision 165687)
+++ fe.h	(working copy)
@@ -6,7 +6,7 @@ 
  *                                                                          *
  *                              C Header File                               *
  *                                                                          *
- *          Copyright (C) 1992-2009, Free Software Foundation, Inc.         *
+ *          Copyright (C) 1992-2010, 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- *
@@ -163,6 +163,7 @@ 
 /* opt: */
 
 #define Global_Discard_Names           opt__global_discard_names
+#define Exception_Extra_Info           opt__exception_extra_info
 #define Exception_Locations_Suppressed opt__exception_locations_suppressed
 #define Exception_Mechanism            opt__exception_mechanism
 #define Back_Annotate_Rep_Info         opt__back_annotate_rep_info
@@ -170,6 +171,7 @@ 
 typedef enum {Setjmp_Longjmp, Back_End_Exceptions} Exception_Mechanism_Type;
 
 extern Boolean Global_Discard_Names;
+extern Boolean Exception_Extra_Info;
 extern Boolean Exception_Locations_Suppressed;
 extern Exception_Mechanism_Type Exception_Mechanism;
 extern Boolean Back_Annotate_Rep_Info;
Index: usage.adb
===================================================================
--- usage.adb	(revision 165694)
+++ usage.adb	(working copy)
@@ -177,6 +177,11 @@ 
    Write_Switch_Char ("eD?");
    Write_Line ("Define or redefine preprocessing symbol, e.g. -gnateDsym=val");
 
+   --  Line for -gnateE switch
+
+   Write_Switch_Char ("eE");
+   Write_Line ("Generate extra information in exception messages");
+
    --  Line for -gnatef switch
 
    Write_Switch_Char ("ef");
Index: checks.adb
===================================================================
--- checks.adb	(revision 165687)
+++ checks.adb	(working copy)
@@ -5244,7 +5244,7 @@ 
    ----------------------------------
 
    procedure Install_Null_Excluding_Check (N : Node_Id) is
-      Loc : constant Source_Ptr := Sloc (N);
+      Loc : constant Source_Ptr := Sloc (Parent (N));
       Typ : constant Entity_Id  := Etype (N);
 
       function Safe_To_Capture_In_Parameter_Value return Boolean;
Index: gnat_ugn.texi
===================================================================
--- gnat_ugn.texi	(revision 165687)
+++ gnat_ugn.texi	(working copy)
@@ -4123,6 +4123,12 @@ 
 Defines a symbol, associated with @var{value}, for preprocessing.
 (@pxref{Integrated Preprocessing}).
 
+@item -gnateE
+@cindex @option{-gnateE} (@command{gcc})
+Generate extra information in exception messages, in particular display
+extra column information and the value and range associated with index and
+range check failures, and extra column information for access checks.
+
 @item -gnatef
 @cindex @option{-gnatef} (@command{gcc})
 Display full source path name in brief error messages.
Index: sem_util.adb
===================================================================
--- sem_util.adb	(revision 165692)
+++ sem_util.adb	(working copy)
@@ -5569,7 +5569,8 @@ 
    begin
       Save_Interps (N, New_Prefix);
 
-      Rewrite (N, Make_Explicit_Dereference (Sloc (N), Prefix => New_Prefix));
+      Rewrite (N,
+        Make_Explicit_Dereference (Sloc (Parent (N)), Prefix => New_Prefix));
 
       Set_Etype (N, Designated_Type (Etype (New_Prefix)));
 
Index: a-except.adb
===================================================================
--- a-except.adb	(revision 165687)
+++ a-except.adb	(working copy)
@@ -6,7 +6,7 @@ 
 --                                                                          --
 --                                 B o d y                                  --
 --                                                                          --
---          Copyright (C) 1992-2009, Free Software Foundation, Inc.         --
+--          Copyright (C) 1992-2010, 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- --
@@ -93,17 +93,18 @@ 
       ---------------------------------
 
       procedure Set_Exception_C_Msg
-        (Id   : Exception_Id;
-         Msg1 : System.Address;
-         Line : Integer        := 0;
-         Msg2 : System.Address := System.Null_Address);
+        (Id     : Exception_Id;
+         Msg1   : System.Address;
+         Line   : Integer        := 0;
+         Column : Integer        := 0;
+         Msg2   : System.Address := System.Null_Address);
       --  This routine is called to setup the exception referenced by the
       --  Current_Excep field in the TSD to contain the indicated Id value
       --  and message. Msg1 is a null terminated string which is generated
       --  as the exception message. If line is non-zero, then a colon and
       --  the decimal representation of this integer is appended to the
-      --  message. When Msg2 is non-null, a space and this additional null
-      --  terminated string is added to the message.
+      --  message. Ditto for Column. When Msg2 is non-null, a space and this
+      --  additional null terminated string is added to the message.
 
       procedure Set_Exception_Msg
         (Id      : Exception_Id;
@@ -958,7 +959,7 @@ 
       M : System.Address := System.Null_Address)
    is
    begin
-      Exception_Data.Set_Exception_C_Msg (E, F, L, M);
+      Exception_Data.Set_Exception_C_Msg (E, F, L, Msg2 => M);
       Abort_Defer.all;
       Raise_Current_Excep (E);
    end Raise_With_Location_And_Msg;
Index: a-except-2005.adb
===================================================================
--- a-except-2005.adb	(revision 165687)
+++ a-except-2005.adb	(working copy)
@@ -6,7 +6,7 @@ 
 --                                                                          --
 --                                 B o d y                                  --
 --                                                                          --
---          Copyright (C) 1992-2009, Free Software Foundation, Inc.         --
+--          Copyright (C) 1992-2010, 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- --
@@ -94,6 +94,9 @@ 
    --  Store up to Max_Tracebacks in Excep, corresponding to the current
    --  call chain.
 
+   function Image (Index : Integer) return String;
+   --  Return string image corresponding to Index
+
    procedure To_Stderr (S : String);
    pragma Export (Ada, To_Stderr, "__gnat_to_stderr");
    --  Little routine to output string to stderr that is also used
@@ -112,17 +115,18 @@ 
       ---------------------------------
 
       procedure Set_Exception_C_Msg
-        (Id   : Exception_Id;
-         Msg1 : System.Address;
-         Line : Integer        := 0;
-         Msg2 : System.Address := System.Null_Address);
+        (Id     : Exception_Id;
+         Msg1   : System.Address;
+         Line   : Integer        := 0;
+         Column : Integer        := 0;
+         Msg2   : System.Address := System.Null_Address);
       --  This routine is called to setup the exception referenced by the
       --  Current_Excep field in the TSD to contain the indicated Id value
       --  and message. Msg1 is a null terminated string which is generated
       --  as the exception message. If line is non-zero, then a colon and
       --  the decimal representation of this integer is appended to the
-      --  message. When Msg2 is non-null, a space and this additional null
-      --  terminated string is added to the message.
+      --  message. Ditto for Column. When Msg2 is non-null, a space and this
+      --  additional null terminated string is added to the message.
 
       procedure Set_Exception_Msg
         (Id      : Exception_Id;
@@ -307,12 +311,13 @@ 
      (E : Exception_Id;
       F : System.Address;
       L : Integer;
+      C : Integer := 0;
       M : System.Address := System.Null_Address);
    pragma No_Return (Raise_With_Location_And_Msg);
    --  Raise an exception with given exception id value. A filename and line
    --  number is associated with the raise and is stored in the exception
-   --  occurrence and in addition a string message M is appended to
-   --  this (if M is not null).
+   --  occurrence and in addition a column and a string message M may be
+   --  appended to this (if not null/0).
 
    procedure Raise_Constraint_Error
      (File : System.Address;
@@ -323,13 +328,14 @@ 
    --  Raise constraint error with file:line information
 
    procedure Raise_Constraint_Error_Msg
-     (File : System.Address;
-      Line : Integer;
-      Msg  : System.Address);
+     (File   : System.Address;
+      Line   : Integer;
+      Column : Integer;
+      Msg    : System.Address);
    pragma No_Return (Raise_Constraint_Error_Msg);
    pragma Export
      (C, Raise_Constraint_Error_Msg, "__gnat_raise_constraint_error_msg");
-   --  Raise constraint error with file:line + msg information
+   --  Raise constraint error with file:line:col + msg information
 
    procedure Raise_Program_Error
      (File : System.Address;
@@ -459,6 +465,13 @@ 
    procedure Rcheck_32 (File : System.Address; Line : Integer);
    procedure Rcheck_33 (File : System.Address; Line : Integer);
 
+   procedure Rcheck_00_Ext
+     (File : System.Address; Line, Column : Integer);
+   procedure Rcheck_05_Ext
+     (File : System.Address; Line, Column, Index, First, Last : Integer);
+   procedure Rcheck_12_Ext
+     (File : System.Address; Line, Column, Index, First, Last : Integer);
+
    pragma Export (C, Rcheck_00, "__gnat_rcheck_00");
    pragma Export (C, Rcheck_01, "__gnat_rcheck_01");
    pragma Export (C, Rcheck_02, "__gnat_rcheck_02");
@@ -494,6 +507,10 @@ 
    pragma Export (C, Rcheck_32, "__gnat_rcheck_32");
    pragma Export (C, Rcheck_33, "__gnat_rcheck_33");
 
+   pragma Export (C, Rcheck_00_Ext, "__gnat_rcheck_00_ext");
+   pragma Export (C, Rcheck_05_Ext, "__gnat_rcheck_05_ext");
+   pragma Export (C, Rcheck_12_Ext, "__gnat_rcheck_12_ext");
+
    --  None of these procedures ever returns (they raise an exception!). By
    --  using pragma No_Return, we ensure that any junk code after the call,
    --  such as normal return epilog stuff, can be eliminated).
@@ -532,6 +549,10 @@ 
    pragma No_Return (Rcheck_32);
    pragma No_Return (Rcheck_33);
 
+   pragma No_Return (Rcheck_00_Ext);
+   pragma No_Return (Rcheck_05_Ext);
+   pragma No_Return (Rcheck_12_Ext);
+
    ---------------------------------------------
    -- Reason Strings for Run-Time Check Calls --
    ---------------------------------------------
@@ -774,13 +795,9 @@ 
    -- Raise_Constraint_Error --
    ----------------------------
 
-   procedure Raise_Constraint_Error
-     (File : System.Address;
-      Line : Integer)
-   is
+   procedure Raise_Constraint_Error (File : System.Address; Line : Integer) is
    begin
-      Raise_With_Location_And_Msg
-        (Constraint_Error_Def'Access, File, Line);
+      Raise_With_Location_And_Msg (Constraint_Error_Def'Access, File, Line);
    end Raise_Constraint_Error;
 
    --------------------------------
@@ -788,13 +805,14 @@ 
    --------------------------------
 
    procedure Raise_Constraint_Error_Msg
-     (File : System.Address;
-      Line : Integer;
-      Msg  : System.Address)
+     (File   : System.Address;
+      Line   : Integer;
+      Column : Integer;
+      Msg    : System.Address)
    is
    begin
       Raise_With_Location_And_Msg
-        (Constraint_Error_Def'Access, File, Line, Msg);
+        (Constraint_Error_Def'Access, File, Line, Column, Msg);
    end Raise_Constraint_Error_Msg;
 
    -------------------------
@@ -935,8 +953,7 @@ 
       Line : Integer)
    is
    begin
-      Raise_With_Location_And_Msg
-        (Program_Error_Def'Access, File, Line);
+      Raise_With_Location_And_Msg (Program_Error_Def'Access, File, Line);
    end Raise_Program_Error;
 
    -----------------------------
@@ -950,7 +967,7 @@ 
    is
    begin
       Raise_With_Location_And_Msg
-        (Program_Error_Def'Access, File, Line, Msg);
+        (Program_Error_Def'Access, File, Line, M => Msg);
    end Raise_Program_Error_Msg;
 
    -------------------------
@@ -962,8 +979,7 @@ 
       Line : Integer)
    is
    begin
-      Raise_With_Location_And_Msg
-        (Storage_Error_Def'Access, File, Line);
+      Raise_With_Location_And_Msg (Storage_Error_Def'Access, File, Line);
    end Raise_Storage_Error;
 
    -----------------------------
@@ -977,7 +993,7 @@ 
    is
    begin
       Raise_With_Location_And_Msg
-        (Storage_Error_Def'Access, File, Line, Msg);
+        (Storage_Error_Def'Access, File, Line, M => Msg);
    end Raise_Storage_Error_Msg;
 
    ---------------------------------
@@ -988,10 +1004,11 @@ 
      (E : Exception_Id;
       F : System.Address;
       L : Integer;
+      C : Integer := 0;
       M : System.Address := System.Null_Address)
    is
    begin
-      Exception_Data.Set_Exception_C_Msg (E, F, L, M);
+      Exception_Data.Set_Exception_C_Msg (E, F, L, C, M);
       Abort_Defer.all;
       Raise_Current_Excep (E);
    end Raise_With_Location_And_Msg;
@@ -1015,78 +1032,92 @@ 
       Raise_Current_Excep (E);
    end Raise_With_Msg;
 
+   -----------
+   -- Image --
+   -----------
+
+   function Image (Index : Integer) return String is
+      Result : constant String := Integer'Image (Index);
+   begin
+      if Result (1) = ' ' then
+         return Result (2 .. Result'Last);
+      else
+         return Result;
+      end if;
+   end Image;
+
    --------------------------------------
    -- Calls to Run-Time Check Routines --
    --------------------------------------
 
    procedure Rcheck_00 (File : System.Address; Line : Integer) is
    begin
-      Raise_Constraint_Error_Msg (File, Line, Rmsg_00'Address);
+      Raise_Constraint_Error_Msg (File, Line, 0, Rmsg_00'Address);
    end Rcheck_00;
 
    procedure Rcheck_01 (File : System.Address; Line : Integer) is
    begin
-      Raise_Constraint_Error_Msg (File, Line, Rmsg_01'Address);
+      Raise_Constraint_Error_Msg (File, Line, 0, Rmsg_01'Address);
    end Rcheck_01;
 
    procedure Rcheck_02 (File : System.Address; Line : Integer) is
    begin
-      Raise_Constraint_Error_Msg (File, Line, Rmsg_02'Address);
+      Raise_Constraint_Error_Msg (File, Line, 0, Rmsg_02'Address);
    end Rcheck_02;
 
    procedure Rcheck_03 (File : System.Address; Line : Integer) is
    begin
-      Raise_Constraint_Error_Msg (File, Line, Rmsg_03'Address);
+      Raise_Constraint_Error_Msg (File, Line, 0, Rmsg_03'Address);
    end Rcheck_03;
 
    procedure Rcheck_04 (File : System.Address; Line : Integer) is
    begin
-      Raise_Constraint_Error_Msg (File, Line, Rmsg_04'Address);
+      Raise_Constraint_Error_Msg (File, Line, 0, Rmsg_04'Address);
    end Rcheck_04;
 
    procedure Rcheck_05 (File : System.Address; Line : Integer) is
    begin
-      Raise_Constraint_Error_Msg (File, Line, Rmsg_05'Address);
+      Raise_Constraint_Error_Msg (File, Line, 0, Rmsg_05'Address);
    end Rcheck_05;
 
    procedure Rcheck_06 (File : System.Address; Line : Integer) is
    begin
-      Raise_Constraint_Error_Msg (File, Line, Rmsg_06'Address);
+      Raise_Constraint_Error_Msg (File, Line, 0, Rmsg_06'Address);
    end Rcheck_06;
 
    procedure Rcheck_07 (File : System.Address; Line : Integer) is
    begin
-      Raise_Constraint_Error_Msg (File, Line, Rmsg_07'Address);
+      Raise_Constraint_Error_Msg (File, Line, 0, Rmsg_07'Address);
    end Rcheck_07;
 
    procedure Rcheck_08 (File : System.Address; Line : Integer) is
    begin
-      Raise_Constraint_Error_Msg (File, Line, Rmsg_08'Address);
+      Raise_Constraint_Error_Msg (File, Line, 0, Rmsg_08'Address);
    end Rcheck_08;
 
    procedure Rcheck_09 (File : System.Address; Line : Integer) is
    begin
-      Raise_Constraint_Error_Msg (File, Line, Rmsg_09'Address);
+      Raise_Constraint_Error_Msg (File, Line, 0, Rmsg_09'Address);
    end Rcheck_09;
 
    procedure Rcheck_10 (File : System.Address; Line : Integer) is
    begin
-      Raise_Constraint_Error_Msg (File, Line, Rmsg_10'Address);
+      Raise_Constraint_Error_Msg (File, Line, 0, Rmsg_10'Address);
    end Rcheck_10;
 
    procedure Rcheck_11 (File : System.Address; Line : Integer) is
    begin
-      Raise_Constraint_Error_Msg (File, Line, Rmsg_11'Address);
+      Raise_Constraint_Error_Msg (File, Line, 0, Rmsg_11'Address);
    end Rcheck_11;
 
    procedure Rcheck_12 (File : System.Address; Line : Integer) is
    begin
-      Raise_Constraint_Error_Msg (File, Line, Rmsg_12'Address);
+      Raise_Constraint_Error_Msg (File, Line, 0, Rmsg_12'Address);
    end Rcheck_12;
 
    procedure Rcheck_13 (File : System.Address; Line : Integer) is
    begin
-      Raise_Constraint_Error_Msg (File, Line, Rmsg_13'Address);
+      Raise_Constraint_Error_Msg (File, Line, 0, Rmsg_13'Address);
    end Rcheck_13;
 
    procedure Rcheck_14 (File : System.Address; Line : Integer) is
@@ -1189,6 +1220,35 @@ 
       Raise_Storage_Error_Msg (File, Line, Rmsg_33'Address);
    end Rcheck_33;
 
+   procedure Rcheck_00_Ext (File : System.Address; Line, Column : Integer) is
+   begin
+      Raise_Constraint_Error_Msg (File, Line, Column, Rmsg_00'Address);
+   end Rcheck_00_Ext;
+
+   procedure Rcheck_05_Ext
+     (File : System.Address; Line, Column, Index, First, Last : Integer)
+   is
+      Msg : constant String :=
+              Rmsg_05 (Rmsg_05'First .. Rmsg_05'Last - 1) & ASCII.LF &
+              "index " & Image (Index) & " not in " & Image (First) &
+              ".." & Image (Last) & ASCII.NUL;
+
+   begin
+      Raise_Constraint_Error_Msg (File, Line, Column, Msg'Address);
+   end Rcheck_05_Ext;
+
+   procedure Rcheck_12_Ext
+     (File : System.Address; Line, Column, Index, First, Last : Integer)
+   is
+      Msg : constant String :=
+              Rmsg_12 (Rmsg_12'First .. Rmsg_12'Last - 1) & ASCII.LF &
+              "value " & Image (Index) & " not in " & Image (First) &
+              ".." & Image (Last) & ASCII.NUL;
+
+   begin
+      Raise_Constraint_Error_Msg (File, Line, Column, Msg'Address);
+   end Rcheck_12_Ext;
+
    -------------
    -- Reraise --
    -------------
Index: a-exexda.adb
===================================================================
--- a-exexda.adb	(revision 165687)
+++ a-exexda.adb	(working copy)
@@ -6,7 +6,7 @@ 
 --                                                                          --
 --                                 B o d y                                  --
 --                                                                          --
---          Copyright (C) 1992-2009, Free Software Foundation, Inc.         --
+--          Copyright (C) 1992-2010, 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- --
@@ -556,37 +556,31 @@ 
    -------------------------
 
    procedure Set_Exception_C_Msg
-     (Id   : Exception_Id;
-      Msg1 : System.Address;
-      Line : Integer        := 0;
-      Msg2 : System.Address := System.Null_Address)
+     (Id     : Exception_Id;
+      Msg1   : System.Address;
+      Line   : Integer        := 0;
+      Column : Integer        := 0;
+      Msg2   : System.Address := System.Null_Address)
    is
       Excep  : constant EOA := Get_Current_Excep.all;
-      Val    : Integer := Line;
       Remind : Integer;
-      Size   : Integer := 1;
       Ptr    : Natural;
 
-   begin
-      Exception_Propagation.Setup_Exception (Excep, Excep);
-      Excep.Exception_Raised := False;
-      Excep.Id               := Id;
-      Excep.Num_Tracebacks   := 0;
-      Excep.Pid              := Local_Partition_ID;
-      Excep.Msg_Length       := 0;
-      Excep.Cleanup_Flag     := False;
+      procedure Append_Number (Number : Integer);
+      --  Append given number to Excep.Msg
 
-      while To_Ptr (Msg1) (Excep.Msg_Length + 1) /= ASCII.NUL
-        and then Excep.Msg_Length < Exception_Msg_Max_Length
-      loop
-         Excep.Msg_Length := Excep.Msg_Length + 1;
-         Excep.Msg (Excep.Msg_Length) := To_Ptr (Msg1) (Excep.Msg_Length);
-      end loop;
+      -------------------
+      -- Append_Number --
+      -------------------
 
-      --  Append line number if present
+      procedure Append_Number (Number : Integer) is
+         Val  : Integer := Number;
+         Size : Integer := 1;
+      begin
+         if Number <= 0 then
+            return;
+         end if;
 
-      if Line > 0 then
-
          --  Compute the number of needed characters
 
          while Val > 0 loop
@@ -599,7 +593,7 @@ 
          if Excep.Msg_Length <= Exception_Msg_Max_Length - Size then
             Excep.Msg (Excep.Msg_Length + 1) := ':';
             Excep.Msg_Length := Excep.Msg_Length + Size;
-            Val := Line;
+            Val := Number;
             Size := 0;
 
             while Val > 0 loop
@@ -610,8 +604,27 @@ 
                Size := Size + 1;
             end loop;
          end if;
-      end if;
+      end Append_Number;
 
+   begin
+      Exception_Propagation.Setup_Exception (Excep, Excep);
+      Excep.Exception_Raised := False;
+      Excep.Id               := Id;
+      Excep.Num_Tracebacks   := 0;
+      Excep.Pid              := Local_Partition_ID;
+      Excep.Msg_Length       := 0;
+      Excep.Cleanup_Flag     := False;
+
+      while To_Ptr (Msg1) (Excep.Msg_Length + 1) /= ASCII.NUL
+        and then Excep.Msg_Length < Exception_Msg_Max_Length
+      loop
+         Excep.Msg_Length := Excep.Msg_Length + 1;
+         Excep.Msg (Excep.Msg_Length) := To_Ptr (Msg1) (Excep.Msg_Length);
+      end loop;
+
+      Append_Number (Line);
+      Append_Number (Column);
+
       --  Append second message if present
 
       if Msg2 /= System.Null_Address
Index: opt.ads
===================================================================
--- opt.ads	(revision 165694)
+++ opt.ads	(working copy)
@@ -454,10 +454,16 @@ 
    --  It is used to set Warn_On_Exception_Propagation True if the restriction
    --  No_Exception_Propagation is set.
 
+   Exception_Extra_Info : Boolean := False;
+   --  GNAT
+   --  True when switch -gnateE is used. When True, generate extra information
+   --  associated with exception messages (in particular range and index
+   --  checks).
+
    Exception_Locations_Suppressed : Boolean := False;
    --  GNAT
-   --  This flag is set True if a Suppress_Exception_Locations configuration
-   --  pragma is currently active.
+   --  Set to True if a Suppress_Exception_Locations configuration pragma is
+   --  currently active.
 
    type Exception_Mechanism_Type is
    --  Determines the handling of exceptions. See Exp_Ch11 for details
Index: gcc-interface/utils.c
===================================================================
--- gcc-interface/utils.c	(revision 165687)
+++ gcc-interface/utils.c	(working copy)
@@ -79,6 +79,9 @@ 
 /* Functions to call for each of the possible raise reasons.  */
 tree gnat_raise_decls[(int) LAST_REASON_CODE + 1];
 
+/* Functions to call with extra info for each of the possible raise reasons.  */
+tree gnat_raise_decls_ext[(int) LAST_REASON_CODE + 1];
+
 /* Forward declarations for handlers of attributes.  */
 static tree handle_const_attribute (tree *, tree, tree, int, bool *);
 static tree handle_nothrow_attribute (tree *, tree, tree, int, bool *);
Index: gcc-interface/utils2.c
===================================================================
--- gcc-interface/utils2.c	(revision 165687)
+++ gcc-interface/utils2.c	(working copy)
@@ -1519,6 +1519,113 @@ 
 			       filename),
 		       build_int_cst (NULL_TREE, line_number));
 }
+
+/* Similar to build_call_raise, for an index or range check exception as
+   determined by MSG, with extra information generated of the form
+   "INDEX out of range FIRST..LAST".  */
+
+tree
+build_call_raise_range (int msg, Node_Id gnat_node,
+			tree index, tree first, tree last)
+{
+  tree call;
+  tree fndecl = gnat_raise_decls_ext[msg];
+  tree filename;
+  int line_number, column_number;
+  const char *str;
+  int len;
+
+  str
+    = (Debug_Flag_NN || Exception_Locations_Suppressed)
+      ? ""
+      : (gnat_node != Empty && Sloc (gnat_node) != No_Location)
+        ? IDENTIFIER_POINTER
+          (get_identifier (Get_Name_String
+			   (Debug_Source_Name
+			    (Get_Source_File_Index (Sloc (gnat_node))))))
+        : ref_filename;
+
+  len = strlen (str);
+  filename = build_string (len, str);
+  if (gnat_node != Empty && Sloc (gnat_node) != No_Location)
+    {
+      line_number = Get_Logical_Line_Number (Sloc (gnat_node));
+      column_number = Get_Column_Number (Sloc (gnat_node));
+    }
+  else
+    {
+      line_number = input_line;
+      column_number = 0;
+    }
+
+  TREE_TYPE (filename) = build_array_type (unsigned_char_type_node,
+					   build_index_type (size_int (len)));
+
+  call = build_call_nary (TREE_TYPE (TREE_TYPE (fndecl)),
+                          build_unary_op (ADDR_EXPR, NULL_TREE, fndecl),
+                          6,
+			  build1 (ADDR_EXPR,
+				  build_pointer_type (unsigned_char_type_node),
+				  filename),
+			  build_int_cst (NULL_TREE, line_number),
+			  build_int_cst (NULL_TREE, column_number),
+			  convert (integer_type_node, index),
+			  convert (integer_type_node, first),
+			  convert (integer_type_node, last));
+  TREE_SIDE_EFFECTS (call) = 1;
+  return call;
+}
+
+/* Similar to build_call_raise, with extra information about the column
+   where the check failed.  */
+
+tree
+build_call_raise_column (int msg, Node_Id gnat_node)
+{
+  tree fndecl = gnat_raise_decls_ext[msg];
+  tree call;
+  tree filename;
+  int line_number, column_number;
+  const char *str;
+  int len;
+
+  str
+    = (Debug_Flag_NN || Exception_Locations_Suppressed)
+      ? ""
+      : (gnat_node != Empty && Sloc (gnat_node) != No_Location)
+        ? IDENTIFIER_POINTER
+          (get_identifier (Get_Name_String
+			   (Debug_Source_Name
+			    (Get_Source_File_Index (Sloc (gnat_node))))))
+        : ref_filename;
+
+  len = strlen (str);
+  filename = build_string (len, str);
+  if (gnat_node != Empty && Sloc (gnat_node) != No_Location)
+    {
+      line_number = Get_Logical_Line_Number (Sloc (gnat_node));
+      column_number = Get_Column_Number (Sloc (gnat_node));
+    }
+  else
+    {
+      line_number = input_line;
+      column_number = 0;
+    }
+
+  TREE_TYPE (filename) = build_array_type (unsigned_char_type_node,
+					   build_index_type (size_int (len)));
+
+  call = build_call_nary (TREE_TYPE (TREE_TYPE (fndecl)),
+                          build_unary_op (ADDR_EXPR, NULL_TREE, fndecl),
+                          3,
+			  build1 (ADDR_EXPR,
+				  build_pointer_type (unsigned_char_type_node),
+				  filename),
+			  build_int_cst (NULL_TREE, line_number),
+			  build_int_cst (NULL_TREE, column_number));
+  TREE_SIDE_EFFECTS (call) = 1;
+  return call;
+}
 
 /* qsort comparer for the bit positions of two constructor elements
    for record components.  */
Index: gcc-interface/gigi.h
===================================================================
--- gcc-interface/gigi.h	(revision 165687)
+++ gcc-interface/gigi.h	(working copy)
@@ -366,8 +366,19 @@ 
   ADT_all_others_decl,
   ADT_LAST};
 
+/* Define kind of exception information associated with raise statements.  */
+enum exception_info_kind
+{
+  /* Simple exception information: file:line.  */
+  exception_simple,
+  /* Range exception information: file:line + index, first, last.  */
+  exception_range,
+  /* Column exception information: file:line:column.  */
+  exception_column};
+
 extern GTY(()) tree gnat_std_decls[(int) ADT_LAST];
 extern GTY(()) tree gnat_raise_decls[(int) LAST_REASON_CODE + 1];
+extern GTY(()) tree gnat_raise_decls_ext[(int) LAST_REASON_CODE + 1];
 
 #define longest_float_type_node gnat_std_decls[(int) ADT_longest_float_type]
 #define except_type_node gnat_std_decls[(int) ADT_except_type]
@@ -790,6 +801,16 @@ 
     (N_Raise_{Constraint,Storage,Program}_Error).  */
 extern tree build_call_raise (int msg, Node_Id gnat_node, char kind);
 
+/* Similar to build_call_raise, for an index or range check exception as
+   determined by MSG, with extra information generated of the form
+   "INDEX out of range FIRST..LAST".  */
+extern tree build_call_raise_range (int msg, Node_Id gnat_node,
+				    tree index, tree first, tree last);
+
+/* Similar to build_call_raise, with extra information about the column
+   where the check failed.  */
+extern tree build_call_raise_column (int msg, Node_Id gnat_node);
+
 /* Return a CONSTRUCTOR of TYPE whose elements are V.  This is not the
    same as build_constructor in the language-independent tree.c.  */
 extern tree gnat_build_constructor (tree type, VEC(constructor_elt,gc) *v);
Index: gcc-interface/trans.c
===================================================================
--- gcc-interface/trans.c	(revision 165687)
+++ gcc-interface/trans.c	(working copy)
@@ -203,6 +203,7 @@ 
 static void set_expr_location_from_node (tree, Node_Id);
 static void set_gnu_expr_location_from_node (tree, Node_Id);
 static int lvalue_required_p (Node_Id, tree, bool, bool, bool);
+static tree build_raise_check (int, tree, enum exception_info_kind);
 
 /* Hooks for debug info back-ends, only supported and used in a restricted set
    of configurations.  */
@@ -467,34 +468,22 @@ 
 
       for (i = 0; i < (int) ARRAY_SIZE (gnat_raise_decls); i++)
 	gnat_raise_decls[i] = decl;
+      TREE_THIS_VOLATILE (decl) = 1;
+      TREE_SIDE_EFFECTS (decl) = 1;
+      TREE_TYPE (decl)
+	= build_qualified_type (TREE_TYPE (decl), TYPE_QUAL_VOLATILE);
     }
   else
-    /* Otherwise, make one decl for each exception reason.  */
-    for (i = 0; i < (int) ARRAY_SIZE (gnat_raise_decls); i++)
-      {
-	char name[17];
-
-	sprintf (name, "__gnat_rcheck_%.2d", i);
-	gnat_raise_decls[i]
-	  = create_subprog_decl
-	    (get_identifier (name), NULL_TREE,
-	     build_function_type (void_type_node,
-				  tree_cons (NULL_TREE,
-					     build_pointer_type
-					     (unsigned_char_type_node),
-					     tree_cons (NULL_TREE,
-							integer_type_node,
-							t))),
-	     NULL_TREE, false, true, true, NULL, Empty);
-      }
-
-  for (i = 0; i < (int) ARRAY_SIZE (gnat_raise_decls); i++)
     {
-      TREE_THIS_VOLATILE (gnat_raise_decls[i]) = 1;
-      TREE_SIDE_EFFECTS (gnat_raise_decls[i]) = 1;
-      TREE_TYPE (gnat_raise_decls[i])
-	= build_qualified_type (TREE_TYPE (gnat_raise_decls[i]),
-				TYPE_QUAL_VOLATILE);
+      /* Otherwise, make one decl for each exception reason.  */
+      for (i = 0; i < (int) ARRAY_SIZE (gnat_raise_decls); i++)
+	gnat_raise_decls[i] = build_raise_check (i, t, exception_simple);
+      for (i = 0; i < (int) ARRAY_SIZE (gnat_raise_decls_ext); i++)
+	gnat_raise_decls_ext[i]
+	  = build_raise_check (i, t,
+			       i == CE_Index_Check_Failed
+			       || i == CE_Range_Check_Failed ?
+			       exception_range : exception_column);
     }
 
   /* Set the types that GCC and Gigi use from the front end.  */
@@ -640,6 +629,53 @@ 
   error_gnat_node = Empty;
 }
 
+/* Return a subprogram decl corresponding to __gnat_rcheck_xx for the given
+   CHECK (if EXTENDED is false), or __gnat_rcheck_xx_ext (if EXTENDED is
+   true).  */
+
+static tree
+build_raise_check (int check, tree void_tree, enum exception_info_kind kind)
+{
+  char name[21];
+  tree result;
+
+  if (kind != exception_simple)
+    {
+      sprintf (name, "__gnat_rcheck_%.2d_ext", check);
+      result = create_subprog_decl
+	(get_identifier (name), NULL_TREE,
+	 build_function_type
+	   (void_type_node,
+	    tree_cons
+	      (NULL_TREE,
+	       build_pointer_type (unsigned_char_type_node),
+	       tree_cons (NULL_TREE, integer_type_node,
+		 tree_cons (NULL_TREE, integer_type_node,
+		   kind == exception_column ? void_tree :
+		     tree_cons (NULL_TREE, integer_type_node,
+		       tree_cons (NULL_TREE, integer_type_node, void_tree)))))),
+	 NULL_TREE, false, true, true, NULL, Empty);
+    }
+  else
+    {
+      sprintf (name, "__gnat_rcheck_%.2d", check);
+      result = create_subprog_decl
+	(get_identifier (name), NULL_TREE,
+	 build_function_type
+	   (void_type_node,
+	    tree_cons
+	      (NULL_TREE,
+	       build_pointer_type (unsigned_char_type_node),
+	       tree_cons (NULL_TREE, integer_type_node, void_tree))),
+	 NULL_TREE, false, true, true, NULL, Empty);
+    }
+  TREE_THIS_VOLATILE (result) = 1;
+  TREE_SIDE_EFFECTS (result) = 1;
+  TREE_TYPE (result)
+    = build_qualified_type (TREE_TYPE (result), TYPE_QUAL_VOLATILE);
+  return result;
+}
+
 /* Return a positive value if an lvalue is required for GNAT_NODE, which is
    an N_Attribute_Reference.  */
 
@@ -5457,30 +5493,81 @@ 
     case N_Raise_Constraint_Error:
     case N_Raise_Program_Error:
     case N_Raise_Storage_Error:
-      if (type_annotate_only)
-	{
-	  gnu_result = alloc_stmt_list ();
-	  break;
-	}
+      {
+	int reason = UI_To_Int (Reason (gnat_node));
+	Node_Id cond = Condition (gnat_node);
+	bool handled = false;
 
-      gnu_result_type = get_unpadded_type (Etype (gnat_node));
-      gnu_result
-	= build_call_raise (UI_To_Int (Reason (gnat_node)), gnat_node, kind);
+	if (type_annotate_only)
+	  {
+	    gnu_result = alloc_stmt_list ();
+	    break;
+	  }
 
-      /* If the type is VOID, this is a statement, so we need to
-	 generate the code for the call.  Handle a Condition, if there
-	 is one.  */
-      if (TREE_CODE (gnu_result_type) == VOID_TYPE)
-	{
-	  set_expr_location_from_node (gnu_result, gnat_node);
+        gnu_result_type = get_unpadded_type (Etype (gnat_node));
 
-	  if (Present (Condition (gnat_node)))
+	if (Exception_Extra_Info
+	    && !No_Exception_Handlers_Set ()
+	    && !get_exception_label (kind)
+	    && TREE_CODE (gnu_result_type) == VOID_TYPE
+	    && Present (cond))
+	  {
+	    if (reason == CE_Access_Check_Failed)
+	      {
+		handled = true;
+		gnu_result = build_call_raise_column (reason, gnat_node);
+	      }
+	    else if ((reason == CE_Index_Check_Failed
+		      || reason == CE_Range_Check_Failed)
+		     && Nkind (cond) == N_Op_Not
+		     && Nkind (Right_Opnd (cond)) == N_In
+		     && Nkind (Right_Opnd (Right_Opnd (cond))) == N_Range)
+	      {
+		Node_Id op = Right_Opnd (cond);  /* N_In node */
+		Node_Id index = Left_Opnd (op);
+		Node_Id type = Etype (index);
+
+		if (Is_Type (type)
+		    && Known_Esize (type)
+		    && UI_To_Int (Esize (type)) <= 32)
+		  {
+		    handled = true;
+		    gnu_result = build_call_raise_range
+		      (reason, gnat_node,
+		       gnat_to_gnu (index),                         /* index */
+		       gnat_to_gnu (Low_Bound (Right_Opnd (op))),   /* first */
+		       gnat_to_gnu (High_Bound (Right_Opnd (op)))); /* last  */
+		  }
+	      }
+	  }
+
+	if (handled)
+	  {
+	    set_expr_location_from_node (gnu_result, gnat_node);
 	    gnu_result = build3 (COND_EXPR, void_type_node,
-				 gnat_to_gnu (Condition (gnat_node)),
+	    			 gnat_to_gnu (cond),
 				 gnu_result, alloc_stmt_list ());
-	}
-      else
-	gnu_result = build1 (NULL_EXPR, gnu_result_type, gnu_result);
+	  }
+	else
+	  {
+	    gnu_result = build_call_raise (reason, gnat_node, kind);
+
+	    /* If the type is VOID, this is a statement, so we need to
+	       generate the code for the call.  Handle a Condition, if there
+	       is one.  */
+	    if (TREE_CODE (gnu_result_type) == VOID_TYPE)
+	      {
+		set_expr_location_from_node (gnu_result, gnat_node);
+
+		if (Present (cond))
+		  gnu_result = build3 (COND_EXPR, void_type_node,
+				       gnat_to_gnu (cond),
+				       gnu_result, alloc_stmt_list ());
+	      }
+	    else
+	      gnu_result = build1 (NULL_EXPR, gnu_result_type, gnu_result);
+	  }
+      }
       break;
 
     case N_Validate_Unchecked_Conversion: