===================================================================
@@ -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' =>
===================================================================
@@ -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;
===================================================================
@@ -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");
===================================================================
@@ -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;
===================================================================
@@ -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.
===================================================================
@@ -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)));
===================================================================
@@ -6,7 +6,7 @@
-- --
-- B o d y --
-- --
+-- 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;
===================================================================
@@ -6,7 +6,7 @@
-- --
-- B o d y --
-- --
+-- 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 --
-------------
===================================================================
@@ -6,7 +6,7 @@
-- --
-- B o d y --
-- --
+-- 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
===================================================================
@@ -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
===================================================================
@@ -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 *);
===================================================================
@@ -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. */
===================================================================
@@ -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);
===================================================================
@@ -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: