The following makes fold_neagte_const properly handle TREE_OVERFLOW as sticky (even if present on POINTER_TYPE constants).
Bootstrapped and tested on x86_64-unknown-linux-gnu, applied. Richard. 2017-06-25 Richard Biener <rguent...@suse.de> PR middle-end/81505 * fold-const.c (fold_negate_const): TREE_OVERFLOW should be sticky. * gcc.dg/ubsan/pr81505.c: New testcase. Index: gcc/fold-const.c =================================================================== --- gcc/fold-const.c (revision 250386) +++ gcc/fold-const.c (working copy) @@ -13693,8 +13693,8 @@ fold_negate_const (tree arg0, tree type) bool overflow; wide_int val = wi::neg (arg0, &overflow); t = force_fit_type (type, val, 1, - (overflow | TREE_OVERFLOW (arg0)) - && !TYPE_UNSIGNED (type)); + (overflow && ! TYPE_UNSIGNED (type)) + || TREE_OVERFLOW (arg0)); break; } Index: gcc/testsuite/gcc.dg/ubsan/pr81505.c =================================================================== --- gcc/testsuite/gcc.dg/ubsan/pr81505.c (nonexistent) +++ gcc/testsuite/gcc.dg/ubsan/pr81505.c (working copy) @@ -0,0 +1,17 @@ +/* { dg-do compile } */ +/* { dg-options "-O3 -fsanitize=signed-integer-overflow" } */ + +int a, b, c, h; + +int i[5][5]; + +void +fn1 () +{ + int l = 0; + + for (a = 0; a <= 3; a++) + for (b = 1; b >= 0; b -= 1) + l |= i[0][b]; + c = l; +}