diff mbox series

c, c++, c-family: -Wshift-negative-value and -Wshift-overflow* tweaks for -fwrapv and C++20+ [PR104711]

Message ID Yh83anB3ytZRHaIz@tucnak
State New
Headers show
Series c, c++, c-family: -Wshift-negative-value and -Wshift-overflow* tweaks for -fwrapv and C++20+ [PR104711] | expand

Commit Message

Jakub Jelinek March 2, 2022, 9:22 a.m. UTC
Hi!

As mentioned in the PR, different standards have different definition
on what is an UB left shift.  They all agree on out of bounds (including
negative) shift count.
The rules used by ubsan are:
C99-C2x ((unsigned) x >> (uprecm1 - y)) != 0 then UB
C++11-C++17 x < 0 || ((unsigned) x >> (uprecm1 - y)) > 1 then UB
C++20 and later everything is well defined
Now, for C++20, I've in the P1236R1 implementation added an early
exit for -Wshift-overflow* warning so that it never warns, but apparently
-Wshift-negative-value remained as is.  As it is well defined in C++20,
the following patch doesn't enable -Wshift-negative-value from -Wextra
anymore for C++20 and later, if users want for compatibility with C++17
and earlier get the warning, they still can by using -Wshift-negative-value
explicitly.
Another thing is -fwrapv, that is an extension to the standards, so it is up
to us how exactly we define that case.  Our ubsan code treats
TYPE_OVERFLOW_WRAPS (type0) and cxx_dialect >= cxx20 the same as only
diagnosing out of bounds shift count and nothing else and IMHO it is most
sensical to treat -fwrapv signed left shifts the same as C++20 treats
them, https://eel.is/c++draft/expr.shift#2
"The value of E1 << E2 is the unique value congruent to E1×2^E2 modulo 2^N,
where N is the width of the type of the result.
[Note 1: E1 is left-shifted E2 bit positions; vacated bits are zero-filled.
— end note]"
with no UB dependent on the E1 values.  The UB is only
"The behavior is undefined if the right operand is negative, or greater
than or equal to the width of the promoted left operand."
Under the hood (except for FEs and ubsan from FEs) GCC middle-end doesn't
consider UB in left shifts dependent on the first operand's value, only
the out of bounds shifts.

While this change isn't a regression, I'd think it is useful for GCC 12,
it doesn't add new warnings, but just removes warnings that aren't
appropriate.

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

2022-03-02  Jakub Jelinek  <jakub@redhat.com>

	PR c/104711
gcc/
	* doc/invoke.texi (-Wextra): Document that -Wshift-negative-value
	is enabled by it only for C++11 to C++17 rather than for C++03 or
	later.
	(-Wshift-negative-value): Similarly (except here we stated
	that it is enabled for C++11 or later).
gcc/c-family/
	* c-opts.cc (c_common_post_options): Don't enable
	-Wshift-negative-value from -Wextra for C++20 or later.
	* c-ubsan.cc (ubsan_instrument_shift): Adjust comments.
	* c-warn.cc (maybe_warn_shift_overflow): Use TYPE_OVERFLOW_WRAPS
	instead of TYPE_UNSIGNED.
gcc/c/
	* c-fold.cc (c_fully_fold_internal): Don't emit
	-Wshift-negative-value warning if TYPE_OVERFLOW_WRAPS.
	* c-typeck.cc (build_binary_op): Likewise.
gcc/cp/
	* constexpr.cc (cxx_eval_check_shift_p): Use TYPE_OVERFLOW_WRAPS
	instead of TYPE_UNSIGNED.
	* typeck.cc (cp_build_binary_op): Don't emit
	-Wshift-negative-value warning if TYPE_OVERFLOW_WRAPS.
gcc/testsuite/
	* c-c++-common/Wshift-negative-value-1.c: Remove
	dg-additional-options, instead in target selectors of each diagnostic
	check for exact C++ versions where it should be diagnosed.
	* c-c++-common/Wshift-negative-value-2.c: Likewise.
	* c-c++-common/Wshift-negative-value-3.c: Likewise.
	* c-c++-common/Wshift-negative-value-4.c: Likewise.
	* c-c++-common/Wshift-negative-value-7.c: New test.
	* c-c++-common/Wshift-negative-value-8.c: New test.
	* c-c++-common/Wshift-negative-value-9.c: New test.
	* c-c++-common/Wshift-negative-value-10.c: New test.
	* c-c++-common/Wshift-overflow-1.c: Remove
	dg-additional-options, instead in target selectors of each diagnostic
	check for exact C++ versions where it should be diagnosed.
	* c-c++-common/Wshift-overflow-2.c: Likewise.
	* c-c++-common/Wshift-overflow-5.c: Likewise.
	* c-c++-common/Wshift-overflow-6.c: Likewise.
	* c-c++-common/Wshift-overflow-7.c: Likewise.
	* c-c++-common/Wshift-overflow-8.c: New test.
	* c-c++-common/Wshift-overflow-9.c: New test.
	* c-c++-common/Wshift-overflow-10.c: New test.
	* c-c++-common/Wshift-overflow-11.c: New test.
	* c-c++-common/Wshift-overflow-12.c: New test.


	Jakub

Comments

Richard Biener March 2, 2022, 10:17 a.m. UTC | #1
On Wed, Mar 2, 2022 at 10:23 AM Jakub Jelinek via Gcc-patches
<gcc-patches@gcc.gnu.org> wrote:
>
> Hi!
>
> As mentioned in the PR, different standards have different definition
> on what is an UB left shift.  They all agree on out of bounds (including
> negative) shift count.
> The rules used by ubsan are:
> C99-C2x ((unsigned) x >> (uprecm1 - y)) != 0 then UB
> C++11-C++17 x < 0 || ((unsigned) x >> (uprecm1 - y)) > 1 then UB
> C++20 and later everything is well defined
> Now, for C++20, I've in the P1236R1 implementation added an early
> exit for -Wshift-overflow* warning so that it never warns, but apparently
> -Wshift-negative-value remained as is.  As it is well defined in C++20,
> the following patch doesn't enable -Wshift-negative-value from -Wextra
> anymore for C++20 and later, if users want for compatibility with C++17
> and earlier get the warning, they still can by using -Wshift-negative-value
> explicitly.
> Another thing is -fwrapv, that is an extension to the standards, so it is up
> to us how exactly we define that case.  Our ubsan code treats
> TYPE_OVERFLOW_WRAPS (type0) and cxx_dialect >= cxx20 the same as only
> diagnosing out of bounds shift count and nothing else and IMHO it is most
> sensical to treat -fwrapv signed left shifts the same as C++20 treats
> them, https://eel.is/c++draft/expr.shift#2
> "The value of E1 << E2 is the unique value congruent to E1×2^E2 modulo 2^N,
> where N is the width of the type of the result.
> [Note 1: E1 is left-shifted E2 bit positions; vacated bits are zero-filled.
> — end note]"
> with no UB dependent on the E1 values.  The UB is only
> "The behavior is undefined if the right operand is negative, or greater
> than or equal to the width of the promoted left operand."
> Under the hood (except for FEs and ubsan from FEs) GCC middle-end doesn't
> consider UB in left shifts dependent on the first operand's value, only
> the out of bounds shifts.

Indeed the obvious place, tree_binary_nonnegative_warnv_p does not
consider LSHIFT nonnegative if the first operand is.  Not sure about
ranger, but at least

void foo (int i, int n)
{
  if (i > 0)
    {
      int j = i << n;
      if (j < 0)
        __builtin_abort ();
    }
}

is not optimized but it seems it could be (but not in C++20?).

Leaving review of the patch to FE maintainers.

>
> While this change isn't a regression, I'd think it is useful for GCC 12,
> it doesn't add new warnings, but just removes warnings that aren't
> appropriate.
>
> Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk?
>
> 2022-03-02  Jakub Jelinek  <jakub@redhat.com>
>
>         PR c/104711
> gcc/
>         * doc/invoke.texi (-Wextra): Document that -Wshift-negative-value
>         is enabled by it only for C++11 to C++17 rather than for C++03 or
>         later.
>         (-Wshift-negative-value): Similarly (except here we stated
>         that it is enabled for C++11 or later).
> gcc/c-family/
>         * c-opts.cc (c_common_post_options): Don't enable
>         -Wshift-negative-value from -Wextra for C++20 or later.
>         * c-ubsan.cc (ubsan_instrument_shift): Adjust comments.
>         * c-warn.cc (maybe_warn_shift_overflow): Use TYPE_OVERFLOW_WRAPS
>         instead of TYPE_UNSIGNED.
> gcc/c/
>         * c-fold.cc (c_fully_fold_internal): Don't emit
>         -Wshift-negative-value warning if TYPE_OVERFLOW_WRAPS.
>         * c-typeck.cc (build_binary_op): Likewise.
> gcc/cp/
>         * constexpr.cc (cxx_eval_check_shift_p): Use TYPE_OVERFLOW_WRAPS
>         instead of TYPE_UNSIGNED.
>         * typeck.cc (cp_build_binary_op): Don't emit
>         -Wshift-negative-value warning if TYPE_OVERFLOW_WRAPS.
> gcc/testsuite/
>         * c-c++-common/Wshift-negative-value-1.c: Remove
>         dg-additional-options, instead in target selectors of each diagnostic
>         check for exact C++ versions where it should be diagnosed.
>         * c-c++-common/Wshift-negative-value-2.c: Likewise.
>         * c-c++-common/Wshift-negative-value-3.c: Likewise.
>         * c-c++-common/Wshift-negative-value-4.c: Likewise.
>         * c-c++-common/Wshift-negative-value-7.c: New test.
>         * c-c++-common/Wshift-negative-value-8.c: New test.
>         * c-c++-common/Wshift-negative-value-9.c: New test.
>         * c-c++-common/Wshift-negative-value-10.c: New test.
>         * c-c++-common/Wshift-overflow-1.c: Remove
>         dg-additional-options, instead in target selectors of each diagnostic
>         check for exact C++ versions where it should be diagnosed.
>         * c-c++-common/Wshift-overflow-2.c: Likewise.
>         * c-c++-common/Wshift-overflow-5.c: Likewise.
>         * c-c++-common/Wshift-overflow-6.c: Likewise.
>         * c-c++-common/Wshift-overflow-7.c: Likewise.
>         * c-c++-common/Wshift-overflow-8.c: New test.
>         * c-c++-common/Wshift-overflow-9.c: New test.
>         * c-c++-common/Wshift-overflow-10.c: New test.
>         * c-c++-common/Wshift-overflow-11.c: New test.
>         * c-c++-common/Wshift-overflow-12.c: New test.
>
> --- gcc/doc/invoke.texi.jj      2022-02-25 10:46:53.085181500 +0100
> +++ gcc/doc/invoke.texi 2022-03-01 09:59:15.040855224 +0100
> @@ -5809,7 +5809,7 @@ name is still supported, but the newer n
>  -Wredundant-move @r{(only for C++)}  @gol
>  -Wtype-limits  @gol
>  -Wuninitialized  @gol
> --Wshift-negative-value @r{(in C++03 and in C99 and newer)}  @gol
> +-Wshift-negative-value @r{(in C++11 to C++17 and in C99 and newer)}  @gol
>  -Wunused-parameter @r{(only with} @option{-Wunused} @r{or} @option{-Wall}@r{)} @gol
>  -Wunused-but-set-parameter @r{(only with} @option{-Wunused} @r{or} @option{-Wall}@r{)}}
>
> @@ -6839,7 +6839,7 @@ of the type.  This warning is enabled by
>  @opindex Wshift-negative-value
>  @opindex Wno-shift-negative-value
>  Warn if left shifting a negative value.  This warning is enabled by
> -@option{-Wextra} in C99 and C++11 modes (and newer).
> +@option{-Wextra} in C99 (and newer) and C++11 to C++17 modes.
>
>  @item -Wno-shift-overflow
>  @itemx -Wshift-overflow=@var{n}
> --- gcc/c-family/c-opts.cc.jj   2022-01-18 11:58:58.884992028 +0100
> +++ gcc/c-family/c-opts.cc      2022-03-01 09:57:34.880253831 +0100
> @@ -934,10 +934,12 @@ c_common_post_options (const char **pfil
>    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.  */
> +  /* -Wshift-negative-value is enabled by -Wextra in C99 and C++11 to C++17
> +     modes.  */
>    if (warn_shift_negative_value == -1)
>      warn_shift_negative_value = (extra_warnings
> -                                && (cxx_dialect >= cxx11 || flag_isoc99));
> +                                && (cxx_dialect >= cxx11 || flag_isoc99)
> +                                && cxx_dialect < cxx20);
>
>    /* -Wregister is enabled by default in C++17.  */
>    SET_OPTION_IF_UNSET (&global_options, &global_options_set, warn_register,
> --- gcc/c-family/c-ubsan.cc.jj  2022-02-09 15:15:59.288840032 +0100
> +++ gcc/c-family/c-ubsan.cc     2022-03-01 09:55:51.779693845 +0100
> @@ -173,7 +173,7 @@ ubsan_instrument_shift (location_t loc,
>        || cxx_dialect >= cxx20)
>      ;
>
> -  /* For signed x << y, in C99/C11, the following:
> +  /* For signed x << y, in C99 and later, the following:
>       (unsigned) x >> (uprecm1 - y)
>       if non-zero, is undefined.  */
>    else if (code == LSHIFT_EXPR && flag_isoc99 && cxx_dialect < cxx11)
> @@ -186,7 +186,7 @@ ubsan_instrument_shift (location_t loc,
>                         build_int_cst (TREE_TYPE (tt), 0));
>      }
>
> -  /* For signed x << y, in C++11 and later, the following:
> +  /* For signed x << y, in C++11 to C++17, the following:
>       x < 0 || ((unsigned) x >> (uprecm1 - y))
>       if > 1, is undefined.  */
>    else if (code == LSHIFT_EXPR && cxx_dialect >= cxx11)
> --- gcc/c-family/c-warn.cc.jj   2022-01-18 11:58:58.922991486 +0100
> +++ gcc/c-family/c-warn.cc      2022-03-01 10:02:41.634971050 +0100
> @@ -2605,7 +2605,7 @@ maybe_warn_shift_overflow (location_t lo
>    unsigned int prec0 = TYPE_PRECISION (type0);
>
>    /* Left-hand operand must be signed.  */
> -  if (TYPE_UNSIGNED (type0) || cxx_dialect >= cxx20)
> +  if (TYPE_OVERFLOW_WRAPS (type0) || cxx_dialect >= cxx20)
>      return false;
>
>    unsigned int min_prec = (wi::min_precision (wi::to_wide (op0), SIGNED)
> --- gcc/c/c-fold.cc.jj  2022-02-09 20:45:24.253211303 +0100
> +++ gcc/c/c-fold.cc     2022-03-01 11:39:32.153859825 +0100
> @@ -382,6 +382,7 @@ c_fully_fold_internal (tree expr, bool i
>           && TREE_CODE (TREE_TYPE (orig_op0)) == INTEGER_TYPE
>           && TREE_CODE (op0) == INTEGER_CST
>           && c_inhibit_evaluation_warnings == 0
> +         && !TYPE_OVERFLOW_WRAPS (TREE_TYPE (orig_op0))
>           && tree_int_cst_sgn (op0) < 0)
>         warning_at (loc, OPT_Wshift_negative_value,
>                     "left shift of negative value");
> --- gcc/c/c-typeck.cc.jj        2022-02-11 00:19:22.135067293 +0100
> +++ gcc/c/c-typeck.cc   2022-03-01 10:04:20.925584897 +0100
> @@ -12213,7 +12213,8 @@ build_binary_op (location_t location, en
>         {
>           doing_shift = true;
>           if (TREE_CODE (op0) == INTEGER_CST
> -             && tree_int_cst_sgn (op0) < 0)
> +             && tree_int_cst_sgn (op0) < 0
> +             && !TYPE_OVERFLOW_WRAPS (type0))
>             {
>               /* Don't reject a left shift of a negative value in a context
>                  where a constant expression is needed in C90.  */
> --- gcc/cp/constexpr.cc.jj      2022-02-18 12:37:51.081601299 +0100
> +++ gcc/cp/constexpr.cc 2022-03-01 11:56:12.874890444 +0100
> @@ -3165,7 +3165,7 @@ cxx_eval_check_shift_p (location_t loc,
>       The value of E1 << E2 is the unique value congruent to E1 x 2^E2 modulo
>       2^N, where N is the range exponent of the type of the result.  */
>    if (code == LSHIFT_EXPR
> -      && !TYPE_UNSIGNED (lhstype)
> +      && !TYPE_OVERFLOW_WRAPS (lhstype)
>        && cxx_dialect >= cxx11
>        && cxx_dialect < cxx20)
>      {
> --- gcc/cp/typeck.cc.jj 2022-02-18 12:38:06.065393230 +0100
> +++ gcc/cp/typeck.cc    2022-03-01 10:04:57.726071137 +0100
> @@ -5382,6 +5382,7 @@ cp_build_binary_op (const op_location_t
>           doing_shift = true;
>           if (TREE_CODE (const_op0) == INTEGER_CST
>               && tree_int_cst_sgn (const_op0) < 0
> +             && !TYPE_OVERFLOW_WRAPS (type0)
>               && (complain & tf_warning)
>               && c_inhibit_evaluation_warnings == 0)
>             warning_at (location, OPT_Wshift_negative_value,
> --- gcc/testsuite/c-c++-common/Wshift-negative-value-1.c.jj     2020-01-12 11:54:36.995404628 +0100
> +++ gcc/testsuite/c-c++-common/Wshift-negative-value-1.c        2022-03-01 11:43:47.217299318 +0100
> @@ -1,13 +1,12 @@
>  /* PR c/65179 */
>  /* { dg-do compile } */
>  /* { dg-options "-O -Wextra" } */
> -/* { dg-additional-options "-std=c++11" { target c++ } } */
>
>  enum E {
>    A = 0 << 1,
>    B = 1 << 1,
> -  C = -1 << 1, /* { dg-warning "10:left shift of negative value|not an integer constant" } */
> -  /* { dg-error "left operand of shift expression" "shift" { target c++ } .-1 } */
> +  C = -1 << 1, /* { dg-warning "10:left shift of negative value|not an integer constant" "" { target { c || { c++11 && c++17_down } } } } */
> +  /* { dg-error "left operand of shift expression" "shift" { target { c++11 && c++17_down } } .-1 } */
>    D = 0 >> 1,
>    E = 1 >> 1,
>    F = -1 >> 1
> @@ -23,10 +22,10 @@ left (int x)
>    int r = 0;
>    r += z << x;
>    r += o << x;
> -  r += m << x; /* { dg-warning "10:left shift of negative value" } */
> +  r += m << x; /* { dg-warning "10:left shift of negative value" "" { target { c || { c++11 && c++17_down } } } } */
>    r += 0 << x;
>    r += 1 << x;
> -  r += -1 << x; /* { dg-warning "11:left shift of negative value" } */
> +  r += -1 << x; /* { dg-warning "11:left shift of negative value" "" { target { c || { c++11 && c++17_down } } } } */
>    r += -1U << x;
>    return r;
>  }
> --- gcc/testsuite/c-c++-common/Wshift-negative-value-2.c.jj     2020-01-12 11:54:36.995404628 +0100
> +++ gcc/testsuite/c-c++-common/Wshift-negative-value-2.c        2022-03-01 11:47:41.695026169 +0100
> @@ -1,14 +1,13 @@
>  /* PR c/65179 */
>  /* { dg-do compile } */
>  /* { dg-options "-O -Wshift-negative-value" } */
> -/* { dg-additional-options "-std=c++11" { target c++ } } */
>
>  enum E {
>    A = 0 << 1,
>    B = 1 << 1,
>    C = -1 << 1, /* { dg-warning "10:left shift of negative value" } */
> -  /* { dg-error "not an integer constant" "no constant" { target c++ } .-1 } */
> -  /* { dg-error "left operand of shift expression" "shift" { target c++ } .-2 } */
> +  /* { dg-error "not an integer constant" "no constant" { target { c++11 && c++17_down } } .-1 } */
> +  /* { dg-error "left operand of shift expression" "shift" { target { c++11 && c++17_down } } .-2 } */
>    D = 0 >> 1,
>    E = 1 >> 1,
>    F = -1 >> 1
> --- gcc/testsuite/c-c++-common/Wshift-negative-value-3.c.jj     2020-01-12 11:54:36.995404628 +0100
> +++ gcc/testsuite/c-c++-common/Wshift-negative-value-3.c        2022-03-01 11:48:01.029756269 +0100
> @@ -1,14 +1,13 @@
>  /* PR c/65179 */
>  /* { dg-do compile } */
>  /* { dg-options "-O -Wextra -Wno-shift-negative-value" } */
> -/* { dg-additional-options "-std=c++11" { target c++ } } */
>
>  enum E {
>    A = 0 << 1,
>    B = 1 << 1,
>    C = -1 << 1,
> -  /* { dg-error "not an integer constant" "no constant" { target c++ } .-1 } */
> -  /* { dg-error "left operand of shift expression" "shift" { target c++ } .-2 } */
> +  /* { dg-error "not an integer constant" "no constant" { target { c++11 && c++17_down } } .-1 } */
> +  /* { dg-error "left operand of shift expression" "shift" { target { c++11 && c++17_down } } .-2 } */
>    D = 0 >> 1,
>    E = 1 >> 1,
>    F = -1 >> 1
> --- gcc/testsuite/c-c++-common/Wshift-negative-value-4.c.jj     2020-01-12 11:54:36.995404628 +0100
> +++ gcc/testsuite/c-c++-common/Wshift-negative-value-4.c        2022-03-01 11:48:46.740118184 +0100
> @@ -1,14 +1,13 @@
>  /* PR c/65179 */
>  /* { dg-do compile } */
>  /* { dg-options "-O" } */
> -/* { dg-additional-options "-std=c++11" { target c++ } } */
>
>  enum E {
>    A = 0 << 1,
>    B = 1 << 1,
>    C = -1 << 1,
> -  /* { dg-error "not an integer constant" "no constant" { target c++ } .-1 } */
> -  /* { dg-error "left operand of shift expression" "shift" { target c++ } .-2 } */
> +  /* { dg-error "not an integer constant" "no constant" { target { c++11 && c++17_down } } .-1 } */
> +  /* { dg-error "left operand of shift expression" "shift" { target { c++11 && c++17_down } } .-2 } */
>    D = 0 >> 1,
>    E = 1 >> 1,
>    F = -1 >> 1
> --- gcc/testsuite/c-c++-common/Wshift-negative-value-7.c.jj     2022-03-01 11:00:56.877179511 +0100
> +++ gcc/testsuite/c-c++-common/Wshift-negative-value-7.c        2022-03-01 11:59:32.535103327 +0100
> @@ -0,0 +1,5 @@
> +/* PR c/65179 */
> +/* { dg-do compile } */
> +/* { dg-options "-O -Wextra -fwrapv" } */
> +
> +#include "Wshift-negative-value-1.c"
> --- gcc/testsuite/c-c++-common/Wshift-negative-value-8.c.jj     2022-03-01 11:01:41.087562363 +0100
> +++ gcc/testsuite/c-c++-common/Wshift-negative-value-8.c        2022-03-01 11:59:43.084956059 +0100
> @@ -0,0 +1,5 @@
> +/* PR c/65179 */
> +/* { dg-do compile } */
> +/* { dg-options "-O -Wshift-negative-value -fwrapv" } */
> +
> +#include "Wshift-negative-value-1.c"
> --- gcc/testsuite/c-c++-common/Wshift-negative-value-9.c.jj     2022-03-01 11:02:38.837756210 +0100
> +++ gcc/testsuite/c-c++-common/Wshift-negative-value-9.c        2022-03-01 11:59:51.733835326 +0100
> @@ -0,0 +1,5 @@
> +/* PR c/65179 */
> +/* { dg-do compile } */
> +/* { dg-options "-O -fwrapv" } */
> +
> +#include "Wshift-negative-value-1.c"
> --- gcc/testsuite/c-c++-common/Wshift-negative-value-10.c.jj    2022-03-01 11:03:28.922057068 +0100
> +++ gcc/testsuite/c-c++-common/Wshift-negative-value-10.c       2022-03-01 11:03:44.101845168 +0100
> @@ -0,0 +1,7 @@
> +/* PR c/65179 */
> +/* { dg-do compile } */
> +/* { dg-options "-O -Wshift-negative-value -fwrapv" } */
> +/* { dg-additional-options "-std=c++03" { target c++ } } */
> +/* { dg-additional-options "-std=c90" { target c } } */
> +
> +#include "Wshift-negative-value-1.c"
> --- gcc/testsuite/c-c++-common/Wshift-overflow-1.c.jj   2020-01-12 11:54:36.995404628 +0100
> +++ gcc/testsuite/c-c++-common/Wshift-overflow-1.c      2022-03-01 12:01:33.792410660 +0100
> @@ -1,7 +1,6 @@
>  /* 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)
> @@ -12,16 +11,16 @@
>  #define LONG_LONG_MIN (-__LONG_LONG_MAX__-1)
>
>  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 i2 = 9 << INTM1; /* { dg-warning "requires 36 bits to represent" "" { target { c || { c++11 && c++17_down } } } } */
> +int i3 = 10 << INTM2; /* { dg-warning "requires 35 bits to represent" "" { target { c || { c++11 && c++17_down } } } } */
> +int i4 = __INT_MAX__ << 2; /* { dg-warning "requires 34 bits to represent" "" { target { c || { c++11 && c++17_down } } } } */
> +int i5 = __INT_MAX__ << INTM1; /* { dg-warning "requires 63 bits to represent" "" { target { c || { c++11 && c++17_down } } } } */
>  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 i11 = INT_MIN << 1; /* { dg-warning "requires 33 bits to represent" } */
> +int i7 = -9 << INTM1; /* { dg-warning "requires 36 bits to represent" "" { target { c || { c++11 && c++17_down } } } } */
> +int i8 = -10 << INTM2; /* { dg-warning "requires 35 bits to represent" "" { target { c || { c++11 && c++17_down } } } } */
> +int i9 = -__INT_MAX__ << 2; /* { dg-warning "requires 34 bits to represent" "" { target { c || { c++11 && c++17_down } } } } */
> +int i10 = -__INT_MAX__ << INTM1; /* { dg-warning "requires 63 bits to represent" "" { target { c || { c++11 && c++17_down } } } } */
> +int i11 = INT_MIN << 1; /* { dg-warning "requires 33 bits to represent" "" { target { c || { c++11 && c++17_down } } } } */
>
>  int r1 = 1 >> INTM1;
>  int r2 = 9 >> INTM1;
> @@ -35,29 +34,29 @@ 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 u2 = 9 << INTM1; /* { dg-warning "requires 36 bits to represent" "" { target { c || { c++11 && c++17_down } } } } */
>  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 l2 = 9LL << LLONGM1; /* { dg-warning "requires 68 bits to represent" "" { target { c || { c++11 && c++17_down } } } } */
> +long long int l3 = 10LL << LLONGM2; /* { dg-warning "requires 67 bits to represent" "" { target { c || { c++11 && c++17_down } } } } */
> +long long int l4 = __LONG_LONG_MAX__ << 2; /* { dg-warning "requires 66 bits to represent" "" { target { c || { c++11 && c++17_down } } } } */
> +long long int l5 = __LONG_LONG_MAX__ << LLONGM1; /* { dg-warning "requires 127 bits to represent" "" { target { c || { c++11 && c++17_down } } } } */
>  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" } */
> -long long int l11 = LONG_LONG_MIN << 1; /* { dg-warning "requires 65 bits to represent" } */
> +long long int l7 = -9LL << LLONGM1; /* { dg-warning "requires 68 bits to represent" "" { target { c || { c++11 && c++17_down } } } } */
> +long long int l8 = -10LL << LLONGM2; /* { dg-warning "requires 67 bits to represent" "" { target { c || { c++11 && c++17_down } } } } */
> +long long int l9 = -__LONG_LONG_MAX__ << 2; /* { dg-warning "requires 66 bits to represent" "" { target { c || { c++11 && c++17_down } } } } */
> +long long int l10 = -__LONG_LONG_MAX__ << LLONGM1; /* { dg-warning "requires 127 bits to represent" "" { target { c || { c++11 && c++17_down } } } } */
> +long long int l11 = LONG_LONG_MIN << 1; /* { dg-warning "requires 65 bits to represent" "" { target { c || { c++11 && c++17_down } } } } */
>
>  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" } */
> +  int k1 = a << b; /* { dg-warning "requires 36 bits to represent" "" { target { c || { c++11 && c++17_down } } } } */
> +  int k2 = 10 << b; /* { dg-warning "requires 36 bits to represent" "" { target { c || { c++11 && c++17_down } } } } */
> +  int k3 = a << INTM1; /* { dg-warning "requires 36 bits to represent" "" { target { c || { c++11 && c++17_down } } } } */
>  }
> --- gcc/testsuite/c-c++-common/Wshift-overflow-2.c.jj   2020-01-12 11:54:36.995404628 +0100
> +++ gcc/testsuite/c-c++-common/Wshift-overflow-2.c      2022-03-01 11:20:16.498991992 +0100
> @@ -1,7 +1,6 @@
>  /* 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)
> --- gcc/testsuite/c-c++-common/Wshift-overflow-5.c.jj   2020-01-12 11:54:36.995404628 +0100
> +++ gcc/testsuite/c-c++-common/Wshift-overflow-5.c      2022-03-01 12:05:27.955141905 +0100
> @@ -1,11 +1,10 @@
>  /* 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" } */
> +int i1 = 1 << INTM1; /* { dg-warning "requires 33 bits to represent" "" { target { c || c++11_down } } } */
> +unsigned u1 = 1 << INTM1; /* { dg-warning "requires 33 bits to represent" "" { target { c || c++11_down } } } */
> +long long int l1 = 1LL << LLONGM1; /* { dg-warning "requires 65 bits to represent" "" { target { c || c++11_down } } } */
> --- gcc/testsuite/c-c++-common/Wshift-overflow-6.c.jj   2020-01-12 11:54:36.995404628 +0100
> +++ gcc/testsuite/c-c++-common/Wshift-overflow-6.c      2022-03-01 12:06:15.950471922 +0100
> @@ -1,7 +1,6 @@
>  /* PR c++/55095 */
>  /* { dg-do compile { target int32 } } */
>  /* { dg-options "-Wshift-overflow=1" } */
> -/* { dg-additional-options "-std=c++11" { target c++ } } */
>
>  int i00 = 0b1 << 31;
>  int i01 = 0b10 << 30;
> @@ -34,4 +33,4 @@ int i27 = 0b1000000000000000000000000000
>  int i28 = 0b10000000000000000000000000000 << 3;
>  int i29 = 0b100000000000000000000000000000 << 2;
>  int i30 = 0b1000000000000000000000000000000 << 1;
> -int i31 = (int) 0b10000000000000000000000000000000u << 1; /* { dg-warning "requires 33 bits to represent" } */
> +int i31 = (int) 0b10000000000000000000000000000000u << 1; /* { dg-warning "requires 33 bits to represent" "" { target { c || c++17_down } } } */
> --- gcc/testsuite/c-c++-common/Wshift-overflow-7.c.jj   2020-01-12 11:54:36.995404628 +0100
> +++ gcc/testsuite/c-c++-common/Wshift-overflow-7.c      2022-03-01 12:08:09.738883507 +0100
> @@ -1,37 +1,36 @@
>  /* PR c++/55095 */
>  /* { dg-do compile { target int32 } } */
>  /* { dg-options "-Wshift-overflow=2" } */
> -/* { dg-additional-options "-std=c++11" { target c++ } } */
>
> -int i00 = 0b1 << 31; /* { dg-warning "requires 33 bits to represent" } */
> -int i01 = 0b10 << 30; /* { dg-warning "requires 33 bits to represent" } */
> -int i02 = 0b100 << 29; /* { dg-warning "requires 33 bits to represent" } */
> -int i03 = 0b1000 << 28; /* { dg-warning "requires 33 bits to represent" } */
> -int i04 = 0b10000 << 27; /* { dg-warning "requires 33 bits to represent" } */
> -int i05 = 0b100000 << 26; /* { dg-warning "requires 33 bits to represent" } */
> -int i06 = 0b1000000 << 25; /* { dg-warning "requires 33 bits to represent" } */
> -int i07 = 0b10000000 << 24; /* { dg-warning "requires 33 bits to represent" } */
> -int i08 = 0b100000000 << 23; /* { dg-warning "requires 33 bits to represent" } */
> -int i09 = 0b1000000000 << 22; /* { dg-warning "requires 33 bits to represent" } */
> -int i10 = 0b10000000000 << 21; /* { dg-warning "requires 33 bits to represent" } */
> -int i11 = 0b100000000000 << 20; /* { dg-warning "requires 33 bits to represent" } */
> -int i12 = 0b1000000000000 << 19; /* { dg-warning "requires 33 bits to represent" } */
> -int i13 = 0b10000000000000 << 18; /* { dg-warning "requires 33 bits to represent" } */
> -int i14 = 0b100000000000000 << 17; /* { dg-warning "requires 33 bits to represent" } */
> -int i15 = 0b1000000000000000 << 16; /* { dg-warning "requires 33 bits to represent" } */
> -int i16 = 0b10000000000000000 << 15; /* { dg-warning "requires 33 bits to represent" } */
> -int i17 = 0b100000000000000000 << 14; /* { dg-warning "requires 33 bits to represent" } */
> -int i18 = 0b1000000000000000000 << 13; /* { dg-warning "requires 33 bits to represent" } */
> -int i19 = 0b10000000000000000000 << 12; /* { dg-warning "requires 33 bits to represent" } */
> -int i20 = 0b100000000000000000000 << 11; /* { dg-warning "requires 33 bits to represent" } */
> -int i21 = 0b1000000000000000000000 << 10; /* { dg-warning "requires 33 bits to represent" } */
> -int i22 = 0b10000000000000000000000 << 9; /* { dg-warning "requires 33 bits to represent" } */
> -int i23 = 0b100000000000000000000000 << 8; /* { dg-warning "requires 33 bits to represent" } */
> -int i24 = 0b1000000000000000000000000 << 7; /* { dg-warning "requires 33 bits to represent" } */
> -int i25 = 0b10000000000000000000000000 << 6; /* { dg-warning "requires 33 bits to represent" } */
> -int i26 = 0b100000000000000000000000000 << 5; /* { dg-warning "requires 33 bits to represent" } */
> -int i27 = 0b1000000000000000000000000000 << 4; /* { dg-warning "requires 33 bits to represent" } */
> -int i28 = 0b10000000000000000000000000000 << 3; /* { dg-warning "requires 33 bits to represent" } */
> -int i29 = 0b100000000000000000000000000000 << 2; /* { dg-warning "requires 33 bits to represent" } */
> -int i30 = 0b1000000000000000000000000000000 << 1; /* { dg-warning "requires 33 bits to represent" } */
> -int i31 = (int) 0b10000000000000000000000000000000u << 1; /* { dg-warning "requires 33 bits to represent" } */
> +int i00 = 0b1 << 31; /* { dg-warning "requires 33 bits to represent" "" { target { c || c++11_down } } } */
> +int i01 = 0b10 << 30; /* { dg-warning "requires 33 bits to represent" "" { target { c || c++11_down } } } */
> +int i02 = 0b100 << 29; /* { dg-warning "requires 33 bits to represent" "" { target { c || c++11_down } } } */
> +int i03 = 0b1000 << 28; /* { dg-warning "requires 33 bits to represent" "" { target { c || c++11_down } } } */
> +int i04 = 0b10000 << 27; /* { dg-warning "requires 33 bits to represent" "" { target { c || c++11_down } } } */
> +int i05 = 0b100000 << 26; /* { dg-warning "requires 33 bits to represent" "" { target { c || c++11_down } } } */
> +int i06 = 0b1000000 << 25; /* { dg-warning "requires 33 bits to represent" "" { target { c || c++11_down } } } */
> +int i07 = 0b10000000 << 24; /* { dg-warning "requires 33 bits to represent" "" { target { c || c++11_down } } } */
> +int i08 = 0b100000000 << 23; /* { dg-warning "requires 33 bits to represent" "" { target { c || c++11_down } } } */
> +int i09 = 0b1000000000 << 22; /* { dg-warning "requires 33 bits to represent" "" { target { c || c++11_down } } } */
> +int i10 = 0b10000000000 << 21; /* { dg-warning "requires 33 bits to represent" "" { target { c || c++11_down } } } */
> +int i11 = 0b100000000000 << 20; /* { dg-warning "requires 33 bits to represent" "" { target { c || c++11_down } } } */
> +int i12 = 0b1000000000000 << 19; /* { dg-warning "requires 33 bits to represent" "" { target { c || c++11_down } } } */
> +int i13 = 0b10000000000000 << 18; /* { dg-warning "requires 33 bits to represent" "" { target { c || c++11_down } } } */
> +int i14 = 0b100000000000000 << 17; /* { dg-warning "requires 33 bits to represent" "" { target { c || c++11_down } } } */
> +int i15 = 0b1000000000000000 << 16; /* { dg-warning "requires 33 bits to represent" "" { target { c || c++11_down } } } */
> +int i16 = 0b10000000000000000 << 15; /* { dg-warning "requires 33 bits to represent" "" { target { c || c++11_down } } } */
> +int i17 = 0b100000000000000000 << 14; /* { dg-warning "requires 33 bits to represent" "" { target { c || c++11_down } } } */
> +int i18 = 0b1000000000000000000 << 13; /* { dg-warning "requires 33 bits to represent" "" { target { c || c++11_down } } } */
> +int i19 = 0b10000000000000000000 << 12; /* { dg-warning "requires 33 bits to represent" "" { target { c || c++11_down } } } */
> +int i20 = 0b100000000000000000000 << 11; /* { dg-warning "requires 33 bits to represent" "" { target { c || c++11_down } } } */
> +int i21 = 0b1000000000000000000000 << 10; /* { dg-warning "requires 33 bits to represent" "" { target { c || c++11_down } } } */
> +int i22 = 0b10000000000000000000000 << 9; /* { dg-warning "requires 33 bits to represent" "" { target { c || c++11_down } } } */
> +int i23 = 0b100000000000000000000000 << 8; /* { dg-warning "requires 33 bits to represent" "" { target { c || c++11_down } } } */
> +int i24 = 0b1000000000000000000000000 << 7; /* { dg-warning "requires 33 bits to represent" "" { target { c || c++11_down } } } */
> +int i25 = 0b10000000000000000000000000 << 6; /* { dg-warning "requires 33 bits to represent" "" { target { c || c++11_down } } } */
> +int i26 = 0b100000000000000000000000000 << 5; /* { dg-warning "requires 33 bits to represent" "" { target { c || c++11_down } } } */
> +int i27 = 0b1000000000000000000000000000 << 4; /* { dg-warning "requires 33 bits to represent" "" { target { c || c++11_down } } } */
> +int i28 = 0b10000000000000000000000000000 << 3; /* { dg-warning "requires 33 bits to represent" "" { target { c || c++11_down } } } */
> +int i29 = 0b100000000000000000000000000000 << 2; /* { dg-warning "requires 33 bits to represent" "" { target { c || c++11_down } } } */
> +int i30 = 0b1000000000000000000000000000000 << 1; /* { dg-warning "requires 33 bits to represent" "" { target { c || c++11_down } } } */
> +int i31 = (int) 0b10000000000000000000000000000000u << 1; /* { dg-warning "requires 33 bits to represent" "" { target { c || c++17_down } } } */
> --- gcc/testsuite/c-c++-common/Wshift-overflow-8.c.jj   2022-03-01 11:06:15.451732430 +0100
> +++ gcc/testsuite/c-c++-common/Wshift-overflow-8.c      2022-03-01 11:21:43.500777502 +0100
> @@ -0,0 +1,5 @@
> +/* PR c++/55095 */
> +/* { dg-do compile { target int32 } } */
> +/* { dg-options "-O -fwrapv" } */
> +
> +#include "Wshift-overflow-1.c"
> --- gcc/testsuite/c-c++-common/Wshift-overflow-9.c.jj   2022-03-01 11:07:04.998040795 +0100
> +++ gcc/testsuite/c-c++-common/Wshift-overflow-9.c      2022-03-01 11:07:30.015691566 +0100
> @@ -0,0 +1,7 @@
> +/* PR c++/55095 */
> +/* { dg-do compile { target int32 } } */
> +/* { dg-options "-O -Wshift-overflow -fwrapv" } */
> +/* { dg-additional-options "-std=gnu90" { target c } } */
> +/* { dg-additional-options "-std=c++03" { target c++ } } */
> +
> +#include "Wshift-overflow-1.c"
> --- gcc/testsuite/c-c++-common/Wshift-overflow-10.c.jj  2022-03-01 11:09:17.167195807 +0100
> +++ gcc/testsuite/c-c++-common/Wshift-overflow-10.c     2022-03-01 11:21:54.518623704 +0100
> @@ -0,0 +1,5 @@
> +/* PR c++/55095 */
> +/* { dg-do compile { target int32 } } */
> +/* { dg-options "-O -Wshift-overflow=2 -fwrapv" } */
> +
> +#include "Wshift-overflow-5.c"
> --- gcc/testsuite/c-c++-common/Wshift-overflow-11.c.jj  2022-03-01 11:09:46.991779477 +0100
> +++ gcc/testsuite/c-c++-common/Wshift-overflow-11.c     2022-03-01 11:21:59.235557860 +0100
> @@ -0,0 +1,5 @@
> +/* PR c++/55095 */
> +/* { dg-do compile { target int32 } } */
> +/* { dg-options "-Wshift-overflow=1 -fwrapv" } */
> +
> +#include "Wshift-overflow-6.c"
> --- gcc/testsuite/c-c++-common/Wshift-overflow-12.c.jj  2022-03-01 11:10:19.121330974 +0100
> +++ gcc/testsuite/c-c++-common/Wshift-overflow-12.c     2022-03-01 11:22:04.561483512 +0100
> @@ -0,0 +1,5 @@
> +/* PR c++/55095 */
> +/* { dg-do compile { target int32 } } */
> +/* { dg-options "-Wshift-overflow=2 -fwrapv" } */
> +
> +#include "Wshift-overflow-7.c"
>
>         Jakub
>
Jason Merrill March 8, 2022, 11:16 p.m. UTC | #2
On 3/2/22 05:22, Jakub Jelinek wrote:
> Hi!
> 
> As mentioned in the PR, different standards have different definition
> on what is an UB left shift.  They all agree on out of bounds (including
> negative) shift count.
> The rules used by ubsan are:
> C99-C2x ((unsigned) x >> (uprecm1 - y)) != 0 then UB
> C++11-C++17 x < 0 || ((unsigned) x >> (uprecm1 - y)) > 1 then UB
> C++20 and later everything is well defined
> Now, for C++20, I've in the P1236R1 implementation added an early
> exit for -Wshift-overflow* warning so that it never warns, but apparently
> -Wshift-negative-value remained as is.  As it is well defined in C++20,
> the following patch doesn't enable -Wshift-negative-value from -Wextra
> anymore for C++20 and later, if users want for compatibility with C++17
> and earlier get the warning, they still can by using -Wshift-negative-value
> explicitly.
> Another thing is -fwrapv, that is an extension to the standards, so it is up
> to us how exactly we define that case.  Our ubsan code treats
> TYPE_OVERFLOW_WRAPS (type0) and cxx_dialect >= cxx20 the same as only
> diagnosing out of bounds shift count and nothing else and IMHO it is most
> sensical to treat -fwrapv signed left shifts the same as C++20 treats
> them, https://eel.is/c++draft/expr.shift#2
> "The value of E1 << E2 is the unique value congruent to E1×2^E2 modulo 2^N,
> where N is the width of the type of the result.
> [Note 1: E1 is left-shifted E2 bit positions; vacated bits are zero-filled.
> — end note]"
> with no UB dependent on the E1 values.  The UB is only
> "The behavior is undefined if the right operand is negative, or greater
> than or equal to the width of the promoted left operand."
> Under the hood (except for FEs and ubsan from FEs) GCC middle-end doesn't
> consider UB in left shifts dependent on the first operand's value, only
> the out of bounds shifts.
> 
> While this change isn't a regression, I'd think it is useful for GCC 12,
> it doesn't add new warnings, but just removes warnings that aren't
> appropriate.
> 
> Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk?

OK.

> 2022-03-02  Jakub Jelinek  <jakub@redhat.com>
> 
> 	PR c/104711
> gcc/
> 	* doc/invoke.texi (-Wextra): Document that -Wshift-negative-value
> 	is enabled by it only for C++11 to C++17 rather than for C++03 or
> 	later.
> 	(-Wshift-negative-value): Similarly (except here we stated
> 	that it is enabled for C++11 or later).
> gcc/c-family/
> 	* c-opts.cc (c_common_post_options): Don't enable
> 	-Wshift-negative-value from -Wextra for C++20 or later.
> 	* c-ubsan.cc (ubsan_instrument_shift): Adjust comments.
> 	* c-warn.cc (maybe_warn_shift_overflow): Use TYPE_OVERFLOW_WRAPS
> 	instead of TYPE_UNSIGNED.
> gcc/c/
> 	* c-fold.cc (c_fully_fold_internal): Don't emit
> 	-Wshift-negative-value warning if TYPE_OVERFLOW_WRAPS.
> 	* c-typeck.cc (build_binary_op): Likewise.
> gcc/cp/
> 	* constexpr.cc (cxx_eval_check_shift_p): Use TYPE_OVERFLOW_WRAPS
> 	instead of TYPE_UNSIGNED.
> 	* typeck.cc (cp_build_binary_op): Don't emit
> 	-Wshift-negative-value warning if TYPE_OVERFLOW_WRAPS.
> gcc/testsuite/
> 	* c-c++-common/Wshift-negative-value-1.c: Remove
> 	dg-additional-options, instead in target selectors of each diagnostic
> 	check for exact C++ versions where it should be diagnosed.
> 	* c-c++-common/Wshift-negative-value-2.c: Likewise.
> 	* c-c++-common/Wshift-negative-value-3.c: Likewise.
> 	* c-c++-common/Wshift-negative-value-4.c: Likewise.
> 	* c-c++-common/Wshift-negative-value-7.c: New test.
> 	* c-c++-common/Wshift-negative-value-8.c: New test.
> 	* c-c++-common/Wshift-negative-value-9.c: New test.
> 	* c-c++-common/Wshift-negative-value-10.c: New test.
> 	* c-c++-common/Wshift-overflow-1.c: Remove
> 	dg-additional-options, instead in target selectors of each diagnostic
> 	check for exact C++ versions where it should be diagnosed.
> 	* c-c++-common/Wshift-overflow-2.c: Likewise.
> 	* c-c++-common/Wshift-overflow-5.c: Likewise.
> 	* c-c++-common/Wshift-overflow-6.c: Likewise.
> 	* c-c++-common/Wshift-overflow-7.c: Likewise.
> 	* c-c++-common/Wshift-overflow-8.c: New test.
> 	* c-c++-common/Wshift-overflow-9.c: New test.
> 	* c-c++-common/Wshift-overflow-10.c: New test.
> 	* c-c++-common/Wshift-overflow-11.c: New test.
> 	* c-c++-common/Wshift-overflow-12.c: New test.
> 
> --- gcc/doc/invoke.texi.jj	2022-02-25 10:46:53.085181500 +0100
> +++ gcc/doc/invoke.texi	2022-03-01 09:59:15.040855224 +0100
> @@ -5809,7 +5809,7 @@ name is still supported, but the newer n
>   -Wredundant-move @r{(only for C++)}  @gol
>   -Wtype-limits  @gol
>   -Wuninitialized  @gol
> --Wshift-negative-value @r{(in C++03 and in C99 and newer)}  @gol
> +-Wshift-negative-value @r{(in C++11 to C++17 and in C99 and newer)}  @gol
>   -Wunused-parameter @r{(only with} @option{-Wunused} @r{or} @option{-Wall}@r{)} @gol
>   -Wunused-but-set-parameter @r{(only with} @option{-Wunused} @r{or} @option{-Wall}@r{)}}
>   
> @@ -6839,7 +6839,7 @@ of the type.  This warning is enabled by
>   @opindex Wshift-negative-value
>   @opindex Wno-shift-negative-value
>   Warn if left shifting a negative value.  This warning is enabled by
> -@option{-Wextra} in C99 and C++11 modes (and newer).
> +@option{-Wextra} in C99 (and newer) and C++11 to C++17 modes.
>   
>   @item -Wno-shift-overflow
>   @itemx -Wshift-overflow=@var{n}
> --- gcc/c-family/c-opts.cc.jj	2022-01-18 11:58:58.884992028 +0100
> +++ gcc/c-family/c-opts.cc	2022-03-01 09:57:34.880253831 +0100
> @@ -934,10 +934,12 @@ c_common_post_options (const char **pfil
>     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.  */
> +  /* -Wshift-negative-value is enabled by -Wextra in C99 and C++11 to C++17
> +     modes.  */
>     if (warn_shift_negative_value == -1)
>       warn_shift_negative_value = (extra_warnings
> -				 && (cxx_dialect >= cxx11 || flag_isoc99));
> +				 && (cxx_dialect >= cxx11 || flag_isoc99)
> +				 && cxx_dialect < cxx20);
>   
>     /* -Wregister is enabled by default in C++17.  */
>     SET_OPTION_IF_UNSET (&global_options, &global_options_set, warn_register,
> --- gcc/c-family/c-ubsan.cc.jj	2022-02-09 15:15:59.288840032 +0100
> +++ gcc/c-family/c-ubsan.cc	2022-03-01 09:55:51.779693845 +0100
> @@ -173,7 +173,7 @@ ubsan_instrument_shift (location_t loc,
>         || cxx_dialect >= cxx20)
>       ;
>   
> -  /* For signed x << y, in C99/C11, the following:
> +  /* For signed x << y, in C99 and later, the following:
>        (unsigned) x >> (uprecm1 - y)
>        if non-zero, is undefined.  */
>     else if (code == LSHIFT_EXPR && flag_isoc99 && cxx_dialect < cxx11)
> @@ -186,7 +186,7 @@ ubsan_instrument_shift (location_t loc,
>   			build_int_cst (TREE_TYPE (tt), 0));
>       }
>   
> -  /* For signed x << y, in C++11 and later, the following:
> +  /* For signed x << y, in C++11 to C++17, the following:
>        x < 0 || ((unsigned) x >> (uprecm1 - y))
>        if > 1, is undefined.  */
>     else if (code == LSHIFT_EXPR && cxx_dialect >= cxx11)
> --- gcc/c-family/c-warn.cc.jj	2022-01-18 11:58:58.922991486 +0100
> +++ gcc/c-family/c-warn.cc	2022-03-01 10:02:41.634971050 +0100
> @@ -2605,7 +2605,7 @@ maybe_warn_shift_overflow (location_t lo
>     unsigned int prec0 = TYPE_PRECISION (type0);
>   
>     /* Left-hand operand must be signed.  */
> -  if (TYPE_UNSIGNED (type0) || cxx_dialect >= cxx20)
> +  if (TYPE_OVERFLOW_WRAPS (type0) || cxx_dialect >= cxx20)
>       return false;
>   
>     unsigned int min_prec = (wi::min_precision (wi::to_wide (op0), SIGNED)
> --- gcc/c/c-fold.cc.jj	2022-02-09 20:45:24.253211303 +0100
> +++ gcc/c/c-fold.cc	2022-03-01 11:39:32.153859825 +0100
> @@ -382,6 +382,7 @@ c_fully_fold_internal (tree expr, bool i
>   	  && TREE_CODE (TREE_TYPE (orig_op0)) == INTEGER_TYPE
>   	  && TREE_CODE (op0) == INTEGER_CST
>   	  && c_inhibit_evaluation_warnings == 0
> +	  && !TYPE_OVERFLOW_WRAPS (TREE_TYPE (orig_op0))
>   	  && tree_int_cst_sgn (op0) < 0)
>   	warning_at (loc, OPT_Wshift_negative_value,
>   		    "left shift of negative value");
> --- gcc/c/c-typeck.cc.jj	2022-02-11 00:19:22.135067293 +0100
> +++ gcc/c/c-typeck.cc	2022-03-01 10:04:20.925584897 +0100
> @@ -12213,7 +12213,8 @@ build_binary_op (location_t location, en
>   	{
>   	  doing_shift = true;
>   	  if (TREE_CODE (op0) == INTEGER_CST
> -	      && tree_int_cst_sgn (op0) < 0)
> +	      && tree_int_cst_sgn (op0) < 0
> +	      && !TYPE_OVERFLOW_WRAPS (type0))
>   	    {
>   	      /* Don't reject a left shift of a negative value in a context
>   		 where a constant expression is needed in C90.  */
> --- gcc/cp/constexpr.cc.jj	2022-02-18 12:37:51.081601299 +0100
> +++ gcc/cp/constexpr.cc	2022-03-01 11:56:12.874890444 +0100
> @@ -3165,7 +3165,7 @@ cxx_eval_check_shift_p (location_t loc,
>        The value of E1 << E2 is the unique value congruent to E1 x 2^E2 modulo
>        2^N, where N is the range exponent of the type of the result.  */
>     if (code == LSHIFT_EXPR
> -      && !TYPE_UNSIGNED (lhstype)
> +      && !TYPE_OVERFLOW_WRAPS (lhstype)
>         && cxx_dialect >= cxx11
>         && cxx_dialect < cxx20)
>       {
> --- gcc/cp/typeck.cc.jj	2022-02-18 12:38:06.065393230 +0100
> +++ gcc/cp/typeck.cc	2022-03-01 10:04:57.726071137 +0100
> @@ -5382,6 +5382,7 @@ cp_build_binary_op (const op_location_t
>   	  doing_shift = true;
>   	  if (TREE_CODE (const_op0) == INTEGER_CST
>   	      && tree_int_cst_sgn (const_op0) < 0
> +	      && !TYPE_OVERFLOW_WRAPS (type0)
>   	      && (complain & tf_warning)
>   	      && c_inhibit_evaluation_warnings == 0)
>   	    warning_at (location, OPT_Wshift_negative_value,
> --- gcc/testsuite/c-c++-common/Wshift-negative-value-1.c.jj	2020-01-12 11:54:36.995404628 +0100
> +++ gcc/testsuite/c-c++-common/Wshift-negative-value-1.c	2022-03-01 11:43:47.217299318 +0100
> @@ -1,13 +1,12 @@
>   /* PR c/65179 */
>   /* { dg-do compile } */
>   /* { dg-options "-O -Wextra" } */
> -/* { dg-additional-options "-std=c++11" { target c++ } } */
>   
>   enum E {
>     A = 0 << 1,
>     B = 1 << 1,
> -  C = -1 << 1, /* { dg-warning "10:left shift of negative value|not an integer constant" } */
> -  /* { dg-error "left operand of shift expression" "shift" { target c++ } .-1 } */
> +  C = -1 << 1, /* { dg-warning "10:left shift of negative value|not an integer constant" "" { target { c || { c++11 && c++17_down } } } } */
> +  /* { dg-error "left operand of shift expression" "shift" { target { c++11 && c++17_down } } .-1 } */
>     D = 0 >> 1,
>     E = 1 >> 1,
>     F = -1 >> 1
> @@ -23,10 +22,10 @@ left (int x)
>     int r = 0;
>     r += z << x;
>     r += o << x;
> -  r += m << x; /* { dg-warning "10:left shift of negative value" } */
> +  r += m << x; /* { dg-warning "10:left shift of negative value" "" { target { c || { c++11 && c++17_down } } } } */
>     r += 0 << x;
>     r += 1 << x;
> -  r += -1 << x; /* { dg-warning "11:left shift of negative value" } */
> +  r += -1 << x; /* { dg-warning "11:left shift of negative value" "" { target { c || { c++11 && c++17_down } } } } */
>     r += -1U << x;
>     return r;
>   }
> --- gcc/testsuite/c-c++-common/Wshift-negative-value-2.c.jj	2020-01-12 11:54:36.995404628 +0100
> +++ gcc/testsuite/c-c++-common/Wshift-negative-value-2.c	2022-03-01 11:47:41.695026169 +0100
> @@ -1,14 +1,13 @@
>   /* PR c/65179 */
>   /* { dg-do compile } */
>   /* { dg-options "-O -Wshift-negative-value" } */
> -/* { dg-additional-options "-std=c++11" { target c++ } } */
>   
>   enum E {
>     A = 0 << 1,
>     B = 1 << 1,
>     C = -1 << 1, /* { dg-warning "10:left shift of negative value" } */
> -  /* { dg-error "not an integer constant" "no constant" { target c++ } .-1 } */
> -  /* { dg-error "left operand of shift expression" "shift" { target c++ } .-2 } */
> +  /* { dg-error "not an integer constant" "no constant" { target { c++11 && c++17_down } } .-1 } */
> +  /* { dg-error "left operand of shift expression" "shift" { target { c++11 && c++17_down } } .-2 } */
>     D = 0 >> 1,
>     E = 1 >> 1,
>     F = -1 >> 1
> --- gcc/testsuite/c-c++-common/Wshift-negative-value-3.c.jj	2020-01-12 11:54:36.995404628 +0100
> +++ gcc/testsuite/c-c++-common/Wshift-negative-value-3.c	2022-03-01 11:48:01.029756269 +0100
> @@ -1,14 +1,13 @@
>   /* PR c/65179 */
>   /* { dg-do compile } */
>   /* { dg-options "-O -Wextra -Wno-shift-negative-value" } */
> -/* { dg-additional-options "-std=c++11" { target c++ } } */
>   
>   enum E {
>     A = 0 << 1,
>     B = 1 << 1,
>     C = -1 << 1,
> -  /* { dg-error "not an integer constant" "no constant" { target c++ } .-1 } */
> -  /* { dg-error "left operand of shift expression" "shift" { target c++ } .-2 } */
> +  /* { dg-error "not an integer constant" "no constant" { target { c++11 && c++17_down } } .-1 } */
> +  /* { dg-error "left operand of shift expression" "shift" { target { c++11 && c++17_down } } .-2 } */
>     D = 0 >> 1,
>     E = 1 >> 1,
>     F = -1 >> 1
> --- gcc/testsuite/c-c++-common/Wshift-negative-value-4.c.jj	2020-01-12 11:54:36.995404628 +0100
> +++ gcc/testsuite/c-c++-common/Wshift-negative-value-4.c	2022-03-01 11:48:46.740118184 +0100
> @@ -1,14 +1,13 @@
>   /* PR c/65179 */
>   /* { dg-do compile } */
>   /* { dg-options "-O" } */
> -/* { dg-additional-options "-std=c++11" { target c++ } } */
>   
>   enum E {
>     A = 0 << 1,
>     B = 1 << 1,
>     C = -1 << 1,
> -  /* { dg-error "not an integer constant" "no constant" { target c++ } .-1 } */
> -  /* { dg-error "left operand of shift expression" "shift" { target c++ } .-2 } */
> +  /* { dg-error "not an integer constant" "no constant" { target { c++11 && c++17_down } } .-1 } */
> +  /* { dg-error "left operand of shift expression" "shift" { target { c++11 && c++17_down } } .-2 } */
>     D = 0 >> 1,
>     E = 1 >> 1,
>     F = -1 >> 1
> --- gcc/testsuite/c-c++-common/Wshift-negative-value-7.c.jj	2022-03-01 11:00:56.877179511 +0100
> +++ gcc/testsuite/c-c++-common/Wshift-negative-value-7.c	2022-03-01 11:59:32.535103327 +0100
> @@ -0,0 +1,5 @@
> +/* PR c/65179 */
> +/* { dg-do compile } */
> +/* { dg-options "-O -Wextra -fwrapv" } */
> +
> +#include "Wshift-negative-value-1.c"
> --- gcc/testsuite/c-c++-common/Wshift-negative-value-8.c.jj	2022-03-01 11:01:41.087562363 +0100
> +++ gcc/testsuite/c-c++-common/Wshift-negative-value-8.c	2022-03-01 11:59:43.084956059 +0100
> @@ -0,0 +1,5 @@
> +/* PR c/65179 */
> +/* { dg-do compile } */
> +/* { dg-options "-O -Wshift-negative-value -fwrapv" } */
> +
> +#include "Wshift-negative-value-1.c"
> --- gcc/testsuite/c-c++-common/Wshift-negative-value-9.c.jj	2022-03-01 11:02:38.837756210 +0100
> +++ gcc/testsuite/c-c++-common/Wshift-negative-value-9.c	2022-03-01 11:59:51.733835326 +0100
> @@ -0,0 +1,5 @@
> +/* PR c/65179 */
> +/* { dg-do compile } */
> +/* { dg-options "-O -fwrapv" } */
> +
> +#include "Wshift-negative-value-1.c"
> --- gcc/testsuite/c-c++-common/Wshift-negative-value-10.c.jj	2022-03-01 11:03:28.922057068 +0100
> +++ gcc/testsuite/c-c++-common/Wshift-negative-value-10.c	2022-03-01 11:03:44.101845168 +0100
> @@ -0,0 +1,7 @@
> +/* PR c/65179 */
> +/* { dg-do compile } */
> +/* { dg-options "-O -Wshift-negative-value -fwrapv" } */
> +/* { dg-additional-options "-std=c++03" { target c++ } } */
> +/* { dg-additional-options "-std=c90" { target c } } */
> +
> +#include "Wshift-negative-value-1.c"
> --- gcc/testsuite/c-c++-common/Wshift-overflow-1.c.jj	2020-01-12 11:54:36.995404628 +0100
> +++ gcc/testsuite/c-c++-common/Wshift-overflow-1.c	2022-03-01 12:01:33.792410660 +0100
> @@ -1,7 +1,6 @@
>   /* 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)
> @@ -12,16 +11,16 @@
>   #define LONG_LONG_MIN (-__LONG_LONG_MAX__-1)
>   
>   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 i2 = 9 << INTM1; /* { dg-warning "requires 36 bits to represent" "" { target { c || { c++11 && c++17_down } } } } */
> +int i3 = 10 << INTM2; /* { dg-warning "requires 35 bits to represent" "" { target { c || { c++11 && c++17_down } } } } */
> +int i4 = __INT_MAX__ << 2; /* { dg-warning "requires 34 bits to represent" "" { target { c || { c++11 && c++17_down } } } } */
> +int i5 = __INT_MAX__ << INTM1; /* { dg-warning "requires 63 bits to represent" "" { target { c || { c++11 && c++17_down } } } } */
>   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 i11 = INT_MIN << 1; /* { dg-warning "requires 33 bits to represent" } */
> +int i7 = -9 << INTM1; /* { dg-warning "requires 36 bits to represent" "" { target { c || { c++11 && c++17_down } } } } */
> +int i8 = -10 << INTM2; /* { dg-warning "requires 35 bits to represent" "" { target { c || { c++11 && c++17_down } } } } */
> +int i9 = -__INT_MAX__ << 2; /* { dg-warning "requires 34 bits to represent" "" { target { c || { c++11 && c++17_down } } } } */
> +int i10 = -__INT_MAX__ << INTM1; /* { dg-warning "requires 63 bits to represent" "" { target { c || { c++11 && c++17_down } } } } */
> +int i11 = INT_MIN << 1; /* { dg-warning "requires 33 bits to represent" "" { target { c || { c++11 && c++17_down } } } } */
>   
>   int r1 = 1 >> INTM1;
>   int r2 = 9 >> INTM1;
> @@ -35,29 +34,29 @@ 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 u2 = 9 << INTM1; /* { dg-warning "requires 36 bits to represent" "" { target { c || { c++11 && c++17_down } } } } */
>   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 l2 = 9LL << LLONGM1; /* { dg-warning "requires 68 bits to represent" "" { target { c || { c++11 && c++17_down } } } } */
> +long long int l3 = 10LL << LLONGM2; /* { dg-warning "requires 67 bits to represent" "" { target { c || { c++11 && c++17_down } } } } */
> +long long int l4 = __LONG_LONG_MAX__ << 2; /* { dg-warning "requires 66 bits to represent" "" { target { c || { c++11 && c++17_down } } } } */
> +long long int l5 = __LONG_LONG_MAX__ << LLONGM1; /* { dg-warning "requires 127 bits to represent" "" { target { c || { c++11 && c++17_down } } } } */
>   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" } */
> -long long int l11 = LONG_LONG_MIN << 1; /* { dg-warning "requires 65 bits to represent" } */
> +long long int l7 = -9LL << LLONGM1; /* { dg-warning "requires 68 bits to represent" "" { target { c || { c++11 && c++17_down } } } } */
> +long long int l8 = -10LL << LLONGM2; /* { dg-warning "requires 67 bits to represent" "" { target { c || { c++11 && c++17_down } } } } */
> +long long int l9 = -__LONG_LONG_MAX__ << 2; /* { dg-warning "requires 66 bits to represent" "" { target { c || { c++11 && c++17_down } } } } */
> +long long int l10 = -__LONG_LONG_MAX__ << LLONGM1; /* { dg-warning "requires 127 bits to represent" "" { target { c || { c++11 && c++17_down } } } } */
> +long long int l11 = LONG_LONG_MIN << 1; /* { dg-warning "requires 65 bits to represent" "" { target { c || { c++11 && c++17_down } } } } */
>   
>   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" } */
> +  int k1 = a << b; /* { dg-warning "requires 36 bits to represent" "" { target { c || { c++11 && c++17_down } } } } */
> +  int k2 = 10 << b; /* { dg-warning "requires 36 bits to represent" "" { target { c || { c++11 && c++17_down } } } } */
> +  int k3 = a << INTM1; /* { dg-warning "requires 36 bits to represent" "" { target { c || { c++11 && c++17_down } } } } */
>   }
> --- gcc/testsuite/c-c++-common/Wshift-overflow-2.c.jj	2020-01-12 11:54:36.995404628 +0100
> +++ gcc/testsuite/c-c++-common/Wshift-overflow-2.c	2022-03-01 11:20:16.498991992 +0100
> @@ -1,7 +1,6 @@
>   /* 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)
> --- gcc/testsuite/c-c++-common/Wshift-overflow-5.c.jj	2020-01-12 11:54:36.995404628 +0100
> +++ gcc/testsuite/c-c++-common/Wshift-overflow-5.c	2022-03-01 12:05:27.955141905 +0100
> @@ -1,11 +1,10 @@
>   /* 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" } */
> +int i1 = 1 << INTM1; /* { dg-warning "requires 33 bits to represent" "" { target { c || c++11_down } } } */
> +unsigned u1 = 1 << INTM1; /* { dg-warning "requires 33 bits to represent" "" { target { c || c++11_down } } } */
> +long long int l1 = 1LL << LLONGM1; /* { dg-warning "requires 65 bits to represent" "" { target { c || c++11_down } } } */
> --- gcc/testsuite/c-c++-common/Wshift-overflow-6.c.jj	2020-01-12 11:54:36.995404628 +0100
> +++ gcc/testsuite/c-c++-common/Wshift-overflow-6.c	2022-03-01 12:06:15.950471922 +0100
> @@ -1,7 +1,6 @@
>   /* PR c++/55095 */
>   /* { dg-do compile { target int32 } } */
>   /* { dg-options "-Wshift-overflow=1" } */
> -/* { dg-additional-options "-std=c++11" { target c++ } } */
>   
>   int i00 = 0b1 << 31;
>   int i01 = 0b10 << 30;
> @@ -34,4 +33,4 @@ int i27 = 0b1000000000000000000000000000
>   int i28 = 0b10000000000000000000000000000 << 3;
>   int i29 = 0b100000000000000000000000000000 << 2;
>   int i30 = 0b1000000000000000000000000000000 << 1;
> -int i31 = (int) 0b10000000000000000000000000000000u << 1; /* { dg-warning "requires 33 bits to represent" } */
> +int i31 = (int) 0b10000000000000000000000000000000u << 1; /* { dg-warning "requires 33 bits to represent" "" { target { c || c++17_down } } } */
> --- gcc/testsuite/c-c++-common/Wshift-overflow-7.c.jj	2020-01-12 11:54:36.995404628 +0100
> +++ gcc/testsuite/c-c++-common/Wshift-overflow-7.c	2022-03-01 12:08:09.738883507 +0100
> @@ -1,37 +1,36 @@
>   /* PR c++/55095 */
>   /* { dg-do compile { target int32 } } */
>   /* { dg-options "-Wshift-overflow=2" } */
> -/* { dg-additional-options "-std=c++11" { target c++ } } */
>   
> -int i00 = 0b1 << 31; /* { dg-warning "requires 33 bits to represent" } */
> -int i01 = 0b10 << 30; /* { dg-warning "requires 33 bits to represent" } */
> -int i02 = 0b100 << 29; /* { dg-warning "requires 33 bits to represent" } */
> -int i03 = 0b1000 << 28; /* { dg-warning "requires 33 bits to represent" } */
> -int i04 = 0b10000 << 27; /* { dg-warning "requires 33 bits to represent" } */
> -int i05 = 0b100000 << 26; /* { dg-warning "requires 33 bits to represent" } */
> -int i06 = 0b1000000 << 25; /* { dg-warning "requires 33 bits to represent" } */
> -int i07 = 0b10000000 << 24; /* { dg-warning "requires 33 bits to represent" } */
> -int i08 = 0b100000000 << 23; /* { dg-warning "requires 33 bits to represent" } */
> -int i09 = 0b1000000000 << 22; /* { dg-warning "requires 33 bits to represent" } */
> -int i10 = 0b10000000000 << 21; /* { dg-warning "requires 33 bits to represent" } */
> -int i11 = 0b100000000000 << 20; /* { dg-warning "requires 33 bits to represent" } */
> -int i12 = 0b1000000000000 << 19; /* { dg-warning "requires 33 bits to represent" } */
> -int i13 = 0b10000000000000 << 18; /* { dg-warning "requires 33 bits to represent" } */
> -int i14 = 0b100000000000000 << 17; /* { dg-warning "requires 33 bits to represent" } */
> -int i15 = 0b1000000000000000 << 16; /* { dg-warning "requires 33 bits to represent" } */
> -int i16 = 0b10000000000000000 << 15; /* { dg-warning "requires 33 bits to represent" } */
> -int i17 = 0b100000000000000000 << 14; /* { dg-warning "requires 33 bits to represent" } */
> -int i18 = 0b1000000000000000000 << 13; /* { dg-warning "requires 33 bits to represent" } */
> -int i19 = 0b10000000000000000000 << 12; /* { dg-warning "requires 33 bits to represent" } */
> -int i20 = 0b100000000000000000000 << 11; /* { dg-warning "requires 33 bits to represent" } */
> -int i21 = 0b1000000000000000000000 << 10; /* { dg-warning "requires 33 bits to represent" } */
> -int i22 = 0b10000000000000000000000 << 9; /* { dg-warning "requires 33 bits to represent" } */
> -int i23 = 0b100000000000000000000000 << 8; /* { dg-warning "requires 33 bits to represent" } */
> -int i24 = 0b1000000000000000000000000 << 7; /* { dg-warning "requires 33 bits to represent" } */
> -int i25 = 0b10000000000000000000000000 << 6; /* { dg-warning "requires 33 bits to represent" } */
> -int i26 = 0b100000000000000000000000000 << 5; /* { dg-warning "requires 33 bits to represent" } */
> -int i27 = 0b1000000000000000000000000000 << 4; /* { dg-warning "requires 33 bits to represent" } */
> -int i28 = 0b10000000000000000000000000000 << 3; /* { dg-warning "requires 33 bits to represent" } */
> -int i29 = 0b100000000000000000000000000000 << 2; /* { dg-warning "requires 33 bits to represent" } */
> -int i30 = 0b1000000000000000000000000000000 << 1; /* { dg-warning "requires 33 bits to represent" } */
> -int i31 = (int) 0b10000000000000000000000000000000u << 1; /* { dg-warning "requires 33 bits to represent" } */
> +int i00 = 0b1 << 31; /* { dg-warning "requires 33 bits to represent" "" { target { c || c++11_down } } } */
> +int i01 = 0b10 << 30; /* { dg-warning "requires 33 bits to represent" "" { target { c || c++11_down } } } */
> +int i02 = 0b100 << 29; /* { dg-warning "requires 33 bits to represent" "" { target { c || c++11_down } } } */
> +int i03 = 0b1000 << 28; /* { dg-warning "requires 33 bits to represent" "" { target { c || c++11_down } } } */
> +int i04 = 0b10000 << 27; /* { dg-warning "requires 33 bits to represent" "" { target { c || c++11_down } } } */
> +int i05 = 0b100000 << 26; /* { dg-warning "requires 33 bits to represent" "" { target { c || c++11_down } } } */
> +int i06 = 0b1000000 << 25; /* { dg-warning "requires 33 bits to represent" "" { target { c || c++11_down } } } */
> +int i07 = 0b10000000 << 24; /* { dg-warning "requires 33 bits to represent" "" { target { c || c++11_down } } } */
> +int i08 = 0b100000000 << 23; /* { dg-warning "requires 33 bits to represent" "" { target { c || c++11_down } } } */
> +int i09 = 0b1000000000 << 22; /* { dg-warning "requires 33 bits to represent" "" { target { c || c++11_down } } } */
> +int i10 = 0b10000000000 << 21; /* { dg-warning "requires 33 bits to represent" "" { target { c || c++11_down } } } */
> +int i11 = 0b100000000000 << 20; /* { dg-warning "requires 33 bits to represent" "" { target { c || c++11_down } } } */
> +int i12 = 0b1000000000000 << 19; /* { dg-warning "requires 33 bits to represent" "" { target { c || c++11_down } } } */
> +int i13 = 0b10000000000000 << 18; /* { dg-warning "requires 33 bits to represent" "" { target { c || c++11_down } } } */
> +int i14 = 0b100000000000000 << 17; /* { dg-warning "requires 33 bits to represent" "" { target { c || c++11_down } } } */
> +int i15 = 0b1000000000000000 << 16; /* { dg-warning "requires 33 bits to represent" "" { target { c || c++11_down } } } */
> +int i16 = 0b10000000000000000 << 15; /* { dg-warning "requires 33 bits to represent" "" { target { c || c++11_down } } } */
> +int i17 = 0b100000000000000000 << 14; /* { dg-warning "requires 33 bits to represent" "" { target { c || c++11_down } } } */
> +int i18 = 0b1000000000000000000 << 13; /* { dg-warning "requires 33 bits to represent" "" { target { c || c++11_down } } } */
> +int i19 = 0b10000000000000000000 << 12; /* { dg-warning "requires 33 bits to represent" "" { target { c || c++11_down } } } */
> +int i20 = 0b100000000000000000000 << 11; /* { dg-warning "requires 33 bits to represent" "" { target { c || c++11_down } } } */
> +int i21 = 0b1000000000000000000000 << 10; /* { dg-warning "requires 33 bits to represent" "" { target { c || c++11_down } } } */
> +int i22 = 0b10000000000000000000000 << 9; /* { dg-warning "requires 33 bits to represent" "" { target { c || c++11_down } } } */
> +int i23 = 0b100000000000000000000000 << 8; /* { dg-warning "requires 33 bits to represent" "" { target { c || c++11_down } } } */
> +int i24 = 0b1000000000000000000000000 << 7; /* { dg-warning "requires 33 bits to represent" "" { target { c || c++11_down } } } */
> +int i25 = 0b10000000000000000000000000 << 6; /* { dg-warning "requires 33 bits to represent" "" { target { c || c++11_down } } } */
> +int i26 = 0b100000000000000000000000000 << 5; /* { dg-warning "requires 33 bits to represent" "" { target { c || c++11_down } } } */
> +int i27 = 0b1000000000000000000000000000 << 4; /* { dg-warning "requires 33 bits to represent" "" { target { c || c++11_down } } } */
> +int i28 = 0b10000000000000000000000000000 << 3; /* { dg-warning "requires 33 bits to represent" "" { target { c || c++11_down } } } */
> +int i29 = 0b100000000000000000000000000000 << 2; /* { dg-warning "requires 33 bits to represent" "" { target { c || c++11_down } } } */
> +int i30 = 0b1000000000000000000000000000000 << 1; /* { dg-warning "requires 33 bits to represent" "" { target { c || c++11_down } } } */
> +int i31 = (int) 0b10000000000000000000000000000000u << 1; /* { dg-warning "requires 33 bits to represent" "" { target { c || c++17_down } } } */
> --- gcc/testsuite/c-c++-common/Wshift-overflow-8.c.jj	2022-03-01 11:06:15.451732430 +0100
> +++ gcc/testsuite/c-c++-common/Wshift-overflow-8.c	2022-03-01 11:21:43.500777502 +0100
> @@ -0,0 +1,5 @@
> +/* PR c++/55095 */
> +/* { dg-do compile { target int32 } } */
> +/* { dg-options "-O -fwrapv" } */
> +
> +#include "Wshift-overflow-1.c"
> --- gcc/testsuite/c-c++-common/Wshift-overflow-9.c.jj	2022-03-01 11:07:04.998040795 +0100
> +++ gcc/testsuite/c-c++-common/Wshift-overflow-9.c	2022-03-01 11:07:30.015691566 +0100
> @@ -0,0 +1,7 @@
> +/* PR c++/55095 */
> +/* { dg-do compile { target int32 } } */
> +/* { dg-options "-O -Wshift-overflow -fwrapv" } */
> +/* { dg-additional-options "-std=gnu90" { target c } } */
> +/* { dg-additional-options "-std=c++03" { target c++ } } */
> +
> +#include "Wshift-overflow-1.c"
> --- gcc/testsuite/c-c++-common/Wshift-overflow-10.c.jj	2022-03-01 11:09:17.167195807 +0100
> +++ gcc/testsuite/c-c++-common/Wshift-overflow-10.c	2022-03-01 11:21:54.518623704 +0100
> @@ -0,0 +1,5 @@
> +/* PR c++/55095 */
> +/* { dg-do compile { target int32 } } */
> +/* { dg-options "-O -Wshift-overflow=2 -fwrapv" } */
> +
> +#include "Wshift-overflow-5.c"
> --- gcc/testsuite/c-c++-common/Wshift-overflow-11.c.jj	2022-03-01 11:09:46.991779477 +0100
> +++ gcc/testsuite/c-c++-common/Wshift-overflow-11.c	2022-03-01 11:21:59.235557860 +0100
> @@ -0,0 +1,5 @@
> +/* PR c++/55095 */
> +/* { dg-do compile { target int32 } } */
> +/* { dg-options "-Wshift-overflow=1 -fwrapv" } */
> +
> +#include "Wshift-overflow-6.c"
> --- gcc/testsuite/c-c++-common/Wshift-overflow-12.c.jj	2022-03-01 11:10:19.121330974 +0100
> +++ gcc/testsuite/c-c++-common/Wshift-overflow-12.c	2022-03-01 11:22:04.561483512 +0100
> @@ -0,0 +1,5 @@
> +/* PR c++/55095 */
> +/* { dg-do compile { target int32 } } */
> +/* { dg-options "-Wshift-overflow=2 -fwrapv" } */
> +
> +#include "Wshift-overflow-7.c"
> 
> 	Jakub
>
diff mbox series

Patch

--- gcc/doc/invoke.texi.jj	2022-02-25 10:46:53.085181500 +0100
+++ gcc/doc/invoke.texi	2022-03-01 09:59:15.040855224 +0100
@@ -5809,7 +5809,7 @@  name is still supported, but the newer n
 -Wredundant-move @r{(only for C++)}  @gol
 -Wtype-limits  @gol
 -Wuninitialized  @gol
--Wshift-negative-value @r{(in C++03 and in C99 and newer)}  @gol
+-Wshift-negative-value @r{(in C++11 to C++17 and in C99 and newer)}  @gol
 -Wunused-parameter @r{(only with} @option{-Wunused} @r{or} @option{-Wall}@r{)} @gol
 -Wunused-but-set-parameter @r{(only with} @option{-Wunused} @r{or} @option{-Wall}@r{)}}
 
@@ -6839,7 +6839,7 @@  of the type.  This warning is enabled by
 @opindex Wshift-negative-value
 @opindex Wno-shift-negative-value
 Warn if left shifting a negative value.  This warning is enabled by
-@option{-Wextra} in C99 and C++11 modes (and newer).
+@option{-Wextra} in C99 (and newer) and C++11 to C++17 modes.
 
 @item -Wno-shift-overflow
 @itemx -Wshift-overflow=@var{n}
--- gcc/c-family/c-opts.cc.jj	2022-01-18 11:58:58.884992028 +0100
+++ gcc/c-family/c-opts.cc	2022-03-01 09:57:34.880253831 +0100
@@ -934,10 +934,12 @@  c_common_post_options (const char **pfil
   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.  */
+  /* -Wshift-negative-value is enabled by -Wextra in C99 and C++11 to C++17
+     modes.  */
   if (warn_shift_negative_value == -1)
     warn_shift_negative_value = (extra_warnings
-				 && (cxx_dialect >= cxx11 || flag_isoc99));
+				 && (cxx_dialect >= cxx11 || flag_isoc99)
+				 && cxx_dialect < cxx20);
 
   /* -Wregister is enabled by default in C++17.  */
   SET_OPTION_IF_UNSET (&global_options, &global_options_set, warn_register,
--- gcc/c-family/c-ubsan.cc.jj	2022-02-09 15:15:59.288840032 +0100
+++ gcc/c-family/c-ubsan.cc	2022-03-01 09:55:51.779693845 +0100
@@ -173,7 +173,7 @@  ubsan_instrument_shift (location_t loc,
       || cxx_dialect >= cxx20)
     ;
 
-  /* For signed x << y, in C99/C11, the following:
+  /* For signed x << y, in C99 and later, the following:
      (unsigned) x >> (uprecm1 - y)
      if non-zero, is undefined.  */
   else if (code == LSHIFT_EXPR && flag_isoc99 && cxx_dialect < cxx11)
@@ -186,7 +186,7 @@  ubsan_instrument_shift (location_t loc,
 			build_int_cst (TREE_TYPE (tt), 0));
     }
 
-  /* For signed x << y, in C++11 and later, the following:
+  /* For signed x << y, in C++11 to C++17, the following:
      x < 0 || ((unsigned) x >> (uprecm1 - y))
      if > 1, is undefined.  */
   else if (code == LSHIFT_EXPR && cxx_dialect >= cxx11)
--- gcc/c-family/c-warn.cc.jj	2022-01-18 11:58:58.922991486 +0100
+++ gcc/c-family/c-warn.cc	2022-03-01 10:02:41.634971050 +0100
@@ -2605,7 +2605,7 @@  maybe_warn_shift_overflow (location_t lo
   unsigned int prec0 = TYPE_PRECISION (type0);
 
   /* Left-hand operand must be signed.  */
-  if (TYPE_UNSIGNED (type0) || cxx_dialect >= cxx20)
+  if (TYPE_OVERFLOW_WRAPS (type0) || cxx_dialect >= cxx20)
     return false;
 
   unsigned int min_prec = (wi::min_precision (wi::to_wide (op0), SIGNED)
--- gcc/c/c-fold.cc.jj	2022-02-09 20:45:24.253211303 +0100
+++ gcc/c/c-fold.cc	2022-03-01 11:39:32.153859825 +0100
@@ -382,6 +382,7 @@  c_fully_fold_internal (tree expr, bool i
 	  && TREE_CODE (TREE_TYPE (orig_op0)) == INTEGER_TYPE
 	  && TREE_CODE (op0) == INTEGER_CST
 	  && c_inhibit_evaluation_warnings == 0
+	  && !TYPE_OVERFLOW_WRAPS (TREE_TYPE (orig_op0))
 	  && tree_int_cst_sgn (op0) < 0)
 	warning_at (loc, OPT_Wshift_negative_value,
 		    "left shift of negative value");
--- gcc/c/c-typeck.cc.jj	2022-02-11 00:19:22.135067293 +0100
+++ gcc/c/c-typeck.cc	2022-03-01 10:04:20.925584897 +0100
@@ -12213,7 +12213,8 @@  build_binary_op (location_t location, en
 	{
 	  doing_shift = true;
 	  if (TREE_CODE (op0) == INTEGER_CST
-	      && tree_int_cst_sgn (op0) < 0)
+	      && tree_int_cst_sgn (op0) < 0
+	      && !TYPE_OVERFLOW_WRAPS (type0))
 	    {
 	      /* Don't reject a left shift of a negative value in a context
 		 where a constant expression is needed in C90.  */
--- gcc/cp/constexpr.cc.jj	2022-02-18 12:37:51.081601299 +0100
+++ gcc/cp/constexpr.cc	2022-03-01 11:56:12.874890444 +0100
@@ -3165,7 +3165,7 @@  cxx_eval_check_shift_p (location_t loc,
      The value of E1 << E2 is the unique value congruent to E1 x 2^E2 modulo
      2^N, where N is the range exponent of the type of the result.  */
   if (code == LSHIFT_EXPR
-      && !TYPE_UNSIGNED (lhstype)
+      && !TYPE_OVERFLOW_WRAPS (lhstype)
       && cxx_dialect >= cxx11
       && cxx_dialect < cxx20)
     {
--- gcc/cp/typeck.cc.jj	2022-02-18 12:38:06.065393230 +0100
+++ gcc/cp/typeck.cc	2022-03-01 10:04:57.726071137 +0100
@@ -5382,6 +5382,7 @@  cp_build_binary_op (const op_location_t
 	  doing_shift = true;
 	  if (TREE_CODE (const_op0) == INTEGER_CST
 	      && tree_int_cst_sgn (const_op0) < 0
+	      && !TYPE_OVERFLOW_WRAPS (type0)
 	      && (complain & tf_warning)
 	      && c_inhibit_evaluation_warnings == 0)
 	    warning_at (location, OPT_Wshift_negative_value,
--- gcc/testsuite/c-c++-common/Wshift-negative-value-1.c.jj	2020-01-12 11:54:36.995404628 +0100
+++ gcc/testsuite/c-c++-common/Wshift-negative-value-1.c	2022-03-01 11:43:47.217299318 +0100
@@ -1,13 +1,12 @@ 
 /* PR c/65179 */
 /* { dg-do compile } */
 /* { dg-options "-O -Wextra" } */
-/* { dg-additional-options "-std=c++11" { target c++ } } */
 
 enum E {
   A = 0 << 1,
   B = 1 << 1,
-  C = -1 << 1, /* { dg-warning "10:left shift of negative value|not an integer constant" } */
-  /* { dg-error "left operand of shift expression" "shift" { target c++ } .-1 } */
+  C = -1 << 1, /* { dg-warning "10:left shift of negative value|not an integer constant" "" { target { c || { c++11 && c++17_down } } } } */
+  /* { dg-error "left operand of shift expression" "shift" { target { c++11 && c++17_down } } .-1 } */
   D = 0 >> 1,
   E = 1 >> 1,
   F = -1 >> 1
@@ -23,10 +22,10 @@  left (int x)
   int r = 0;
   r += z << x;
   r += o << x;
-  r += m << x; /* { dg-warning "10:left shift of negative value" } */
+  r += m << x; /* { dg-warning "10:left shift of negative value" "" { target { c || { c++11 && c++17_down } } } } */
   r += 0 << x;
   r += 1 << x;
-  r += -1 << x; /* { dg-warning "11:left shift of negative value" } */
+  r += -1 << x; /* { dg-warning "11:left shift of negative value" "" { target { c || { c++11 && c++17_down } } } } */
   r += -1U << x;
   return r;
 }
--- gcc/testsuite/c-c++-common/Wshift-negative-value-2.c.jj	2020-01-12 11:54:36.995404628 +0100
+++ gcc/testsuite/c-c++-common/Wshift-negative-value-2.c	2022-03-01 11:47:41.695026169 +0100
@@ -1,14 +1,13 @@ 
 /* PR c/65179 */
 /* { dg-do compile } */
 /* { dg-options "-O -Wshift-negative-value" } */
-/* { dg-additional-options "-std=c++11" { target c++ } } */
 
 enum E {
   A = 0 << 1,
   B = 1 << 1,
   C = -1 << 1, /* { dg-warning "10:left shift of negative value" } */
-  /* { dg-error "not an integer constant" "no constant" { target c++ } .-1 } */
-  /* { dg-error "left operand of shift expression" "shift" { target c++ } .-2 } */
+  /* { dg-error "not an integer constant" "no constant" { target { c++11 && c++17_down } } .-1 } */
+  /* { dg-error "left operand of shift expression" "shift" { target { c++11 && c++17_down } } .-2 } */
   D = 0 >> 1,
   E = 1 >> 1,
   F = -1 >> 1
--- gcc/testsuite/c-c++-common/Wshift-negative-value-3.c.jj	2020-01-12 11:54:36.995404628 +0100
+++ gcc/testsuite/c-c++-common/Wshift-negative-value-3.c	2022-03-01 11:48:01.029756269 +0100
@@ -1,14 +1,13 @@ 
 /* PR c/65179 */
 /* { dg-do compile } */
 /* { dg-options "-O -Wextra -Wno-shift-negative-value" } */
-/* { dg-additional-options "-std=c++11" { target c++ } } */
 
 enum E {
   A = 0 << 1,
   B = 1 << 1,
   C = -1 << 1,
-  /* { dg-error "not an integer constant" "no constant" { target c++ } .-1 } */
-  /* { dg-error "left operand of shift expression" "shift" { target c++ } .-2 } */
+  /* { dg-error "not an integer constant" "no constant" { target { c++11 && c++17_down } } .-1 } */
+  /* { dg-error "left operand of shift expression" "shift" { target { c++11 && c++17_down } } .-2 } */
   D = 0 >> 1,
   E = 1 >> 1,
   F = -1 >> 1
--- gcc/testsuite/c-c++-common/Wshift-negative-value-4.c.jj	2020-01-12 11:54:36.995404628 +0100
+++ gcc/testsuite/c-c++-common/Wshift-negative-value-4.c	2022-03-01 11:48:46.740118184 +0100
@@ -1,14 +1,13 @@ 
 /* PR c/65179 */
 /* { dg-do compile } */
 /* { dg-options "-O" } */
-/* { dg-additional-options "-std=c++11" { target c++ } } */
 
 enum E {
   A = 0 << 1,
   B = 1 << 1,
   C = -1 << 1,
-  /* { dg-error "not an integer constant" "no constant" { target c++ } .-1 } */
-  /* { dg-error "left operand of shift expression" "shift" { target c++ } .-2 } */
+  /* { dg-error "not an integer constant" "no constant" { target { c++11 && c++17_down } } .-1 } */
+  /* { dg-error "left operand of shift expression" "shift" { target { c++11 && c++17_down } } .-2 } */
   D = 0 >> 1,
   E = 1 >> 1,
   F = -1 >> 1
--- gcc/testsuite/c-c++-common/Wshift-negative-value-7.c.jj	2022-03-01 11:00:56.877179511 +0100
+++ gcc/testsuite/c-c++-common/Wshift-negative-value-7.c	2022-03-01 11:59:32.535103327 +0100
@@ -0,0 +1,5 @@ 
+/* PR c/65179 */
+/* { dg-do compile } */
+/* { dg-options "-O -Wextra -fwrapv" } */
+
+#include "Wshift-negative-value-1.c"
--- gcc/testsuite/c-c++-common/Wshift-negative-value-8.c.jj	2022-03-01 11:01:41.087562363 +0100
+++ gcc/testsuite/c-c++-common/Wshift-negative-value-8.c	2022-03-01 11:59:43.084956059 +0100
@@ -0,0 +1,5 @@ 
+/* PR c/65179 */
+/* { dg-do compile } */
+/* { dg-options "-O -Wshift-negative-value -fwrapv" } */
+
+#include "Wshift-negative-value-1.c"
--- gcc/testsuite/c-c++-common/Wshift-negative-value-9.c.jj	2022-03-01 11:02:38.837756210 +0100
+++ gcc/testsuite/c-c++-common/Wshift-negative-value-9.c	2022-03-01 11:59:51.733835326 +0100
@@ -0,0 +1,5 @@ 
+/* PR c/65179 */
+/* { dg-do compile } */
+/* { dg-options "-O -fwrapv" } */
+
+#include "Wshift-negative-value-1.c"
--- gcc/testsuite/c-c++-common/Wshift-negative-value-10.c.jj	2022-03-01 11:03:28.922057068 +0100
+++ gcc/testsuite/c-c++-common/Wshift-negative-value-10.c	2022-03-01 11:03:44.101845168 +0100
@@ -0,0 +1,7 @@ 
+/* PR c/65179 */
+/* { dg-do compile } */
+/* { dg-options "-O -Wshift-negative-value -fwrapv" } */
+/* { dg-additional-options "-std=c++03" { target c++ } } */
+/* { dg-additional-options "-std=c90" { target c } } */
+
+#include "Wshift-negative-value-1.c"
--- gcc/testsuite/c-c++-common/Wshift-overflow-1.c.jj	2020-01-12 11:54:36.995404628 +0100
+++ gcc/testsuite/c-c++-common/Wshift-overflow-1.c	2022-03-01 12:01:33.792410660 +0100
@@ -1,7 +1,6 @@ 
 /* 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)
@@ -12,16 +11,16 @@ 
 #define LONG_LONG_MIN (-__LONG_LONG_MAX__-1)
 
 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 i2 = 9 << INTM1; /* { dg-warning "requires 36 bits to represent" "" { target { c || { c++11 && c++17_down } } } } */
+int i3 = 10 << INTM2; /* { dg-warning "requires 35 bits to represent" "" { target { c || { c++11 && c++17_down } } } } */
+int i4 = __INT_MAX__ << 2; /* { dg-warning "requires 34 bits to represent" "" { target { c || { c++11 && c++17_down } } } } */
+int i5 = __INT_MAX__ << INTM1; /* { dg-warning "requires 63 bits to represent" "" { target { c || { c++11 && c++17_down } } } } */
 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 i11 = INT_MIN << 1; /* { dg-warning "requires 33 bits to represent" } */
+int i7 = -9 << INTM1; /* { dg-warning "requires 36 bits to represent" "" { target { c || { c++11 && c++17_down } } } } */
+int i8 = -10 << INTM2; /* { dg-warning "requires 35 bits to represent" "" { target { c || { c++11 && c++17_down } } } } */
+int i9 = -__INT_MAX__ << 2; /* { dg-warning "requires 34 bits to represent" "" { target { c || { c++11 && c++17_down } } } } */
+int i10 = -__INT_MAX__ << INTM1; /* { dg-warning "requires 63 bits to represent" "" { target { c || { c++11 && c++17_down } } } } */
+int i11 = INT_MIN << 1; /* { dg-warning "requires 33 bits to represent" "" { target { c || { c++11 && c++17_down } } } } */
 
 int r1 = 1 >> INTM1;
 int r2 = 9 >> INTM1;
@@ -35,29 +34,29 @@  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 u2 = 9 << INTM1; /* { dg-warning "requires 36 bits to represent" "" { target { c || { c++11 && c++17_down } } } } */
 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 l2 = 9LL << LLONGM1; /* { dg-warning "requires 68 bits to represent" "" { target { c || { c++11 && c++17_down } } } } */
+long long int l3 = 10LL << LLONGM2; /* { dg-warning "requires 67 bits to represent" "" { target { c || { c++11 && c++17_down } } } } */
+long long int l4 = __LONG_LONG_MAX__ << 2; /* { dg-warning "requires 66 bits to represent" "" { target { c || { c++11 && c++17_down } } } } */
+long long int l5 = __LONG_LONG_MAX__ << LLONGM1; /* { dg-warning "requires 127 bits to represent" "" { target { c || { c++11 && c++17_down } } } } */
 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" } */
-long long int l11 = LONG_LONG_MIN << 1; /* { dg-warning "requires 65 bits to represent" } */
+long long int l7 = -9LL << LLONGM1; /* { dg-warning "requires 68 bits to represent" "" { target { c || { c++11 && c++17_down } } } } */
+long long int l8 = -10LL << LLONGM2; /* { dg-warning "requires 67 bits to represent" "" { target { c || { c++11 && c++17_down } } } } */
+long long int l9 = -__LONG_LONG_MAX__ << 2; /* { dg-warning "requires 66 bits to represent" "" { target { c || { c++11 && c++17_down } } } } */
+long long int l10 = -__LONG_LONG_MAX__ << LLONGM1; /* { dg-warning "requires 127 bits to represent" "" { target { c || { c++11 && c++17_down } } } } */
+long long int l11 = LONG_LONG_MIN << 1; /* { dg-warning "requires 65 bits to represent" "" { target { c || { c++11 && c++17_down } } } } */
 
 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" } */
+  int k1 = a << b; /* { dg-warning "requires 36 bits to represent" "" { target { c || { c++11 && c++17_down } } } } */
+  int k2 = 10 << b; /* { dg-warning "requires 36 bits to represent" "" { target { c || { c++11 && c++17_down } } } } */
+  int k3 = a << INTM1; /* { dg-warning "requires 36 bits to represent" "" { target { c || { c++11 && c++17_down } } } } */
 }
--- gcc/testsuite/c-c++-common/Wshift-overflow-2.c.jj	2020-01-12 11:54:36.995404628 +0100
+++ gcc/testsuite/c-c++-common/Wshift-overflow-2.c	2022-03-01 11:20:16.498991992 +0100
@@ -1,7 +1,6 @@ 
 /* 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)
--- gcc/testsuite/c-c++-common/Wshift-overflow-5.c.jj	2020-01-12 11:54:36.995404628 +0100
+++ gcc/testsuite/c-c++-common/Wshift-overflow-5.c	2022-03-01 12:05:27.955141905 +0100
@@ -1,11 +1,10 @@ 
 /* 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" } */
+int i1 = 1 << INTM1; /* { dg-warning "requires 33 bits to represent" "" { target { c || c++11_down } } } */
+unsigned u1 = 1 << INTM1; /* { dg-warning "requires 33 bits to represent" "" { target { c || c++11_down } } } */
+long long int l1 = 1LL << LLONGM1; /* { dg-warning "requires 65 bits to represent" "" { target { c || c++11_down } } } */
--- gcc/testsuite/c-c++-common/Wshift-overflow-6.c.jj	2020-01-12 11:54:36.995404628 +0100
+++ gcc/testsuite/c-c++-common/Wshift-overflow-6.c	2022-03-01 12:06:15.950471922 +0100
@@ -1,7 +1,6 @@ 
 /* PR c++/55095 */
 /* { dg-do compile { target int32 } } */
 /* { dg-options "-Wshift-overflow=1" } */
-/* { dg-additional-options "-std=c++11" { target c++ } } */
 
 int i00 = 0b1 << 31;
 int i01 = 0b10 << 30;
@@ -34,4 +33,4 @@  int i27 = 0b1000000000000000000000000000
 int i28 = 0b10000000000000000000000000000 << 3;
 int i29 = 0b100000000000000000000000000000 << 2;
 int i30 = 0b1000000000000000000000000000000 << 1;
-int i31 = (int) 0b10000000000000000000000000000000u << 1; /* { dg-warning "requires 33 bits to represent" } */
+int i31 = (int) 0b10000000000000000000000000000000u << 1; /* { dg-warning "requires 33 bits to represent" "" { target { c || c++17_down } } } */
--- gcc/testsuite/c-c++-common/Wshift-overflow-7.c.jj	2020-01-12 11:54:36.995404628 +0100
+++ gcc/testsuite/c-c++-common/Wshift-overflow-7.c	2022-03-01 12:08:09.738883507 +0100
@@ -1,37 +1,36 @@ 
 /* PR c++/55095 */
 /* { dg-do compile { target int32 } } */
 /* { dg-options "-Wshift-overflow=2" } */
-/* { dg-additional-options "-std=c++11" { target c++ } } */
 
-int i00 = 0b1 << 31; /* { dg-warning "requires 33 bits to represent" } */
-int i01 = 0b10 << 30; /* { dg-warning "requires 33 bits to represent" } */
-int i02 = 0b100 << 29; /* { dg-warning "requires 33 bits to represent" } */
-int i03 = 0b1000 << 28; /* { dg-warning "requires 33 bits to represent" } */
-int i04 = 0b10000 << 27; /* { dg-warning "requires 33 bits to represent" } */
-int i05 = 0b100000 << 26; /* { dg-warning "requires 33 bits to represent" } */
-int i06 = 0b1000000 << 25; /* { dg-warning "requires 33 bits to represent" } */
-int i07 = 0b10000000 << 24; /* { dg-warning "requires 33 bits to represent" } */
-int i08 = 0b100000000 << 23; /* { dg-warning "requires 33 bits to represent" } */
-int i09 = 0b1000000000 << 22; /* { dg-warning "requires 33 bits to represent" } */
-int i10 = 0b10000000000 << 21; /* { dg-warning "requires 33 bits to represent" } */
-int i11 = 0b100000000000 << 20; /* { dg-warning "requires 33 bits to represent" } */
-int i12 = 0b1000000000000 << 19; /* { dg-warning "requires 33 bits to represent" } */
-int i13 = 0b10000000000000 << 18; /* { dg-warning "requires 33 bits to represent" } */
-int i14 = 0b100000000000000 << 17; /* { dg-warning "requires 33 bits to represent" } */
-int i15 = 0b1000000000000000 << 16; /* { dg-warning "requires 33 bits to represent" } */
-int i16 = 0b10000000000000000 << 15; /* { dg-warning "requires 33 bits to represent" } */
-int i17 = 0b100000000000000000 << 14; /* { dg-warning "requires 33 bits to represent" } */
-int i18 = 0b1000000000000000000 << 13; /* { dg-warning "requires 33 bits to represent" } */
-int i19 = 0b10000000000000000000 << 12; /* { dg-warning "requires 33 bits to represent" } */
-int i20 = 0b100000000000000000000 << 11; /* { dg-warning "requires 33 bits to represent" } */
-int i21 = 0b1000000000000000000000 << 10; /* { dg-warning "requires 33 bits to represent" } */
-int i22 = 0b10000000000000000000000 << 9; /* { dg-warning "requires 33 bits to represent" } */
-int i23 = 0b100000000000000000000000 << 8; /* { dg-warning "requires 33 bits to represent" } */
-int i24 = 0b1000000000000000000000000 << 7; /* { dg-warning "requires 33 bits to represent" } */
-int i25 = 0b10000000000000000000000000 << 6; /* { dg-warning "requires 33 bits to represent" } */
-int i26 = 0b100000000000000000000000000 << 5; /* { dg-warning "requires 33 bits to represent" } */
-int i27 = 0b1000000000000000000000000000 << 4; /* { dg-warning "requires 33 bits to represent" } */
-int i28 = 0b10000000000000000000000000000 << 3; /* { dg-warning "requires 33 bits to represent" } */
-int i29 = 0b100000000000000000000000000000 << 2; /* { dg-warning "requires 33 bits to represent" } */
-int i30 = 0b1000000000000000000000000000000 << 1; /* { dg-warning "requires 33 bits to represent" } */
-int i31 = (int) 0b10000000000000000000000000000000u << 1; /* { dg-warning "requires 33 bits to represent" } */
+int i00 = 0b1 << 31; /* { dg-warning "requires 33 bits to represent" "" { target { c || c++11_down } } } */
+int i01 = 0b10 << 30; /* { dg-warning "requires 33 bits to represent" "" { target { c || c++11_down } } } */
+int i02 = 0b100 << 29; /* { dg-warning "requires 33 bits to represent" "" { target { c || c++11_down } } } */
+int i03 = 0b1000 << 28; /* { dg-warning "requires 33 bits to represent" "" { target { c || c++11_down } } } */
+int i04 = 0b10000 << 27; /* { dg-warning "requires 33 bits to represent" "" { target { c || c++11_down } } } */
+int i05 = 0b100000 << 26; /* { dg-warning "requires 33 bits to represent" "" { target { c || c++11_down } } } */
+int i06 = 0b1000000 << 25; /* { dg-warning "requires 33 bits to represent" "" { target { c || c++11_down } } } */
+int i07 = 0b10000000 << 24; /* { dg-warning "requires 33 bits to represent" "" { target { c || c++11_down } } } */
+int i08 = 0b100000000 << 23; /* { dg-warning "requires 33 bits to represent" "" { target { c || c++11_down } } } */
+int i09 = 0b1000000000 << 22; /* { dg-warning "requires 33 bits to represent" "" { target { c || c++11_down } } } */
+int i10 = 0b10000000000 << 21; /* { dg-warning "requires 33 bits to represent" "" { target { c || c++11_down } } } */
+int i11 = 0b100000000000 << 20; /* { dg-warning "requires 33 bits to represent" "" { target { c || c++11_down } } } */
+int i12 = 0b1000000000000 << 19; /* { dg-warning "requires 33 bits to represent" "" { target { c || c++11_down } } } */
+int i13 = 0b10000000000000 << 18; /* { dg-warning "requires 33 bits to represent" "" { target { c || c++11_down } } } */
+int i14 = 0b100000000000000 << 17; /* { dg-warning "requires 33 bits to represent" "" { target { c || c++11_down } } } */
+int i15 = 0b1000000000000000 << 16; /* { dg-warning "requires 33 bits to represent" "" { target { c || c++11_down } } } */
+int i16 = 0b10000000000000000 << 15; /* { dg-warning "requires 33 bits to represent" "" { target { c || c++11_down } } } */
+int i17 = 0b100000000000000000 << 14; /* { dg-warning "requires 33 bits to represent" "" { target { c || c++11_down } } } */
+int i18 = 0b1000000000000000000 << 13; /* { dg-warning "requires 33 bits to represent" "" { target { c || c++11_down } } } */
+int i19 = 0b10000000000000000000 << 12; /* { dg-warning "requires 33 bits to represent" "" { target { c || c++11_down } } } */
+int i20 = 0b100000000000000000000 << 11; /* { dg-warning "requires 33 bits to represent" "" { target { c || c++11_down } } } */
+int i21 = 0b1000000000000000000000 << 10; /* { dg-warning "requires 33 bits to represent" "" { target { c || c++11_down } } } */
+int i22 = 0b10000000000000000000000 << 9; /* { dg-warning "requires 33 bits to represent" "" { target { c || c++11_down } } } */
+int i23 = 0b100000000000000000000000 << 8; /* { dg-warning "requires 33 bits to represent" "" { target { c || c++11_down } } } */
+int i24 = 0b1000000000000000000000000 << 7; /* { dg-warning "requires 33 bits to represent" "" { target { c || c++11_down } } } */
+int i25 = 0b10000000000000000000000000 << 6; /* { dg-warning "requires 33 bits to represent" "" { target { c || c++11_down } } } */
+int i26 = 0b100000000000000000000000000 << 5; /* { dg-warning "requires 33 bits to represent" "" { target { c || c++11_down } } } */
+int i27 = 0b1000000000000000000000000000 << 4; /* { dg-warning "requires 33 bits to represent" "" { target { c || c++11_down } } } */
+int i28 = 0b10000000000000000000000000000 << 3; /* { dg-warning "requires 33 bits to represent" "" { target { c || c++11_down } } } */
+int i29 = 0b100000000000000000000000000000 << 2; /* { dg-warning "requires 33 bits to represent" "" { target { c || c++11_down } } } */
+int i30 = 0b1000000000000000000000000000000 << 1; /* { dg-warning "requires 33 bits to represent" "" { target { c || c++11_down } } } */
+int i31 = (int) 0b10000000000000000000000000000000u << 1; /* { dg-warning "requires 33 bits to represent" "" { target { c || c++17_down } } } */
--- gcc/testsuite/c-c++-common/Wshift-overflow-8.c.jj	2022-03-01 11:06:15.451732430 +0100
+++ gcc/testsuite/c-c++-common/Wshift-overflow-8.c	2022-03-01 11:21:43.500777502 +0100
@@ -0,0 +1,5 @@ 
+/* PR c++/55095 */
+/* { dg-do compile { target int32 } } */
+/* { dg-options "-O -fwrapv" } */
+
+#include "Wshift-overflow-1.c"
--- gcc/testsuite/c-c++-common/Wshift-overflow-9.c.jj	2022-03-01 11:07:04.998040795 +0100
+++ gcc/testsuite/c-c++-common/Wshift-overflow-9.c	2022-03-01 11:07:30.015691566 +0100
@@ -0,0 +1,7 @@ 
+/* PR c++/55095 */
+/* { dg-do compile { target int32 } } */
+/* { dg-options "-O -Wshift-overflow -fwrapv" } */
+/* { dg-additional-options "-std=gnu90" { target c } } */
+/* { dg-additional-options "-std=c++03" { target c++ } } */
+
+#include "Wshift-overflow-1.c"
--- gcc/testsuite/c-c++-common/Wshift-overflow-10.c.jj	2022-03-01 11:09:17.167195807 +0100
+++ gcc/testsuite/c-c++-common/Wshift-overflow-10.c	2022-03-01 11:21:54.518623704 +0100
@@ -0,0 +1,5 @@ 
+/* PR c++/55095 */
+/* { dg-do compile { target int32 } } */
+/* { dg-options "-O -Wshift-overflow=2 -fwrapv" } */
+
+#include "Wshift-overflow-5.c"
--- gcc/testsuite/c-c++-common/Wshift-overflow-11.c.jj	2022-03-01 11:09:46.991779477 +0100
+++ gcc/testsuite/c-c++-common/Wshift-overflow-11.c	2022-03-01 11:21:59.235557860 +0100
@@ -0,0 +1,5 @@ 
+/* PR c++/55095 */
+/* { dg-do compile { target int32 } } */
+/* { dg-options "-Wshift-overflow=1 -fwrapv" } */
+
+#include "Wshift-overflow-6.c"
--- gcc/testsuite/c-c++-common/Wshift-overflow-12.c.jj	2022-03-01 11:10:19.121330974 +0100
+++ gcc/testsuite/c-c++-common/Wshift-overflow-12.c	2022-03-01 11:22:04.561483512 +0100
@@ -0,0 +1,5 @@ 
+/* PR c++/55095 */
+/* { dg-do compile { target int32 } } */
+/* { dg-options "-Wshift-overflow=2 -fwrapv" } */
+
+#include "Wshift-overflow-7.c"