On Sat, 20 Sep 2025, Martin Uecker wrote:

> Bootstrapped and regression tested on x86_64.

How's it useful when all UBSAN generated traps get a compile-time
diagnostic?  Specifically for the testcase you add, how is this
diagnostig useful?

I'd instead have expected path isolation to diagnose inserted traps.

Richard.

> 
>     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);
> 

-- 
Richard Biener <[email protected]>
SUSE Software Solutions Germany GmbH,
Frankenstrasse 146, 90461 Nuernberg, Germany;
GF: Ivo Totev, Andrew McDonald, Werner Knoblich; (HRB 36809, AG Nuernberg)

Reply via email to