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 <pola...@redhat.com> Richard Sandiford <richard.sandif...@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