On Wed, 19 Nov 2014, Marek Polacek wrote: > The problem here is that negate_expr_p returns true (as it should) > for UINT_MAX(OVF), but fold_negate_expr didn't actually fold it, > and that is a no-no; if negate_expr_p is true, fold_negate_expr must > not return NULL_TREE. I added the following hunk for bootstrap and > regtest for better coverage: > > @@ -752,6 +755,12 @@ fold_negate_expr (location_t loc, tree t) > break; > } > > +#ifdef ENABLE_CHECKING > + if (negate_expr_p (t)) > + internal_error ("fold_negate_expr should never return NULL_TREE " > + "if negate_expr_p is true"); > +#endif > + > return NULL_TREE; > } > > Fixed by adjusting fold_negate_expr so that it folds non-trapping > wrapping constants. The SANITIZE_SI_OVERFLOW check is important > to not regress -Woverflow warnings (ug). > > negate_expr_p hunk is to match the NEGATE_EXPR case in fold_negate_expr. > > Bootstrapped/regtested on power8-linux, ok for trunk?
Ok. Thanks, Richard. > 2014-11-19 Marek Polacek <pola...@redhat.com> > > PR sanitizer/63879 > * fold-const.c (negate_expr_p) <case NEGATE_EXPR>: Return > !TYPE_OVERFLOW_SANITIZED. > (fold_negate_expr) <case INTEGER_CST>: Fold when overflow > does not trap and when overflow wraps, or when SANITIZE_SI_OVERFLOW > is 0. > > * c-c++-common/ubsan/pr63879-1.c: New test. > * c-c++-common/ubsan/pr63879-2.c: New test. > > diff --git gcc/fold-const.c gcc/fold-const.c > index f6fb8af..719e06e 100644 > --- gcc/fold-const.c > +++ gcc/fold-const.c > @@ -408,9 +408,11 @@ negate_expr_p (tree t) > && TYPE_OVERFLOW_WRAPS (type)); > > case FIXED_CST: > - case NEGATE_EXPR: > return true; > > + case NEGATE_EXPR: > + return !TYPE_OVERFLOW_SANITIZED (type); > + > case REAL_CST: > /* We want to canonicalize to positive real constants. Pretend > that only negative ones can be easily negated. */ > @@ -555,7 +557,8 @@ fold_negate_expr (location_t loc, tree t) > tem = fold_negate_const (t, type); > if (TREE_OVERFLOW (tem) == TREE_OVERFLOW (t) > || (!TYPE_OVERFLOW_TRAPS (type) > - && (flag_sanitize & SANITIZE_SI_OVERFLOW) == 0)) > + && TYPE_OVERFLOW_WRAPS (type)) > + || (flag_sanitize & SANITIZE_SI_OVERFLOW) == 0) > return tem; > break; > > diff --git gcc/testsuite/c-c++-common/ubsan/pr63879-1.c > gcc/testsuite/c-c++-common/ubsan/pr63879-1.c > index e69de29..2035849 100644 > --- gcc/testsuite/c-c++-common/ubsan/pr63879-1.c > +++ gcc/testsuite/c-c++-common/ubsan/pr63879-1.c > @@ -0,0 +1,23 @@ > +/* PR sanitizer/63879 */ > +/* { dg-do compile } */ > +/* { dg-options "-fsanitize=undefined" } */ > + > +struct A > +{ > + int inode; > +} * a; > +int b, c; > +void > +fn1 () > +{ > + int d = 0; > + while (b) > + { > + if (a->inode) > + d++; > + a = 0; > + } > + c = d - 1; > + for (; c >= 0; c--) > + ; > +} > diff --git gcc/testsuite/c-c++-common/ubsan/pr63879-2.c > gcc/testsuite/c-c++-common/ubsan/pr63879-2.c > index e69de29..34eb8e7 100644 > --- gcc/testsuite/c-c++-common/ubsan/pr63879-2.c > +++ gcc/testsuite/c-c++-common/ubsan/pr63879-2.c > @@ -0,0 +1,13 @@ > +/* PR sanitizer/63879 */ > +/* { dg-do compile } */ > +/* { dg-options "-fsanitize=undefined" } */ > + > +int a; > +void > +fn1 () > +{ > + int b = 2; > + for (; a;) > + while (b >= 0) > + b--; > +} > > Marek > > -- Richard Biener <rguent...@suse.de> SUSE LINUX GmbH, GF: Jeff Hawn, Jennifer Guild, Felix Imendoerffer, HRB 21284 (AG Nuernberg) Maxfeldstrasse 5, 90409 Nuernberg, Germany