On Tue, Sep 1, 2026 at 9:35 AM Jakub Jelinek <[email protected]> wrote:

> On Mon, Aug 31, 2026 at 04:53:49PM +0200, Jakub Jelinek wrote:
> > The following patch implements the <bit> part of
> > C++29 P3793R2 - Better shifting
> > paper.
>
> Full bootstrap/regtest on x86_64-linux and i686-linux revealed a bug,
> I forgot preprocessor guards around shl/shr, so
> +FAIL: g++.dg/plugin/std-module-exports-c++20.C
> -fplugin=./std_module_exports_plugin.so (test for excess errors)
> +FAIL: g++.dg/plugin/std-module-exports-c++23.C
> -fplugin=./std_module_exports_plugin.so (test for excess errors)
> +FAIL: g++.dg/plugin/std-module-exports-c++26.C
> -fplugin=./std_module_exports_plugin.so (test for excess errors)
> failed because of that.
>
> The following patch adds those and slightly improves the tests,
> doesn't call test_negative_shifts at all if SInt is unsigned type
> instead of checking for signedness in every loop iteration, small
> formatting
> nit and adds
> static_assert( std::shl(-1, 0x7fffffff00000001LL) == 0 );
> static_assert( std::shl(2, 0x7fffffff00000001LL) == 0 );
> static_assert( std::shl(-1, -0x7fffffff00000001LL) == -1 );
> static_assert( std::shl(2, -0x7fffffff00000001LL) == 0 );
> and
> static_assert( std::shr(-1, 0x7fffffff00000001LL) == -1 );
> static_assert( std::shr(2, 0x7fffffff00000001LL) == 0 );
> static_assert( std::shr(-1, -0x7fffffff00000001LL) == 0 );
> static_assert( std::shr(2, -0x7fffffff00000001LL) == 0 );
> tests to verify nothing truncates the shift counts to say int or unsigned
> int.
>
> 2026-09-01  Jakub Jelinek  <[email protected]>
>
>         * include/std/bit: Implement C++29 P3793R2 - Better shifting.
>         (std::__signed_or_unsigned_integer): New concept.
>         (std::shl, std::shr): New function templates.
>         * include/bits/version.def (bitops): Add different value for C++29.
>         * include/bits/version.h: Regenerate.
>         * src/c++23/std.cc.in (std::shl, std::shr): Export for C++29.
>         * testsuite/26_numerics/bit/bit.shift/shl.cc: New test.
>         * testsuite/26_numerics/bit/bit.shift/shr.cc: New test.
>
> --- a/libstdc++-v3/include/std/bit      2026-08-19 22:18:21.873878488 +0200
> +++ b/libstdc++-v3/include/std/bit      2026-09-01 09:03:56.393613654 +0200
> @@ -407,9 +407,46 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
>    /// @cond undocumented
>    template<typename _Tp>
>      concept __unsigned_integer = __is_unsigned_integer<_Tp>::value;
> +
> +  template<typename _Tp>
> +    concept __signed_or_unsigned_integer
> +      = __is_signed_or_unsigned_integer<_Tp>::value;
>    /// @endcond
>
> -  // [bit.rot], rotating
> +#if __cpp_lib_bitops >= 202606L // >= C++29
> +  // [bit.shift], shifting
> +  template<__signed_or_unsigned_integer _Tp, __signed_or_unsigned_integer
> _Sp>
> +    [[nodiscard]] constexpr _Tp
> +    shl(_Tp __x, _Sp __s) noexcept
> +    {
> +      constexpr auto _Nd = __gnu_cxx::__int_traits<_Tp>::__digits
> +                          + is_signed_v<_Tp>;
> +      if constexpr (is_signed_v<_Sp>)
> +       {
>
We do not need these braces.

> +         if (__s < 0)
> +           return (__s > -_Nd
> +                   ? __x >> -__s
> +                   : static_cast<_Tp>(__x < 0 ? -1 : 0));
>
Does this (and one below) produces an warning about meaningless comparsion
if _Tp is unsigned?
(cannot be smaller than zero)?  We could do something like:
if constexpr (is_signed_v<_Sp>)
  if (__s < 0)
     {
        if (__s > -Nd)
          return (__x >> -s);
        if constexpr (is_signed_v<_Tp>)
          if (__x < 0)
            return _Tp(-1);
        return _Tp(0);
     }
And the same for shr.

> +       }
> +      return __s < _Nd ? __x << __s : static_cast<_Tp>(0);
> +    }
> +
> +  template<__signed_or_unsigned_integer _Tp, __signed_or_unsigned_integer
> _Sp>
> +    [[nodiscard]] constexpr _Tp
> +    shr(_Tp __x, _Sp __s) noexcept
> +    {
> +      constexpr auto _Nd = __gnu_cxx::__int_traits<_Tp>::__digits
> +                          + is_signed_v<_Tp>;
> +      if constexpr (is_signed_v<_Sp>)
> +       {
>
And these braces aren't needed; I would prefer to remove them.

> +         if (__s < 0)
> +           return __s > -_Nd ? __x << -__s : static_cast<_Tp>(0);
> +       }
> +      return __s < _Nd ? __x >> __s : static_cast<_Tp>(__x < 0 ? -1 : 0);
> +    }
> +#endif
> +
> +  // [bit.rotate], rotating
>
>    /// Rotate `x` to the left by `s` bits.
>    template<__unsigned_integer _Tp>
> --- a/libstdc++-v3/include/bits/version.def     2026-08-25
> 22:58:07.419638978 +0200
> +++ b/libstdc++-v3/include/bits/version.def     2026-08-31
> 14:13:18.308546251 +0200
> @@ -891,6 +891,10 @@ ftms = {
>  ftms = {
>    name = bitops;
>    values = {
> +    v = 202606;
> +    cxxmin = 29;
> +  };
> +  values = {
>      v = 201907;
>      cxxmin = 20;
>    };
> --- a/libstdc++-v3/include/bits/version.h       2026-08-25
> 22:58:07.420655732 +0200
> +++ b/libstdc++-v3/include/bits/version.h       2026-08-31
> 14:13:28.350218071 +0200
> @@ -989,7 +989,12 @@
>  #undef __glibcxx_want_bit_cast
>
>  #if !defined(__cpp_lib_bitops)
> -# if (__cplusplus >= 202002L)
> +# if (__cplusplus >  202603L)
> +#  define __glibcxx_bitops 202606L
> +#  if defined(__glibcxx_want_all) || defined(__glibcxx_want_bitops)
> +#   define __cpp_lib_bitops 202606L
> +#  endif
> +# elif (__cplusplus >= 202002L)
>  #  define __glibcxx_bitops 201907L
>  #  if defined(__glibcxx_want_all) || defined(__glibcxx_want_bitops)
>  #   define __cpp_lib_bitops 201907L
> --- a/libstdc++-v3/src/c++23/std.cc.in  2026-08-25 22:58:07.422503202
> +0200
> +++ b/libstdc++-v3/src/c++23/std.cc.in  2026-08-31 15:51:26.976711069
> +0200
> @@ -695,6 +695,10 @@ export namespace std
>  #if __cpp_lib_byteswap // >= C++23
>    using std::byteswap;
>  #endif
> +#if __cpp_lib_bitops >= 202606L // >= C++29
> +  using std::shl;
> +  using std::shr;
> +#endif
>  }
>
>  // 22.9 <bitset>
> --- a/libstdc++-v3/testsuite/26_numerics/bit/bit.shift/shl.cc   2026-08-31
> 15:07:47.877829751 +0200
> +++ b/libstdc++-v3/testsuite/26_numerics/bit/bit.shift/shl.cc   2026-09-01
> 09:07:37.403608042 +0200
> @@ -0,0 +1,159 @@
> +// { dg-do compile { target c++29 } }
> +
> +#include <bit>
> +#include <limits>
> +
> +template<typename Int, typename SInt>
> +constexpr bool
> +test_negative_shifts()
> +{
> +  constexpr unsigned digits = std::numeric_limits<Int>::digits
> +                             + std::is_signed_v<Int>;
> +
> +  Int xarr[] = { (Int)-1, 0, 1, 3, 6, 7, 0x10, 0x11, 0x22, 0x44,
> (Int)0x80,
> +                (Int)-55, (Int)-927 };
> +  SInt sarr[] = { 1, 4, 5, digits - 1, digits, (SInt)-12 };
> +  for (Int x : xarr)
> +    for (SInt s : sarr)
> +      if (std::shl(x, -s) != std::shr(x, s))
> +       return false;
> +  return true;
> +}
> +
> +template<typename Int, typename SInt>
> +constexpr auto
> +test(Int x, SInt y)
> +-> decltype(std::shl(x, y))
> +{
> +  static_assert( noexcept(std::shl(x, 0)) );
> +
> +  constexpr unsigned digits = std::numeric_limits<Int>::digits
> +                             + std::is_signed_v<Int>;
> +
> +  static_assert( std::shl((Int)0, (SInt)0) == 0 );
> +  static_assert( std::shl((Int)0, (SInt)1) == 0 );
> +  static_assert( std::shl((Int)0, (SInt)4) == 0 );
> +  static_assert( std::shl((Int)0, (SInt)8) == 0 );
> +  static_assert( std::shl((Int)0, (SInt)-4) == 0 );
> +  static_assert( std::shl((Int)-1, (SInt)0) == (Int)((Int)-1 << 0) );
> +  static_assert( std::shl((Int)-1, (SInt)1) == (Int)((Int)-1 << 1) );
> +  static_assert( std::shl((Int)-1, (SInt)4) == (Int)((Int)-1 << 4) );
> +  static_assert( std::shl((Int)-1, (SInt)8) == (Int)((Int)-1 << 8) );
> +  static_assert( std::shl((Int)-1, (SInt)-4)
> +                == ((SInt)-4 < 0 ? (Int)-1 >> (SInt)4
> +                    : (SInt)-4 >= digits ? 0
> +                    : (Int)((Int)-1 << ((SInt)-4 < 0 ? 0 : (SInt)-4))) );
> +
> +  static_assert( std::shl((Int)1, (SInt)0) == (Int)1 << 0 );
> +  static_assert( std::shl((Int)1, (SInt)1) == (Int)1 << 1 );
> +  static_assert( std::shl((Int)1, (SInt)4) == (Int)1 << 4 );
> +  static_assert( std::shl((Int)1, (SInt)digits) == (Int)0 );
> +  static_assert( std::shl((Int)7, (SInt)digits) == (Int)0 );
> +  static_assert( std::shl((Int)6, (SInt)digits - 1) == (Int)0 );
> +  static_assert( std::shl((Int)3, (SInt)6) == (Int)((Int)3 << 6) );
> +
> +  static_assert( std::shl((Int)0b0110'1100, (SInt)1) == (Int)0b1101'1000
> );
> +  static_assert( std::shl((Int)0b0110'1100, (SInt)digits - 1) == 0 );
> +
> +  static_assert( std::shl((Int)0x01, (SInt)0 ) == 0x01 );
> +  static_assert( std::shl((Int)0x10, (SInt)0 ) == 0x10 );
> +  static_assert( std::shl((Int)0x10, (SInt)1 ) == 0x20 );
> +  static_assert( std::shl((Int)0x10, (SInt)2 ) == 0x40 );
> +  static_assert( std::shl((Int)0x10, (SInt)3 ) == (Int)0x80 );
> +  static_assert( std::shl((Int)0x11, (SInt)1 ) == 0x22 );
> +  static_assert( std::shl((Int)0x11, (SInt)2 ) == 0x44 );
> +  static_assert( std::shl((Int)0x11, (SInt)-2 )
> +                == ((SInt)-2 < 0 ? 4
> +                    : (SInt)-2 >= digits ? 0
> +                    : (Int)0x11 << ((SInt)-2 < 0 ? 0 : (SInt)-2)) );
> +
> +  if constexpr (std::numeric_limits<Int>::digits > 8)
> +    {
> +      static_assert( std::shl((Int)0b0011'0111, (SInt)3) == 0b1'1011'1000
> );
> +      static_assert( std::shl((Int)0b1010'0101, (SInt)4) ==
> 0b1010'0101'0000 );
> +    }
> +
> +  if constexpr (std::is_signed_v<SInt>)
> +    static_assert( test_negative_shifts<Int, SInt>() );
> +
> +  return true;
> +}
> +
> +static_assert( test( (unsigned char)0, (unsigned short)0 ) );
> +static_assert( test( (unsigned short)0, (unsigned int)0 ) );
> +static_assert( test( (unsigned int)0, (unsigned long)0 ) );
> +static_assert( test( (unsigned long)0, (unsigned long long)0 ) );
> +static_assert( test( (unsigned long long)0, (unsigned char)0 ) );
> +static_assert( test( (signed char)0, (unsigned int)0 ) );
> +static_assert( test( (signed short)0, (unsigned long)0 ) );
> +static_assert( test( (signed int)0, (unsigned long long)0 ) );
> +static_assert( test( (signed long)0, (unsigned char)0 ) );
> +static_assert( test( (signed long long)0, (unsigned short)0 ) );
> +static_assert( test( (unsigned char)0, (signed long long)0 ) );
> +static_assert( test( (unsigned short)0, (signed char)0 ) );
> +static_assert( test( (unsigned int)0, (signed short)0 ) );
> +static_assert( test( (unsigned long)0, (signed int)0 ) );
> +static_assert( test( (unsigned long long)0, (signed long)0 ) );
> +static_assert( test( (signed char)0, (signed char)0 ) );
> +static_assert( test( (signed short)0, (signed short)0 ) );
> +static_assert( test( (signed int)0, (signed int)0 ) );
> +static_assert( test( (signed long)0, (signed long)0 ) );
> +static_assert( test( (signed long long)0, (signed long long)0 ) );
> +
> +struct X { constexpr bool did_not_match() { return true; } };
> +constexpr X test(...) { return X{}; }
> +static_assert( test( (bool)0, 0 ).did_not_match() );
> +static_assert( test( (char)0, 0 ).did_not_match() );
> +static_assert( test( (char16_t)0, 0 ).did_not_match() );
> +static_assert( test( (float)0, 0 ).did_not_match() );
> +static_assert( test( (void*)0, 0 ).did_not_match() );
> +static_assert( test( X{}, 0 ).did_not_match() );
> +static_assert( test( 0U, (bool)0 ).did_not_match() );
> +static_assert( test( 0U, (char)0 ).did_not_match() );
> +static_assert( test( 0U, (char16_t)0 ).did_not_match() );
> +static_assert( test( 0, (float)0 ).did_not_match() );
> +static_assert( test( 0, (void*)0 ).did_not_match() );
> +static_assert( test( 0, X{} ).did_not_match() );
> +enum E : unsigned { e };
> +static_assert( test( e, 0 ).did_not_match() );
> +static_assert( test( 0U, e ).did_not_match() );
> +
> +#if !defined(__STRICT_ANSI__) && defined __SIZEOF_INT128__
> +static_assert( test( (unsigned __int128)0, (__int128)0 ) );
> +static_assert( test( (__int128)0, (unsigned __int128)0 ) );
> +static_assert( test( (unsigned __int128)0, 0U ) );
> +static_assert( test( (__int128)0, 0 ) );
> +#endif
> +#if defined(__GLIBCXX_TYPE_INT_N_0)
> +static_assert( test( (unsigned __GLIBCXX_TYPE_INT_N_0)0,
> (__GLIBCXX_TYPE_INT_N_0)0 ) );
> +static_assert( test( (__GLIBCXX_TYPE_INT_N_0)0, (unsigned
> __GLIBCXX_TYPE_INT_N_0)0 ) );
> +static_assert( test( (unsigned __GLIBCXX_TYPE_INT_N_0)0, 0U ) );
> +static_assert( test( (__GLIBCXX_TYPE_INT_N_0)0, 0 ) );
> +#endif
> +#if defined(__GLIBCXX_TYPE_INT_N_1)
> +static_assert( test( (unsigned __GLIBCXX_TYPE_INT_N_1)0,
> (__GLIBCXX_TYPE_INT_N_1)0 ) );
> +static_assert( test( (__GLIBCXX_TYPE_INT_N_1)0, (unsigned
> __GLIBCXX_TYPE_INT_N_1)0 ) );
> +static_assert( test( (unsigned __GLIBCXX_TYPE_INT_N_1)0, 0U ) );
> +static_assert( test( (__GLIBCXX_TYPE_INT_N_1)0, 0 ) );
> +#endif
> +#if defined(__GLIBCXX_TYPE_INT_N_2)
> +static_assert( test( (unsigned __GLIBCXX_TYPE_INT_N_2)0,
> (__GLIBCXX_TYPE_INT_N_2)0 ) );
> +static_assert( test( (__GLIBCXX_TYPE_INT_N_2)0, (unsigned
> __GLIBCXX_TYPE_INT_N_2)0 ) );
> +static_assert( test( (unsigned __GLIBCXX_TYPE_INT_N_2)0, 0U ) );
> +static_assert( test( (__GLIBCXX_TYPE_INT_N_2)0, 0 ) );
> +#endif
> +#if defined(__GLIBCXX_TYPE_INT_N_3)
> +static_assert( test( (unsigned __GLIBCXX_TYPE_INT_N_3)0,
> (__GLIBCXX_TYPE_INT_N_3)0 ) );
> +static_assert( test( (__GLIBCXX_TYPE_INT_N_3)0, (unsigned
> __GLIBCXX_TYPE_INT_N_3)0 ) );
> +static_assert( test( (unsigned __GLIBCXX_TYPE_INT_N_3)0, 0U ) );
> +static_assert( test( (__GLIBCXX_TYPE_INT_N_3)0, 0 ) );
> +#endif
> +
> +static_assert( std::shl(-1, 0x7fffffff00000001LL) == 0 );
> +static_assert( std::shl(2, 0x7fffffff00000001LL) == 0 );
> +static_assert( std::shl(-1, -0x7fffffff00000001LL) == -1 );
> +static_assert( std::shl(2, -0x7fffffff00000001LL) == 0 );
> +
> +#include <cstddef>
> +static_assert( test( (std::byte)0, 0 ).did_not_match() );
> +static_assert( test( 0, (std::byte)0 ).did_not_match() );
> --- a/libstdc++-v3/testsuite/26_numerics/bit/bit.shift/shr.cc   2026-08-31
> 15:57:52.031939621 +0200
> +++ b/libstdc++-v3/testsuite/26_numerics/bit/bit.shift/shr.cc   2026-09-01
> 09:09:28.880092022 +0200
> @@ -0,0 +1,159 @@
> +// { dg-do compile { target c++29 } }
> +
> +#include <bit>
> +#include <limits>
> +
> +template<typename Int, typename SInt>
> +constexpr bool
> +test_negative_shifts()
> +{
> +  constexpr unsigned digits = std::numeric_limits<Int>::digits
> +                             + std::is_signed_v<Int>;
> +
> +  Int xarr[] = { (Int)-1, 0, 1, 3, 6, 7, 0x10, 0x11, 0x22, 0x44,
> (Int)0x80,
> +                (Int)-55, (Int)-927 };
> +  SInt sarr[] = { 1, 4, 5, digits - 1, digits, (SInt)-12 };
> +  for (Int x : xarr)
> +    for (SInt s : sarr)
> +      if (std::shr(x, -s) != std::shl(x, s))
> +       return false;
> +  return true;
> +}
> +
> +template<typename Int, typename SInt>
> +constexpr auto
> +test(Int x, SInt y)
> +-> decltype(std::shr(x, y))
> +{
> +  static_assert( noexcept(std::shr(x, 0)) );
> +
> +  constexpr unsigned digits = std::numeric_limits<Int>::digits
> +                             + std::is_signed_v<Int>;
> +
> +  static_assert( std::shr((Int)0, (SInt)0) == 0 );
> +  static_assert( std::shr((Int)0, (SInt)1) == 0 );
> +  static_assert( std::shr((Int)0, (SInt)4) == 0 );
> +  static_assert( std::shr((Int)0, (SInt)8) == 0 );
> +  static_assert( std::shr((Int)0, (SInt)-4) == 0 );
> +  static_assert( std::shr((Int)-1, (SInt)0) == (Int)((Int)-1 >> 0) );
> +  static_assert( std::shr((Int)-1, (SInt)1) == (Int)((Int)-1 >> 1) );
> +  static_assert( std::shr((Int)-1, (SInt)4) == (Int)((Int)-1 >> 4) );
> +  static_assert( std::shr((Int)-1, (SInt)8) == (Int)((Int)-1 >> 8) );
> +  static_assert( std::shr((Int)-1, (SInt)-4)
> +                == ((SInt)-4 < 0 ? (Int)((Int)-1 << (SInt)4)
> +                    : (SInt)-4 >= digits ? ((Int)-1 < 0 ? (Int)-1 : 0)
> +                    : (Int)((Int)-1 >> ((SInt)-4 < 0 ? 0 : (SInt)-4))) );
> +
> +  static_assert( std::shr((Int)1, (SInt)0) == (Int)1 >> 0 );
> +  static_assert( std::shr((Int)1, (SInt)1) == (Int)1 >> 1 );
> +  static_assert( std::shr((Int)1, (SInt)4) == (Int)1 >> 4 );
> +  static_assert( std::shr((Int)1, (SInt)digits) == (Int)0 );
> +  static_assert( std::shr((Int)7, (SInt)digits) == (Int)0 );
> +  static_assert( std::shr((Int)6, (SInt)digits - 1) == (Int)0 );
> +  static_assert( std::shr((Int)3, (SInt)6) == (Int)((Int)3 >> 6) );
> +
> +  static_assert( std::shr((Int)0b0110'1100, (SInt)1) == (Int)0b0011'0110
> );
> +  static_assert( std::shr((Int)0b0110'1100, (SInt)digits - 1) == 0 );
> +
> +  static_assert( std::shr((Int)0x01, (SInt)0 ) == 0x01 );
> +  static_assert( std::shr((Int)0x10, (SInt)0 ) == 0x10 );
> +  static_assert( std::shr((Int)0x10, (SInt)1 ) == 0x08 );
> +  static_assert( std::shr((Int)0x10, (SInt)2 ) == 0x04 );
> +  static_assert( std::shr((Int)0x10, (SInt)3 ) == 0x02 );
> +  static_assert( std::shr((Int)0x22, (SInt)1 ) == 0x11 );
> +  static_assert( std::shr((Int)0x22, (SInt)2 ) == 0x08 );
> +  static_assert( std::shr((Int)0x11, (SInt)-2 )
> +                == ((SInt)-2 < 0 ? 0x44
> +                    : (SInt)-2 >= digits ? 0
> +                    : (Int)0x11 >> ((SInt)-2 < 0 ? 0 : (SInt)-2)) );
> +
> +  if constexpr (std::numeric_limits<Int>::digits > 8)
> +    {
> +      static_assert( std::shr((Int)0b1'1011'1000, (SInt)3) == 0b0011'0111
> );
> +      static_assert( std::shr((Int)0b1'1011'1000, (SInt)4) == 0b0001'1011
> );
> +    }
> +
> +  if constexpr (std::is_signed_v<SInt>)
> +    static_assert( test_negative_shifts<Int, SInt>() );
> +
> +  return true;
> +}
> +
> +static_assert( test( (unsigned char)0, (unsigned short)0 ) );
> +static_assert( test( (unsigned short)0, (unsigned int)0 ) );
> +static_assert( test( (unsigned int)0, (unsigned long)0 ) );
> +static_assert( test( (unsigned long)0, (unsigned long long)0 ) );
> +static_assert( test( (unsigned long long)0, (unsigned char)0 ) );
> +static_assert( test( (signed char)0, (unsigned int)0 ) );
> +static_assert( test( (signed short)0, (unsigned long)0 ) );
> +static_assert( test( (signed int)0, (unsigned long long)0 ) );
> +static_assert( test( (signed long)0, (unsigned char)0 ) );
> +static_assert( test( (signed long long)0, (unsigned short)0 ) );
> +static_assert( test( (unsigned char)0, (signed long long)0 ) );
> +static_assert( test( (unsigned short)0, (signed char)0 ) );
> +static_assert( test( (unsigned int)0, (signed short)0 ) );
> +static_assert( test( (unsigned long)0, (signed int)0 ) );
> +static_assert( test( (unsigned long long)0, (signed long)0 ) );
> +static_assert( test( (signed char)0, (signed char)0 ) );
> +static_assert( test( (signed short)0, (signed short)0 ) );
> +static_assert( test( (signed int)0, (signed int)0 ) );
> +static_assert( test( (signed long)0, (signed long)0 ) );
> +static_assert( test( (signed long long)0, (signed long long)0 ) );
> +
> +struct X { constexpr bool did_not_match() { return true; } };
> +constexpr X test(...) { return X{}; }
> +static_assert( test( (bool)0, 0 ).did_not_match() );
> +static_assert( test( (char)0, 0 ).did_not_match() );
> +static_assert( test( (char16_t)0, 0 ).did_not_match() );
> +static_assert( test( (float)0, 0 ).did_not_match() );
> +static_assert( test( (void*)0, 0 ).did_not_match() );
> +static_assert( test( X{}, 0 ).did_not_match() );
> +static_assert( test( 0U, (bool)0 ).did_not_match() );
> +static_assert( test( 0U, (char)0 ).did_not_match() );
> +static_assert( test( 0U, (char16_t)0 ).did_not_match() );
> +static_assert( test( 0, (float)0 ).did_not_match() );
> +static_assert( test( 0, (void*)0 ).did_not_match() );
> +static_assert( test( 0, X{} ).did_not_match() );
> +enum E : unsigned { e };
> +static_assert( test( e, 0 ).did_not_match() );
> +static_assert( test( 0U, e ).did_not_match() );
> +
> +#if !defined(__STRICT_ANSI__) && defined __SIZEOF_INT128__
> +static_assert( test( (unsigned __int128)0, (__int128)0 ) );
> +static_assert( test( (__int128)0, (unsigned __int128)0 ) );
> +static_assert( test( (unsigned __int128)0, 0U ) );
> +static_assert( test( (__int128)0, 0 ) );
> +#endif
> +#if defined(__GLIBCXX_TYPE_INT_N_0)
> +static_assert( test( (unsigned __GLIBCXX_TYPE_INT_N_0)0,
> (__GLIBCXX_TYPE_INT_N_0)0 ) );
> +static_assert( test( (__GLIBCXX_TYPE_INT_N_0)0, (unsigned
> __GLIBCXX_TYPE_INT_N_0)0 ) );
> +static_assert( test( (unsigned __GLIBCXX_TYPE_INT_N_0)0, 0U ) );
> +static_assert( test( (__GLIBCXX_TYPE_INT_N_0)0, 0 ) );
> +#endif
> +#if defined(__GLIBCXX_TYPE_INT_N_1)
> +static_assert( test( (unsigned __GLIBCXX_TYPE_INT_N_1)0,
> (__GLIBCXX_TYPE_INT_N_1)0 ) );
> +static_assert( test( (__GLIBCXX_TYPE_INT_N_1)0, (unsigned
> __GLIBCXX_TYPE_INT_N_1)0 ) );
> +static_assert( test( (unsigned __GLIBCXX_TYPE_INT_N_1)0, 0U ) );
> +static_assert( test( (__GLIBCXX_TYPE_INT_N_1)0, 0 ) );
> +#endif
> +#if defined(__GLIBCXX_TYPE_INT_N_2)
> +static_assert( test( (unsigned __GLIBCXX_TYPE_INT_N_2)0,
> (__GLIBCXX_TYPE_INT_N_2)0 ) );
> +static_assert( test( (__GLIBCXX_TYPE_INT_N_2)0, (unsigned
> __GLIBCXX_TYPE_INT_N_2)0 ) );
> +static_assert( test( (unsigned __GLIBCXX_TYPE_INT_N_2)0, 0U ) );
> +static_assert( test( (__GLIBCXX_TYPE_INT_N_2)0, 0 ) );
> +#endif
> +#if defined(__GLIBCXX_TYPE_INT_N_3)
> +static_assert( test( (unsigned __GLIBCXX_TYPE_INT_N_3)0,
> (__GLIBCXX_TYPE_INT_N_3)0 ) );
> +static_assert( test( (__GLIBCXX_TYPE_INT_N_3)0, (unsigned
> __GLIBCXX_TYPE_INT_N_3)0 ) );
> +static_assert( test( (unsigned __GLIBCXX_TYPE_INT_N_3)0, 0U ) );
> +static_assert( test( (__GLIBCXX_TYPE_INT_N_3)0, 0 ) );
> +#endif
> +
> +static_assert( std::shr(-1, 0x7fffffff00000001LL) == -1 );
> +static_assert( std::shr(2, 0x7fffffff00000001LL) == 0 );
> +static_assert( std::shr(-1, -0x7fffffff00000001LL) == 0 );
> +static_assert( std::shr(2, -0x7fffffff00000001LL) == 0 );
> +
> +#include <cstddef>
> +static_assert( test( (std::byte)0, 0 ).did_not_match() );
> +static_assert( test( 0, (std::byte)0 ).did_not_match() );
>
>         Jakub
>
>

Reply via email to