diff options
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/builtins.cc | 9 | ||||
-rw-r--r-- | gcc/cgraphunit.cc | 3 | ||||
-rw-r--r-- | gcc/common.opt | 4 | ||||
-rw-r--r-- | gcc/cp/constexpr.cc | 29 | ||||
-rw-r--r-- | gcc/cp/cp-gimplify.cc | 7 | ||||
-rw-r--r-- | gcc/doc/invoke.texi | 14 | ||||
-rw-r--r-- | gcc/gimple-fold.cc | 7 | ||||
-rw-r--r-- | gcc/gimple.cc | 13 | ||||
-rw-r--r-- | gcc/gimple.h | 1 | ||||
-rw-r--r-- | gcc/ipa-fnsummary.cc | 4 | ||||
-rw-r--r-- | gcc/ipa-prop.cc | 4 | ||||
-rw-r--r-- | gcc/ipa.cc | 3 | ||||
-rw-r--r-- | gcc/opts.cc | 4 | ||||
-rw-r--r-- | gcc/sanopt.cc | 10 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/ubsan/return-8a.C | 16 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/ubsan/return-8b.C | 17 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/ubsan/return-8d.C | 16 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/ubsan/return-8e.C | 17 | ||||
-rw-r--r-- | gcc/tree-cfg.cc | 7 | ||||
-rw-r--r-- | gcc/tree-ssa-loop-ivcanon.cc | 7 | ||||
-rw-r--r-- | gcc/tree-ssa-sccvn.cc | 2 | ||||
-rw-r--r-- | gcc/tree.cc | 40 | ||||
-rw-r--r-- | gcc/tree.h | 5 | ||||
-rw-r--r-- | gcc/ubsan.cc | 48 | ||||
-rw-r--r-- | gcc/ubsan.h | 1 |
25 files changed, 233 insertions, 55 deletions
diff --git a/gcc/builtins.cc b/gcc/builtins.cc index 971b18c..e6816d5 100644 --- a/gcc/builtins.cc +++ b/gcc/builtins.cc @@ -5184,6 +5184,9 @@ expand_builtin_trap (void) static void expand_builtin_unreachable (void) { + /* Use gimple_build_builtin_unreachable or builtin_decl_unreachable + to avoid this. */ + gcc_checking_assert (!sanitize_flags_p (SANITIZE_UNREACHABLE)); emit_barrier (); } @@ -9261,6 +9264,12 @@ fold_builtin_0 (location_t loc, tree fndecl) case BUILT_IN_CLASSIFY_TYPE: return fold_builtin_classify_type (NULL_TREE); + case BUILT_IN_UNREACHABLE: + /* Rewrite any explicit calls to __builtin_unreachable. */ + if (sanitize_flags_p (SANITIZE_UNREACHABLE)) + return build_builtin_unreachable (loc); + break; + default: break; } diff --git a/gcc/cgraphunit.cc b/gcc/cgraphunit.cc index e77bf97..836e759 100644 --- a/gcc/cgraphunit.cc +++ b/gcc/cgraphunit.cc @@ -1033,8 +1033,7 @@ walk_polymorphic_call_targets (hash_set<void *> *reachable_call_targets, if (targets.length () == 1) target = targets[0]; else - target = cgraph_node::create - (builtin_decl_implicit (BUILT_IN_UNREACHABLE)); + target = cgraph_node::create (builtin_decl_unreachable ()); if (symtab->dump_file) { diff --git a/gcc/common.opt b/gcc/common.opt index 32917aa..da5d23d 100644 --- a/gcc/common.opt +++ b/gcc/common.opt @@ -3017,6 +3017,10 @@ funit-at-a-time Common Var(flag_unit_at_a_time) Init(1) Compile whole compilation unit at a time. +funreachable-traps +Common Var(flag_unreachable_traps) Optimization +Trap on __builtin_unreachable instead of using it for optimization. + funroll-loops Common Var(flag_unroll_loops) Optimization EnabledBy(funroll-all-loops) Perform loop unrolling when iteration count is known. diff --git a/gcc/cp/constexpr.cc b/gcc/cp/constexpr.cc index fd7f8c0..0dc94d9 100644 --- a/gcc/cp/constexpr.cc +++ b/gcc/cp/constexpr.cc @@ -1438,6 +1438,20 @@ cxx_eval_builtin_function_call (const constexpr_ctx *ctx, tree t, tree fun, /* These builtins shall be ignored during constant expression evaluation. */ return void_node; + case BUILT_IN_UNREACHABLE: + case BUILT_IN_TRAP: + if (!*non_constant_p && !ctx->quiet) + { + /* Do not allow__builtin_unreachable in constexpr function. + The __builtin_unreachable call with BUILTINS_LOCATION + comes from cp_maybe_instrument_return. */ + if (EXPR_LOCATION (t) == BUILTINS_LOCATION) + error ("%<constexpr%> call flows off the end of the function"); + else + error ("%q+E is not a constant expression", t); + } + *non_constant_p = true; + return t; default: break; } @@ -1531,18 +1545,9 @@ cxx_eval_builtin_function_call (const constexpr_ctx *ctx, tree t, tree fun, { if (!*non_constant_p && !ctx->quiet) { - /* Do not allow__builtin_unreachable in constexpr function. - The __builtin_unreachable call with BUILTINS_LOCATION - comes from cp_maybe_instrument_return. */ - if (fndecl_built_in_p (fun, BUILT_IN_UNREACHABLE) - && EXPR_LOCATION (t) == BUILTINS_LOCATION) - error ("%<constexpr%> call flows off the end of the function"); - else - { - new_call = build_call_array_loc (EXPR_LOCATION (t), TREE_TYPE (t), - CALL_EXPR_FN (t), nargs, args); - error ("%q+E is not a constant expression", new_call); - } + new_call = build_call_array_loc (EXPR_LOCATION (t), TREE_TYPE (t), + CALL_EXPR_FN (t), nargs, args); + error ("%q+E is not a constant expression", new_call); } *non_constant_p = true; return t; diff --git a/gcc/cp/cp-gimplify.cc b/gcc/cp/cp-gimplify.cc index 6f84d15..c05be83 100644 --- a/gcc/cp/cp-gimplify.cc +++ b/gcc/cp/cp-gimplify.cc @@ -1814,7 +1814,7 @@ cp_maybe_instrument_return (tree fndecl) information is provided, while the __builtin_unreachable () below if return sanitization is disabled will just result in hard to understand runtime error without location. */ - && (!optimize + && ((!optimize && !flag_unreachable_traps) || sanitize_flags_p (SANITIZE_UNREACHABLE, fndecl))) return; @@ -1864,10 +1864,7 @@ cp_maybe_instrument_return (tree fndecl) if (sanitize_flags_p (SANITIZE_RETURN, fndecl)) t = ubsan_instrument_return (loc); else - { - tree fndecl = builtin_decl_explicit (BUILT_IN_UNREACHABLE); - t = build_call_expr_loc (BUILTINS_LOCATION, fndecl, 0); - } + t = build_builtin_unreachable (BUILTINS_LOCATION); append_to_statement_list (t, p); } diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi index fb50636..e7526c5 100644 --- a/gcc/doc/invoke.texi +++ b/gcc/doc/invoke.texi @@ -12939,6 +12939,20 @@ also at @option{-O0} if @option{-fsection-anchors} is explicitly requested. Additionally @option{-fno-toplevel-reorder} implies @option{-fno-section-anchors}. +@item -funreachable-traps +@opindex funreachable-traps +With this option, the compiler turns calls to +@code{__builtin_unreachable} into traps, instead of using them for +optimization. This also affects any such calls implicitly generated +by the compiler. + +This option has the same effect as @option{-fsanitize=unreachable +-fsanitize-trap=unreachable}, but does not affect the values of those +options. If @option{-fsanitize=unreachable} is enabled, that option +takes priority over this one. + +This option is enabled by default at @option{-O0} and @option{-Og}. + @item -fweb @opindex fweb Constructs webs as commonly used for register allocation purposes and assign diff --git a/gcc/gimple-fold.cc b/gcc/gimple-fold.cc index f61bc87..a170478 100644 --- a/gcc/gimple-fold.cc +++ b/gcc/gimple-fold.cc @@ -5510,9 +5510,8 @@ gimple_fold_call (gimple_stmt_iterator *gsi, bool inplace) } else { - tree fndecl = builtin_decl_implicit (BUILT_IN_UNREACHABLE); - gimple *new_stmt = gimple_build_call (fndecl, 0); - gimple_set_location (new_stmt, gimple_location (stmt)); + location_t loc = gimple_location (stmt); + gimple *new_stmt = gimple_build_builtin_unreachable (loc); /* If the call had a SSA name as lhs morph that into an uninitialized value. */ if (lhs && TREE_CODE (lhs) == SSA_NAME) @@ -8396,7 +8395,7 @@ gimple_get_virt_method_for_vtable (HOST_WIDE_INT token, if (!fn || (TREE_CODE (fn) != ADDR_EXPR && TREE_CODE (fn) != FDESC_EXPR) || TREE_CODE (TREE_OPERAND (fn, 0)) != FUNCTION_DECL) - fn = builtin_decl_implicit (BUILT_IN_UNREACHABLE); + fn = builtin_decl_unreachable (); else { fn = TREE_OPERAND (fn, 0); diff --git a/gcc/gimple.cc b/gcc/gimple.cc index b70ab4d..9b15639 100644 --- a/gcc/gimple.cc +++ b/gcc/gimple.cc @@ -44,6 +44,7 @@ along with GCC; see the file COPYING3. If not see #include "stringpool.h" #include "attribs.h" #include "asan.h" +#include "ubsan.h" #include "langhooks.h" #include "attr-fnspec.h" #include "ipa-modref-tree.h" @@ -421,6 +422,18 @@ gimple_build_call_from_tree (tree t, tree fnptrtype) return call; } +/* Build a gcall to __builtin_unreachable as rewritten by + -fsanitize=unreachable. */ + +gcall * +gimple_build_builtin_unreachable (location_t loc) +{ + tree data = NULL_TREE; + tree fn = sanitize_unreachable_fn (&data, loc); + gcall *g = gimple_build_call (fn, data != NULL_TREE, data); + gimple_set_location (g, loc); + return g; +} /* Build a GIMPLE_ASSIGN statement. diff --git a/gcc/gimple.h b/gcc/gimple.h index 870629c..1d15ff9 100644 --- a/gcc/gimple.h +++ b/gcc/gimple.h @@ -1638,6 +1638,7 @@ extern void maybe_remove_unused_call_args (struct function *, gimple *); extern bool gimple_inexpensive_call_p (gcall *); extern bool stmt_can_terminate_bb_p (gimple *); extern location_t gimple_or_expr_nonartificial_location (gimple *, tree); +gcall *gimple_build_builtin_unreachable (location_t); /* Return the disposition for a warning (or all warnings by default) for a statement. */ diff --git a/gcc/ipa-fnsummary.cc b/gcc/ipa-fnsummary.cc index b12e7a1..c956445 100644 --- a/gcc/ipa-fnsummary.cc +++ b/gcc/ipa-fnsummary.cc @@ -250,8 +250,8 @@ static struct cgraph_edge * redirect_to_unreachable (struct cgraph_edge *e) { struct cgraph_node *callee = !e->inline_failed ? e->callee : NULL; - struct cgraph_node *target = cgraph_node::get_create - (builtin_decl_implicit (BUILT_IN_UNREACHABLE)); + struct cgraph_node *target + = cgraph_node::get_create (builtin_decl_unreachable ()); if (e->speculative) e = cgraph_edge::resolve_speculation (e, target->decl); diff --git a/gcc/ipa-prop.cc b/gcc/ipa-prop.cc index c037668..e1fc481 100644 --- a/gcc/ipa-prop.cc +++ b/gcc/ipa-prop.cc @@ -3410,7 +3410,7 @@ ipa_make_edge_direct_to_target (struct cgraph_edge *ie, tree target, ie->caller->dump_name ()); } - target = builtin_decl_implicit (BUILT_IN_UNREACHABLE); + target = builtin_decl_unreachable (); callee = cgraph_node::get_create (target); unreachable = true; } @@ -3821,7 +3821,7 @@ ipa_impossible_devirt_target (struct cgraph_edge *ie, tree target) "No devirtualization target in %s\n", ie->caller->dump_name ()); } - tree new_target = builtin_decl_implicit (BUILT_IN_UNREACHABLE); + tree new_target = builtin_decl_unreachable (); cgraph_node::get_create (new_target); return new_target; } @@ -232,8 +232,7 @@ walk_polymorphic_call_targets (hash_set<void *> *reachable_call_targets, if (targets.length () == 1) target = targets[0]; else - target = cgraph_node::get_create - (builtin_decl_implicit (BUILT_IN_UNREACHABLE)); + target = cgraph_node::get_create (builtin_decl_unreachable ()); if (dump_enabled_p ()) { diff --git a/gcc/opts.cc b/gcc/opts.cc index 959d48d..9982974 100644 --- a/gcc/opts.cc +++ b/gcc/opts.cc @@ -1122,6 +1122,10 @@ finish_options (struct gcc_options *opts, struct gcc_options *opts_set, opts->x_flag_no_inline = 1; } + /* At -O0 or -Og, turn __builtin_unreachable into a trap. */ + if (!opts->x_optimize || opts->x_optimize_debug) + SET_OPTION_IF_UNSET (opts, opts_set, flag_unreachable_traps, true); + /* Pipelining of outer loops is only possible when general pipelining capabilities are requested. */ if (!opts->x_flag_sel_sched_pipelining) diff --git a/gcc/sanopt.cc b/gcc/sanopt.cc index c318763..2b05553 100644 --- a/gcc/sanopt.cc +++ b/gcc/sanopt.cc @@ -942,7 +942,15 @@ public: {} /* opt_pass methods: */ - virtual bool gate (function *) { return flag_sanitize; } + virtual bool gate (function *) + { + /* SANITIZE_RETURN is handled in the front-end. When trapping, + SANITIZE_UNREACHABLE is handled by builtin_decl_unreachable. */ + unsigned int mask = SANITIZE_RETURN; + if (flag_sanitize_trap & SANITIZE_UNREACHABLE) + mask |= SANITIZE_UNREACHABLE; + return flag_sanitize & ~mask; + } virtual unsigned int execute (function *); }; // class pass_sanopt diff --git a/gcc/testsuite/g++.dg/ubsan/return-8a.C b/gcc/testsuite/g++.dg/ubsan/return-8a.C new file mode 100644 index 0000000..54f1c7b --- /dev/null +++ b/gcc/testsuite/g++.dg/ubsan/return-8a.C @@ -0,0 +1,16 @@ +// PR c++/104642 + +// At -O0 and -Og we default to -funreachable-traps +// so the below should abort at runtime. + +// { dg-do run } +// { dg-shouldfail { *-*-* } } +// { dg-additional-options "-O0" } + +bool b; + +int f() { + if (b) return 42; +} // { dg-warning "-Wreturn-type" } + +int main() { f(); } diff --git a/gcc/testsuite/g++.dg/ubsan/return-8b.C b/gcc/testsuite/g++.dg/ubsan/return-8b.C new file mode 100644 index 0000000..bdaea60 --- /dev/null +++ b/gcc/testsuite/g++.dg/ubsan/return-8b.C @@ -0,0 +1,17 @@ +// PR c++/104642 + +// With -fsanitize=unreachable we shouldn't optimize away the call to f. + +// { dg-do run } +// { dg-shouldfail { *-*-* } } +// { dg-additional-options "-O -fsanitize=unreachable" } + +bool b; + +int f() { + if (b) return 42; + __builtin_unreachable (); + return 24; +} + +int main() { f(); } diff --git a/gcc/testsuite/g++.dg/ubsan/return-8d.C b/gcc/testsuite/g++.dg/ubsan/return-8d.C new file mode 100644 index 0000000..7eaded0 --- /dev/null +++ b/gcc/testsuite/g++.dg/ubsan/return-8d.C @@ -0,0 +1,16 @@ +// PR c++/104642 + +// At -O0 and -Og we default to -funreachable-traps +// so the below should abort at runtime. + +// { dg-do run } +// { dg-shouldfail { *-*-* } } +// { dg-additional-options "-Og" } + +bool b; + +int f() { + if (b) return 42; +} // { dg-warning "-Wreturn-type" } + +int main() { f(); } diff --git a/gcc/testsuite/g++.dg/ubsan/return-8e.C b/gcc/testsuite/g++.dg/ubsan/return-8e.C new file mode 100644 index 0000000..fba402b --- /dev/null +++ b/gcc/testsuite/g++.dg/ubsan/return-8e.C @@ -0,0 +1,17 @@ +// PR c++/104642 + +// At -O0 and -Og we default to -funreachable-traps +// so the below should abort at runtime. + +// { dg-do run } +// { dg-shouldfail { *-*-* } } +// { dg-additional-options "-O2" } + +bool b; + +__attribute__ ((optimize ("Og"))) +int f() { + if (b) return 42; +} // { dg-warning "-Wreturn-type" } + +int main() { f(); } diff --git a/gcc/tree-cfg.cc b/gcc/tree-cfg.cc index c67c278..734fddd 100644 --- a/gcc/tree-cfg.cc +++ b/gcc/tree-cfg.cc @@ -9503,9 +9503,8 @@ pass_warn_function_return::execute (function *fun) with __builtin_unreachable () call. */ if (optimize && gimple_code (last) == GIMPLE_RETURN) { - tree fndecl = builtin_decl_implicit (BUILT_IN_UNREACHABLE); - gimple *new_stmt = gimple_build_call (fndecl, 0); - gimple_set_location (new_stmt, gimple_location (last)); + location_t loc = gimple_location (last); + gimple *new_stmt = gimple_build_builtin_unreachable (loc); gimple_stmt_iterator gsi = gsi_for_stmt (last); gsi_replace (&gsi, new_stmt, true); remove_edge (e); @@ -9834,7 +9833,7 @@ execute_fixup_cfg (void) { if (stmt && is_gimple_call (stmt)) gimple_call_set_ctrl_altering (stmt, false); - tree fndecl = builtin_decl_implicit (BUILT_IN_UNREACHABLE); + tree fndecl = builtin_decl_unreachable (); stmt = gimple_build_call (fndecl, 0); gimple_stmt_iterator gsi = gsi_last_bb (bb); gsi_insert_after (&gsi, stmt, GSI_NEW_STMT); diff --git a/gcc/tree-ssa-loop-ivcanon.cc b/gcc/tree-ssa-loop-ivcanon.cc index 2ee00a3..6a38b77 100644 --- a/gcc/tree-ssa-loop-ivcanon.cc +++ b/gcc/tree-ssa-loop-ivcanon.cc @@ -505,9 +505,8 @@ remove_exits_and_undefined_stmts (class loop *loop, unsigned int npeeled) && wi::ltu_p (elt->bound, npeeled)) { gimple_stmt_iterator gsi = gsi_for_stmt (elt->stmt); - gcall *stmt = gimple_build_call - (builtin_decl_implicit (BUILT_IN_UNREACHABLE), 0); - gimple_set_location (stmt, gimple_location (elt->stmt)); + location_t loc = gimple_location (elt->stmt); + gcall *stmt = gimple_build_builtin_unreachable (loc); gsi_insert_before (&gsi, stmt, GSI_NEW_STMT); split_block (gimple_bb (stmt), stmt); changed = true; @@ -641,7 +640,7 @@ unloop_loops (bitmap loop_closed_ssa_invalidated, /* Create new basic block for the latch edge destination and wire it in. */ - stmt = gimple_build_call (builtin_decl_implicit (BUILT_IN_UNREACHABLE), 0); + stmt = gimple_build_builtin_unreachable (locus); latch_edge = make_edge (latch, create_basic_block (NULL, NULL, latch), flags); latch_edge->probability = profile_probability::never (); latch_edge->flags |= flags; diff --git a/gcc/tree-ssa-sccvn.cc b/gcc/tree-ssa-sccvn.cc index ed68557..776dccb 100644 --- a/gcc/tree-ssa-sccvn.cc +++ b/gcc/tree-ssa-sccvn.cc @@ -6807,7 +6807,7 @@ eliminate_dom_walker::eliminate_stmt (basic_block b, gimple_stmt_iterator *gsi) if (targets.length () == 1) fn = targets[0]->decl; else - fn = builtin_decl_implicit (BUILT_IN_UNREACHABLE); + fn = builtin_decl_unreachable (); if (dump_enabled_p ()) { dump_printf_loc (MSG_OPTIMIZED_LOCATIONS, stmt, diff --git a/gcc/tree.cc b/gcc/tree.cc index 2bfb674..84000dd 100644 --- a/gcc/tree.cc +++ b/gcc/tree.cc @@ -71,6 +71,8 @@ along with GCC; see the file COPYING3. If not see #include "gimple-range.h" #include "gomp-constants.h" #include "dfp.h" +#include "asan.h" +#include "ubsan.h" /* Tree code classes. */ @@ -9649,6 +9651,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_ABORT)) { ftype = build_function_type (void_type_node, void_list_node); @@ -9662,6 +9665,10 @@ build_common_builtin_nodes (void) local_define_builtin ("__builtin_abort", ftype, BUILT_IN_ABORT, "abort", ECF_LEAF | ECF_NORETURN | ECF_CONST | ECF_COLD); + if (!builtin_decl_explicit_p (BUILT_IN_TRAP)) + 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_MEMCPY) @@ -10779,6 +10786,39 @@ build_alloca_call_expr (tree size, unsigned int align, HOST_WIDE_INT max_size) } } +/* The built-in decl to use to mark code points believed to be unreachable. + Typically __builtin_unreachable, but __builtin_trap if + -fsanitize=unreachable -fsanitize-trap=unreachable. If only + -fsanitize=unreachable, we rely on sanopt to replace calls with the + appropriate ubsan function. When building a call directly, use + {gimple_},build_builtin_unreachable instead. */ + +tree +builtin_decl_unreachable () +{ + enum built_in_function fncode = BUILT_IN_UNREACHABLE; + + if (sanitize_flags_p (SANITIZE_UNREACHABLE) + ? (flag_sanitize_trap & SANITIZE_UNREACHABLE) + : flag_unreachable_traps) + fncode = BUILT_IN_TRAP; + /* For non-trapping sanitize, we will rewrite __builtin_unreachable () later, + in the sanopt pass. */ + + return builtin_decl_explicit (fncode); +} + +/* Build a call to __builtin_unreachable, possibly rewritten by + -fsanitize=unreachable. Use this rather than the above when practical. */ + +tree +build_builtin_unreachable (location_t loc) +{ + tree data = NULL_TREE; + tree fn = sanitize_unreachable_fn (&data, loc); + return build_call_expr_loc (loc, fn, data != NULL_TREE, data); +} + /* Create a new constant string literal of type ELTYPE[SIZE] (or LEN if SIZE == -1) and return a tree node representing char* pointer to it as an ADDR_EXPR (ARRAY_REF (ELTYPE, ...)). When STR is nonnull @@ -5858,6 +5858,11 @@ builtin_decl_implicit (enum built_in_function fncode) return builtin_info[uns_fncode].decl; } +/* For BUILTIN_UNREACHABLE, use one of these or + gimple_build_builtin_unreachable instead of one of the above. */ +extern tree builtin_decl_unreachable (); +extern tree build_builtin_unreachable (location_t); + /* Set explicit builtin function nodes and whether it is an implicit function. */ diff --git a/gcc/ubsan.cc b/gcc/ubsan.cc index 3aa25b5..f150268 100644 --- a/gcc/ubsan.cc +++ b/gcc/ubsan.cc @@ -638,27 +638,43 @@ ubsan_create_data (const char *name, int loccnt, const location_t *ploc, ...) return var; } -/* Instrument the __builtin_unreachable call. We just call the libubsan - routine instead. */ +/* Shared between *build_builtin_unreachable. */ -bool -ubsan_instrument_unreachable (gimple_stmt_iterator *gsi) +tree +sanitize_unreachable_fn (tree *data, location_t loc) { - gimple *g; - location_t loc = gimple_location (gsi_stmt (*gsi)); - - if (flag_sanitize_trap & SANITIZE_UNREACHABLE) - g = gimple_build_call (builtin_decl_explicit (BUILT_IN_TRAP), 0); + tree fn = NULL_TREE; + bool san = sanitize_flags_p (SANITIZE_UNREACHABLE); + if (san + ? (flag_sanitize_trap & SANITIZE_UNREACHABLE) + : flag_unreachable_traps) + { + fn = builtin_decl_explicit (BUILT_IN_TRAP); + *data = NULL_TREE; + } + else if (san) + { + fn = builtin_decl_explicit (BUILT_IN_UBSAN_HANDLE_BUILTIN_UNREACHABLE); + *data = ubsan_create_data ("__ubsan_unreachable_data", 1, &loc, + NULL_TREE, NULL_TREE); + *data = build_fold_addr_expr_loc (loc, *data); + } else { - tree data = ubsan_create_data ("__ubsan_unreachable_data", 1, &loc, - NULL_TREE, NULL_TREE); - data = build_fold_addr_expr_loc (loc, data); - tree fn - = builtin_decl_explicit (BUILT_IN_UBSAN_HANDLE_BUILTIN_UNREACHABLE); - g = gimple_build_call (fn, 1, data); + fn = builtin_decl_explicit (BUILT_IN_UNREACHABLE); + *data = NULL_TREE; } - gimple_set_location (g, loc); + return fn; +} + +/* Rewrite a gcall to __builtin_unreachable for -fsanitize=unreachable. Called + by the sanopt pass. */ + +bool +ubsan_instrument_unreachable (gimple_stmt_iterator *gsi) +{ + location_t loc = gimple_location (gsi_stmt (*gsi)); + gimple *g = gimple_build_builtin_unreachable (loc); gsi_replace (gsi, g, false); return false; } diff --git a/gcc/ubsan.h b/gcc/ubsan.h index 17c5254..71a40a3 100644 --- a/gcc/ubsan.h +++ b/gcc/ubsan.h @@ -65,5 +65,6 @@ extern tree ubsan_build_overflow_builtin (tree_code, location_t, tree, tree, tree, tree *); extern tree ubsan_instrument_float_cast (location_t, tree, tree); extern tree ubsan_get_source_location_type (void); +extern tree sanitize_unreachable_fn (tree *data, location_t loc); #endif /* GCC_UBSAN_H */ |