diff mbox

[C/C++] Implement -Wshift-overflow (PR c++/55095) (take 2)

Message ID 20150602192532.GD2756@redhat.com
State New
Headers show

Commit Message

Marek Polacek June 2, 2015, 7:25 p.m. UTC
On Fri, May 29, 2015 at 08:49:58PM +0000, Joseph Myers wrote:
> On Mon, 25 May 2015, Marek Polacek wrote:
> 
> > +/* Warn if signed left shift overflows.  Note that we don't warn
> > +   about left-shifting 1 into the sign bit; cf.
> > +   <http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2012/n3367.html#1457>
> > +   for C++ and <http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1817.htm>
> > +   for C.  LOC is a location of the shift; OP0 and OP1 are the operands.
> > +   Return true if an overflow is detected, false otherwise.  */
> 
> But for C that was declared not a defect.  See 
> <http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1931.htm#dr_463>.  So 
> for C99 and later we *should* consider this an overflow (for the purposes 
> of pedwarns-if-pedantic in contexts where an integer constant expression 
> is required; maybe -Wshift-overflow=2 for other warnings?).  If then a 
> future C standard changes things here (in the list of issues to be 
> considered for a future C standard in Standing Document 3, 
> <http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1917.htm>), then, as a 
> non-defect change, it should be considered a non-overflow in GCC only for 
> future C standard versions as well as C90.
> 
> (Although treating something as not an integer constant expression does 
> have consequences beyond pedwarns-if-pedantic - a zero derived from that 
> expression is not a null pointer constant and that can affect the types of 
> conditional expressions - I don't expect any significant breakage of real 
> code from that.)

Well, ok then.  This new version incorporates Richard S.'s suggestion,
and warns even for 1 << 31 in C99/C11 (also in C90 when -Wshift-overflow
is explicitely specified).  For C++, it warns about 1 << 31 by default
only in C++11 mode, in C++14 never, otherwise only if -Wshift-overflow
is specified.

But the fallout seems to be nonnegligible.  So I think the default should
be -Wshift-overflow=1 that doesn't warn about 1 << 31, but still rejects
e.g. enum { A = 1 << 31 };.  And -Wshift-overflow=2 would warn even about
1 << 31.  (Perhaps this is exactly what you had in mind, but I'm not sure.)

In C90, shift overflow in contexts where an integer constant expression
is required does not cause the program be rejected.

Bootstrapped/regtested on x86_64-linux.

2015-06-02  Marek Polacek  <polacek@redhat.com>
	    Richard Sandiford  <richard.sandiford@arm.com>

	PR c++/55095
	* c-common.c (c_fully_fold_internal): Warn about left shift overflows.
	Use EXPR_LOC_OR_LOC.
	(maybe_warn_shift_overflow): New function.
	* c-common.h (maybe_warn_shift_overflow): Declare.
	* c-opts.c (c_common_post_options): Set warn_shift_overflow.
	* c.opt (Wshift-overflow): New option.

	* c-typeck.c (digest_init): Pass OPT_Wpedantic to pedwarn_init.
	(build_binary_op): Warn about left shift overflows.

	* typeck.c (cp_build_binary_op): Warn about left shift overflows.

	* doc/invoke.texi: Document -Wshift-overflow.

	* c-c++-common/Wshift-overflow-1.c: New test.
	* c-c++-common/Wshift-overflow-2.c: New test.
	* c-c++-common/Wshift-overflow-3.c: New test.
	* c-c++-common/Wshift-overflow-4.c: New test.
	* g++.dg/cpp1y/left-shift-1.C: New test.
	* gcc.dg/c90-left-shift-2.c: New test.
	* gcc.dg/c90-left-shift-3.c: New test.
	* gcc.dg/c99-left-shift-2.c: New test.
	* gcc.dg/c99-left-shift-3.c: New test.
	* gcc.c-torture/execute/pr40386.c: Use -Wno-shift-overflow.
	* gcc.dg/fixuns-trunc-1.c: Likewise.
	* gcc.dg/multiple-overflow-warn-3.c: Likewise.
	* gcc.dg/pr40501.c: Likewise.
	* gcc.dg/tree-ssa/vrp67.c: Likewise.
	* gcc.dg/vect/pr33373.c: Likewise.
	* gcc.dg/vect/vect-shift-2-big-array.c: Likewise.
	* gcc.dg/vect/vect-shift-2.c: Likewise.
	* gcc.target/i386/avx-vmaskmovps-1.c: Likewise.
	* gcc.target/i386/avx-vmaskmovps-2.c: Likewise.
	* gcc.target/i386/avx-vmaskmovps-256-1.c: Likewise.
	* gcc.target/i386/avx-vmaskmovps-256-2.c: Likewise.
	* gcc.target/i386/avx2-vpmaskloadd-2.c: Likewise.
	* gcc.target/i386/avx2-vpmaskloadd256-2.c: Likewise.
	* gcc.target/i386/avx2-vpmaskstored-2.c: Likewise.
	* gcc.target/i386/avx2-vpmaskstored256-2.c: Likewise.
diff mbox

Patch

diff --git gcc/c-family/c-common.c gcc/c-family/c-common.c
index 36c984c..7ff6343 100644
--- gcc/c-family/c-common.c
+++ gcc/c-family/c-common.c
@@ -1371,7 +1371,7 @@  c_fully_fold_internal (tree expr, bool in_init, bool *maybe_const_operands,
       if (TREE_OVERFLOW_P (ret)
 	  && !TREE_OVERFLOW_P (op0)
 	  && !TREE_OVERFLOW_P (op1))
-	overflow_warning (EXPR_LOCATION (expr), ret);
+	overflow_warning (EXPR_LOC_OR_LOC (expr, input_location), ret);
       if (code == LSHIFT_EXPR
 	  && TREE_CODE (orig_op0) != INTEGER_CST
 	  && TREE_CODE (TREE_TYPE (orig_op0)) == INTEGER_TYPE
@@ -1401,6 +1401,18 @@  c_fully_fold_internal (tree expr, bool in_init, bool *maybe_const_operands,
 			 ? G_("left shift count >= width of type")
 			 : G_("right shift count >= width of type")));
 	}
+      if (code == LSHIFT_EXPR
+	  /* If either OP0 has been folded to INTEGER_CST...  */
+	  && ((TREE_CODE (orig_op0) != INTEGER_CST
+	       && TREE_CODE (TREE_TYPE (orig_op0)) == INTEGER_TYPE
+	       && TREE_CODE (op0) == INTEGER_CST)
+	      /* ...or if OP1 has been folded to INTEGER_CST...  */
+	      || (TREE_CODE (orig_op1) != INTEGER_CST
+		  && TREE_CODE (TREE_TYPE (orig_op1)) == INTEGER_TYPE
+		  && TREE_CODE (op1) == INTEGER_CST))
+	  && c_inhibit_evaluation_warnings == 0)
+	/* ...then maybe we can detect an overflow.  */
+	maybe_warn_shift_overflow (loc, op0, op1);
       if ((code == TRUNC_DIV_EXPR
 	   || code == CEIL_DIV_EXPR
 	   || code == FLOOR_DIV_EXPR
@@ -12226,6 +12238,45 @@  maybe_warn_bool_compare (location_t loc, enum tree_code code, tree op0,
     }
 }
 
+/* Warn if signed left shift overflows.  We don't warn
+   about left-shifting 1 into the sign bit in C++14; cf.
+   <http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2012/n3367.html#1457>
+   LOC is a location of the shift; OP0 and OP1 are the operands.
+   Return true if an overflow is detected, false otherwise.  */
+
+bool
+maybe_warn_shift_overflow (location_t loc, tree op0, tree op1)
+{
+  if (TREE_CODE (op0) != INTEGER_CST
+      || TREE_CODE (op1) != INTEGER_CST)
+    return false;
+
+  tree type0 = TREE_TYPE (op0);
+  unsigned int prec0 = TYPE_PRECISION (type0);
+
+  /* Left-hand operand must be signed.  */
+  if (TYPE_UNSIGNED (type0))
+    return false;
+
+  /* Handle the left-shifting 1 into the sign bit case.  */
+  if (cxx_dialect >= cxx14
+      && integer_onep (op0)
+      && compare_tree_int (op1, prec0 - 1) == 0)
+    return false;
+
+  unsigned int min_prec = (wi::min_precision (op0, SIGNED)
+			   + TREE_INT_CST_LOW (op1));
+  bool overflowed = min_prec > prec0;
+  if (overflowed && c_inhibit_evaluation_warnings == 0)
+    warning_at (loc, OPT_Wshift_overflow,
+		"result of %qE requires %u bits to represent, "
+		"but %qT only has %u bits",
+		build2_loc (loc, LSHIFT_EXPR, type0, op0, op1),
+		min_prec, type0, prec0);
+
+  return overflowed;
+}
+
 /* The C and C++ parsers both use vectors to hold function arguments.
    For efficiency, we keep a cache of unused vectors.  This is the
    cache.  */
diff --git gcc/c-family/c-common.h gcc/c-family/c-common.h
index 61900db..c067f42 100644
--- gcc/c-family/c-common.h
+++ gcc/c-family/c-common.h
@@ -1061,6 +1061,7 @@  extern void record_locally_defined_typedef (tree);
 extern void maybe_record_typedef_use (tree);
 extern void maybe_warn_unused_local_typedefs (void);
 extern void maybe_warn_bool_compare (location_t, enum tree_code, tree, tree);
+extern bool maybe_warn_shift_overflow (location_t, tree, tree);
 extern vec<tree, va_gc> *make_tree_vector (void);
 extern void release_tree_vector (vec<tree, va_gc> *);
 extern vec<tree, va_gc> *make_tree_vector_single (tree);
diff --git gcc/c-family/c-opts.c gcc/c-family/c-opts.c
index 8996fe3..2e9f785 100644
--- gcc/c-family/c-opts.c
+++ gcc/c-family/c-opts.c
@@ -866,6 +866,10 @@  c_common_post_options (const char **pfilename)
   if (warn_implicit_int == -1)
     warn_implicit_int = flag_isoc99;
 
+  /* -Wshift-overflow is enabled by default in C99 and C++11 modes.  */
+  if (warn_shift_overflow == -1)
+    warn_shift_overflow = cxx_dialect >= cxx11 || flag_isoc99;
+
   /* -Wshift-negative-value is enabled by -Wextra in C99 and C++11 modes.  */
   if (warn_shift_negative_value == -1)
     warn_shift_negative_value = (extra_warnings
diff --git gcc/c-family/c.opt gcc/c-family/c.opt
index 285952e..5d444d4 100644
--- gcc/c-family/c.opt
+++ gcc/c-family/c.opt
@@ -780,6 +780,10 @@  Wshadow-ivar
 ObjC ObjC++ Var(warn_shadow_ivar) EnabledBy(Wshadow) Init(1) Warning
 Warn if a local declaration hides an instance variable
 
+Wshift-overflow
+C ObjC C++ ObjC++ Var(warn_shift_overflow) Init(-1) Warning
+Warn if left shift of a signed value overflows
+
 Wshift-count-negative
 C ObjC C++ ObjC++ Var(warn_shift_count_negative) Init(1) Warning
 Warn if shift count is negative
diff --git gcc/c/c-typeck.c gcc/c/c-typeck.c
index f55d4c6..0d2a7fe 100644
--- gcc/c/c-typeck.c
+++ gcc/c/c-typeck.c
@@ -6909,7 +6909,7 @@  digest_init (location_t init_loc, tree type, tree init, tree origtype,
 	  inside_init = error_mark_node;
 	}
       else if (require_constant && !maybe_const)
-	pedwarn_init (init_loc, 0,
+	pedwarn_init (init_loc, OPT_Wpedantic,
 		      "initializer element is not a constant expression");
 
       return inside_init;
@@ -10630,15 +10630,15 @@  build_binary_op (location_t location, enum tree_code code,
           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))
+	       && 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)
-	  && code1 == INTEGER_TYPE)
+	       && code1 == INTEGER_TYPE)
 	{
 	  doing_shift = true;
 	  if (TREE_CODE (op1) == INTEGER_CST)
@@ -10680,15 +10680,15 @@  build_binary_op (location_t location, enum tree_code code,
           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))
+	       && 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)
-	  && code1 == INTEGER_TYPE)
+	       && code1 == INTEGER_TYPE)
 	{
 	  doing_shift = true;
 	  if (TREE_CODE (op0) == INTEGER_CST
@@ -10711,7 +10711,6 @@  build_binary_op (location_t location, enum tree_code code,
 		    warning_at (location, OPT_Wshift_count_negative,
 				"left shift count is negative");
 		}
-
 	      else if (compare_tree_int (op1, TYPE_PRECISION (type0)) >= 0)
 		{
 		  int_const = false;
@@ -10719,6 +10718,10 @@  build_binary_op (location_t location, enum tree_code code,
 		    warning_at (location, OPT_Wshift_count_overflow,
 				"left shift count >= width of type");
 		}
+	      else if (TREE_CODE (op0) == INTEGER_CST
+		       && maybe_warn_shift_overflow (location, op0, op1)
+		       && flag_isoc99)
+		int_const = false;
 	    }
 
 	  /* Use the type of the value to be shifted.  */
diff --git gcc/cp/typeck.c gcc/cp/typeck.c
index fef4f4f..5e2ab11 100644
--- gcc/cp/typeck.c
+++ gcc/cp/typeck.c
@@ -4360,6 +4360,9 @@  cp_build_binary_op (location_t location,
 		    warning (OPT_Wshift_count_overflow,
 			     "left shift count >= width of type");
 		}
+	      else if (TREE_CODE (const_op0) == INTEGER_CST
+		       && (complain & tf_warning))
+		maybe_warn_shift_overflow (location, const_op0, const_op1);
 	    }
 	  /* Avoid converting op1 to result_type later.  */
 	  converted = 1;
diff --git gcc/doc/invoke.texi gcc/doc/invoke.texi
index e25bd62..20aeedc 100644
--- gcc/doc/invoke.texi
+++ gcc/doc/invoke.texi
@@ -273,6 +273,7 @@  Objective-C and Objective-C++ Dialects}.
 -Wpointer-arith  -Wno-pointer-to-int-cast @gol
 -Wredundant-decls  -Wno-return-local-addr @gol
 -Wreturn-type  -Wsequence-point  -Wshadow  -Wno-shadow-ivar @gol
+-Wshift-overflow @gol
 -Wshift-count-negative -Wshift-count-overflow -Wshift-negative-value @gol
 -Wsign-compare  -Wsign-conversion -Wfloat-conversion @gol
 -Wsizeof-pointer-memaccess  -Wsizeof-array-argument @gol
@@ -3981,6 +3982,13 @@  Warn if shift count >= width of type. This warning is enabled by default.
 Warn if left shifting a negative value.  This warning is enabled by
 @option{-Wextra} in C99 and C++11 modes (and newer).
 
+@item -Wshift-overflow
+@opindex Wshift-overflow
+@opindex Wno-shift-overflow
+Warn if left shift overflows.  This warning is enabled by
+default in C99 and C++11 modes (and newer).  This warning does not warn
+about left-shifting 1 into the sign bit in C++14 mode.
+
 @item -Wswitch
 @opindex Wswitch
 @opindex Wno-switch
diff --git gcc/testsuite/c-c++-common/Wshift-overflow-1.c gcc/testsuite/c-c++-common/Wshift-overflow-1.c
index e69de29..1d8b345 100644
--- gcc/testsuite/c-c++-common/Wshift-overflow-1.c
+++ gcc/testsuite/c-c++-common/Wshift-overflow-1.c
@@ -0,0 +1,58 @@ 
+/* PR c++/55095 */
+/* { dg-do compile { target int32 } } */
+/* { dg-options "-O" } */
+/* { dg-additional-options "-std=c++11" { target c++ } } */
+
+#define INTM1 (sizeof (int) * __CHAR_BIT__ - 1)
+#define INTM2 (sizeof (int) * __CHAR_BIT__ - 2)
+#define LLONGM1 (sizeof (long long) * __CHAR_BIT__ - 1)
+#define LLONGM2 (sizeof (long long) * __CHAR_BIT__ - 2)
+
+int i1 = 1 << INTM1; /* { dg-warning "requires 33 bits to represent" } */
+int i2 = 9 << INTM1; /* { dg-warning "requires 36 bits to represent" } */
+int i3 = 10 << INTM2; /* { dg-warning "requires 35 bits to represent" } */
+int i4 = __INT_MAX__ << 2; /* { dg-warning "requires 34 bits to represent" } */
+int i5 = __INT_MAX__ << INTM1; /* { dg-warning "requires 63 bits to represent" } */
+int i6 = -1 << INTM1;
+int i7 = -9 << INTM1; /* { dg-warning "requires 36 bits to represent" } */
+int i8 = -10 << INTM2; /* { dg-warning "requires 35 bits to represent" } */
+int i9 = -__INT_MAX__ << 2; /* { dg-warning "requires 34 bits to represent" } */
+int i10 = -__INT_MAX__ << INTM1; /* { dg-warning "requires 63 bits to represent" } */
+
+int r1 = 1 >> INTM1;
+int r2 = 9 >> INTM1;
+int r3 = 10 >> INTM2;
+int r4 = __INT_MAX__ >> 2;
+int r5 = __INT_MAX__ >> INTM1;
+int r6 = -1 >> INTM1;
+int r7 = -9 >> INTM1;
+int r8 = -10 >> INTM2;
+int r9 = -__INT_MAX__ >> 2;
+int r10 = -__INT_MAX__ >> INTM1;
+
+unsigned u1 = 1 << INTM1; /* { dg-warning "requires 33 bits to represent" } */
+unsigned u2 = 9 << INTM1; /* { dg-warning "requires 36 bits to represent" } */
+unsigned u3 = 2U << INTM1;
+unsigned u4 = 9U << INTM1;
+unsigned u5 = 10U << INTM2;
+
+long long int l1 = 1LL << LLONGM1; /* { dg-warning "requires 65 bits to represent" } */
+long long int l2 = 9LL << LLONGM1; /* { dg-warning "requires 68 bits to represent" } */
+long long int l3 = 10LL << LLONGM2; /* { dg-warning "requires 67 bits to represent" } */
+long long int l4 = __LONG_LONG_MAX__ << 2; /* { dg-warning "requires 66 bits to represent" } */
+long long int l5 = __LONG_LONG_MAX__ << LLONGM1; /* { dg-warning "requires 127 bits to represent" } */
+long long int l6 = -1LL << LLONGM1;
+long long int l7 = -9LL << LLONGM1; /* { dg-warning "requires 68 bits to represent" } */
+long long int l8 = -10LL << LLONGM2; /* { dg-warning "requires 67 bits to represent" } */
+long long int l9 = -__LONG_LONG_MAX__ << 2; /* { dg-warning "requires 66 bits to represent" } */
+long long int l10 = -__LONG_LONG_MAX__ << LLONGM1; /* { dg-warning "requires 127 bits to represent" } */
+
+void
+fn (void)
+{
+  const int a = 10;
+  const __SIZE_TYPE__ b = INTM1;
+  int k1 = a << b; /* { dg-warning "requires 36 bits to represent" } */
+  int k2 = 10 << b; /* { dg-warning "requires 36 bits to represent" } */
+  int k3 = a << INTM1; /* { dg-warning "requires 36 bits to represent" } */
+}
diff --git gcc/testsuite/c-c++-common/Wshift-overflow-2.c gcc/testsuite/c-c++-common/Wshift-overflow-2.c
index e69de29..d5115d0 100644
--- gcc/testsuite/c-c++-common/Wshift-overflow-2.c
+++ gcc/testsuite/c-c++-common/Wshift-overflow-2.c
@@ -0,0 +1,58 @@ 
+/* PR c++/55095 */
+/* { dg-do compile { target int32 } } */
+/* { dg-options "-O -Wno-shift-overflow" } */
+/* { dg-additional-options "-std=c++11" { target c++ } } */
+
+#define INTM1 (sizeof (int) * __CHAR_BIT__ - 1)
+#define INTM2 (sizeof (int) * __CHAR_BIT__ - 2)
+#define LLONGM1 (sizeof (long long) * __CHAR_BIT__ - 1)
+#define LLONGM2 (sizeof (long long) * __CHAR_BIT__ - 2)
+
+int i1 = 1 << INTM1;
+int i2 = 9 << INTM1;
+int i3 = 10 << INTM2;
+int i4 = __INT_MAX__ << 2;
+int i5 = __INT_MAX__ << INTM1;
+int i6 = -1 << INTM1;
+int i7 = -9 << INTM1;
+int i8 = -10 << INTM2;
+int i9 = -__INT_MAX__ << 2;
+int i10 = -__INT_MAX__ << INTM1;
+
+int r1 = 1 >> INTM1;
+int r2 = 9 >> INTM1;
+int r3 = 10 >> INTM2;
+int r4 = __INT_MAX__ >> 2;
+int r5 = __INT_MAX__ >> INTM1;
+int r6 = -1 >> INTM1;
+int r7 = -9 >> INTM1;
+int r8 = -10 >> INTM2;
+int r9 = -__INT_MAX__ >> 2;
+int r10 = -__INT_MAX__ >> INTM1;
+
+unsigned u1 = 1 << INTM1;
+unsigned u2 = 9 << INTM1;
+unsigned u3 = 2U << INTM1;
+unsigned u4 = 9U << INTM1;
+unsigned u5 = 10U << INTM2;
+
+long long int l1 = 1LL << LLONGM1;
+long long int l2 = 9LL << LLONGM1;
+long long int l3 = 10LL << LLONGM2;
+long long int l4 = __LONG_LONG_MAX__ << 2;
+long long int l5 = __LONG_LONG_MAX__ << LLONGM1;
+long long int l6 = -1LL << LLONGM1;
+long long int l7 = -9LL << LLONGM1;
+long long int l8 = -10LL << LLONGM2;
+long long int l9 = -__LONG_LONG_MAX__ << 2;
+long long int l10 = -__LONG_LONG_MAX__ << LLONGM1;
+
+void
+fn (void)
+{
+  const int a = 10;
+  const __SIZE_TYPE__ b = INTM1;
+  int k1 = a << b;
+  int k2 = 10 << b;
+  int k3 = a << INTM1;
+}
diff --git gcc/testsuite/c-c++-common/Wshift-overflow-3.c gcc/testsuite/c-c++-common/Wshift-overflow-3.c
index e69de29..71283d0 100644
--- gcc/testsuite/c-c++-common/Wshift-overflow-3.c
+++ gcc/testsuite/c-c++-common/Wshift-overflow-3.c
@@ -0,0 +1,59 @@ 
+/* PR c++/55095 */
+/* { dg-do compile { target int32 } } */
+/* { dg-options "-O -Wshift-overflow" } */
+/* { dg-additional-options "-std=gnu90" { target c } } */
+/* { dg-additional-options "-std=c++03" { target c++ } } */
+
+#define INTM1 (sizeof (int) * __CHAR_BIT__ - 1)
+#define INTM2 (sizeof (int) * __CHAR_BIT__ - 2)
+#define LLONGM1 (sizeof (long long) * __CHAR_BIT__ - 1)
+#define LLONGM2 (sizeof (long long) * __CHAR_BIT__ - 2)
+
+int i1 = 1 << INTM1; /* { dg-warning "requires 33 bits to represent" } */
+int i2 = 9 << INTM1; /* { dg-warning "requires 36 bits to represent" } */
+int i3 = 10 << INTM2; /* { dg-warning "requires 35 bits to represent" } */
+int i4 = __INT_MAX__ << 2; /* { dg-warning "requires 34 bits to represent" } */
+int i5 = __INT_MAX__ << INTM1; /* { dg-warning "requires 63 bits to represent" } */
+int i6 = -1 << INTM1;
+int i7 = -9 << INTM1; /* { dg-warning "requires 36 bits to represent" } */
+int i8 = -10 << INTM2; /* { dg-warning "requires 35 bits to represent" } */
+int i9 = -__INT_MAX__ << 2; /* { dg-warning "requires 34 bits to represent" } */
+int i10 = -__INT_MAX__ << INTM1; /* { dg-warning "requires 63 bits to represent" } */
+
+int r1 = 1 >> INTM1;
+int r2 = 9 >> INTM1;
+int r3 = 10 >> INTM2;
+int r4 = __INT_MAX__ >> 2;
+int r5 = __INT_MAX__ >> INTM1;
+int r6 = -1 >> INTM1;
+int r7 = -9 >> INTM1;
+int r8 = -10 >> INTM2;
+int r9 = -__INT_MAX__ >> 2;
+int r10 = -__INT_MAX__ >> INTM1;
+
+unsigned u1 = 1 << INTM1; /* { dg-warning "requires 33 bits to represent" } */
+unsigned u2 = 9 << INTM1; /* { dg-warning "requires 36 bits to represent" } */
+unsigned u3 = 2U << INTM1;
+unsigned u4 = 9U << INTM1;
+unsigned u5 = 10U << INTM2;
+
+long long int l1 = 1LL << LLONGM1; /* { dg-warning "requires 65 bits to represent" } */
+long long int l2 = 9LL << LLONGM1; /* { dg-warning "requires 68 bits to represent" } */
+long long int l3 = 10LL << LLONGM2; /* { dg-warning "requires 67 bits to represent" } */
+long long int l4 = __LONG_LONG_MAX__ << 2; /* { dg-warning "requires 66 bits to represent" } */
+long long int l5 = __LONG_LONG_MAX__ << LLONGM1; /* { dg-warning "requires 127 bits to represent" } */
+long long int l6 = -1LL << LLONGM1;
+long long int l7 = -9LL << LLONGM1; /* { dg-warning "requires 68 bits to represent" } */
+long long int l8 = -10LL << LLONGM2; /* { dg-warning "requires 67 bits to represent" } */
+long long int l9 = -__LONG_LONG_MAX__ << 2; /* { dg-warning "requires 66 bits to represent" } */
+long long int l10 = -__LONG_LONG_MAX__ << LLONGM1; /* { dg-warning "requires 127 bits to represent" } */
+
+void
+fn (void)
+{
+  const int a = 10;
+  const __SIZE_TYPE__ b = INTM1;
+  int k1 = a << b; /* { dg-warning "requires 36 bits to represent" } */
+  int k2 = 10 << b; /* { dg-warning "requires 36 bits to represent" } */
+  int k3 = a << INTM1; /* { dg-warning "requires 36 bits to represent" } */
+}
diff --git gcc/testsuite/c-c++-common/Wshift-overflow-4.c gcc/testsuite/c-c++-common/Wshift-overflow-4.c
index e69de29..92f8cf8 100644
--- gcc/testsuite/c-c++-common/Wshift-overflow-4.c
+++ gcc/testsuite/c-c++-common/Wshift-overflow-4.c
@@ -0,0 +1,59 @@ 
+/* PR c++/55095 */
+/* { dg-do compile { target int32 } } */
+/* { dg-options "-O" } */
+/* { dg-additional-options "-std=gnu90" { target c } } */
+/* { dg-additional-options "-std=c++03" { target c++ } } */
+
+#define INTM1 (sizeof (int) * __CHAR_BIT__ - 1)
+#define INTM2 (sizeof (int) * __CHAR_BIT__ - 2)
+#define LLONGM1 (sizeof (long long) * __CHAR_BIT__ - 1)
+#define LLONGM2 (sizeof (long long) * __CHAR_BIT__ - 2)
+
+int i1 = 1 << INTM1;
+int i2 = 9 << INTM1;
+int i3 = 10 << INTM2;
+int i4 = __INT_MAX__ << 2;
+int i5 = __INT_MAX__ << INTM1;
+int i6 = -1 << INTM1;
+int i7 = -9 << INTM1;
+int i8 = -10 << INTM2;
+int i9 = -__INT_MAX__ << 2;
+int i10 = -__INT_MAX__ << INTM1;
+
+int r1 = 1 >> INTM1;
+int r2 = 9 >> INTM1;
+int r3 = 10 >> INTM2;
+int r4 = __INT_MAX__ >> 2;
+int r5 = __INT_MAX__ >> INTM1;
+int r6 = -1 >> INTM1;
+int r7 = -9 >> INTM1;
+int r8 = -10 >> INTM2;
+int r9 = -__INT_MAX__ >> 2;
+int r10 = -__INT_MAX__ >> INTM1;
+
+unsigned u1 = 1 << INTM1;
+unsigned u2 = 9 << INTM1;
+unsigned u3 = 2U << INTM1;
+unsigned u4 = 9U << INTM1;
+unsigned u5 = 10U << INTM2;
+
+long long int l1 = 1LL << LLONGM1;
+long long int l2 = 9LL << LLONGM1;
+long long int l3 = 10LL << LLONGM2;
+long long int l4 = __LONG_LONG_MAX__ << 2;
+long long int l5 = __LONG_LONG_MAX__ << LLONGM1;
+long long int l6 = -1LL << LLONGM1;
+long long int l7 = -9LL << LLONGM1;
+long long int l8 = -10LL << LLONGM2;
+long long int l9 = -__LONG_LONG_MAX__ << 2;
+long long int l10 = -__LONG_LONG_MAX__ << LLONGM1;
+
+void
+fn (void)
+{
+  const int a = 10;
+  const __SIZE_TYPE__ b = INTM1;
+  int k1 = a << b;
+  int k2 = 10 << b;
+  int k3 = a << INTM1;
+}
diff --git gcc/testsuite/g++.dg/cpp1y/left-shift-1.C gcc/testsuite/g++.dg/cpp1y/left-shift-1.C
index e69de29..b74698c 100644
--- gcc/testsuite/g++.dg/cpp1y/left-shift-1.C
+++ gcc/testsuite/g++.dg/cpp1y/left-shift-1.C
@@ -0,0 +1,12 @@ 
+// PR c++/55095
+// { dg-do compile { target c++14 } }
+// { dg-require-effective-target int32plus }
+
+#define INTM1 (sizeof (int) * __CHAR_BIT__ - 1)
+#define INTM2 (sizeof (int) * __CHAR_BIT__ - 2)
+#define LLONGM1 (sizeof (long long) * __CHAR_BIT__ - 1)
+#define LLONGM2 (sizeof (long long) * __CHAR_BIT__ - 2)
+
+int i1 = 1 << INTM1;
+unsigned u1 = 1 << INTM1;
+long long int l1 = 1LL << LLONGM1;
diff --git gcc/testsuite/gcc.c-torture/execute/pr40386.c gcc/testsuite/gcc.c-torture/execute/pr40386.c
index f39f1de..c701304 100644
--- gcc/testsuite/gcc.c-torture/execute/pr40386.c
+++ gcc/testsuite/gcc.c-torture/execute/pr40386.c
@@ -1,4 +1,4 @@ 
-/* { dg-options "-fno-ira-share-spill-slots" } */
+/* { dg-options "-fno-ira-share-spill-slots -Wno-shift-overflow" } */
 
 extern void abort (void);
 extern void exit (int);
diff --git gcc/testsuite/gcc.dg/c90-left-shift-2.c gcc/testsuite/gcc.dg/c90-left-shift-2.c
index e69de29..f79ab8b 100644
--- gcc/testsuite/gcc.dg/c90-left-shift-2.c
+++ gcc/testsuite/gcc.dg/c90-left-shift-2.c
@@ -0,0 +1,14 @@ 
+/* { dg-do compile } */
+/* { dg-options "-std=iso9899:1990 -pedantic-errors" } */
+
+#define INTM2 (sizeof (int) * __CHAR_BIT__ - 2)
+
+enum { A = 10 << INTM2 };
+int k = 10 << INTM2;
+
+void
+fn (int i)
+{
+  switch (i)
+  case 10 << INTM2: break;
+}
diff --git gcc/testsuite/gcc.dg/c90-left-shift-3.c gcc/testsuite/gcc.dg/c90-left-shift-3.c
index e69de29..43942dd 100644
--- gcc/testsuite/gcc.dg/c90-left-shift-3.c
+++ gcc/testsuite/gcc.dg/c90-left-shift-3.c
@@ -0,0 +1,14 @@ 
+/* { dg-do compile } */
+/* { dg-options "-std=iso9899:1990 -pedantic-errors" } */
+
+#define INTM1 (sizeof (int) * __CHAR_BIT__ - 1)
+
+enum { A = 1 << INTM1 };
+int k = 1 << INTM1;
+
+void
+fn (int i)
+{
+  switch (i)
+  case 1 << INTM1: break;
+}
diff --git gcc/testsuite/gcc.dg/c99-left-shift-2.c gcc/testsuite/gcc.dg/c99-left-shift-2.c
index e69de29..e35786e 100644
--- gcc/testsuite/gcc.dg/c99-left-shift-2.c
+++ gcc/testsuite/gcc.dg/c99-left-shift-2.c
@@ -0,0 +1,14 @@ 
+/* { dg-do compile } */
+/* { dg-options "-std=iso9899:1999 -pedantic-errors -Wno-shift-overflow" } */
+
+#define INTM2 (sizeof (int) * __CHAR_BIT__ - 2)
+
+enum { A = 10 << INTM2 }; /* { dg-error "constant expression" } */
+int k = 10 << INTM2; /* { dg-error "constant expression" } */
+
+void
+fn (int i)
+{
+  switch (i)
+  case 10 << INTM2: break; /* { dg-error "constant expression" } */
+}
diff --git gcc/testsuite/gcc.dg/c99-left-shift-3.c gcc/testsuite/gcc.dg/c99-left-shift-3.c
index e69de29..59d0f24 100644
--- gcc/testsuite/gcc.dg/c99-left-shift-3.c
+++ gcc/testsuite/gcc.dg/c99-left-shift-3.c
@@ -0,0 +1,14 @@ 
+/* { dg-do compile } */
+/* { dg-options "-std=iso9899:1999 -pedantic-errors -Wno-shift-overflow" } */
+
+#define INTM1 (sizeof (int) * __CHAR_BIT__ - 1)
+
+enum { A = 1 << INTM1 }; /* { dg-error "constant expression" } */
+int k = 1 << INTM1; /* { dg-error "constant expression" } */
+
+void
+fn (int i)
+{
+  switch (i)
+  case 1 << INTM1: break; /* { dg-error "constant expression" } */
+}
diff --git gcc/testsuite/gcc.dg/fixuns-trunc-1.c gcc/testsuite/gcc.dg/fixuns-trunc-1.c
index 0d09429..accf673 100644
--- gcc/testsuite/gcc.dg/fixuns-trunc-1.c
+++ gcc/testsuite/gcc.dg/fixuns-trunc-1.c
@@ -1,5 +1,5 @@ 
 /* { dg-do run } */
-/* { dg-options "-std=c99" } */
+/* { dg-options "-std=c99 -Wno-shift-overflow" } */
 
 unsigned long foo(double d)
 {
diff --git gcc/testsuite/gcc.dg/multiple-overflow-warn-3.c gcc/testsuite/gcc.dg/multiple-overflow-warn-3.c
index da19de5..09f8d6e 100644
--- gcc/testsuite/gcc.dg/multiple-overflow-warn-3.c
+++ gcc/testsuite/gcc.dg/multiple-overflow-warn-3.c
@@ -1,6 +1,6 @@ 
 /* PR 30465 : Test for duplicated warnings in a conversion.  */
 /* { dg-do compile } */
-/* { dg-options "-Woverflow" } */
+/* { dg-options "-Woverflow -Wno-shift-overflow" } */
 
 short int
 g (void)
diff --git gcc/testsuite/gcc.dg/pr40501.c gcc/testsuite/gcc.dg/pr40501.c
index e6ce217..7610a20 100644
--- gcc/testsuite/gcc.dg/pr40501.c
+++ gcc/testsuite/gcc.dg/pr40501.c
@@ -1,5 +1,5 @@ 
 /* { dg-do compile { target alpha*-*-* ia64*-*-* i?86-*-* x86_64-*-* s390x-*-* } } */
-/* { dg-options "-O2" } */
+/* { dg-options "-O2 -Wno-shift-overflow" } */
 /* { dg-require-effective-target lp64 } */
 
 /* PR middle-end/40501 */
diff --git gcc/testsuite/gcc.dg/tree-ssa/vrp67.c gcc/testsuite/gcc.dg/tree-ssa/vrp67.c
index ef5e8f9..1ecf6dc 100644
--- gcc/testsuite/gcc.dg/tree-ssa/vrp67.c
+++ gcc/testsuite/gcc.dg/tree-ssa/vrp67.c
@@ -1,5 +1,5 @@ 
 /* { dg-do compile } */
-/* { dg-options "-O2 -fdump-tree-vrp1" } */
+/* { dg-options "-O2 -fdump-tree-vrp1 -Wno-shift-overflow" } */
 
 extern void link_error (void);
 
diff --git gcc/testsuite/gcc.dg/vect/pr33373.c gcc/testsuite/gcc.dg/vect/pr33373.c
index 8da4371..ab79a7c 100644
--- gcc/testsuite/gcc.dg/vect/pr33373.c
+++ gcc/testsuite/gcc.dg/vect/pr33373.c
@@ -1,4 +1,5 @@ 
 /* { dg-do compile } */
+/* { dg-options "-Wno-shift-overflow" } */
 void DOSMEM_FillIsrTable(int*isr) {
     int i;
 
diff --git gcc/testsuite/gcc.dg/vect/vect-shift-2-big-array.c gcc/testsuite/gcc.dg/vect/vect-shift-2-big-array.c
index 46909ca..85ff0e0 100644
--- gcc/testsuite/gcc.dg/vect/vect-shift-2-big-array.c
+++ gcc/testsuite/gcc.dg/vect/vect-shift-2-big-array.c
@@ -1,3 +1,4 @@ 
+/* { dg-options "-Wno-shift-overflow" } */
 /* { dg-require-effective-target vect_shift } */
 /* { dg-require-effective-target vect_int } */
 /* Check the standard integer types for left and right shifts to see if the
diff --git gcc/testsuite/gcc.dg/vect/vect-shift-2.c gcc/testsuite/gcc.dg/vect/vect-shift-2.c
index 68186db..6199cd6 100644
--- gcc/testsuite/gcc.dg/vect/vect-shift-2.c
+++ gcc/testsuite/gcc.dg/vect/vect-shift-2.c
@@ -1,3 +1,4 @@ 
+/* { dg-options "-Wno-shift-overflow" } */
 /* { dg-require-effective-target vect_shift } */
 /* { dg-require-effective-target vect_int } */
 /* Check the standard integer types for left and right shifts to see if the
diff --git gcc/testsuite/gcc.target/i386/avx-vmaskmovps-1.c gcc/testsuite/gcc.target/i386/avx-vmaskmovps-1.c
index 360a04d..370c87e 100644
--- gcc/testsuite/gcc.target/i386/avx-vmaskmovps-1.c
+++ gcc/testsuite/gcc.target/i386/avx-vmaskmovps-1.c
@@ -1,6 +1,6 @@ 
 /* { dg-do run } */
 /* { dg-require-effective-target avx } */
-/* { dg-options "-O2 -mavx" } */
+/* { dg-options "-O2 -mavx -Wno-shift-overflow" } */
 
 #include "avx-check.h"
 
diff --git gcc/testsuite/gcc.target/i386/avx-vmaskmovps-2.c gcc/testsuite/gcc.target/i386/avx-vmaskmovps-2.c
index 3dde965..76baa9b 100644
--- gcc/testsuite/gcc.target/i386/avx-vmaskmovps-2.c
+++ gcc/testsuite/gcc.target/i386/avx-vmaskmovps-2.c
@@ -1,6 +1,6 @@ 
 /* { dg-do run } */
 /* { dg-require-effective-target avx } */
-/* { dg-options "-O2 -mavx" } */
+/* { dg-options "-O2 -mavx -Wno-shift-overflow" } */
 
 #include "avx-check.h"
 
diff --git gcc/testsuite/gcc.target/i386/avx-vmaskmovps-256-1.c gcc/testsuite/gcc.target/i386/avx-vmaskmovps-256-1.c
index 647ce3f..c185d6b 100644
--- gcc/testsuite/gcc.target/i386/avx-vmaskmovps-256-1.c
+++ gcc/testsuite/gcc.target/i386/avx-vmaskmovps-256-1.c
@@ -1,6 +1,6 @@ 
 /* { dg-do run } */
 /* { dg-require-effective-target avx } */
-/* { dg-options "-O2 -mavx" } */
+/* { dg-options "-O2 -mavx -Wno-shift-overflow" } */
 
 #include "avx-check.h"
 
diff --git gcc/testsuite/gcc.target/i386/avx-vmaskmovps-256-2.c gcc/testsuite/gcc.target/i386/avx-vmaskmovps-256-2.c
index 016904d..67f8975 100644
--- gcc/testsuite/gcc.target/i386/avx-vmaskmovps-256-2.c
+++ gcc/testsuite/gcc.target/i386/avx-vmaskmovps-256-2.c
@@ -1,6 +1,6 @@ 
 /* { dg-do run } */
 /* { dg-require-effective-target avx } */
-/* { dg-options "-O2 -mavx" } */
+/* { dg-options "-O2 -mavx -Wno-shift-overflow" } */
 
 #include "avx-check.h"
 
diff --git gcc/testsuite/gcc.target/i386/avx2-vpmaskloadd-2.c gcc/testsuite/gcc.target/i386/avx2-vpmaskloadd-2.c
index 9bc3f31..bec050e 100644
--- gcc/testsuite/gcc.target/i386/avx2-vpmaskloadd-2.c
+++ gcc/testsuite/gcc.target/i386/avx2-vpmaskloadd-2.c
@@ -1,6 +1,6 @@ 
 /* { dg-do run } */
 /* { dg-require-effective-target avx2 } */
-/* { dg-options "-O2 -mavx2" } */
+/* { dg-options "-O2 -mavx2 -Wno-shift-overflow" } */
 
 #include "avx2-check.h"
 
diff --git gcc/testsuite/gcc.target/i386/avx2-vpmaskloadd256-2.c gcc/testsuite/gcc.target/i386/avx2-vpmaskloadd256-2.c
index b5a82bd..eaa745b 100644
--- gcc/testsuite/gcc.target/i386/avx2-vpmaskloadd256-2.c
+++ gcc/testsuite/gcc.target/i386/avx2-vpmaskloadd256-2.c
@@ -1,6 +1,6 @@ 
 /* { dg-do run } */
 /* { dg-require-effective-target avx2 } */
-/* { dg-options "-O2 -mavx2" } */
+/* { dg-options "-O2 -mavx2 -Wno-shift-overflow" } */
 
 #include "avx2-check.h"
 
diff --git gcc/testsuite/gcc.target/i386/avx2-vpmaskstored-2.c gcc/testsuite/gcc.target/i386/avx2-vpmaskstored-2.c
index 89b54f5..2cf4c1c 100644
--- gcc/testsuite/gcc.target/i386/avx2-vpmaskstored-2.c
+++ gcc/testsuite/gcc.target/i386/avx2-vpmaskstored-2.c
@@ -1,6 +1,6 @@ 
 /* { dg-do run } */
 /* { dg-require-effective-target avx2 } */
-/* { dg-options "-O2 -mavx2" } */
+/* { dg-options "-O2 -mavx2 -Wno-shift-overflow" } */
 
 #include "avx2-check.h"
 
diff --git gcc/testsuite/gcc.target/i386/avx2-vpmaskstored256-2.c gcc/testsuite/gcc.target/i386/avx2-vpmaskstored256-2.c
index 7b66a08..0ee9b78 100644
--- gcc/testsuite/gcc.target/i386/avx2-vpmaskstored256-2.c
+++ gcc/testsuite/gcc.target/i386/avx2-vpmaskstored256-2.c
@@ -1,6 +1,6 @@ 
 /* { dg-do run } */
 /* { dg-require-effective-target avx2 } */
-/* { dg-options "-O2 -mavx2" } */
+/* { dg-options "-O2 -mavx2 -Wno-shift-overflow" } */
 
 #include "avx2-check.h"