I am re-testing the following patch to fix PR81065 with the fold_addr_of_array_ref_difference hunk added which was the only case causing the gcc_unreachable to trigger in a all languages bootstrap and regtest on x86_64-unknown-linux-gnu. The patch to commit will omit this case completely.
Bootstrap and regtest running on x86_64-unknown-linux-gnu. Richard. 2017-06-12 Richard Biener <rguent...@suse.de> PR middle-end/81065 * fold-const.c (extract_muldiv_1): Remove bogus distribution case of C * (x * C2 + C3). (fold_addr_of_array_ref_difference): Properly fold index difference. * c-c++-common/ubsan/pr81065.c: New testcase. Index: gcc/testsuite/c-c++-common/ubsan/pr81065.c =================================================================== --- gcc/testsuite/c-c++-common/ubsan/pr81065.c (nonexistent) +++ gcc/testsuite/c-c++-common/ubsan/pr81065.c (working copy) @@ -0,0 +1,13 @@ +/* { dg-do run } */ +/* { dg-options "-fsanitize=undefined -fsanitize-undefined-trap-on-error" } */ + +unsigned char x = 154; +int foo() { + // 8575 * (254408 - 9057) = 8575 * 245351 = 2103884825 = 0x7d66bc19 + return 8575 * (1652 * x - 9057); +} + +int main() { + foo(); + return 0; +} Index: gcc/fold-const.c =================================================================== --- gcc/fold-const.c (revision 249112) +++ gcc/fold-const.c (working copy) @@ -6243,8 +6243,11 @@ extract_muldiv_1 (tree t, tree c, enum t /* If we were able to eliminate our operation from the first side, apply our operation to the second side and reform the PLUS. */ - if (t1 != 0 && (TREE_CODE (t1) != code || code == MULT_EXPR)) + if (t1 != 0 && TREE_CODE (t1) != code) + { + gcc_unreachable (); return fold_build2 (tcode, ctype, fold_convert (ctype, t1), op1); + } /* The last case is if we are a multiply. In that case, we can apply the distributive law to commute the multiply and addition @@ -8908,7 +8911,7 @@ fold_addr_of_array_ref_difference (locat tree op0 = fold_convert_loc (loc, type, TREE_OPERAND (aref0, 1)); tree op1 = fold_convert_loc (loc, type, TREE_OPERAND (aref1, 1)); tree esz = fold_convert_loc (loc, type, array_ref_element_size (aref0)); - tree diff = build2 (MINUS_EXPR, type, op0, op1); + tree diff = fold_build2_loc (loc, MINUS_EXPR, type, op0, op1); return fold_build2_loc (loc, PLUS_EXPR, type, base_offset, fold_build2_loc (loc, MULT_EXPR, type,