diff options
author | Jakub Jelinek <jakub@redhat.com> | 2024-04-18 09:45:14 +0200 |
---|---|---|
committer | Jakub Jelinek <jakub@redhat.com> | 2024-04-18 09:45:14 +0200 |
commit | 6c152c9db3b5b9d43e12846fb7a44977c0b65fc2 (patch) | |
tree | b34bf7adaaec17cbe92764278ac6dc3ce511e667 /gcc | |
parent | 6e62ede7aaccc6ebe027c8e00224f65e226072e9 (diff) | |
download | gcc-6c152c9db3b5b9d43e12846fb7a44977c0b65fc2.zip gcc-6c152c9db3b5b9d43e12846fb7a44977c0b65fc2.tar.gz gcc-6c152c9db3b5b9d43e12846fb7a44977c0b65fc2.tar.bz2 |
internal-fn: Temporarily disable flag_trapv during .{ADD,SUB,MUL}_OVERFLOW etc. expansion [PR114753]
__builtin_{add,sub,mul}_overflow{,_p} builtins are well defined
for all inputs even for -ftrapv, and the -fsanitize=signed-integer-overflow
ifns shouldn't abort in libgcc but emit the desired ubsan diagnostics
or abort depending on -fsanitize* setting regardless of -ftrapv.
The expansion of these internal functions uses expand_expr* in various
places (e.g. MULT_EXPR at least in 2 spots), so temporarily disabling
flag_trapv in all those spots would be hard.
The following patch disables it around the bodies of 3 functions
which can do the expand_expr calls.
If it was in the C++ FE, I'd use some RAII sentinel, but I don't think
we have one in the middle-end.
2024-04-18 Jakub Jelinek <jakub@redhat.com>
PR middle-end/114753
* internal-fn.cc (expand_mul_overflow): Save flag_trapv and
temporarily clear it for the duration of the function, then
restore previous value.
(expand_vector_ubsan_overflow): Likewise.
(expand_arith_overflow): Likewise.
* gcc.dg/pr114753.c: New test.
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/internal-fn.cc | 18 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/pr114753.c | 14 |
2 files changed, 32 insertions, 0 deletions
diff --git a/gcc/internal-fn.cc b/gcc/internal-fn.cc index 5269f0a..c7c5222 100644 --- a/gcc/internal-fn.cc +++ b/gcc/internal-fn.cc @@ -1631,7 +1631,11 @@ expand_mul_overflow (location_t loc, tree lhs, tree arg0, tree arg1, rtx target = NULL_RTX; signop sign; enum insn_code icode; + int save_flag_trapv = flag_trapv; + /* We don't want any __mulv?i3 etc. calls from the expansion of + these internal functions, so disable -ftrapv temporarily. */ + flag_trapv = 0; done_label = gen_label_rtx (); do_error = gen_label_rtx (); @@ -2479,6 +2483,7 @@ expand_mul_overflow (location_t loc, tree lhs, tree arg0, tree arg1, else expand_arith_overflow_result_store (lhs, target, mode, res); } + flag_trapv = save_flag_trapv; } /* Expand UBSAN_CHECK_* internal function if it has vector operands. */ @@ -2499,7 +2504,11 @@ expand_vector_ubsan_overflow (location_t loc, enum tree_code code, tree lhs, rtx resvr = NULL_RTX; unsigned HOST_WIDE_INT const_cnt = 0; bool use_loop_p = (!cnt.is_constant (&const_cnt) || const_cnt > 4); + int save_flag_trapv = flag_trapv; + /* We don't want any __mulv?i3 etc. calls from the expansion of + these internal functions, so disable -ftrapv temporarily. */ + flag_trapv = 0; if (lhs) { optab op; @@ -2629,6 +2638,7 @@ expand_vector_ubsan_overflow (location_t loc, enum tree_code code, tree lhs, } else if (resvr) emit_move_insn (lhsr, resvr); + flag_trapv = save_flag_trapv; } /* Expand UBSAN_CHECK_ADD call STMT. */ @@ -2707,7 +2717,11 @@ expand_arith_overflow (enum tree_code code, gimple *stmt) prec0 = MIN (prec0, pr); pr = get_min_precision (arg1, uns1_p ? UNSIGNED : SIGNED); prec1 = MIN (prec1, pr); + int save_flag_trapv = flag_trapv; + /* We don't want any __mulv?i3 etc. calls from the expansion of + these internal functions, so disable -ftrapv temporarily. */ + flag_trapv = 0; /* If uns0_p && uns1_p, precop is minimum needed precision of unsigned type to hold the exact result, otherwise precop is minimum needed precision of signed type to @@ -2748,6 +2762,7 @@ expand_arith_overflow (enum tree_code code, gimple *stmt) ops.location = loc; rtx tem = expand_expr_real_2 (&ops, NULL_RTX, mode, EXPAND_NORMAL); expand_arith_overflow_result_store (lhs, target, mode, tem); + flag_trapv = save_flag_trapv; return; } @@ -2771,6 +2786,7 @@ expand_arith_overflow (enum tree_code code, gimple *stmt) if (integer_zerop (arg0) && !unsr_p) { expand_neg_overflow (loc, lhs, arg1, false, NULL); + flag_trapv = save_flag_trapv; return; } /* FALLTHRU */ @@ -2781,6 +2797,7 @@ expand_arith_overflow (enum tree_code code, gimple *stmt) case MULT_EXPR: expand_mul_overflow (loc, lhs, arg0, arg1, unsr_p, unsr_p, unsr_p, false, NULL); + flag_trapv = save_flag_trapv; return; default: gcc_unreachable (); @@ -2826,6 +2843,7 @@ expand_arith_overflow (enum tree_code code, gimple *stmt) else expand_mul_overflow (loc, lhs, arg0, arg1, unsr_p, uns0_p, uns1_p, false, NULL); + flag_trapv = save_flag_trapv; return; } diff --git a/gcc/testsuite/gcc.dg/pr114753.c b/gcc/testsuite/gcc.dg/pr114753.c new file mode 100644 index 0000000..117f2c3 --- /dev/null +++ b/gcc/testsuite/gcc.dg/pr114753.c @@ -0,0 +1,14 @@ +/* PR middle-end/114753 */ +/* { dg-do run } */ +/* { dg-options "-O2 -ftrapv" } */ + +int +main () +{ + volatile long long i = __LONG_LONG_MAX__; + volatile long long j = 2; + long long k; + if (!__builtin_mul_overflow (i, j, &k) || k != -2LL) + __builtin_abort (); + return 0; +} |