This fixes sanitizer/64906 by also pre-evaluating OP1. The problem in this testcase is that OP1 is "SAVE_EXPR <f ? 8 : 0>" which can't be folded any more, but when we're creating the EQ_EXPR -- checking whether this expression equals zero -- it can be folded further to "f == 0". Afterwards we end up with this (crap omitted):
ret = if (SAVE_EXPR <(long unsigned int) s>;, SAVE_EXPR <f == 0>;) { __ubsan (..., (SAVE_EXPR <f != 0 ? 8 : 0>)); } else { }, (... / (SAVE_EXPR <f != 0 ? 8 : 0>)); I.e. the SAVE_EXPR <f != 0 ? 8 : 0> would be evaluated inside the if and not before. So do what we already do for OP0. The shift instrumentation should be fine in this regard. Bootstrapped/regtested on x86_64-linux, ok for trunk and 5? 2015-09-22 Marek Polacek <pola...@redhat.com> PR sanitizer/64906 * c-ubsan.c (ubsan_instrument_division): Also pre-evaluate OP1. * c-c++-common/ubsan/pr64906.c: New test. diff --git gcc/c-family/c-ubsan.c gcc/c-family/c-ubsan.c index e0cce84..d2bc264 100644 --- gcc/c-family/c-ubsan.c +++ gcc/c-family/c-ubsan.c @@ -104,6 +104,7 @@ ubsan_instrument_division (location_t loc, tree op0, tree op1) } } t = fold_build2 (COMPOUND_EXPR, TREE_TYPE (t), unshare_expr (op0), t); + t = fold_build2 (COMPOUND_EXPR, TREE_TYPE (t), unshare_expr (op1), t); if (flag_sanitize_undefined_trap_on_error) tt = build_call_expr_loc (loc, builtin_decl_explicit (BUILT_IN_TRAP), 0); else diff --git gcc/testsuite/c-c++-common/ubsan/pr64906.c gcc/testsuite/c-c++-common/ubsan/pr64906.c index e69de29..e0ac0ee 100644 --- gcc/testsuite/c-c++-common/ubsan/pr64906.c +++ gcc/testsuite/c-c++-common/ubsan/pr64906.c @@ -0,0 +1,12 @@ +/* PR sanitizer/64906 */ +/* { dg-do compile } */ +/* { dg-options "-fsanitize=integer-divide-by-zero -O -Werror=maybe-uninitialized" } */ + +int +fn1 (int f, int s) +{ + int ret = 0; + if (f) + ret = s / (f ? (unsigned long) 8 : 0); + return ret; +} Marek