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 > >
