re PR c/63862 (C frontend converts shift-count to int while standard wants integer...
authorMarek Polacek <polacek@redhat.com>
Fri, 28 Nov 2014 09:06:48 +0000 (09:06 +0000)
committerMarek Polacek <mpolacek@gcc.gnu.org>
Fri, 28 Nov 2014 09:06:48 +0000 (09:06 +0000)
PR c/63862
c-family/
* c-ubsan.c (ubsan_instrument_shift): Change the type of a MINUS_EXPR
to op1_utype.
* c-gimplify.c (c_gimplify_expr): Convert right operand of a shift
expression to unsigned_type_node.
c/
* c-typeck.c (build_binary_op) <RSHIFT_EXPR, LSHIFT_EXPR>: Don't
convert the right operand to integer type.
cp/
* typeck.c (cp_build_binary_op) <RSHIFT_EXPR, LSHIFT_EXPR>: Don't
convert the right operand to integer type.
testsuite/
* gcc.c-torture/execute/shiftopt-1.c: Don't XFAIL anymore.
* c-c++-common/ubsan/shift-7.c: New test.

From-SVN: r218142

gcc/c-family/ChangeLog
gcc/c-family/c-gimplify.c
gcc/c-family/c-ubsan.c
gcc/c/ChangeLog
gcc/c/c-typeck.c
gcc/cp/ChangeLog
gcc/cp/typeck.c
gcc/testsuite/ChangeLog
gcc/testsuite/c-c++-common/ubsan/shift-7.c [new file with mode: 0644]
gcc/testsuite/gcc.c-torture/execute/shiftopt-1.c

index 74172f9624207b9b36ff3ab8d039fee32e0f12fd..efb4735f01adf58ae22678015d85caea8a43a9c8 100644 (file)
@@ -1,3 +1,11 @@
+2014-11-28  Marek Polacek  <polacek@redhat.com>
+
+       PR c/63862
+       * c-ubsan.c (ubsan_instrument_shift): Change the type of a MINUS_EXPR
+       to op1_utype.
+       * c-gimplify.c (c_gimplify_expr): Convert right operand of a shift
+       expression to unsigned_type_node.
+
 2014-11-20  Mark Wielaard  <mjw@redhat.com>
 
        PR debug/38757
index 85b42237538b665e3ab7f7cd3648511cf99bfd32..2cfa5d96a65a17fa99c0a472e5030ed92632c054 100644 (file)
@@ -242,6 +242,24 @@ c_gimplify_expr (tree *expr_p, gimple_seq *pre_p ATTRIBUTE_UNUSED,
 
   switch (code)
     {
+    case LSHIFT_EXPR:
+    case RSHIFT_EXPR:
+      {
+       /* We used to convert the right operand of a shift-expression
+          to an integer_type_node in the FEs.  But it is unnecessary
+          and not desirable for diagnostics and sanitizers.  We keep
+          this here to not pessimize the code, but we convert to an
+          unsigned type, because negative shift counts are undefined
+          anyway.
+          We should get rid of this conversion when we have a proper
+          type demotion/promotion pass.  */
+       tree *op1_p = &TREE_OPERAND (*expr_p, 1);
+       if (TREE_CODE (TREE_TYPE (*op1_p)) != VECTOR_TYPE
+           && TYPE_MAIN_VARIANT (TREE_TYPE (*op1_p)) != unsigned_type_node)
+         *op1_p = convert (unsigned_type_node, *op1_p);
+       break;
+      }
+
     case DECL_EXPR:
       /* This is handled mostly by gimplify.c, but we have to deal with
         not warning about int x = x; as it is a GCC extension to turn off
index 90b03f23e73993497ab19d0a9b2c5a6d88650aa8..96afc674866b5f6f6d0b62d92200f7f4170253cd 100644 (file)
@@ -151,7 +151,7 @@ ubsan_instrument_shift (location_t loc, enum tree_code code,
       && !TYPE_UNSIGNED (type0)
       && flag_isoc99)
     {
-      tree x = fold_build2 (MINUS_EXPR, unsigned_type_node, uprecm1,
+      tree x = fold_build2 (MINUS_EXPR, op1_utype, uprecm1,
                            fold_convert (op1_utype, op1));
       tt = fold_convert_loc (loc, unsigned_type_for (type0), op0);
       tt = fold_build2 (RSHIFT_EXPR, TREE_TYPE (tt), tt, x);
index e2a96309c7b6f3fbe67ca9dd6142fecd57e1efec..0f42b10c0cfdc825a3e304fe82d8a85d419f7c5b 100644 (file)
@@ -1,3 +1,9 @@
+2014-11-28  Marek Polacek  <polacek@redhat.com>
+
+       PR c/63862
+       * c-typeck.c (build_binary_op) <RSHIFT_EXPR, LSHIFT_EXPR>: Don't
+       convert the right operand to integer type.
+
 2014-11-25  Marek Polacek  <polacek@redhat.com>
 
        PR c/63877
index 67efb465a2440120d43a0b82fa25b7c94b408878..bf0f30624d6cd2a4579b476d5e9cde74cb7ccd55 100644 (file)
@@ -10513,11 +10513,6 @@ build_binary_op (location_t location, enum tree_code code,
 
          /* Use the type of the value to be shifted.  */
          result_type = type0;
-         /* Convert the non vector shift-count to an integer, regardless
-            of size of value being shifted.  */
-         if (TREE_CODE (TREE_TYPE (op1)) != VECTOR_TYPE
-             && TYPE_MAIN_VARIANT (TREE_TYPE (op1)) != integer_type_node)
-           op1 = convert (integer_type_node, op1);
          /* Avoid converting op1 to result_type later.  */
          converted = 1;
        }
@@ -10563,11 +10558,6 @@ build_binary_op (location_t location, enum tree_code code,
 
          /* Use the type of the value to be shifted.  */
          result_type = type0;
-         /* Convert the non vector shift-count to an integer, regardless
-            of size of value being shifted.  */
-         if (TREE_CODE (TREE_TYPE (op1)) != VECTOR_TYPE
-             && TYPE_MAIN_VARIANT (TREE_TYPE (op1)) != integer_type_node)
-           op1 = convert (integer_type_node, op1);
          /* Avoid converting op1 to result_type later.  */
          converted = 1;
        }
index a59182bdeb42dab5fb2e58ceb3396940dbf601fa..daf7f9ba06da6b4422a8109d4fab50c5c3ad2ecc 100644 (file)
@@ -1,3 +1,9 @@
+2014-11-28  Marek Polacek  <polacek@redhat.com>
+
+       PR c/63862
+       * typeck.c (cp_build_binary_op) <RSHIFT_EXPR, LSHIFT_EXPR>: Don't
+       convert the right operand to integer type.
+
 2014-11-27  Kai Tietz  <ktietz@redhat.com>
 
        PR c++/63904
index 8b66acc9011e6dbe06195ff104ea0eab5eb2168f..6ca346b8bd35e2c292dada0f94ffcdddcbc55da2 100644 (file)
@@ -4295,10 +4295,6 @@ cp_build_binary_op (location_t location,
                             "right shift count >= width of type");
                }
            }
-         /* Convert the shift-count to an integer, regardless of
-            size of value being shifted.  */
-         if (TYPE_MAIN_VARIANT (TREE_TYPE (op1)) != integer_type_node)
-           op1 = cp_convert (integer_type_node, op1, complain);
          /* Avoid converting op1 to result_type later.  */
          converted = 1;
        }
@@ -4344,10 +4340,6 @@ cp_build_binary_op (location_t location,
                             "left shift count >= width of type");
                }
            }
-         /* Convert the shift-count to an integer, regardless of
-            size of value being shifted.  */
-         if (TYPE_MAIN_VARIANT (TREE_TYPE (op1)) != integer_type_node)
-           op1 = cp_convert (integer_type_node, op1, complain);
          /* Avoid converting op1 to result_type later.  */
          converted = 1;
        }
index 4647a46595d6f5bf93b4c2a1b201487949d749bd..4bb39e1915bb21c12b7352a05285c748e63fd84a 100644 (file)
@@ -1,3 +1,9 @@
+2014-11-28  Marek Polacek  <polacek@redhat.com>
+
+       PR c/63862
+       * gcc.c-torture/execute/shiftopt-1.c: Don't XFAIL anymore.
+       * c-c++-common/ubsan/shift-7.c: New test.
+
 2014-11-28  Richard Biener  <rguenther@suse.de>
 
        PR middle-end/64084
diff --git a/gcc/testsuite/c-c++-common/ubsan/shift-7.c b/gcc/testsuite/c-c++-common/ubsan/shift-7.c
new file mode 100644 (file)
index 0000000..1e33273
--- /dev/null
@@ -0,0 +1,27 @@
+/* PR c/63862 */
+/* { dg-do run } */
+/* { dg-options "-fsanitize=undefined" } */
+
+unsigned long long int __attribute__ ((noinline, noclone))
+foo (unsigned long long int i, unsigned long long int j)
+{
+  asm ("");
+  return i >> j;
+}
+
+unsigned long long int __attribute__ ((noinline, noclone))
+bar (unsigned long long int i, unsigned long long int j)
+{
+  asm ("");
+  return i << j;
+}
+
+int
+main ()
+{
+  foo (1ULL, 0x100000000ULL);
+  bar (1ULL, 0x100000000ULL);
+}
+
+/* { dg-output "shift exponent 4294967296 is too large for \[^\n\r]*-bit type 'long long unsigned int'\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*shift exponent 4294967296 is too large for \[^\n\r]*-bit type 'long long unsigned int'\[^\n\r]*(\n|\r\n|\r)" } */
index 3ff714d3b475fddfd82c6059610ad74596ca0d6a..8c855b88895bbe211a683c34a984ed14176db6dc 100644 (file)
@@ -22,16 +22,11 @@ utest (unsigned int x)
   if (0 >> x != 0)
     link_error ();
 
-  /* XFAIL: the C frontend converts the shift amount to 'int'
-     thus we get -1 >> (int)x which means the shift amount may
-     be negative.  See PR63862.  */
-#if 0
   if (-1 >> x != -1)
     link_error ();
 
   if (~0 >> x != ~0)
     link_error ();
-#endif
 }
 
 void