The associate case in folding ignores overflow when one of the literals
involved has TREE_OVERFLOW set.  That is obviously wrong as TREE_OVERFLOW
doesn't necessarily mean sth undefined happened (and thus GIGO) as we
are setting TREE_OVERFLOW also on implementation-defined unsigned->int
conversions.

Simply drop that wart and the overflow flag from literals in split_tree
to avoid doing less than before.

Bootstrapped and tested on x86_64-unknown-linux-gnu, applied to trunk
sofar.

Richard.

2017-06-14  Richard Biener  <rguent...@suse.de>

        PR middle-end/81088
        * fold-const.c (split_tree): Drop TREE_OVERFLOW flag from
        literal constants.
        (fold_binary_loc): When associating do not treat pre-existing
        TREE_OVERFLOW on literal constants as a reason to allow
        TREE_OVERFLOW on associated literal constants.

        * c-c++-common/ubsan/pr81088.c: New testcase.

Index: gcc/fold-const.c
===================================================================
*** gcc/fold-const.c    (revision 249185)
--- gcc/fold-const.c    (working copy)
*************** split_tree (location_t loc, tree in, tre
*** 880,885 ****
--- 880,892 ----
        }
      }
  
+   if (*litp
+       && TREE_OVERFLOW_P (*litp))
+     *litp = drop_tree_overflow (*litp);
+   if (*minus_litp
+       && TREE_OVERFLOW_P (*minus_litp))
+     *minus_litp = drop_tree_overflow (*minus_litp);
+ 
    return var;
  }
  
*************** fold_binary_loc (location_t loc,
*** 9703,9713 ****
                       + (lit0 != 0) + (lit1 != 0)
                       + (minus_lit0 != 0) + (minus_lit1 != 0))))
            {
-             bool any_overflows = false;
-             if (lit0) any_overflows |= TREE_OVERFLOW (lit0);
-             if (lit1) any_overflows |= TREE_OVERFLOW (lit1);
-             if (minus_lit0) any_overflows |= TREE_OVERFLOW (minus_lit0);
-             if (minus_lit1) any_overflows |= TREE_OVERFLOW (minus_lit1);
              var0 = associate_trees (loc, var0, var1, code, atype);
              con0 = associate_trees (loc, con0, con1, code, atype);
              lit0 = associate_trees (loc, lit0, lit1, code, atype);
--- 9710,9715 ----
*************** fold_binary_loc (location_t loc,
*** 9738,9746 ****
                }
  
              /* Don't introduce overflows through reassociation.  */
!             if (!any_overflows
!                 && ((lit0 && TREE_OVERFLOW_P (lit0))
!                     || (minus_lit0 && TREE_OVERFLOW_P (minus_lit0))))
                return NULL_TREE;
  
              if (minus_lit0)
--- 9740,9747 ----
                }
  
              /* Don't introduce overflows through reassociation.  */
!             if ((lit0 && TREE_OVERFLOW_P (lit0))
!                 || (minus_lit0 && TREE_OVERFLOW_P (minus_lit0)))
                return NULL_TREE;
  
              if (minus_lit0)
Index: gcc/testsuite/c-c++-common/ubsan/pr81088.c
===================================================================
*** gcc/testsuite/c-c++-common/ubsan/pr81088.c  (nonexistent)
--- gcc/testsuite/c-c++-common/ubsan/pr81088.c  (working copy)
***************
*** 0 ****
--- 1,11 ----
+ /* { dg-do run } */
+ /* { dg-options "-fsanitize=undefined -fsanitize-undefined-trap-on-error" } */
+ 
+ short s = 2;
+ short y = 1;
+ int i;
+ int main()
+ {
+   i = -(s + (int)(~(unsigned)(0 / y))) + 0x7fffffff;
+   return 0;
+ }

Reply via email to