Bootstrapped and regression tested on x86_64.
Add reason string to compiler emitted traps.
For traps generated by the compiler, add a short string stating
the reason. This string will be shown with -Wtrap when the trap
is actually emitted.
gcc/ChangeLog:
* builtins.cc (expand_builtin_trap): Add string argument.
(expand_builtin): Add reasons for traps.
(expand_builtin_object_size): Don't emit message after error.
* expr.cc (expand_assignment): Add reason for trap.
* stmt.cc (expand_sjlj_dispatch_table): Add reason for trap.
* ubsan.cc (ubsan_build_string): New function.
(ubsan_build_string_ptr): New function.
(ubsan_trap): New functions.
(ubsan_source_location): Use ubsan_build_string_ptr.
(ubsan_type_descriptor): Use ubsan_build_string.
(ubsan_expand_bounds_ifn): Use ubsan_trap.
(ubsan_expand_bounds_null): Dito.
(ubsan_expand_objsize_ifn): Dito.
(ubsan_expand_ptr_ifn): Dito.
(instrument_bool_enum_load): Dito.
(instrument_nonnull_arg): Dito.
(instrument_nonnull_return): Dito.
(instrument_builtin): Dito.
(ubsan_build_overflow_builtin): Add message.
(ubsan_instrument_float_case): Dito.
gcc/testsuite/ChangeLog:
* gcc.dg/Wtrap-2.c: New test.
diff --git a/gcc/builtins.cc b/gcc/builtins.cc
index de5c96f3a25..2e3ac9df86d 100644
--- a/gcc/builtins.cc
+++ b/gcc/builtins.cc
@@ -5968,10 +5968,10 @@ expand_builtin_trap_no_msg (void)
/* Expand a call to __builtin_trap. */
void
-expand_builtin_trap ()
+expand_builtin_trap (const char *reason)
{
if (warn_trap)
- warning_at (input_location, OPT_Wtrap, "trap generated");
+ warning_at (input_location, OPT_Wtrap, "trap generated: \"%.99s\"",
reason);
return expand_builtin_trap_no_msg ();
}
@@ -8448,8 +8448,11 @@ expand_builtin (tree exp, rtx target, rtx subtarget,
machine_mode mode,
return const0_rtx;
case BUILT_IN_TRAP:
+ expand_builtin_trap ("builtin");
+ return const0_rtx;
+
case BUILT_IN_UNREACHABLE_TRAP:
- expand_builtin_trap ();
+ expand_builtin_trap ("unreachable");
return const0_rtx;
case BUILT_IN_UNREACHABLE:
@@ -11554,7 +11557,7 @@ expand_builtin_object_size (tree exp)
{
error ("first argument of %qD must be a pointer, second integer
constant",
fndecl);
- expand_builtin_trap ();
+ expand_builtin_trap_no_msg ();
return const0_rtx;
}
@@ -11567,7 +11570,7 @@ expand_builtin_object_size (tree exp)
{
error ("last argument of %qD is not integer constant between 0 and 3",
fndecl);
- expand_builtin_trap ();
+ expand_builtin_trap_no_msg ();
return const0_rtx;
}
diff --git a/gcc/builtins.h b/gcc/builtins.h
index 5a553a9c836..ae4ba4a9b96 100644
--- a/gcc/builtins.h
+++ b/gcc/builtins.h
@@ -129,7 +129,7 @@ extern tree std_build_builtin_va_list (void);
extern tree std_fn_abi_va_list (tree);
extern tree std_canonical_va_list_type (tree);
extern void std_expand_builtin_va_start (tree, rtx);
-extern void expand_builtin_trap (void);
+extern void expand_builtin_trap (const char *);
extern void expand_ifn_atomic_bit_test_and (gcall *);
extern void expand_ifn_atomic_compare_exchange (gcall *);
extern void expand_ifn_atomic_op_fetch_cmp_0 (gcall *);
diff --git a/gcc/expr.cc b/gcc/expr.cc
index 4a699101bb5..c6fc3b25f42 100644
--- a/gcc/expr.cc
+++ b/gcc/expr.cc
@@ -6102,7 +6102,7 @@ expand_assignment (tree to, tree from, bool nontemporal)
user code. Translate this to a trap instead of ICEing. */
if (TREE_CODE (offset) == INTEGER_CST)
{
- expand_builtin_trap ();
+ expand_builtin_trap ("invalid offset");
to_rtx = gen_rtx_MEM (BLKmode, const0_rtx);
}
/* Else spill for variable offset to the destination. We expect
diff --git a/gcc/stmt.cc b/gcc/stmt.cc
index 7942aa3e484..2e95b207603 100644
--- a/gcc/stmt.cc
+++ b/gcc/stmt.cc
@@ -1393,7 +1393,7 @@ expand_sjlj_dispatch_table (rtx dispatch_index,
}
/* Dispatching something not handled? Trap! */
- expand_builtin_trap ();
+ expand_builtin_trap ("dispatch not handled");
reorder_insns (NEXT_INSN (before_case), get_last_insn (), before_case);
diff --git a/gcc/testsuite/gcc.dg/Wtrap-2.c b/gcc/testsuite/gcc.dg/Wtrap-2.c
new file mode 100644
index 00000000000..ce2e596d947
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/Wtrap-2.c
@@ -0,0 +1,13 @@
+/* { dg-do compile } */
+/* { dg-options "-Wtrap -fsanitize=bounds -fsanitize-trap=bounds" } */
+
+void foo(int n, char (*buf)[n])
+{
+ (*buf)[10] = 1; /* { dg-warning "trap generated:
\"bounds (sanitizer)\"" } */
+}
+
+void bar()
+{
+ __builtin_unreachable(); /* { dg-warning "trap generated:
\"unreachable\"" } */
+}
+
diff --git a/gcc/ubsan.cc b/gcc/ubsan.cc
index 6d748258b1e..801f4c7830e 100644
--- a/gcc/ubsan.cc
+++ b/gcc/ubsan.cc
@@ -303,6 +303,35 @@ ubsan_get_source_location_type (void)
return ret;
}
+
+static tree
+ubsan_build_string (const char *cstr)
+{
+ size_t len = strlen (cstr) + 1;
+ tree str = build_string (len, cstr);
+ TREE_TYPE (str) = build_array_type_nelts (char_type_node, len);
+ TREE_READONLY (str) = 1;
+ TREE_STATIC (str) = 1;
+ return str;
+}
+
+static tree
+ubsan_build_string_ptr (const char *cstr)
+{
+ return build_fold_addr_expr (ubsan_build_string (cstr));
+}
+
+/* Helper routine that expands a trap with a message. */
+
+static gimple *
+ubsan_trap (const char *cstr)
+{
+ return gimple_build_call (builtin_decl_explicit (BUILT_IN_TRAP_MSG),
+ 1, ubsan_build_string_ptr (cstr));
+}
+
+
+
/* Helper routine that returns a CONSTRUCTOR of __ubsan_source_location
type with its fields filled from a location_t LOC. */
@@ -323,12 +352,7 @@ ubsan_source_location (location_t loc)
else
{
/* Fill in the values from LOC. */
- size_t len = strlen (xloc.file) + 1;
- str = build_string (len, xloc.file);
- TREE_TYPE (str) = build_array_type_nelts (char_type_node, len);
- TREE_READONLY (str) = 1;
- TREE_STATIC (str) = 1;
- str = build_fold_addr_expr (str);
+ str = ubsan_build_string_ptr (xloc.file);
}
tree ctor = build_constructor_va (type, 3, NULL_TREE, str, NULL_TREE,
build_int_cst (unsigned_type_node,
@@ -542,11 +566,7 @@ ubsan_type_descriptor (tree type, enum ubsan_print_style
pstyle)
/* Create a new VAR_DECL of type descriptor. */
const char *tmp = pp_formatted_text (&pretty_name);
- size_t len = strlen (tmp) + 1;
- tree str = build_string (len, tmp);
- TREE_TYPE (str) = build_array_type_nelts (char_type_node, len);
- TREE_READONLY (str) = 1;
- TREE_STATIC (str) = 1;
+ tree str = ubsan_build_string (tmp);
decl = build_decl (UNKNOWN_LOCATION, VAR_DECL,
generate_internal_label ("Lubsan_type"), dtype);
@@ -786,7 +806,7 @@ ubsan_expand_bounds_ifn (gimple_stmt_iterator *gsi)
/* Generate __ubsan_handle_out_of_bounds call. */
*gsi = gsi_after_labels (then_bb);
if (flag_sanitize_trap & SANITIZE_BOUNDS)
- g = gimple_build_call (builtin_decl_explicit (BUILT_IN_TRAP), 0);
+ g = ubsan_trap ("bounds (sanitizer)");
else
{
tree data
@@ -902,7 +922,7 @@ ubsan_expand_null_ifn (gimple_stmt_iterator *gsip)
/* Put the ubsan builtin call into the newly created BB. */
if (flag_sanitize_trap & ((check_align ? SANITIZE_ALIGNMENT + 0 : 0)
| (check_null ? SANITIZE_NULL + 0 : 0)))
- g = gimple_build_call (builtin_decl_implicit (BUILT_IN_TRAP), 0);
+ g = ubsan_trap ("alignment / null (sanitizer)");
else
{
enum built_in_function bcode
@@ -1072,7 +1092,7 @@ ubsan_expand_objsize_ifn (gimple_stmt_iterator *gsi)
/* Generate __ubsan_handle_type_mismatch call. */
if (flag_sanitize_trap & SANITIZE_OBJECT_SIZE)
- g = gimple_build_call (builtin_decl_explicit (BUILT_IN_TRAP), 0);
+ g = ubsan_trap ("object size (sanitizer)");
else
{
tree data
@@ -1218,7 +1238,7 @@ ubsan_expand_ptr_ifn (gimple_stmt_iterator *gsip)
/* Put the ubsan builtin call into the newly created BB. */
if (flag_sanitize_trap & SANITIZE_POINTER_OVERFLOW)
- g = gimple_build_call (builtin_decl_implicit (BUILT_IN_TRAP), 0);
+ g = ubsan_trap ("pointer overflow (sanitizer)");
else
{
enum built_in_function bcode
@@ -1601,8 +1621,11 @@ ubsan_build_overflow_builtin (tree_code code, location_t
loc, tree lhstype,
tree op0, tree op1, tree *datap)
{
if (flag_sanitize_trap & SANITIZE_SI_OVERFLOW)
- return build_call_expr_loc (loc, builtin_decl_explicit (BUILT_IN_TRAP), 0);
-
+ {
+ tree reason = ubsan_build_string_ptr ("signed overflow (sanitizer)");
+ return build_call_expr_loc (loc, builtin_decl_explicit
(BUILT_IN_TRAP_MSG),
+ 1, reason);
+ }
tree data;
if (datap && *datap)
data = *datap;
@@ -1830,7 +1853,7 @@ instrument_bool_enum_load (gimple_stmt_iterator *gsi)
gsi2 = gsi_after_labels (then_bb);
if (flag_sanitize_trap & (TREE_CODE (type) == BOOLEAN_TYPE
? SANITIZE_BOOL : SANITIZE_ENUM))
- g = gimple_build_call (builtin_decl_explicit (BUILT_IN_TRAP), 0);
+ g = ubsan_trap ("bool / enum (sanitizer)");
else
{
tree data = ubsan_create_data ("__ubsan_invalid_value_data", 1, &loc,
@@ -1991,7 +2014,11 @@ ubsan_instrument_float_cast (location_t loc, tree type,
tree expr)
return NULL_TREE;
if (flag_sanitize_trap & SANITIZE_FLOAT_CAST)
- fn = build_call_expr_loc (loc, builtin_decl_explicit (BUILT_IN_TRAP), 0);
+ {
+ tree reason = ubsan_build_string_ptr ("float cast (sanitizer)");
+ fn = build_call_expr_loc (loc, builtin_decl_explicit (BUILT_IN_TRAP_MSG),
+ 1, reason);
+ }
else
{
location_t *loc_ptr = NULL;
@@ -2102,7 +2129,7 @@ instrument_nonnull_arg (gimple_stmt_iterator *gsi)
*gsi = gsi_after_labels (then_bb);
}
if (flag_sanitize_trap & SANITIZE_NONNULL_ATTRIBUTE)
- g = gimple_build_call (builtin_decl_explicit (BUILT_IN_TRAP), 0);
+ g = ubsan_trap ("nonnull (sanitizer)");
else
{
tree data = ubsan_create_data ("__ubsan_nonnull_arg_data",
@@ -2158,7 +2185,7 @@ instrument_nonnull_return (gimple_stmt_iterator *gsi)
*gsi = gsi_after_labels (then_bb);
if (flag_sanitize_trap & SANITIZE_RETURNS_NONNULL_ATTRIBUTE)
- g = gimple_build_call (builtin_decl_explicit (BUILT_IN_TRAP), 0);
+ g = ubsan_trap ("returns nonnull (sanitizer)");
else
{
tree data = ubsan_create_data ("__ubsan_nonnull_return_data",
@@ -2404,7 +2431,7 @@ instrument_builtin (gimple_stmt_iterator *gsi)
*gsi = gsi_after_labels (then_bb);
if (flag_sanitize_trap & SANITIZE_BUILTIN)
- g = gimple_build_call (builtin_decl_explicit (BUILT_IN_TRAP), 0);
+ g = ubsan_trap ("builtin (sanitizer)");
else
{
tree t = build_int_cst (unsigned_char_type_node, kind);