re PR c++/55095 (Wshift-overflow)
authorMarek Polacek <polacek@redhat.com>
Mon, 20 Jul 2015 13:43:45 +0000 (13:43 +0000)
committerMarek Polacek <mpolacek@gcc.gnu.org>
Mon, 20 Jul 2015 13:43:45 +0000 (13:43 +0000)
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.

Co-Authored-By: Richard Sandiford <richard.sandiford@arm.com>
From-SVN: r225998

27 files changed:
gcc/ChangeLog
gcc/c-family/ChangeLog
gcc/c-family/c-common.c
gcc/c-family/c-common.h
gcc/c-family/c-opts.c
gcc/c-family/c.opt
gcc/c/ChangeLog
gcc/c/c-typeck.c
gcc/cp/ChangeLog
gcc/cp/typeck.c
gcc/doc/invoke.texi
gcc/testsuite/ChangeLog
gcc/testsuite/c-c++-common/Wshift-overflow-1.c [new file with mode: 0644]
gcc/testsuite/c-c++-common/Wshift-overflow-2.c [new file with mode: 0644]
gcc/testsuite/c-c++-common/Wshift-overflow-3.c [new file with mode: 0644]
gcc/testsuite/c-c++-common/Wshift-overflow-4.c [new file with mode: 0644]
gcc/testsuite/c-c++-common/Wshift-overflow-5.c [new file with mode: 0644]
gcc/testsuite/g++.dg/cpp1y/left-shift-1.C [new file with mode: 0644]
gcc/testsuite/gcc.c-torture/execute/pr40386.c
gcc/testsuite/gcc.dg/c90-left-shift-2.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/c90-left-shift-3.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/c99-left-shift-2.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/c99-left-shift-3.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/pr40501.c
gcc/testsuite/gcc.dg/vect/pr33373.c
gcc/testsuite/gcc.dg/vect/vect-shift-2-big-array.c
gcc/testsuite/gcc.dg/vect/vect-shift-2.c

index addf8ad6a32dd24d3043e875be8e5194ca5b54ed..202416df923e10a28d42e1f9e568204933475437 100644 (file)
@@ -1,3 +1,8 @@
+2015-07-20  Marek Polacek  <polacek@redhat.com>
+
+       PR c++/55095
+       * doc/invoke.texi: Document -Wshift-overflow and -Wshift-overflow=.
+
 2015-07-20  Kyrylo Tkachov  <kyrylo.tkachov@arm.com>
 
        * simplify-rtx.c (simplify_unary_operation_1, NEG case):
index 85582c96653d9cfc64b61d58e3211e0e1b33f6ad..9751ba97550917da1438cbfbed08f2b6308c510d 100644 (file)
@@ -1,3 +1,14 @@
+2015-07-20  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.
+
 2015-07-16  Martin Liska  <mliska@suse.cz>
 
        * c-format.c (static void check_format_info_main): Use
index 84e7242ec0a0450b43c2b2c7a3d5d63b066b7541..c94596f89bac57d216cf666c70e2c9db0463108c 100644 (file)
@@ -1364,7 +1364,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
@@ -1394,6 +1394,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
@@ -12328,6 +12340,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.  */
index a2a46212e8320261ca698a50b923802e29391915..a198e794f5baa30305ff10e63dc1683cfdd4349f 100644 (file)
@@ -1052,6 +1052,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);
index 4dbb109d06aad9eb8436e9e63decd7d0198ba7a8..73f5db0a664b2b70edba7d43e93ae20be3e4d087 100644 (file)
@@ -853,6 +853,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
index 285952ea5fdfd10e0d574e1a924b6334694f7695..dc760d7179997cf72a79ace816865e3ef2505c6c 100644 (file)
@@ -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
index a75f2e8a292d7635ff1bfbe48166c44f6f7ded54..18443aea3dba8f38686d88166850e28a32d1fe10 100644 (file)
@@ -1,3 +1,9 @@
+2015-07-20  Marek Polacek  <polacek@redhat.com>
+
+       PR c++/55095
+       * c-typeck.c (digest_init): Pass OPT_Wpedantic to pedwarn_init.
+       (build_binary_op): Warn about left shift overflows.
+
 2015-07-09  Andrew MacLeod  <amacleod@redhat.com>
 
        * c-array-notation.c: Adjust includes for flags.h changes.
index 247a7bf329d51c19bbbe374717ae0e3d12ea72cd..d3d0abdb2cb137efa6cc3dd2bb83fa1282711f11 100644 (file)
@@ -6892,7 +6892,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;
@@ -10624,15 +10624,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)
@@ -10674,15 +10674,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
@@ -10705,7 +10705,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;
@@ -10713,6 +10712,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.  */
index 6b92826118e4210ce76bdb621cd7618280eca76d..b72b22f5ef8d13becd270b7693144aae8707a5aa 100644 (file)
@@ -1,3 +1,8 @@
+2015-07-20  Marek Polacek  <polacek@redhat.com>
+
+       PR c++/55095
+       * typeck.c (cp_build_binary_op): Warn about left shift overflows.
+
 2015-07-15  Jason Merrill  <jason@redhat.com>
 
        PR c++/65091
index 3e252f93e5ec8a4f36d27b358460e8f2abfb9502..b88a3fd42cff716fd2af3c24095252d7933bb85a 100644 (file)
@@ -4350,6 +4350,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;
index a62c8b33e9253dff6900596ab5c95cae78c6d402..55c26593180220313a6f396e055ce454a448fa81 100644 (file)
@@ -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
@@ -3982,6 +3983,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
index 9df1d41c151c9c7120bf5ef3c347abaf8eee168e..aa6693c58fee005e9b0172f425d326460f7abff6 100644 (file)
@@ -1,3 +1,22 @@
+2015-07-20  Marek Polacek  <polacek@redhat.com>
+
+       PR c++/55095
+       * 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.
+
 2015-07-20  Kyrylo Tkachov  <kyrylo.tkachov@arm.com>
 
        * gcc.target/aarch64/neg_abs_1.c: New test.
diff --git a/gcc/testsuite/c-c++-common/Wshift-overflow-1.c b/gcc/testsuite/c-c++-common/Wshift-overflow-1.c
new file mode 100644 (file)
index 0000000..9969629
--- /dev/null
@@ -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 a/gcc/testsuite/c-c++-common/Wshift-overflow-2.c b/gcc/testsuite/c-c++-common/Wshift-overflow-2.c
new file mode 100644 (file)
index 0000000..d5115d0
--- /dev/null
@@ -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 a/gcc/testsuite/c-c++-common/Wshift-overflow-3.c b/gcc/testsuite/c-c++-common/Wshift-overflow-3.c
new file mode 100644 (file)
index 0000000..ed57d5d
--- /dev/null
@@ -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 a/gcc/testsuite/c-c++-common/Wshift-overflow-4.c b/gcc/testsuite/c-c++-common/Wshift-overflow-4.c
new file mode 100644 (file)
index 0000000..92f8cf8
--- /dev/null
@@ -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 a/gcc/testsuite/c-c++-common/Wshift-overflow-5.c b/gcc/testsuite/c-c++-common/Wshift-overflow-5.c
new file mode 100644 (file)
index 0000000..c9f4643
--- /dev/null
@@ -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 a/gcc/testsuite/g++.dg/cpp1y/left-shift-1.C b/gcc/testsuite/g++.dg/cpp1y/left-shift-1.C
new file mode 100644 (file)
index 0000000..a24caae
--- /dev/null
@@ -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;
index f39f1defa0e6b72e2e5de7a6f19ce4bda0f81819..c701304a1b4e92bfa922ce8a75e3c775e31a1228 100644 (file)
@@ -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 a/gcc/testsuite/gcc.dg/c90-left-shift-2.c b/gcc/testsuite/gcc.dg/c90-left-shift-2.c
new file mode 100644 (file)
index 0000000..f79ab8b
--- /dev/null
@@ -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 a/gcc/testsuite/gcc.dg/c90-left-shift-3.c b/gcc/testsuite/gcc.dg/c90-left-shift-3.c
new file mode 100644 (file)
index 0000000..43942dd
--- /dev/null
@@ -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 a/gcc/testsuite/gcc.dg/c99-left-shift-2.c b/gcc/testsuite/gcc.dg/c99-left-shift-2.c
new file mode 100644 (file)
index 0000000..e35786e
--- /dev/null
@@ -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 a/gcc/testsuite/gcc.dg/c99-left-shift-3.c b/gcc/testsuite/gcc.dg/c99-left-shift-3.c
new file mode 100644 (file)
index 0000000..59d0f24
--- /dev/null
@@ -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" } */
+}
index e6ce217b626761db36b827a491c86e2ad080b985..7610a2062c287a4e14375087a48b5f32cd975f04 100644 (file)
@@ -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 */
index 8da43710e70269608d89044787ec29b5ce181440..efba2ab3190822018596b1c8c532f575703fa8bc 100644 (file)
@@ -1,3 +1,4 @@
+/* { dg-options "-Wno-shift-overflow" } */
 /* { dg-do compile } */
 void DOSMEM_FillIsrTable(int*isr) {
     int i;
index 46909ca7ecdd3c791ce33644e3fb8e4730f12fd4..85ff0e041f6d34908c0e69de52799ad13cd0b61f 100644 (file)
@@ -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
index 68186dbbf3e14ff461908a14a74b3a55992941b3..6199cd615141f163d33923c3a8362ced78179fcb 100644 (file)
@@ -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