(forgot to add the list)


For the previous version, there was a suggestion to add additional
context.  This adds a new builtin where a context string can be
provided.  The second patch in the series adds messages for compiler
generated traps.

Bootstrapped and regression tested on x86_64.



    Add warning option that warns when a trap is generated.
    
    This adds an option -Wtrap for a warning that is emitted when
    a trap is generated.  It also adds a new built-in function
    __builtin_trap_msg that takes a string argument that is then
    added to the warning.
    
    gcc/ChangeLog:
            * common.opt (Wtrap): Add warning.
            * builtin-types.def: Add new function type.
            * builtins.cc (expand_builtin_trap): Add warning.
            (expand_builtin_trap_no_msg): New function.
            (expand_builtin): Add BUILT_IN_TRAP_MSG.
            (is_inexpensive_builtin): Add BUILT_IN_TRAP_MSG.
            * builtins.def: Add BUILT_IN_TRAP_MSG.
            * tree.cc (build_common_builtin_nodes): Add support.
            * ipa-devirt.cc (possible_polymorphic_call_target_p): Adapt.
            * tree-cfg.cc (pass_warn_function_return::execute): Adapt.
            * doc/invoke.texi (Wtrap): Document warning.
            * doc/extend.texi (__builtin_trap_msg): Document built-in.
    
    gcc/testsuite/ChangeLog:
            * gcc.dg/Wtrap.c: New test.

diff --git a/gcc/builtin-types.def b/gcc/builtin-types.def
index 9583d30dfc0..c540b4729ce 100644
--- a/gcc/builtin-types.def
+++ b/gcc/builtin-types.def
@@ -366,6 +366,7 @@ DEF_FUNCTION_TYPE_1 (BT_FN_PTR_PTR, BT_PTR, BT_PTR)
 DEF_FUNCTION_TYPE_1 (BT_FN_VOID_VALIST_REF, BT_VOID, BT_VALIST_REF)
 DEF_FUNCTION_TYPE_1 (BT_FN_VOID_INT, BT_VOID, BT_INT)
 DEF_FUNCTION_TYPE_1 (BT_FN_VOID_BOOL, BT_VOID, BT_BOOL)
+DEF_FUNCTION_TYPE_1 (BT_FN_VOID_CONST_STRING, BT_VOID, BT_CONST_STRING)
 DEF_FUNCTION_TYPE_1 (BT_FN_FLOAT_CONST_STRING, BT_FLOAT, BT_CONST_STRING)
 DEF_FUNCTION_TYPE_1 (BT_FN_DOUBLE_CONST_STRING, BT_DOUBLE, BT_CONST_STRING)
 DEF_FUNCTION_TYPE_1 (BT_FN_LONGDOUBLE_CONST_STRING,
diff --git a/gcc/builtins.cc b/gcc/builtins.cc
index de3e389c5d4..de5c96f3a25 100644
--- a/gcc/builtins.cc
+++ b/gcc/builtins.cc
@@ -5941,8 +5941,9 @@ expand_builtin_assume_aligned (tree exp, rtx target)
   return target;
 }
 
-void
-expand_builtin_trap (void)
+
+static void
+expand_builtin_trap_no_msg (void)
 {
   if (targetm.have_trap ())
     {
@@ -5963,11 +5964,25 @@ expand_builtin_trap (void)
   emit_barrier ();
 }
 
+
+/* Expand a call to __builtin_trap.  */
+
+void
+expand_builtin_trap ()
+{
+  if (warn_trap)
+    warning_at (input_location, OPT_Wtrap, "trap generated");
+
+  return expand_builtin_trap_no_msg ();
+}
+
+
 /* Expand a call to __builtin_unreachable.  We do nothing except emit
    a barrier saying that control flow will not pass here.
 
    It is the responsibility of the program being compiled to ensure
    that control flow does never reach __builtin_unreachable.  */
+
 static void
 expand_builtin_unreachable (void)
 {
@@ -8419,6 +8434,19 @@ expand_builtin (tree exp, rtx target, rtx subtarget, 
machine_mode mode,
        }
       break;
 
+    case BUILT_IN_TRAP_MSG:
+      {
+       tree arg = CALL_EXPR_ARG (exp, 0);
+       if (TREE_CODE (arg) != ADDR_EXPR
+           || TREE_CODE (TREE_OPERAND (arg, 0)) != STRING_CST)
+         error ("%<__builtin_trap_msg%> argument must be a string literal");
+       else if (warn_trap)
+         warning_at (input_location, OPT_Wtrap, "trap generated: %E",
+                     TREE_OPERAND (arg, 0));
+      }
+      expand_builtin_trap_no_msg ();
+      return const0_rtx;
+
     case BUILT_IN_TRAP:
     case BUILT_IN_UNREACHABLE_TRAP:
       expand_builtin_trap ();
@@ -12382,6 +12410,7 @@ is_inexpensive_builtin (tree decl)
       case BUILT_IN_VA_ARG_PACK_LEN:
       case BUILT_IN_VA_COPY:
       case BUILT_IN_TRAP:
+      case BUILT_IN_TRAP_MSG:
       case BUILT_IN_UNREACHABLE_TRAP:
       case BUILT_IN_SAVEREGS:
       case BUILT_IN_POPCOUNTL:
diff --git a/gcc/builtins.def b/gcc/builtins.def
index 3dc2333c6f2..ddcd8d7ab0d 100644
--- a/gcc/builtins.def
+++ b/gcc/builtins.def
@@ -1136,6 +1136,7 @@ DEF_GCC_BUILTIN        (BUILT_IN_SETJMP, "setjmp", 
BT_FN_INT_PTR, ATTR_RT_NOTHRO
 DEF_EXT_LIB_BUILTIN    (BUILT_IN_STRFMON, "strfmon", 
BT_FN_SSIZE_STRING_SIZE_CONST_STRING_VAR, ATTR_FORMAT_STRFMON_NOTHROW_3_4)
 DEF_LIB_BUILTIN        (BUILT_IN_STRFTIME, "strftime", 
BT_FN_SIZE_STRING_SIZE_CONST_STRING_CONST_TM_PTR, 
ATTR_FORMAT_STRFTIME_NOTHROW_3_0)
 DEF_GCC_BUILTIN        (BUILT_IN_TRAP, "trap", BT_FN_VOID, 
ATTR_NORETURN_NOTHROW_LEAF_COLD_LIST)
+DEF_GCC_BUILTIN        (BUILT_IN_TRAP_MSG, "trap_msg", 
BT_FN_VOID_CONST_STRING, ATTR_NORETURN_NOTHROW_LEAF_COLD_LIST)
 DEF_C2Y_BUILTIN        (BUILT_IN_UABS, "uabs", BT_FN_UINT_INT, 
ATTR_CONST_NOTHROW_LEAF_LIST)
 DEF_C2Y_BUILTIN        (BUILT_IN_UMAXABS, "umaxabs", BT_FN_UINTMAX_INTMAX, 
ATTR_CONST_NOTHROW_LEAF_LIST)
 DEF_C2Y_BUILTIN        (BUILT_IN_ULABS, "ulabs", BT_FN_ULONG_LONG, 
ATTR_CONST_NOTHROW_LEAF_LIST)
diff --git a/gcc/common.opt b/gcc/common.opt
index f6d93dc05fb..0f26e1dfc8b 100644
--- a/gcc/common.opt
+++ b/gcc/common.opt
@@ -822,6 +822,10 @@ Wtautological-compare
 Common Var(warn_tautological_compare) Warning LangEnabledBy(C ObjC C++ 
ObjC++,Wall)
 Warn if a comparison always evaluates to true or false.
 
+Wtrap
+Common Var(warn_trap) Warning
+Warn whenever a trap is generated.
+
 Wtrampolines
 Common Var(warn_trampolines) Warning
 Warn whenever a trampoline is generated.
diff --git a/gcc/doc/extend.texi b/gcc/doc/extend.texi
index 596cb5d3259..82e690fdcb8 100644
--- a/gcc/doc/extend.texi
+++ b/gcc/doc/extend.texi
@@ -17911,9 +17911,19 @@ This function causes the program to exit abnormally.  
GCC implements
 this function by using a target-dependent mechanism (such as
 intentionally executing an illegal instruction) or by calling
 @code{abort}.  The mechanism used may vary from release to release so
-you should not rely on any particular implementation.
+you should not rely on any particular implementation.  With @option{-Wtrap}
+a warning is emitted when a trap is actually generated by the compiler
+(i.e. not when the trap is optimized away).
 @enddefbuiltin
 
+
+@defbuiltin{void __builtin_trap_msg (const char *)}
+This function causes the program to exit abnormally.  It is the same
+as @code{__builtin_trap} except that it takes an optional argument
+that is shown as part of the warning generated by @option{-Wtrap}.
+@enddefbuiltin
+
+
 @defbuiltin{void __builtin_unreachable (void)}
 If control flow reaches the point of the @code{__builtin_unreachable},
 the program is undefined.  It is useful in situations where the
diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi
index 76ecea550f3..68927d478d1 100644
--- a/gcc/doc/invoke.texi
+++ b/gcc/doc/invoke.texi
@@ -9381,6 +9381,20 @@ made up of data only and thus requires no special 
treatment.  But, for
 most targets, it is made up of code and thus requires the stack to be
 made executable in order for the program to work properly.
 
+@opindex Wtrap
+@opindex Wno-trap
+@item -Wtrap
+Warn when explicit traps are generated.  Traps may be generated for
+a variety of reasons, e.g. when using the built-in functions
+@code{__builtin_trap} and @code{__builtin_trap_msg}, or by the compiler
+when using options such as @option{-fsanitize-trap=},
+@option{-funreachable-traps}, @option{-fisolate-erroneous-paths-dereference}
+@option{-fisolate-erroneous-paths-attribute}, @option{-ftrapv}
+@option{-fharden-compares}, @option{-fharden-conditional-branches},
+or others.  Note that the warning is emitted only for traps that appear
+in the executable, and is not generated for traps that are optimized away
+because they are unreachable.
+
 @opindex Wfloat-equal
 @opindex Wno-float-equal
 @item -Wfloat-equal
diff --git a/gcc/ipa-devirt.cc b/gcc/ipa-devirt.cc
index 18cb5a82195..2946760bf08 100644
--- a/gcc/ipa-devirt.cc
+++ b/gcc/ipa-devirt.cc
@@ -3487,6 +3487,7 @@ possible_polymorphic_call_target_p (tree otr_type,
   if (fndecl_built_in_p (n->decl, BUILT_IN_NORMAL)
       && (DECL_FUNCTION_CODE (n->decl) == BUILT_IN_UNREACHABLE
          || DECL_FUNCTION_CODE (n->decl) == BUILT_IN_TRAP
+         || DECL_FUNCTION_CODE (n->decl) == BUILT_IN_TRAP_MSG
          || DECL_FUNCTION_CODE (n->decl) == BUILT_IN_UNREACHABLE_TRAP))
     return true;
 
diff --git a/gcc/testsuite/gcc.dg/Wtrap.c b/gcc/testsuite/gcc.dg/Wtrap.c
new file mode 100644
index 00000000000..a0f26dd772f
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/Wtrap.c
@@ -0,0 +1,13 @@
+/* { dg-do compile } */
+/* { dg-options "-Wtrap" } */
+
+void foo(void)
+{
+       __builtin_trap();               /* { dg-warning "trap generated" } */
+}
+
+void foo2(void)
+{
+       __builtin_trap_msg("Hello");    /* { dg-warning "trap generated: 
\"Hello\"" } */
+}
+
diff --git a/gcc/tree-cfg.cc b/gcc/tree-cfg.cc
index c3883446de8..bc75727cec7 100644
--- a/gcc/tree-cfg.cc
+++ b/gcc/tree-cfg.cc
@@ -9787,7 +9787,8 @@ pass_warn_function_return::execute (function *fun)
                       && (gimple_call_builtin_p (last, BUILT_IN_UNREACHABLE)
                           || gimple_call_builtin_p (last,
                                                     BUILT_IN_UNREACHABLE_TRAP)
-                          || gimple_call_builtin_p (last, BUILT_IN_TRAP)))
+                          || gimple_call_builtin_p (last, BUILT_IN_TRAP)
+                          || gimple_call_builtin_p (last, BUILT_IN_TRAP_MSG)))
                      || gimple_call_builtin_p (last, ubsan_missing_ret)))
                {
                  gimple_stmt_iterator gsi = gsi_for_stmt (last);
diff --git a/gcc/tree.cc b/gcc/tree.cc
index 5d52a3886ce..e6851a8ab22 100644
--- a/gcc/tree.cc
+++ b/gcc/tree.cc
@@ -10047,6 +10047,7 @@ build_common_builtin_nodes (void)
 
   if (!builtin_decl_explicit_p (BUILT_IN_UNREACHABLE)
       || !builtin_decl_explicit_p (BUILT_IN_TRAP)
+      || !builtin_decl_explicit_p (BUILT_IN_TRAP_MSG)
       || !builtin_decl_explicit_p (BUILT_IN_UNREACHABLE_TRAP)
       || !builtin_decl_explicit_p (BUILT_IN_ABORT))
     {
@@ -10071,6 +10072,10 @@ build_common_builtin_nodes (void)
        local_define_builtin ("__builtin_trap", ftype, BUILT_IN_TRAP,
                              "__builtin_trap",
                              ECF_NORETURN | ECF_NOTHROW | ECF_LEAF | ECF_COLD);
+      if (!builtin_decl_explicit_p (BUILT_IN_TRAP_MSG))
+       local_define_builtin ("__builtin_trap_msg", ftype, BUILT_IN_TRAP_MSG,
+                             "__builtin_trap_msg",
+                             ECF_NORETURN | ECF_NOTHROW | ECF_LEAF | ECF_COLD);
     }
 
   if (!builtin_decl_explicit_p (BUILT_IN_MEMCPY)

Reply via email to