extend shift count warnings to vector types
authorJan Beulich <jbeulich@suse.com>
Mon, 1 Aug 2016 09:39:52 +0000 (09:39 +0000)
committerJan Beulich <jbeulich@gcc.gnu.org>
Mon, 1 Aug 2016 09:39:52 +0000 (09:39 +0000)
gcc/c/
2016-08-01  Jan Beulich  <jbeulich@suse.com>

* c-fold.c (c_fully_fold_internal): Also emit shift count
warnings for vector types.
* c-typeck.c (build_binary_op): Likewise.

gcc/testsuite/
2016-08-01  Jan Beulich  <jbeulich@suse.com>

* gcc.dg/vshift-6.c, gcc.dg/vshift-7.c: New.

From-SVN: r238936

gcc/c/ChangeLog
gcc/c/c-fold.c
gcc/c/c-typeck.c
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.dg/vshift-6.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/vshift-7.c [new file with mode: 0644]

index 06507581fad785558e8812bff1fc65fc1676298b..1c0688b29a1020f740e7fe3551e700914b32a7bb 100644 (file)
@@ -1,3 +1,9 @@
+2016-08-01  Jan Beulich  <jbeulich@suse.com>
+
+       * c-fold.c (c_fully_fold_internal): Also emit shift count
+       warnings for vector types.
+       * c-typeck.c (build_binary_op): Likewise.
+
 2016-07-29  Marek Polacek  <polacek@redhat.com>
 
        PR c/71742
index 6c82f242bf142c050ebcff8210126c5a930d94b5..8bc3a9c178f5ff708e31505b0b60c79cdea20f8a 100644 (file)
@@ -320,8 +320,6 @@ c_fully_fold_internal (tree expr, bool in_init, bool *maybe_const_operands,
       if ((code == LSHIFT_EXPR || code == RSHIFT_EXPR)
          && TREE_CODE (orig_op1) != INTEGER_CST
          && TREE_CODE (op1) == INTEGER_CST
-         && (TREE_CODE (TREE_TYPE (orig_op0)) == INTEGER_TYPE
-             || TREE_CODE (TREE_TYPE (orig_op0)) == FIXED_POINT_TYPE)
          && TREE_CODE (TREE_TYPE (orig_op1)) == INTEGER_TYPE
          && c_inhibit_evaluation_warnings == 0)
        {
@@ -330,13 +328,23 @@ c_fully_fold_internal (tree expr, bool in_init, bool *maybe_const_operands,
                        (code == LSHIFT_EXPR
                         ? G_("left shift count is negative")
                         : G_("right shift count is negative")));
-         else if (compare_tree_int (op1,
-                                    TYPE_PRECISION (TREE_TYPE (orig_op0)))
-                  >= 0)
+         else if ((TREE_CODE (TREE_TYPE (orig_op0)) == INTEGER_TYPE
+                   || TREE_CODE (TREE_TYPE (orig_op0)) == FIXED_POINT_TYPE)
+                  && compare_tree_int (op1,
+                                       TYPE_PRECISION (TREE_TYPE (orig_op0)))
+                     >= 0)
            warning_at (loc, OPT_Wshift_count_overflow,
                        (code == LSHIFT_EXPR
                         ? G_("left shift count >= width of type")
                         : G_("right shift count >= width of type")));
+         else if (TREE_CODE (TREE_TYPE (orig_op0)) == VECTOR_TYPE
+                  && compare_tree_int (op1,
+                                       TYPE_PRECISION (TREE_TYPE (TREE_TYPE (orig_op0))))
+                     >= 0)
+           warning_at (loc, OPT_Wshift_count_overflow,
+                       code == LSHIFT_EXPR
+                       ? G_("left shift count >= width of vector element")
+                       : G_("right shift count >= width of vector element"));
        }
       if (code == LSHIFT_EXPR
          /* If either OP0 has been folded to INTEGER_CST...  */
index 07e39ef04d1b4c95bc9db4df2bc9d3389c3238c5..33c06d40417cf8a89af9a4f2ec7aedf37517c930 100644 (file)
@@ -10986,21 +10986,16 @@ build_binary_op (location_t location, enum tree_code code,
         Also set SHORT_SHIFT if shifting rightward.  */
 
     case RSHIFT_EXPR:
-      if (code0 == VECTOR_TYPE && code1 == INTEGER_TYPE
-          && TREE_CODE (TREE_TYPE (type0)) == INTEGER_TYPE)
-        {
-          result_type = type0;
-          converted = 1;
-        }
-      else if (code0 == VECTOR_TYPE && code1 == VECTOR_TYPE
-              && TREE_CODE (TREE_TYPE (type0)) == INTEGER_TYPE
-              && TREE_CODE (TREE_TYPE (type1)) == INTEGER_TYPE
-              && TYPE_VECTOR_SUBPARTS (type0) == TYPE_VECTOR_SUBPARTS (type1))
+      if (code0 == VECTOR_TYPE && code1 == VECTOR_TYPE
+         && TREE_CODE (TREE_TYPE (type0)) == INTEGER_TYPE
+         && TREE_CODE (TREE_TYPE (type1)) == INTEGER_TYPE
+         && TYPE_VECTOR_SUBPARTS (type0) == TYPE_VECTOR_SUBPARTS (type1))
        {
          result_type = type0;
          converted = 1;
        }
-      else if ((code0 == INTEGER_TYPE || code0 == FIXED_POINT_TYPE)
+      else if ((code0 == INTEGER_TYPE || code0 == FIXED_POINT_TYPE
+               || code0 == VECTOR_TYPE)
               && code1 == INTEGER_TYPE)
        {
          doing_shift = true;
@@ -11013,6 +11008,18 @@ build_binary_op (location_t location, enum tree_code code,
                    warning_at (location, OPT_Wshift_count_negative,
                                "right shift count is negative");
                }
+             else if (code0 == VECTOR_TYPE)
+               {
+                 if (compare_tree_int (op1,
+                                       TYPE_PRECISION (TREE_TYPE (type0)))
+                     >= 0)
+                   {
+                     int_const = false;
+                     if (c_inhibit_evaluation_warnings == 0)
+                       warning_at (location, OPT_Wshift_count_overflow,
+                                   "right shift count >= width of vector element");
+                   }
+               }
              else
                {
                  if (!integer_zerop (op1))
@@ -11036,21 +11043,16 @@ build_binary_op (location_t location, enum tree_code code,
       break;
 
     case LSHIFT_EXPR:
-      if (code0 == VECTOR_TYPE && code1 == INTEGER_TYPE
-          && TREE_CODE (TREE_TYPE (type0)) == INTEGER_TYPE)
-        {
-          result_type = type0;
-          converted = 1;
-        }
-      else if (code0 == VECTOR_TYPE && code1 == VECTOR_TYPE
-              && TREE_CODE (TREE_TYPE (type0)) == INTEGER_TYPE
-              && TREE_CODE (TREE_TYPE (type1)) == INTEGER_TYPE
-              && TYPE_VECTOR_SUBPARTS (type0) == TYPE_VECTOR_SUBPARTS (type1))
+      if (code0 == VECTOR_TYPE && code1 == VECTOR_TYPE
+         && TREE_CODE (TREE_TYPE (type0)) == INTEGER_TYPE
+         && TREE_CODE (TREE_TYPE (type1)) == INTEGER_TYPE
+         && TYPE_VECTOR_SUBPARTS (type0) == TYPE_VECTOR_SUBPARTS (type1))
        {
          result_type = type0;
          converted = 1;
        }
-      else if ((code0 == INTEGER_TYPE || code0 == FIXED_POINT_TYPE)
+      else if ((code0 == INTEGER_TYPE || code0 == FIXED_POINT_TYPE
+               || code0 == VECTOR_TYPE)
               && code1 == INTEGER_TYPE)
        {
          doing_shift = true;
@@ -11074,6 +11076,18 @@ build_binary_op (location_t location, enum tree_code code,
                    warning_at (location, OPT_Wshift_count_negative,
                                "left shift count is negative");
                }
+             else if (code0 == VECTOR_TYPE)
+               {
+                 if (compare_tree_int (op1,
+                                       TYPE_PRECISION (TREE_TYPE (type0)))
+                     >= 0)
+                   {
+                     int_const = false;
+                     if (c_inhibit_evaluation_warnings == 0)
+                       warning_at (location, OPT_Wshift_count_overflow,
+                                   "left shift count >= width of vector element");
+                   }
+               }
              else if (compare_tree_int (op1, TYPE_PRECISION (type0)) >= 0)
                {
                  int_const = false;
index ec6d798e1be956d9bdf6e3e4ec8b818060af746d..c16b269862499aa399ad8ee33644768ddf48bc66 100644 (file)
@@ -1,3 +1,7 @@
+2016-08-01  Jan Beulich  <jbeulich@suse.com>
+
+       * gcc.dg/vshift-6.c, gcc.dg/vshift-7.c: New.
+
 2016-07-31  Bill Schmidt  <wschmidt@linux.vnet.ibm.com>
 
        * gcc.target/powerpc/divkc3-1.c: Require POWER8 hardware.
diff --git a/gcc/testsuite/gcc.dg/vshift-6.c b/gcc/testsuite/gcc.dg/vshift-6.c
new file mode 100644 (file)
index 0000000..6f7a0b0
--- /dev/null
@@ -0,0 +1,42 @@
+/* { dg-do compile } */
+/* { dg-options "-Wshift-count-negative -Wshift-count-overflow" } */
+
+typedef unsigned int v1qi_t __attribute__((mode(QI), vector_size(1)));
+typedef unsigned int v1hi_t __attribute__((mode(HI), vector_size(2)));
+typedef unsigned int v1si_t __attribute__((mode(SI), vector_size(4)));
+
+v1qi_t test1qi(v1qi_t x, int c) {
+       switch(c) {
+       case 0: return x << -1; /* { dg-warning "shift count is negative" } */
+       case 1: return x << 7;
+       case 2: return x << 8; /* { dg-warning "shift count >= width" } */
+       case ~0: return x >> -1; /* { dg-warning "shift count is negative" } */
+       case ~1: return x >> 7;
+       case ~2: return x >> 8; /* { dg-warning "shift count >= width" } */
+       }
+       return c < 0 ? x >> -c : x << c;
+}
+
+v1hi_t test1hi(v1hi_t x, int c) {
+       switch(c) {
+       case 0: return x << -1; /* { dg-warning "shift count is negative" } */
+       case 1: return x << 15;
+       case 2: return x << 16; /* { dg-warning "shift count >= width" } */
+       case ~0: return x >> -1; /* { dg-warning "shift count is negative" } */
+       case ~1: return x >> 15;
+       case ~2: return x >> 16; /* { dg-warning "shift count >= width" } */
+       }
+       return c < 0 ? x >> -c : x << c;
+}
+
+v1si_t test1si(v1si_t x, int c) {
+       switch(c) {
+       case 0: return x << -1; /* { dg-warning "shift count is negative" } */
+       case 1: return x << 31;
+       case 2: return x << 32; /* { dg-warning "shift count >= width" } */
+       case ~0: return x >> -1; /* { dg-warning "shift count is negative" } */
+       case ~1: return x >> 31;
+       case ~2: return x >> 32; /* { dg-warning "shift count >= width" } */
+       }
+       return c < 0 ? x >> -c : x << c;
+}
diff --git a/gcc/testsuite/gcc.dg/vshift-7.c b/gcc/testsuite/gcc.dg/vshift-7.c
new file mode 100644 (file)
index 0000000..2732120
--- /dev/null
@@ -0,0 +1,47 @@
+/* { dg-do compile } */
+/* { dg-options "-O1 -Wshift-count-negative -Wshift-count-overflow" } */
+
+typedef unsigned int v1qi_t __attribute__((mode(QI), vector_size(1)));
+typedef unsigned int v1hi_t __attribute__((mode(HI), vector_size(2)));
+typedef unsigned int v1si_t __attribute__((mode(SI), vector_size(4)));
+
+static const signed shift_neg = -1;
+static const unsigned shift_qi = 8;
+static const unsigned shift_hi = 16;
+static const unsigned shift_si = 32;
+
+v1qi_t test1qi(v1qi_t x, int c) {
+       switch(c) {
+       case 0: return x << shift_neg; /* { dg-warning "shift count is negative" } */
+       case 1: return x << (shift_qi - 1);
+       case 2: return x << shift_qi; /* { dg-warning "shift count >= width" } */
+       case ~0: return x >> shift_neg; /* { dg-warning "shift count is negative" } */
+       case ~1: return x >> (shift_qi - 1);
+       case ~2: return x >> shift_qi; /* { dg-warning "shift count >= width" } */
+       }
+       return c < 0 ? x >> -c : x << c;
+}
+
+v1hi_t test1hi(v1hi_t x, int c) {
+       switch(c) {
+       case 0: return x << shift_neg; /* { dg-warning "shift count is negative" } */
+       case 1: return x << (shift_hi - 1);
+       case 2: return x << shift_hi; /* { dg-warning "shift count >= width" } */
+       case ~0: return x >> shift_neg; /* { dg-warning "shift count is negative" } */
+       case ~1: return x >> (shift_hi - 1);
+       case ~2: return x >> shift_hi; /* { dg-warning "shift count >= width" } */
+       }
+       return c < 0 ? x >> -c : x << c;
+}
+
+v1si_t test1si(v1si_t x, int c) {
+       switch(c) {
+       case 0: return x << shift_neg; /* { dg-warning "shift count is negative" } */
+       case 1: return x << (shift_si - 1);
+       case 2: return x << shift_si; /* { dg-warning "shift count >= width" } */
+       case ~0: return x >> shift_neg; /* { dg-warning "shift count is negative" } */
+       case ~1: return x >> (shift_si - 1);
+       case ~2: return x >> shift_si; /* { dg-warning "shift count >= width" } */
+       }
+       return c < 0 ? x >> -c : x << c;
+}