This fixes a wrong re-association which can introduce undefined overflow. The fix is to perform this only when overflow is known to wrap.
Bootstrap and regtest pending on x86_64-unknown-linux-gnu. Richard. 2011-08-03 Richard Guenther <rguent...@suse.de> PR middle-end/49958 * fold-const.c (fold_binary_loc): Only associate (+ (+ (* a b) c) (* d e)) as (+ (+ (* a b) (* d e)) c) if overflow wraps. Index: gcc/fold-const.c =================================================================== --- gcc/fold-const.c (revision 177094) +++ gcc/fold-const.c (working copy) @@ -9712,12 +9712,13 @@ fold_binary_loc (location_t loc, /* Reassociate (plus (plus (mult) (foo)) (mult)) as (plus (plus (mult) (mult)) (foo)) so that we can take advantage of the factoring cases below. */ - if (((TREE_CODE (arg0) == PLUS_EXPR - || TREE_CODE (arg0) == MINUS_EXPR) - && TREE_CODE (arg1) == MULT_EXPR) - || ((TREE_CODE (arg1) == PLUS_EXPR - || TREE_CODE (arg1) == MINUS_EXPR) - && TREE_CODE (arg0) == MULT_EXPR)) + if (TYPE_OVERFLOW_WRAPS (type) + && (((TREE_CODE (arg0) == PLUS_EXPR + || TREE_CODE (arg0) == MINUS_EXPR) + && TREE_CODE (arg1) == MULT_EXPR) + || ((TREE_CODE (arg1) == PLUS_EXPR + || TREE_CODE (arg1) == MINUS_EXPR) + && TREE_CODE (arg0) == MULT_EXPR))) { tree parg0, parg1, parg, marg; enum tree_code pcode; Index: gcc/testsuite/gcc.dg/torture/pr49958.c =================================================================== --- gcc/testsuite/gcc.dg/torture/pr49958.c (revision 0) +++ gcc/testsuite/gcc.dg/torture/pr49958.c (revision 0) @@ -0,0 +1,11 @@ +/* { dg-do run } */ +/* { dg-options "-fstrict-overflow" } */ + +extern void abort (void); +int foo (int i, int j, int o, int m) { return i*o + 1 + j*m > 1; } +int main() +{ + if (foo (- __INT_MAX__ - 1, -1, 1, 1)) + abort (); + return 0; +}