This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[PATCH v2] extend shift count warnings to vector types


gcc/c/
2016-07-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-07-01  Jan Beulich  <jbeulich@suse.com>

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

--- 2016-06-30/gcc/c/c-fold.c
+++ 2016-06-30/gcc/c/c-fold.c
@@ -320,8 +320,6 @@ c_fully_fold_internal (tree expr, bool i
       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 i
 			(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...  */
--- 2016-06-30/gcc/c/c-typeck.c
+++ 2016-06-30/gcc/c/c-typeck.c
@@ -10985,21 +10985,16 @@ build_binary_op (location_t location, en
 	 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;
@@ -11012,6 +11007,18 @@ build_binary_op (location_t location, en
 		    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))
@@ -11035,21 +11042,16 @@ build_binary_op (location_t location, en
       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;
@@ -11073,6 +11075,18 @@ build_binary_op (location_t location, en
 		    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;
--- 2016-06-30/gcc/testsuite/gcc.dg/vshift-6.c
+++ 2016-06-30/gcc/testsuite/gcc.dg/vshift-6.c
@@ -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;
+}
--- 2016-06-30/gcc/testsuite/gcc.dg/vshift-7.c
+++ 2016-06-30/gcc/testsuite/gcc.dg/vshift-7.c
@@ -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;
+}



Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]