From 451b5e4830e34b0ee1ae8af9fe3de4afe2fc5631 Mon Sep 17 00:00:00 2001 From: Marek Polacek Date: Mon, 20 Jul 2015 13:43:45 +0000 Subject: [PATCH] re PR c++/55095 (Wshift-overflow) 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 From-SVN: r225998 --- gcc/ChangeLog | 5 ++ gcc/c-family/ChangeLog | 11 ++++ gcc/c-family/c-common.c | 61 ++++++++++++++++++- gcc/c-family/c-common.h | 1 + gcc/c-family/c-opts.c | 4 ++ gcc/c-family/c.opt | 8 +++ gcc/c/ChangeLog | 6 ++ gcc/c/c-typeck.c | 23 ++++--- gcc/cp/ChangeLog | 5 ++ gcc/cp/typeck.c | 3 + gcc/doc/invoke.texi | 21 +++++++ gcc/testsuite/ChangeLog | 19 ++++++ .../c-c++-common/Wshift-overflow-1.c | 58 ++++++++++++++++++ .../c-c++-common/Wshift-overflow-2.c | 58 ++++++++++++++++++ .../c-c++-common/Wshift-overflow-3.c | 59 ++++++++++++++++++ .../c-c++-common/Wshift-overflow-4.c | 59 ++++++++++++++++++ .../c-c++-common/Wshift-overflow-5.c | 11 ++++ gcc/testsuite/g++.dg/cpp1y/left-shift-1.C | 11 ++++ gcc/testsuite/gcc.c-torture/execute/pr40386.c | 2 +- gcc/testsuite/gcc.dg/c90-left-shift-2.c | 14 +++++ gcc/testsuite/gcc.dg/c90-left-shift-3.c | 14 +++++ gcc/testsuite/gcc.dg/c99-left-shift-2.c | 14 +++++ gcc/testsuite/gcc.dg/c99-left-shift-3.c | 14 +++++ gcc/testsuite/gcc.dg/pr40501.c | 2 +- gcc/testsuite/gcc.dg/vect/pr33373.c | 1 + .../gcc.dg/vect/vect-shift-2-big-array.c | 1 + gcc/testsuite/gcc.dg/vect/vect-shift-2.c | 1 + 27 files changed, 473 insertions(+), 13 deletions(-) create mode 100644 gcc/testsuite/c-c++-common/Wshift-overflow-1.c create mode 100644 gcc/testsuite/c-c++-common/Wshift-overflow-2.c create mode 100644 gcc/testsuite/c-c++-common/Wshift-overflow-3.c create mode 100644 gcc/testsuite/c-c++-common/Wshift-overflow-4.c create mode 100644 gcc/testsuite/c-c++-common/Wshift-overflow-5.c create mode 100644 gcc/testsuite/g++.dg/cpp1y/left-shift-1.C create mode 100644 gcc/testsuite/gcc.dg/c90-left-shift-2.c create mode 100644 gcc/testsuite/gcc.dg/c90-left-shift-3.c create mode 100644 gcc/testsuite/gcc.dg/c99-left-shift-2.c create mode 100644 gcc/testsuite/gcc.dg/c99-left-shift-3.c diff --git a/gcc/ChangeLog b/gcc/ChangeLog index addf8ad6a32..202416df923 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,8 @@ +2015-07-20 Marek Polacek + + PR c++/55095 + * doc/invoke.texi: Document -Wshift-overflow and -Wshift-overflow=. + 2015-07-20 Kyrylo Tkachov * simplify-rtx.c (simplify_unary_operation_1, NEG case): diff --git a/gcc/c-family/ChangeLog b/gcc/c-family/ChangeLog index 85582c96653..9751ba97550 100644 --- a/gcc/c-family/ChangeLog +++ b/gcc/c-family/ChangeLog @@ -1,3 +1,14 @@ +2015-07-20 Marek Polacek + Richard Sandiford + + 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 * c-format.c (static void check_format_info_main): Use diff --git a/gcc/c-family/c-common.c b/gcc/c-family/c-common.c index 84e7242ec0a..c94596f89ba 100644 --- a/gcc/c-family/c-common.c +++ b/gcc/c-family/c-common.c @@ -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. + + 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 a/gcc/c-family/c-common.h b/gcc/c-family/c-common.h index a2a46212e83..a198e794f5b 100644 --- a/gcc/c-family/c-common.h +++ b/gcc/c-family/c-common.h @@ -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 *make_tree_vector (void); extern void release_tree_vector (vec *); extern vec *make_tree_vector_single (tree); diff --git a/gcc/c-family/c-opts.c b/gcc/c-family/c-opts.c index 4dbb109d06a..73f5db0a664 100644 --- a/gcc/c-family/c-opts.c +++ b/gcc/c-family/c-opts.c @@ -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 diff --git a/gcc/c-family/c.opt b/gcc/c-family/c.opt index 285952ea5fd..dc760d71799 100644 --- a/gcc/c-family/c.opt +++ b/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 a/gcc/c/ChangeLog b/gcc/c/ChangeLog index a75f2e8a292..18443aea3db 100644 --- a/gcc/c/ChangeLog +++ b/gcc/c/ChangeLog @@ -1,3 +1,9 @@ +2015-07-20 Marek Polacek + + 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 * c-array-notation.c: Adjust includes for flags.h changes. diff --git a/gcc/c/c-typeck.c b/gcc/c/c-typeck.c index 247a7bf329d..d3d0abdb2cb 100644 --- a/gcc/c/c-typeck.c +++ b/gcc/c/c-typeck.c @@ -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. */ diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 6b92826118e..b72b22f5ef8 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,8 @@ +2015-07-20 Marek Polacek + + PR c++/55095 + * typeck.c (cp_build_binary_op): Warn about left shift overflows. + 2015-07-15 Jason Merrill PR c++/65091 diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c index 3e252f93e5e..b88a3fd42cf 100644 --- a/gcc/cp/typeck.c +++ b/gcc/cp/typeck.c @@ -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; diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi index a62c8b33e92..55c26593180 100644 --- a/gcc/doc/invoke.texi +++ b/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 @@ -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 diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 9df1d41c151..aa6693c58fe 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,22 @@ +2015-07-20 Marek Polacek + + 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 * 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 index 00000000000..9969629f2b0 --- /dev/null +++ b/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 a/gcc/testsuite/c-c++-common/Wshift-overflow-2.c b/gcc/testsuite/c-c++-common/Wshift-overflow-2.c new file mode 100644 index 00000000000..d5115d01eae --- /dev/null +++ b/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 a/gcc/testsuite/c-c++-common/Wshift-overflow-3.c b/gcc/testsuite/c-c++-common/Wshift-overflow-3.c new file mode 100644 index 00000000000..ed57d5d8bec --- /dev/null +++ b/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 a/gcc/testsuite/c-c++-common/Wshift-overflow-4.c b/gcc/testsuite/c-c++-common/Wshift-overflow-4.c new file mode 100644 index 00000000000..92f8cf85b50 --- /dev/null +++ b/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 a/gcc/testsuite/c-c++-common/Wshift-overflow-5.c b/gcc/testsuite/c-c++-common/Wshift-overflow-5.c new file mode 100644 index 00000000000..c9f464355dc --- /dev/null +++ b/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 a/gcc/testsuite/g++.dg/cpp1y/left-shift-1.C b/gcc/testsuite/g++.dg/cpp1y/left-shift-1.C new file mode 100644 index 00000000000..a24caaebf26 --- /dev/null +++ b/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 a/gcc/testsuite/gcc.c-torture/execute/pr40386.c b/gcc/testsuite/gcc.c-torture/execute/pr40386.c index f39f1defa0e..c701304a1b4 100644 --- a/gcc/testsuite/gcc.c-torture/execute/pr40386.c +++ b/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 a/gcc/testsuite/gcc.dg/c90-left-shift-2.c b/gcc/testsuite/gcc.dg/c90-left-shift-2.c new file mode 100644 index 00000000000..f79ab8b71de --- /dev/null +++ b/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 a/gcc/testsuite/gcc.dg/c90-left-shift-3.c b/gcc/testsuite/gcc.dg/c90-left-shift-3.c new file mode 100644 index 00000000000..43942dd29d1 --- /dev/null +++ b/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 a/gcc/testsuite/gcc.dg/c99-left-shift-2.c b/gcc/testsuite/gcc.dg/c99-left-shift-2.c new file mode 100644 index 00000000000..e35786e50d9 --- /dev/null +++ b/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 a/gcc/testsuite/gcc.dg/c99-left-shift-3.c b/gcc/testsuite/gcc.dg/c99-left-shift-3.c new file mode 100644 index 00000000000..59d0f24e39d --- /dev/null +++ b/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 a/gcc/testsuite/gcc.dg/pr40501.c b/gcc/testsuite/gcc.dg/pr40501.c index e6ce217b626..7610a2062c2 100644 --- a/gcc/testsuite/gcc.dg/pr40501.c +++ b/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 a/gcc/testsuite/gcc.dg/vect/pr33373.c b/gcc/testsuite/gcc.dg/vect/pr33373.c index 8da43710e70..efba2ab3190 100644 --- a/gcc/testsuite/gcc.dg/vect/pr33373.c +++ b/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 a/gcc/testsuite/gcc.dg/vect/vect-shift-2-big-array.c b/gcc/testsuite/gcc.dg/vect/vect-shift-2-big-array.c index 46909ca7ecd..85ff0e041f6 100644 --- a/gcc/testsuite/gcc.dg/vect/vect-shift-2-big-array.c +++ b/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 a/gcc/testsuite/gcc.dg/vect/vect-shift-2.c b/gcc/testsuite/gcc.dg/vect/vect-shift-2.c index 68186dbbf3e..6199cd61514 100644 --- a/gcc/testsuite/gcc.dg/vect/vect-shift-2.c +++ b/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 -- 2.30.2