public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
* [C/C++ PATCH] Implement -Wshift-overflow (PR c++/55095)
@ 2015-05-25 20:12 Marek Polacek
  2015-05-26 11:07 ` Marek Polacek
                   ` (2 more replies)
  0 siblings, 3 replies; 25+ messages in thread
From: Marek Polacek @ 2015-05-25 20:12 UTC (permalink / raw)
  To: GCC Patches, Jason Merrill, Joseph Myers

Not sure how many packages I'll break this time around, so early testing
appreciated.

The C/C++ standards say that for signed left shift, if E1 x 2^{E2} isn't
representable, the behavior is undefined.  We didn't have a corresponding
warning though, so this patch adds -Wshift-overflow, enabled by default
in C99/C++11 modes.   The approach I took for this was to compute the
shift in widest int, then convert it to the resulting type, then compare
those values, if they don't match, we've got an overflow.  This seems to
work well.  Note that I deliberately don't want to warn about e.g.
1 << 31 or 1L << 63 (which is also how clang behaves).

I went the extra mile to polish the warning so that it looks like:
warning: result of '284 << 29' requires 39 bits to represent, but 'int' only
has 32 bits [-Wshift-overflow]
so that we're on a par with what clang++ prints.

(While at it, I fixed some indentation issues in build_binary_op that had
been bothering me for a while.)

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

2015-05-25  Marek Polacek  <polacek@redhat.com>

	PR c++/55095
	* c-common.c (c_fully_fold_internal): Warn about left shift overflows.
	(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.
	* gcc.dg/c90-left-shift-2.c: New test.
	* gcc.dg/c99-left-shift-2.c: New test.
	* gcc.c-torture/execute/pr40386.c: Use -Wno-shift-overflow.

diff --git gcc/c-family/c-common.c gcc/c-family/c-common.c
index 36c984c..6f7eb50 100644
--- gcc/c-family/c-common.c
+++ gcc/c-family/c-common.c
@@ -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,44 @@ maybe_warn_bool_compare (location_t loc, enum tree_code code, tree op0,
     }
 }
 
+/* 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.  */
+
+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);
+
+  /* Left-hand operand must be signed.  */
+  if (TYPE_UNSIGNED (type0))
+    return false;
+
+  /* Compute the result in infinite precision math (sort of).  */
+  widest_int w = wi::lshift (wi::to_widest (op0), wi::to_widest (op1));
+  unsigned int min_prec = wi::min_precision (w, SIGNED);
+  /* Watch out for shifting a negative value.  */
+  tree r = wide_int_to_tree (tree_int_cst_sgn (op0) >= 0
+			     ? unsigned_type_for (type0)
+			     : type0, w);
+  bool overflowed = wi::cmps (w, wi::to_widest (r));
+  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, TYPE_PRECISION (type0));
+
+  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 0eaff05..bae72af 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 fe5fce7..c8fb632 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 a451537..1241fb6 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.
+
 @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..9969629 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;
+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;
+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;
+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..ed57d5d 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;
+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;
+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;
+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/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/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" } */
+}

	Marek

^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [C/C++ PATCH] Implement -Wshift-overflow (PR c++/55095)
  2015-05-25 20:12 [C/C++ PATCH] Implement -Wshift-overflow (PR c++/55095) Marek Polacek
@ 2015-05-26 11:07 ` Marek Polacek
  2015-05-29 21:25 ` Joseph Myers
  2015-06-01 20:06 ` [C/C++ PATCH] Implement -Wshift-overflow (PR c++/55095) Richard Sandiford
  2 siblings, 0 replies; 25+ messages in thread
From: Marek Polacek @ 2015-05-26 11:07 UTC (permalink / raw)
  To: GCC Patches, Jason Merrill, Joseph Myers

Since the move to C++14 is now imminent, I regtested/bootstrapped
the patch with -Wshift-overflow always enabled for C++ and that
went well.

	Marek

^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [C/C++ PATCH] Implement -Wshift-overflow (PR c++/55095)
  2015-05-25 20:12 [C/C++ PATCH] Implement -Wshift-overflow (PR c++/55095) Marek Polacek
  2015-05-26 11:07 ` Marek Polacek
@ 2015-05-29 21:25 ` Joseph Myers
  2015-06-02 19:26   ` [C/C++ PATCH] Implement -Wshift-overflow (PR c++/55095) (take 2) Marek Polacek
  2015-06-01 20:06 ` [C/C++ PATCH] Implement -Wshift-overflow (PR c++/55095) Richard Sandiford
  2 siblings, 1 reply; 25+ messages in thread
From: Joseph Myers @ 2015-05-29 21:25 UTC (permalink / raw)
  To: Marek Polacek; +Cc: GCC Patches, Jason Merrill

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.)

-- 
Joseph S. Myers
joseph@codesourcery.com

^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [C/C++ PATCH] Implement -Wshift-overflow (PR c++/55095)
  2015-05-25 20:12 [C/C++ PATCH] Implement -Wshift-overflow (PR c++/55095) Marek Polacek
  2015-05-26 11:07 ` Marek Polacek
  2015-05-29 21:25 ` Joseph Myers
@ 2015-06-01 20:06 ` Richard Sandiford
  2015-06-02  8:16   ` Richard Biener
  2 siblings, 1 reply; 25+ messages in thread
From: Richard Sandiford @ 2015-06-01 20:06 UTC (permalink / raw)
  To: Marek Polacek; +Cc: GCC Patches, Jason Merrill, Joseph Myers

Marek Polacek <polacek@redhat.com> writes:
> +  /* Left-hand operand must be signed.  */
> +  if (TYPE_UNSIGNED (type0))
> +    return false;
> +
> +  /* Compute the result in infinite precision math (sort of).  */
> +  widest_int w = wi::lshift (wi::to_widest (op0), wi::to_widest (op1));
> +  unsigned int min_prec = wi::min_precision (w, SIGNED);
> +  /* Watch out for shifting a negative value.  */
> +  tree r = wide_int_to_tree (tree_int_cst_sgn (op0) >= 0
> +			     ? unsigned_type_for (type0)
> +			     : type0, w);
> +  bool overflowed = wi::cmps (w, wi::to_widest (r));
> +  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, TYPE_PRECISION (type0));
> +
> +  return overflowed;

Yeah, this "sort of" is a bit worrying :-)  Especially as the number
of bits in a widest_int depends on the number of bits in the target's
widest integer mode.  E.g. for i386 it's forced to 128, but for ARM
it's 512 (IIRC).

Could you do the check based on the wi::min_precision of the unshifted
value?  I.e. see whether adding the shift amount to that gives a value
greater than type's precision.

Thanks,
Richard

^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [C/C++ PATCH] Implement -Wshift-overflow (PR c++/55095)
  2015-06-01 20:06 ` [C/C++ PATCH] Implement -Wshift-overflow (PR c++/55095) Richard Sandiford
@ 2015-06-02  8:16   ` Richard Biener
  2015-06-02  9:01     ` Richard Sandiford
  0 siblings, 1 reply; 25+ messages in thread
From: Richard Biener @ 2015-06-02  8:16 UTC (permalink / raw)
  To: Marek Polacek, GCC Patches, Jason Merrill, Joseph Myers,
	Richard Sandiford

On Mon, Jun 1, 2015 at 10:06 PM, Richard Sandiford
<rdsandiford@googlemail.com> wrote:
> Marek Polacek <polacek@redhat.com> writes:
>> +  /* Left-hand operand must be signed.  */
>> +  if (TYPE_UNSIGNED (type0))
>> +    return false;
>> +
>> +  /* Compute the result in infinite precision math (sort of).  */
>> +  widest_int w = wi::lshift (wi::to_widest (op0), wi::to_widest (op1));
>> +  unsigned int min_prec = wi::min_precision (w, SIGNED);
>> +  /* Watch out for shifting a negative value.  */
>> +  tree r = wide_int_to_tree (tree_int_cst_sgn (op0) >= 0
>> +                          ? unsigned_type_for (type0)
>> +                          : type0, w);
>> +  bool overflowed = wi::cmps (w, wi::to_widest (r));
>> +  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, TYPE_PRECISION (type0));
>> +
>> +  return overflowed;
>
> Yeah, this "sort of" is a bit worrying :-)  Especially as the number
> of bits in a widest_int depends on the number of bits in the target's
> widest integer mode.  E.g. for i386 it's forced to 128, but for ARM
> it's 512 (IIRC).
>
> Could you do the check based on the wi::min_precision of the unshifted
> value?  I.e. see whether adding the shift amount to that gives a value
> greater than type's precision.

You could always use a FIXED_WIDE_INT like VRP does for its overflow
detection stuff.

Richard.

> Thanks,
> Richard

^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [C/C++ PATCH] Implement -Wshift-overflow (PR c++/55095)
  2015-06-02  8:16   ` Richard Biener
@ 2015-06-02  9:01     ` Richard Sandiford
  2015-06-02 15:05       ` Marek Polacek
  0 siblings, 1 reply; 25+ messages in thread
From: Richard Sandiford @ 2015-06-02  9:01 UTC (permalink / raw)
  To: Richard Biener; +Cc: Marek Polacek, GCC Patches, Jason Merrill, Joseph Myers

Richard Biener <richard.guenther@gmail.com> writes:
> On Mon, Jun 1, 2015 at 10:06 PM, Richard Sandiford
> <rdsandiford@googlemail.com> wrote:
>> Marek Polacek <polacek@redhat.com> writes:
>>> +  /* Left-hand operand must be signed.  */
>>> +  if (TYPE_UNSIGNED (type0))
>>> +    return false;
>>> +
>>> +  /* Compute the result in infinite precision math (sort of).  */
>>> +  widest_int w = wi::lshift (wi::to_widest (op0), wi::to_widest (op1));
>>> +  unsigned int min_prec = wi::min_precision (w, SIGNED);
>>> +  /* Watch out for shifting a negative value.  */
>>> +  tree r = wide_int_to_tree (tree_int_cst_sgn (op0) >= 0
>>> +                          ? unsigned_type_for (type0)
>>> +                          : type0, w);
>>> +  bool overflowed = wi::cmps (w, wi::to_widest (r));
>>> +  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, TYPE_PRECISION (type0));
>>> +
>>> +  return overflowed;
>>
>> Yeah, this "sort of" is a bit worrying :-)  Especially as the number
>> of bits in a widest_int depends on the number of bits in the target's
>> widest integer mode.  E.g. for i386 it's forced to 128, but for ARM
>> it's 512 (IIRC).
>>
>> Could you do the check based on the wi::min_precision of the unshifted
>> value?  I.e. see whether adding the shift amount to that gives a value
>> greater than type's precision.
>
> You could always use a FIXED_WIDE_INT like VRP does for its overflow
> detection stuff.

That would work too, but why impose an arbitrary limit?  Unless I'm
missing something, the code above should be equivalent to:

  unsigned int min_prec = (wi::min_precision (op0, SIGNED)
  			   + TREE_INT_CST_LOW (op1));
  bool overflowed = min_prec > TYPE_PRECISION (type0);
  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, TYPE_PRECISION (type0));

which seems simpler than anything involving wider precision.

Thanks,
Richard

^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [C/C++ PATCH] Implement -Wshift-overflow (PR c++/55095)
  2015-06-02  9:01     ` Richard Sandiford
@ 2015-06-02 15:05       ` Marek Polacek
  0 siblings, 0 replies; 25+ messages in thread
From: Marek Polacek @ 2015-06-02 15:05 UTC (permalink / raw)
  To: Richard Biener, GCC Patches, Jason Merrill, Joseph Myers, rdsandiford

On Tue, Jun 02, 2015 at 09:53:14AM +0100, Richard Sandiford wrote:
>   unsigned int min_prec = (wi::min_precision (op0, SIGNED)
>   			   + TREE_INT_CST_LOW (op1));
>   bool overflowed = min_prec > TYPE_PRECISION (type0);
>   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, TYPE_PRECISION (type0));
> 
> which seems simpler than anything involving wider precision.

Clearly your version is much better, so I'll use it - thanks!
I'm testing a new version of the patch, will post it soon.

	Marek

^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [C/C++ PATCH] Implement -Wshift-overflow (PR c++/55095) (take 2)
  2015-05-29 21:25 ` Joseph Myers
@ 2015-06-02 19:26   ` Marek Polacek
  2015-06-03 13:07     ` [C/C++ PATCH] Implement -Wshift-overflow (PR c++/55095) (take 3) Marek Polacek
  0 siblings, 1 reply; 25+ messages in thread
From: Marek Polacek @ 2015-06-02 19:26 UTC (permalink / raw)
  To: Joseph Myers; +Cc: GCC Patches, Jason Merrill

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 --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"
 


^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [C/C++ PATCH] Implement -Wshift-overflow (PR c++/55095) (take 3)
  2015-06-02 19:26   ` [C/C++ PATCH] Implement -Wshift-overflow (PR c++/55095) (take 2) Marek Polacek
@ 2015-06-03 13:07     ` Marek Polacek
  2015-06-04 21:05       ` Joseph Myers
  0 siblings, 1 reply; 25+ messages in thread
From: Marek Polacek @ 2015-06-03 13:07 UTC (permalink / raw)
  To: Joseph Myers; +Cc: GCC Patches, Jason Merrill

On Tue, Jun 02, 2015 at 09:25:32PM +0200, Marek Polacek wrote:
> 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.)

Done in the following.  I think this is the best approach.  The documentation
hopefully makes it clear what's the intended behavior.

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

2015-06-03  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 and -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.
	* c-c++-common/Wshift-overflow-5.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.dg/pr40501.c: Use -Wno-shift-overflow.
	* gcc.c-torture/execute/pr40386.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.

diff --git gcc/c-family/c-common.c gcc/c-family/c-common.c
index 36c984c..dc31fad 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,53 @@ 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 (integer_onep (op0)
+      && compare_tree_int (op1, prec0 - 1) == 0)
+    {
+      /* Never warn for C++14 onwards.  */
+      if (cxx_dialect >= cxx14)
+	return false;
+      /* Otherwise only if -Wshift-overflow=2.  But return
+	 true to signal an overflow for the sake of integer
+	 constant expressions.  */
+      if (warn_shift_overflow < 2)
+	return true;
+    }
+
+  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..dc760d7 100644
--- gcc/c-family/c.opt
+++ gcc/c-family/c.opt
@@ -780,6 +780,14 @@ 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++ Warning Alias(Wshift-overflow=, 1, 0)
+Warn if left shift of a signed value overflows
+
+Wshift-overflow=
+C ObjC C++ ObjC++ Joined RejectNegative UInteger 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..2d83cfd 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 -Wshift-overflow=@var{n} @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,26 @@ 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
+@itemx -Wshift-overflow=@var{n}
+@opindex Wshift-overflow
+@opindex Wno-shift-overflow
+Warn about left shift overflows.  This warning is enabled by
+default in C99 and C++11 modes (and newer).
+
+@table @gcctabopt
+@item -Wshift-overflow=1
+This is the warning level of @option{-Wshift-overflow} and is enabled
+by default in C99 and C++11 modes (and newer).  This warning level does
+not warn about left-shifting 1 into the sign bit.  (However, in C, such
+an overflow is still rejected in contexts where an integer constant expression
+is required.)
+
+@item -Wshift-overflow=2
+This warning level also warns about left-shifting 1 into the sign bit,
+unless C++14 mode is active.
+@end table
+
 @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..9969629 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;
+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;
+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;
+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..ed57d5d 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;
+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;
+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;
+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/c-c++-common/Wshift-overflow-5.c gcc/testsuite/c-c++-common/Wshift-overflow-5.c
index e69de29..c9f4643 100644
--- gcc/testsuite/c-c++-common/Wshift-overflow-5.c
+++ gcc/testsuite/c-c++-common/Wshift-overflow-5.c
@@ -0,0 +1,11 @@
+/* PR c++/55095 */
+/* { dg-do compile { target int32 } } */
+/* { dg-options "-O -Wshift-overflow=2" } */
+/* { dg-additional-options "-std=c++11" { target c++ } } */
+
+#define INTM1 (sizeof (int) * __CHAR_BIT__ - 1)
+#define LLONGM1 (sizeof (long long) * __CHAR_BIT__ - 1)
+
+int i1 = 1 << INTM1; /* { dg-warning "requires 33 bits to represent" } */
+unsigned u1 = 1 << INTM1; /* { dg-warning "requires 33 bits to represent" } */
+long long int l1 = 1LL << LLONGM1; /* { dg-warning "requires 65 bits to represent" } */
diff --git gcc/testsuite/g++.dg/cpp1y/left-shift-1.C gcc/testsuite/g++.dg/cpp1y/left-shift-1.C
index e69de29..a24caae 100644
--- gcc/testsuite/g++.dg/cpp1y/left-shift-1.C
+++ gcc/testsuite/g++.dg/cpp1y/left-shift-1.C
@@ -0,0 +1,11 @@
+// PR c++/55095
+// { dg-do compile { target c++14 } }
+// { dg-options "-Wshift-overflow=2" }
+// { dg-require-effective-target int32plus }
+
+#define INTM1 (sizeof (int) * __CHAR_BIT__ - 1)
+#define LLONGM1 (sizeof (long long) * __CHAR_BIT__ - 1)
+
+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/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/vect/pr33373.c gcc/testsuite/gcc.dg/vect/pr33373.c
index 8da4371..efba2ab 100644
--- gcc/testsuite/gcc.dg/vect/pr33373.c
+++ gcc/testsuite/gcc.dg/vect/pr33373.c
@@ -1,3 +1,4 @@
+/* { dg-options "-Wno-shift-overflow" } */
 /* { dg-do compile } */
 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

	Marek

^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [C/C++ PATCH] Implement -Wshift-overflow (PR c++/55095) (take 3)
  2015-06-03 13:07     ` [C/C++ PATCH] Implement -Wshift-overflow (PR c++/55095) (take 3) Marek Polacek
@ 2015-06-04 21:05       ` Joseph Myers
  2015-06-05  9:42         ` Marek Polacek
  0 siblings, 1 reply; 25+ messages in thread
From: Joseph Myers @ 2015-06-04 21:05 UTC (permalink / raw)
  To: Marek Polacek; +Cc: GCC Patches, Jason Merrill

On Wed, 3 Jun 2015, Marek Polacek wrote:

> > 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.)
> 
> Done in the following.  I think this is the best approach.  The documentation
> hopefully makes it clear what's the intended behavior.
> 
> Bootstrapped/regtested on x86_64-linux, ok for trunk?

The C changes are OK.

-- 
Joseph S. Myers
joseph@codesourcery.com

^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [C/C++ PATCH] Implement -Wshift-overflow (PR c++/55095) (take 3)
  2015-06-04 21:05       ` Joseph Myers
@ 2015-06-05  9:42         ` Marek Polacek
  2015-06-12  9:08           ` Marek Polacek
  0 siblings, 1 reply; 25+ messages in thread
From: Marek Polacek @ 2015-06-05  9:42 UTC (permalink / raw)
  To: Joseph Myers; +Cc: GCC Patches, Jason Merrill

On Thu, Jun 04, 2015 at 09:04:19PM +0000, Joseph Myers wrote:
> The C changes are OK.

Jason, do you want to approve the C++ parts?

Thanks,

	Marek

^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [C/C++ PATCH] Implement -Wshift-overflow (PR c++/55095) (take 3)
  2015-06-05  9:42         ` Marek Polacek
@ 2015-06-12  9:08           ` Marek Polacek
  2015-06-19 10:51             ` Marek Polacek
  0 siblings, 1 reply; 25+ messages in thread
From: Marek Polacek @ 2015-06-12  9:08 UTC (permalink / raw)
  To: Jason Merrill; +Cc: GCC Patches

Ping.

On Fri, Jun 05, 2015 at 10:55:08AM +0200, Marek Polacek wrote:
> On Thu, Jun 04, 2015 at 09:04:19PM +0000, Joseph Myers wrote:
> > The C changes are OK.
> 
> Jason, do you want to approve the C++ parts?
> 
> Thanks,

	Marek

^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [C/C++ PATCH] Implement -Wshift-overflow (PR c++/55095) (take 3)
  2015-06-12  9:08           ` Marek Polacek
@ 2015-06-19 10:51             ` Marek Polacek
  2015-06-26  8:36               ` Marek Polacek
  0 siblings, 1 reply; 25+ messages in thread
From: Marek Polacek @ 2015-06-19 10:51 UTC (permalink / raw)
  To: Jason Merrill; +Cc: GCC Patches

Ping.

On Fri, Jun 12, 2015 at 11:07:29AM +0200, Marek Polacek wrote:
> Ping.
> 
> On Fri, Jun 05, 2015 at 10:55:08AM +0200, Marek Polacek wrote:
> > On Thu, Jun 04, 2015 at 09:04:19PM +0000, Joseph Myers wrote:
> > > The C changes are OK.
> > 
> > Jason, do you want to approve the C++ parts?

	Marek

^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [C/C++ PATCH] Implement -Wshift-overflow (PR c++/55095) (take 3)
  2015-06-19 10:51             ` Marek Polacek
@ 2015-06-26  8:36               ` Marek Polacek
  2015-07-03  7:42                 ` Marek Polacek
  0 siblings, 1 reply; 25+ messages in thread
From: Marek Polacek @ 2015-06-26  8:36 UTC (permalink / raw)
  To: Jason Merrill; +Cc: GCC Patches

I'm pinging the C++ parts.

On Fri, Jun 19, 2015 at 12:44:36PM +0200, Marek Polacek wrote:
> Ping.
> 
> On Fri, Jun 12, 2015 at 11:07:29AM +0200, Marek Polacek wrote:
> > Ping.
> > 
> > On Fri, Jun 05, 2015 at 10:55:08AM +0200, Marek Polacek wrote:
> > > On Thu, Jun 04, 2015 at 09:04:19PM +0000, Joseph Myers wrote:
> > > > The C changes are OK.
> > > 
> > > Jason, do you want to approve the C++ parts?

	Marek

^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [C/C++ PATCH] Implement -Wshift-overflow (PR c++/55095) (take 3)
  2015-06-26  8:36               ` Marek Polacek
@ 2015-07-03  7:42                 ` Marek Polacek
  2015-07-10 13:23                   ` Marek Polacek
  0 siblings, 1 reply; 25+ messages in thread
From: Marek Polacek @ 2015-07-03  7:42 UTC (permalink / raw)
  To: Jason Merrill; +Cc: GCC Patches

Ping^4.

On Fri, Jun 26, 2015 at 10:08:51AM +0200, Marek Polacek wrote:
> I'm pinging the C++ parts.
> 
> On Fri, Jun 19, 2015 at 12:44:36PM +0200, Marek Polacek wrote:
> > Ping.
> > 
> > On Fri, Jun 12, 2015 at 11:07:29AM +0200, Marek Polacek wrote:
> > > Ping.
> > > 
> > > On Fri, Jun 05, 2015 at 10:55:08AM +0200, Marek Polacek wrote:
> > > > On Thu, Jun 04, 2015 at 09:04:19PM +0000, Joseph Myers wrote:
> > > > > The C changes are OK.
> > > > 
> > > > Jason, do you want to approve the C++ parts?

	Marek

^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [C/C++ PATCH] Implement -Wshift-overflow (PR c++/55095) (take 3)
  2015-07-03  7:42                 ` Marek Polacek
@ 2015-07-10 13:23                   ` Marek Polacek
  2015-07-17  8:32                     ` Marek Polacek
  0 siblings, 1 reply; 25+ messages in thread
From: Marek Polacek @ 2015-07-10 13:23 UTC (permalink / raw)
  To: Jason Merrill; +Cc: GCC Patches

Ping^5.

On Fri, Jul 03, 2015 at 09:42:39AM +0200, Marek Polacek wrote:
> Ping^4.
> 
> On Fri, Jun 26, 2015 at 10:08:51AM +0200, Marek Polacek wrote:
> > I'm pinging the C++ parts.
> > 
> > On Fri, Jun 19, 2015 at 12:44:36PM +0200, Marek Polacek wrote:
> > > Ping.
> > > 
> > > On Fri, Jun 12, 2015 at 11:07:29AM +0200, Marek Polacek wrote:
> > > > Ping.
> > > > 
> > > > On Fri, Jun 05, 2015 at 10:55:08AM +0200, Marek Polacek wrote:
> > > > > On Thu, Jun 04, 2015 at 09:04:19PM +0000, Joseph Myers wrote:
> > > > > > The C changes are OK.
> > > > > 
> > > > > Jason, do you want to approve the C++ parts?

	Marek

^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [C/C++ PATCH] Implement -Wshift-overflow (PR c++/55095) (take 3)
  2015-07-10 13:23                   ` Marek Polacek
@ 2015-07-17  8:32                     ` Marek Polacek
  2015-07-17 23:01                       ` Jeff Law
  0 siblings, 1 reply; 25+ messages in thread
From: Marek Polacek @ 2015-07-17  8:32 UTC (permalink / raw)
  To: Jason Merrill; +Cc: GCC Patches

Ping^6.

On Fri, Jul 10, 2015 at 03:23:43PM +0200, Marek Polacek wrote:
> Ping^5.
> 
> On Fri, Jul 03, 2015 at 09:42:39AM +0200, Marek Polacek wrote:
> > Ping^4.
> > 
> > On Fri, Jun 26, 2015 at 10:08:51AM +0200, Marek Polacek wrote:
> > > I'm pinging the C++ parts.
> > > 
> > > On Fri, Jun 19, 2015 at 12:44:36PM +0200, Marek Polacek wrote:
> > > > Ping.
> > > > 
> > > > On Fri, Jun 12, 2015 at 11:07:29AM +0200, Marek Polacek wrote:
> > > > > Ping.
> > > > > 
> > > > > On Fri, Jun 05, 2015 at 10:55:08AM +0200, Marek Polacek wrote:
> > > > > > On Thu, Jun 04, 2015 at 09:04:19PM +0000, Joseph Myers wrote:
> > > > > > > The C changes are OK.
> > > > > > 
> > > > > > Jason, do you want to approve the C++ parts?

	Marek

^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [C/C++ PATCH] Implement -Wshift-overflow (PR c++/55095) (take 3)
  2015-07-17  8:32                     ` Marek Polacek
@ 2015-07-17 23:01                       ` Jeff Law
  2015-07-20 14:19                         ` Marek Polacek
  0 siblings, 1 reply; 25+ messages in thread
From: Jeff Law @ 2015-07-17 23:01 UTC (permalink / raw)
  To: Marek Polacek, Jason Merrill; +Cc: GCC Patches

On 07/17/2015 02:09 AM, Marek Polacek wrote:
> Ping^6.
>
> On Fri, Jul 10, 2015 at 03:23:43PM +0200, Marek Polacek wrote:
>> Ping^5.
>>
>> On Fri, Jul 03, 2015 at 09:42:39AM +0200, Marek Polacek wrote:
>>> Ping^4.
>>>
>>> On Fri, Jun 26, 2015 at 10:08:51AM +0200, Marek Polacek wrote:
>>>> I'm pinging the C++ parts.
>>>>
>>>> On Fri, Jun 19, 2015 at 12:44:36PM +0200, Marek Polacek wrote:
>>>>> Ping.
>>>>>
>>>>> On Fri, Jun 12, 2015 at 11:07:29AM +0200, Marek Polacek wrote:
>>>>>> Ping.
>>>>>>
>>>>>> On Fri, Jun 05, 2015 at 10:55:08AM +0200, Marek Polacek wrote:
>>>>>>> On Thu, Jun 04, 2015 at 09:04:19PM +0000, Joseph Myers wrote:
>>>>>>>> The C changes are OK.
>>>>>>>
>>>>>>> Jason, do you want to approve the C++ parts?
I'll approve the C++ parts given how simple they are :-)

jeff

^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [C/C++ PATCH] Implement -Wshift-overflow (PR c++/55095) (take 3)
  2015-07-17 23:01                       ` Jeff Law
@ 2015-07-20 14:19                         ` Marek Polacek
  0 siblings, 0 replies; 25+ messages in thread
From: Marek Polacek @ 2015-07-20 14:19 UTC (permalink / raw)
  To: Jeff Law; +Cc: Jason Merrill, GCC Patches

On Fri, Jul 17, 2015 at 03:51:33PM -0600, Jeff Law wrote:
> I'll approve the C++ parts given how simple they are :-)

Thanks, I've committed the patch now after another regtest/bootstrap.

	Marek

^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [C/C++ PATCH] Implement -Wshift-overflow (PR c++/55095) (take 3)
  2015-07-22 12:52       ` Segher Boessenkool
@ 2015-07-22 17:01         ` Marek Polacek
  0 siblings, 0 replies; 25+ messages in thread
From: Marek Polacek @ 2015-07-22 17:01 UTC (permalink / raw)
  To: Segher Boessenkool; +Cc: David Edelsohn, GCC Patches

On Wed, Jul 22, 2015 at 07:48:47AM -0500, Segher Boessenkool wrote:
> vmx.exp sets a bunch of options and the test overrides that now.  Options
> like -maltivec are pretty important for this test to work -- it #includes
> altivec.h, which does #error unless -maltivec is set, and things go downhill
> from that.  unpack-be-order.c works, unpack.c blows up.

Ah, right.
 
> Does your compiler maybe default to -maltivec?

I suppose -- I didn't see any failures on cfarm 112, but I was able to
reproduce the unpack.c fail on cfarm 110.  Turned out I should've used
dg-additional-options.  Thanks.

Tested vmx.exp on powerpc64-unknown-linux-gnu, applying to trunk.

2015-07-22  Marek Polacek  <polacek@redhat.com>

	* gcc.dg/vmx/unpack.c: Use dg-additional-options rather than
	dg-options.

diff --git gcc/testsuite/gcc.dg/vmx/unpack.c gcc/testsuite/gcc.dg/vmx/unpack.c
index e71a5a6..b3ec93a 100644
--- gcc/testsuite/gcc.dg/vmx/unpack.c
+++ gcc/testsuite/gcc.dg/vmx/unpack.c
@@ -1,4 +1,4 @@
-/* { dg-options "-Wno-shift-overflow" } */
+/* { dg-additional-options "-Wno-shift-overflow" } */
 
 #include "harness.h"
 

	Marek

^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [C/C++ PATCH] Implement -Wshift-overflow (PR c++/55095) (take 3)
  2015-07-22 12:51     ` Marek Polacek
@ 2015-07-22 12:52       ` Segher Boessenkool
  2015-07-22 17:01         ` Marek Polacek
  0 siblings, 1 reply; 25+ messages in thread
From: Segher Boessenkool @ 2015-07-22 12:52 UTC (permalink / raw)
  To: Marek Polacek; +Cc: David Edelsohn, GCC Patches

On Wed, Jul 22, 2015 at 02:39:14PM +0200, Marek Polacek wrote:
> On Wed, Jul 22, 2015 at 08:35:12AM -0400, David Edelsohn wrote:
> > On Tue, Jul 21, 2015 at 5:59 AM, Marek Polacek <polacek@redhat.com> wrote:
> > > On Mon, Jul 20, 2015 at 04:23:08PM -0400, David Edelsohn wrote:
> > >> This seems to have caused a number of new failures in the PPC
> > >> testsuite for vmx/unpack.
> > >
> > > Sorry about that.  Should be fixed with this patch I'm about to commit.
> > >
> > > 2015-07-21  Marek Polacek  <polacek@redhat.com>
> > >
> > >         * gcc.dg/vmx/unpack-be-order.c: Use -Wno-shift-overflow.
> > >         * gcc.dg/vmx/unpack.c: Likewise.
> > 
> > This doesn't fully fix the failures.
>  
> Ouch.  What other failures do you see?  I've tried the patch on ppc64-linux
> and didn't see any others.

vmx.exp sets a bunch of options and the test overrides that now.  Options
like -maltivec are pretty important for this test to work -- it #includes
altivec.h, which does #error unless -maltivec is set, and things go downhill
from that.  unpack-be-order.c works, unpack.c blows up.

Does your compiler maybe default to -maltivec?


Segher

^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [C/C++ PATCH] Implement -Wshift-overflow (PR c++/55095) (take 3)
  2015-07-22 12:48   ` David Edelsohn
@ 2015-07-22 12:51     ` Marek Polacek
  2015-07-22 12:52       ` Segher Boessenkool
  0 siblings, 1 reply; 25+ messages in thread
From: Marek Polacek @ 2015-07-22 12:51 UTC (permalink / raw)
  To: David Edelsohn; +Cc: GCC Patches

On Wed, Jul 22, 2015 at 08:35:12AM -0400, David Edelsohn wrote:
> On Tue, Jul 21, 2015 at 5:59 AM, Marek Polacek <polacek@redhat.com> wrote:
> > On Mon, Jul 20, 2015 at 04:23:08PM -0400, David Edelsohn wrote:
> >> This seems to have caused a number of new failures in the PPC
> >> testsuite for vmx/unpack.
> >
> > Sorry about that.  Should be fixed with this patch I'm about to commit.
> >
> > 2015-07-21  Marek Polacek  <polacek@redhat.com>
> >
> >         * gcc.dg/vmx/unpack-be-order.c: Use -Wno-shift-overflow.
> >         * gcc.dg/vmx/unpack.c: Likewise.
> 
> This doesn't fully fix the failures.
 
Ouch.  What other failures do you see?  I've tried the patch on ppc64-linux
and didn't see any others.

It'd be very weird to see -Wshift-overflow warnings when -Wno-shift-overflow
is in effect.

> > --- gcc/testsuite/gcc.dg/vmx/unpack.c
> > +++ gcc/testsuite/gcc.dg/vmx/unpack.c
> > @@ -1,3 +1,5 @@
> > +/* { dg-options "-Wno-shift-overflow" } */
> > +
> 
> Should this be dg-additional-options ?

I did what was in gcc.dg/vmx/unpack-be-order.c, i.e. dg-options.  Or does
using dg-additional-options help?

	Marek

^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [C/C++ PATCH] Implement -Wshift-overflow (PR c++/55095) (take 3)
  2015-07-21 10:11 ` Marek Polacek
@ 2015-07-22 12:48   ` David Edelsohn
  2015-07-22 12:51     ` Marek Polacek
  0 siblings, 1 reply; 25+ messages in thread
From: David Edelsohn @ 2015-07-22 12:48 UTC (permalink / raw)
  To: Marek Polacek; +Cc: GCC Patches

On Tue, Jul 21, 2015 at 5:59 AM, Marek Polacek <polacek@redhat.com> wrote:
> On Mon, Jul 20, 2015 at 04:23:08PM -0400, David Edelsohn wrote:
>> This seems to have caused a number of new failures in the PPC
>> testsuite for vmx/unpack.
>
> Sorry about that.  Should be fixed with this patch I'm about to commit.
>
> 2015-07-21  Marek Polacek  <polacek@redhat.com>
>
>         * gcc.dg/vmx/unpack-be-order.c: Use -Wno-shift-overflow.
>         * gcc.dg/vmx/unpack.c: Likewise.

This doesn't fully fix the failures.

>         * gcc.target/powerpc/quad-atomic.c: Likewise.

> diff --git gcc/testsuite/gcc.dg/vmx/unpack.c gcc/testsuite/gcc.dg/vmx/unpack.c
> index 3c13163..e71a5a6 100644
> --- gcc/testsuite/gcc.dg/vmx/unpack.c
> +++ gcc/testsuite/gcc.dg/vmx/unpack.c
> @@ -1,3 +1,5 @@
> +/* { dg-options "-Wno-shift-overflow" } */
> +

Should this be dg-additional-options ?

>  #include "harness.h"
>
>  #define BIG 4294967295

^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [C/C++ PATCH] Implement -Wshift-overflow (PR c++/55095) (take 3)
  2015-07-20 20:40 [C/C++ PATCH] Implement -Wshift-overflow (PR c++/55095) (take 3) David Edelsohn
@ 2015-07-21 10:11 ` Marek Polacek
  2015-07-22 12:48   ` David Edelsohn
  0 siblings, 1 reply; 25+ messages in thread
From: Marek Polacek @ 2015-07-21 10:11 UTC (permalink / raw)
  To: David Edelsohn; +Cc: GCC Patches

On Mon, Jul 20, 2015 at 04:23:08PM -0400, David Edelsohn wrote:
> This seems to have caused a number of new failures in the PPC
> testsuite for vmx/unpack.

Sorry about that.  Should be fixed with this patch I'm about to commit.

2015-07-21  Marek Polacek  <polacek@redhat.com>

	* gcc.dg/vmx/unpack-be-order.c: Use -Wno-shift-overflow.
	* gcc.dg/vmx/unpack.c: Likewise.
	* gcc.target/powerpc/quad-atomic.c: Likewise.

diff --git gcc/testsuite/gcc.dg/vmx/unpack-be-order.c gcc/testsuite/gcc.dg/vmx/unpack-be-order.c
index e174433..6eb98f4 100644
--- gcc/testsuite/gcc.dg/vmx/unpack-be-order.c
+++ gcc/testsuite/gcc.dg/vmx/unpack-be-order.c
@@ -1,4 +1,4 @@
-/* { dg-options "-maltivec=be -mabi=altivec -std=gnu99 -mno-vsx" } */
+/* { dg-options "-maltivec=be -mabi=altivec -std=gnu99 -mno-vsx -Wno-shift-overflow" } */
 
 #include "harness.h"
 
diff --git gcc/testsuite/gcc.dg/vmx/unpack.c gcc/testsuite/gcc.dg/vmx/unpack.c
index 3c13163..e71a5a6 100644
--- gcc/testsuite/gcc.dg/vmx/unpack.c
+++ gcc/testsuite/gcc.dg/vmx/unpack.c
@@ -1,3 +1,5 @@
+/* { dg-options "-Wno-shift-overflow" } */
+
 #include "harness.h"
 
 #define BIG 4294967295
diff --git gcc/testsuite/gcc.target/powerpc/quad-atomic.c gcc/testsuite/gcc.target/powerpc/quad-atomic.c
index 0d7089b..dc0e3a8 100644
--- gcc/testsuite/gcc.target/powerpc/quad-atomic.c
+++ gcc/testsuite/gcc.target/powerpc/quad-atomic.c
@@ -3,7 +3,7 @@
 /* { dg-skip-if "" { powerpc*-*-*spe* } { "*" } { "" } } */
 /* { dg-require-effective-target p8vector_hw } */
 /* { dg-skip-if "do not override -mcpu" { powerpc*-*-* } { "-mcpu=*" } { "-mcpu=power8" } } */
-/* { dg-options "-mcpu=power8 -O2" } */
+/* { dg-options "-mcpu=power8 -O2 -Wno-shift-overflow" } */
 
 /* Test whether we get the right bits for quad word atomic instructions.  */
 #include <stdlib.h>

	Marek

^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [C/C++ PATCH] Implement -Wshift-overflow (PR c++/55095) (take 3)
@ 2015-07-20 20:40 David Edelsohn
  2015-07-21 10:11 ` Marek Polacek
  0 siblings, 1 reply; 25+ messages in thread
From: David Edelsohn @ 2015-07-20 20:40 UTC (permalink / raw)
  To: Marek Polacek; +Cc: GCC Patches

This seems to have caused a number of new failures in the PPC
testsuite for vmx/unpack.

- David

^ permalink raw reply	[flat|nested] 25+ messages in thread

end of thread, other threads:[~2015-07-22 16:42 UTC | newest]

Thread overview: 25+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2015-05-25 20:12 [C/C++ PATCH] Implement -Wshift-overflow (PR c++/55095) Marek Polacek
2015-05-26 11:07 ` Marek Polacek
2015-05-29 21:25 ` Joseph Myers
2015-06-02 19:26   ` [C/C++ PATCH] Implement -Wshift-overflow (PR c++/55095) (take 2) Marek Polacek
2015-06-03 13:07     ` [C/C++ PATCH] Implement -Wshift-overflow (PR c++/55095) (take 3) Marek Polacek
2015-06-04 21:05       ` Joseph Myers
2015-06-05  9:42         ` Marek Polacek
2015-06-12  9:08           ` Marek Polacek
2015-06-19 10:51             ` Marek Polacek
2015-06-26  8:36               ` Marek Polacek
2015-07-03  7:42                 ` Marek Polacek
2015-07-10 13:23                   ` Marek Polacek
2015-07-17  8:32                     ` Marek Polacek
2015-07-17 23:01                       ` Jeff Law
2015-07-20 14:19                         ` Marek Polacek
2015-06-01 20:06 ` [C/C++ PATCH] Implement -Wshift-overflow (PR c++/55095) Richard Sandiford
2015-06-02  8:16   ` Richard Biener
2015-06-02  9:01     ` Richard Sandiford
2015-06-02 15:05       ` Marek Polacek
2015-07-20 20:40 [C/C++ PATCH] Implement -Wshift-overflow (PR c++/55095) (take 3) David Edelsohn
2015-07-21 10:11 ` Marek Polacek
2015-07-22 12:48   ` David Edelsohn
2015-07-22 12:51     ` Marek Polacek
2015-07-22 12:52       ` Segher Boessenkool
2015-07-22 17:01         ` Marek Polacek

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).