Hi! This is another case where we miss needed folding from argN or their arguments to the expected expression type (type has to be compatible with opN's type, but argN is after STRIP_NOPS).
Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk? 2017-04-11 Jakub Jelinek <ja...@redhat.com> PR sanitizer/80349 * fold-const.c (fold_binary_loc) <case BIT_IOR_EXPR>: Convert arg0's first argument to type. * g++.dg/ubsan/pr80349.C: New test. --- gcc/fold-const.c.jj 2017-04-10 22:27:00.000000000 +0200 +++ gcc/fold-const.c 2017-04-11 20:07:02.459839450 +0200 @@ -9916,12 +9916,12 @@ fold_binary_loc (location_t loc, } if (c3 != c1) - return fold_build2_loc (loc, BIT_IOR_EXPR, type, - fold_build2_loc (loc, BIT_AND_EXPR, type, - TREE_OPERAND (arg0, 0), - wide_int_to_tree (type, - c3)), - arg1); + { + tem = fold_convert_loc (loc, type, TREE_OPERAND (arg0, 0)); + tem = fold_build2_loc (loc, BIT_AND_EXPR, type, tem, + wide_int_to_tree (type, c3)); + return fold_build2_loc (loc, BIT_IOR_EXPR, type, tem, arg1); + } } /* See if this can be simplified into a rotate first. If that --- gcc/testsuite/g++.dg/ubsan/pr80349.C.jj 2017-04-11 20:29:10.154344673 +0200 +++ gcc/testsuite/g++.dg/ubsan/pr80349.C 2017-04-11 20:28:38.000000000 +0200 @@ -0,0 +1,11 @@ +// PR sanitizer/80349 +// { dg-do compile } +// { dg-options "-fsanitize=undefined" } + +extern const long long int v; + +void +foo () +{ + (int)((v & 50 | 051UL) << 0) << 0; +} Jakub