Hi!

Similarly to PR80349, we have other spots where we don't get the
types right.  opN are the original args, argN is the same after
STRIP_NOPS, so when we want to have type of type, we should use
opN rather than argN (opN is less expensive variant to fold_convert
argN to type).

Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk?

2017-04-12  Jakub Jelinek  <ja...@redhat.com>

        PR sanitizer/80403
        PR sanitizer/80404
        PR sanitizer/80405
        * fold-const.c (fold_ternary_loc): Use op1 instead of arg1 as argument
        to fold_build2_loc.  Convert TREE_OPERAND (tem, 0) to type.  Use
        op0 instead of fold_convert_loc (loc, type, arg0).

        * g++.dg/ubsan/pr80403.C: New test.
        * g++.dg/ubsan/pr80404.C: New test.
        * g++.dg/ubsan/pr80405.C: New test.

--- gcc/fold-const.c.jj 2017-04-12 07:20:42.000000000 +0200
+++ gcc/fold-const.c    2017-04-12 08:59:09.044260961 +0200
@@ -11508,10 +11508,12 @@ fold_ternary_loc (location_t loc, enum t
          STRIP_NOPS (tem);
          if (TREE_CODE (tem) == RSHIFT_EXPR
              && tree_fits_uhwi_p (TREE_OPERAND (tem, 1))
-              && (unsigned HOST_WIDE_INT) tree_log2 (arg1) ==
-                tree_to_uhwi (TREE_OPERAND (tem, 1)))
+              && (unsigned HOST_WIDE_INT) tree_log2 (arg1)
+                == tree_to_uhwi (TREE_OPERAND (tem, 1)))
            return fold_build2_loc (loc, BIT_AND_EXPR, type,
-                               TREE_OPERAND (tem, 0), arg1);
+                                   fold_convert_loc (loc, type,
+                                                     TREE_OPERAND (tem, 0)),
+                                   op1);
        }
 
       /* A & N ? N : 0 is simply A & N if N is a power of two.  This
@@ -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);
 
       /* 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)
@@ -11558,7 +11560,7 @@ fold_ternary_loc (location_t loc, enum t
                                         ? BIT_IOR_EXPR
                                         : TRUTH_ORIF_EXPR,
                                    type, fold_convert_loc (loc, type, tem),
-                                   arg1);
+                                   op1);
        }
 
       /* Convert A ? 0 : B into !A && B if A and B are truth values.  */
--- gcc/testsuite/g++.dg/ubsan/pr80403.C.jj     2017-04-12 08:52:20.954465589 
+0200
+++ gcc/testsuite/g++.dg/ubsan/pr80403.C        2017-04-12 08:52:00.000000000 
+0200
@@ -0,0 +1,11 @@
+// PR sanitizer/80403
+// { dg-do compile }
+// { dg-options "-fsanitize=undefined" }
+
+unsigned
+foo ()
+{
+  unsigned a = (unsigned) (!(6044238 >> 0) >= (0 < 0)) % 0;    // { dg-warning 
"division by zero" }
+  unsigned b = (unsigned) (!(6044238 >> 0) >= (0 < 0)) / 0;    // { dg-warning 
"division by zero" }
+  return a + b;
+}
--- gcc/testsuite/g++.dg/ubsan/pr80404.C.jj     2017-04-12 09:08:43.497014011 
+0200
+++ gcc/testsuite/g++.dg/ubsan/pr80404.C        2017-04-12 09:07:26.000000000 
+0200
@@ -0,0 +1,12 @@
+// PR sanitizer/80404
+// { dg-do compile }
+// { dg-options "-fsanitize=undefined" }
+
+extern short v;
+
+unsigned
+foo ()
+{
+  unsigned a = (0 < 0 >= (0 >= 0)) / (unsigned) v;
+  return a;
+}
--- gcc/testsuite/g++.dg/ubsan/pr80405.C.jj     2017-04-12 09:08:46.663973725 
+0200
+++ gcc/testsuite/g++.dg/ubsan/pr80405.C        2017-04-12 09:07:53.000000000 
+0200
@@ -0,0 +1,11 @@
+// PR sanitizer/80405
+// { dg-do compile }
+// { dg-options "-fsanitize=undefined" }
+
+extern unsigned int v, w;
+
+void
+foo ()
+{
+  w = (!~0 >= (unsigned) (0 < 0)) << v;
+}


        Jakub

Reply via email to