diff options
author | Marek Polacek <mpolacek@gcc.gnu.org> | 2013-12-04 22:47:11 +0000 |
---|---|---|
committer | Marek Polacek <mpolacek@gcc.gnu.org> | 2013-12-04 22:47:11 +0000 |
commit | 31e071aeb827f49ce2e891620852198e99d44a0c (patch) | |
tree | 20fca81276f1e6d6224300c11a4e10fa89519d41 /gcc/tree-vrp.c | |
parent | 59b6687cceaf95d8c49afee88248cf4fb0a33105 (diff) | |
download | gcc-31e071aeb827f49ce2e891620852198e99d44a0c.zip gcc-31e071aeb827f49ce2e891620852198e99d44a0c.tar.gz gcc-31e071aeb827f49ce2e891620852198e99d44a0c.tar.bz2 |
Implement -fsanitize=signed-integer-overflow.
From-SVN: r205684
Diffstat (limited to 'gcc/tree-vrp.c')
-rw-r--r-- | gcc/tree-vrp.c | 41 |
1 files changed, 41 insertions, 0 deletions
diff --git a/gcc/tree-vrp.c b/gcc/tree-vrp.c index 89f2ffd..d98b776 100644 --- a/gcc/tree-vrp.c +++ b/gcc/tree-vrp.c @@ -3757,6 +3757,47 @@ extract_range_basic (value_range_t *vr, gimple stmt) break; } } + else if (is_gimple_call (stmt) + && gimple_call_internal_p (stmt)) + { + enum tree_code subcode = ERROR_MARK; + switch (gimple_call_internal_fn (stmt)) + { + case IFN_UBSAN_CHECK_ADD: + subcode = PLUS_EXPR; + break; + case IFN_UBSAN_CHECK_SUB: + subcode = MINUS_EXPR; + break; + case IFN_UBSAN_CHECK_MUL: + subcode = MULT_EXPR; + break; + default: + break; + } + if (subcode != ERROR_MARK) + { + bool saved_flag_wrapv = flag_wrapv; + /* Pretend the arithmetics is wrapping. If there is + any overflow, we'll complain, but will actually do + wrapping operation. */ + flag_wrapv = 1; + extract_range_from_binary_expr (vr, subcode, type, + gimple_call_arg (stmt, 0), + gimple_call_arg (stmt, 1)); + flag_wrapv = saved_flag_wrapv; + + /* If for both arguments vrp_valueize returned non-NULL, + this should have been already folded and if not, it + wasn't folded because of overflow. Avoid removing the + UBSAN_CHECK_* calls in that case. */ + if (vr->type == VR_RANGE + && (vr->min == vr->max + || operand_equal_p (vr->min, vr->max, 0))) + set_value_range_to_varying (vr); + return; + } + } if (INTEGRAL_TYPE_P (type) && gimple_stmt_nonnegative_warnv_p (stmt, &sop)) set_value_range_to_nonnegative (vr, type, |