On Wed, Apr 12, 2017 at 06:12:57PM +0200, Jakub Jelinek wrote: > @@ -11542,7 +11544,7 @@ fold_ternary_loc (location_t loc, enum t > && (code == VEC_COND_EXPR || !VECTOR_TYPE_P (type))) > return fold_build2_loc (loc, code == VEC_COND_EXPR ? BIT_AND_EXPR > : TRUTH_ANDIF_EXPR, > - type, fold_convert_loc (loc, type, arg0), arg1); > + type, op0, op1);
This part (just the fold_convert_loc -> op0) has been a thinko, type is the required type of only the op1 and op2 arguments on *COND_EXPR, op0 can have a different type, thus fold_convert is needed there. I've bootstrapped/regtested following reversion of that + testcase and committed as obvious to trunk. 2017-04-13 Jakub Jelinek <ja...@redhat.com> PR sanitizer/80403 * fold-const.c (fold_ternary_loc): Revert use op0 instead of fold_convert_loc (loc, type, arg0) part of 2017-04-12 change. * g++.dg/ubsan/pr80403-2.C: New test. --- gcc/fold-const.c.jj 2017-04-12 20:07:22.000000000 +0200 +++ gcc/fold-const.c 2017-04-13 16:08:26.429745344 +0200 @@ -11544,7 +11544,7 @@ fold_ternary_loc (location_t loc, enum t && (code == VEC_COND_EXPR || !VECTOR_TYPE_P (type))) return fold_build2_loc (loc, code == VEC_COND_EXPR ? BIT_AND_EXPR : TRUTH_ANDIF_EXPR, - type, op0, op1); + type, fold_convert_loc (loc, type, arg0), op1); /* Convert A ? B : 1 into !A || B if A and B are truth values. */ if (code == VEC_COND_EXPR ? integer_all_onesp (op2) : integer_onep (op2) --- gcc/testsuite/g++.dg/ubsan/pr80403-2.C.jj 2017-04-13 16:11:46.277223411 +0200 +++ gcc/testsuite/g++.dg/ubsan/pr80403-2.C 2017-04-13 16:11:11.000000000 +0200 @@ -0,0 +1,14 @@ +// PR sanitizer/80403 +// { dg-do compile } +// { dg-options "-fsanitize=undefined" } + +extern const long long int v; +extern unsigned long int w; + +int +foo () +{ + int a = (0 - 40U <= (0 == 8)) << !w << (0 < v) == 0; + int b = ((0 ^ 0) < (long) (1066066618772207110 <= 0)) / 0 << 0; // { dg-warning "division by zero" } + return a + b; +} Jakub