From: Jonathan Wakely Date: Mon, 22 Jul 2019 16:53:36 +0000 (+0100) Subject: Adjust std::rotl, std::rotr etc to match final P0553R4 proposal X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=f35da524a26d82cb1aa4a71ce48f92c64d506658;p=gcc.git Adjust std::rotl, std::rotr etc to match final P0553R4 proposal This proposal has now been accepted for C++20, with a few changes. This patch adjusts std::rotl and std::rotr to match the final specification and declares the additions for C++2a mode even when __STRICT_ANSI__ is defined. * include/std/bit (__rotl, __rotr): Change second parameter from unsigned int to int and handle negative values. (rotl, rotr): Remove check for __STRICT_ANSI__. Change second parameter from unsigned int to int. Add nodiscard attribute. * testsuite/26_numerics/bit/bitops.rot/rotl.cc: Rename to ... * testsuite/26_numerics/bit/bit.rotate/rotl.cc: Here. Test negative shifts. * testsuite/26_numerics/bit/bitops.rot/rotr.cc: Rename to ... * testsuite/26_numerics/bit/bit.rotate/rotr.cc: Here. Test negative shifts. From-SVN: r273706 --- diff --git a/libstdc++-v3/ChangeLog b/libstdc++-v3/ChangeLog index 4d163357f5a..6c6e41db802 100644 --- a/libstdc++-v3/ChangeLog +++ b/libstdc++-v3/ChangeLog @@ -1,5 +1,16 @@ 2019-07-22 Jonathan Wakely + * include/std/bit (__rotl, __rotr): Change second parameter from + unsigned int to int and handle negative values. + (rotl, rotr): Remove check for __STRICT_ANSI__. Change second + parameter from unsigned int to int. Add nodiscard attribute. + * testsuite/26_numerics/bit/bitops.rot/rotl.cc: Rename to ... + * testsuite/26_numerics/bit/bit.rotate/rotl.cc: Here. Test negative + shifts. + * testsuite/26_numerics/bit/bitops.rot/rotr.cc: Rename to ... + * testsuite/26_numerics/bit/bit.rotate/rotr.cc: Here. Test negative + shifts. + * include/std/bit (__ceil2): Make unrepresentable results undefined, as per P1355R2. Add debug assertion. Perform one left shift, not two, so that out of range values cause undefined behaviour. Ensure that diff --git a/libstdc++-v3/include/std/bit b/libstdc++-v3/include/std/bit index d019b1ee600..f17d2f1bd59 100644 --- a/libstdc++-v3/include/std/bit +++ b/libstdc++-v3/include/std/bit @@ -42,20 +42,30 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION template constexpr _Tp - __rotl(_Tp __x, unsigned int __s) noexcept + __rotl(_Tp __x, int __s) noexcept { constexpr auto _Nd = numeric_limits<_Tp>::digits; - const unsigned __sN = __s % _Nd; - return (__x << __sN) | (__x >> ((_Nd - __sN) % _Nd)); + const int __r = __s % _Nd; + if (__r == 0) + return __x; + else if (__r > 0) + return (__x << __r) | (__x >> ((_Nd - __r) % _Nd)); + else + return (__x >> -__r) | (__x << ((_Nd + __r) % _Nd)); // rotr(x, -r) } template constexpr _Tp - __rotr(_Tp __x, unsigned int __s) noexcept + __rotr(_Tp __x, int __s) noexcept { constexpr auto _Nd = numeric_limits<_Tp>::digits; - const unsigned __sN = __s % _Nd; - return (__x >> __sN) | (__x << ((_Nd - __sN) % _Nd)); + const int __r = __s % _Nd; + if (__r == 0) + return __x; + else if (__r > 0) + return (__x >> __r) | (__x << ((_Nd - __r) % _Nd)); + else + return (__x << -__r) | (__x >> ((_Nd + __r) % _Nd)); // rotl(x, -r) } template @@ -244,20 +254,19 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION using _If_is_unsigned_integer = enable_if_t<__is_unsigned_integer<_Tp>::value, _Up>; -#if ! __STRICT_ANSI__ - // [bitops.rot], rotating + // [bit.rot], rotating template - constexpr _If_is_unsigned_integer<_Tp> - rotl(_Tp __x, unsigned int __s) noexcept + [[nodiscard]] constexpr _If_is_unsigned_integer<_Tp> + rotl(_Tp __x, int __s) noexcept { return std::__rotl(__x, __s); } template - constexpr _If_is_unsigned_integer<_Tp> - rotr(_Tp __x, unsigned int __s) noexcept + [[nodiscard]] constexpr _If_is_unsigned_integer<_Tp> + rotr(_Tp __x, int __s) noexcept { return std::__rotr(__x, __s); } - // [bitops.count], counting + // [bit.count], counting template constexpr _If_is_unsigned_integer<_Tp, int> @@ -283,9 +292,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION constexpr _If_is_unsigned_integer<_Tp, int> popcount(_Tp __x) noexcept { return std::__popcount(__x); } -#endif - // Integral power-of-two operations + // [bit.pow.two], integral powers of 2 template constexpr _If_is_unsigned_integer<_Tp, bool> diff --git a/libstdc++-v3/testsuite/26_numerics/bit/bit.rotate/rotl.cc b/libstdc++-v3/testsuite/26_numerics/bit/bit.rotate/rotl.cc new file mode 100644 index 00000000000..dfceca071ae --- /dev/null +++ b/libstdc++-v3/testsuite/26_numerics/bit/bit.rotate/rotl.cc @@ -0,0 +1,124 @@ +// Copyright (C) 2018-2019 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License along +// with this library; see the file COPYING3. If not see +// . + +// { dg-options "-std=gnu++2a" } +// { dg-do compile { target c++2a } } + +#include + +template +constexpr bool +test_negative_shifts() +{ + constexpr unsigned digits = std::numeric_limits::digits; + + UInt xarr[] = { (UInt)-1, 0, 1, 3, 6, 7, 0x10, 0x11, 0x22, 0x44, 0x80 }; + int sarr[] = { 1, 4, 5, digits - 1, digits }; + for (UInt x : xarr) + for (int s : sarr) + if (std::rotl(x, -s) != std::rotr(x, s)) + return false; + return true; +} + +template +constexpr auto +test(UInt x) +-> decltype(std::rotl(x, 0)) +{ + static_assert( noexcept(std::rotl(x, 0)) ); + + constexpr unsigned digits = std::numeric_limits::digits; + + static_assert( std::rotl((UInt)0, 0) == 0 ); + static_assert( std::rotl((UInt)0, 1) == 0 ); + static_assert( std::rotl((UInt)0, 4) == 0 ); + static_assert( std::rotl((UInt)0, 8) == 0 ); + static_assert( std::rotl((UInt)-1, 0) == (UInt)-1 ); + static_assert( std::rotl((UInt)-1, 1) == (UInt)-1 ); + static_assert( std::rotl((UInt)-1, 4) == (UInt)-1 ); + static_assert( std::rotl((UInt)-1, 8) == (UInt)-1 ); + + static_assert( std::rotl((UInt)1, 0) == (UInt)1 << 0 ); + static_assert( std::rotl((UInt)1, 1) == (UInt)1 << 1 ); + static_assert( std::rotl((UInt)1, 4) == (UInt)1 << 4 ); + static_assert( std::rotl((UInt)1, digits) == (UInt)1 ); + static_assert( std::rotl((UInt)7, digits) == (UInt)7 ); + static_assert( std::rotl((UInt)6, digits - 1) == (UInt)3 ); + static_assert( std::rotl((UInt)3, 6) == (UInt)3 << 6 ); + + static_assert( std::rotl((UInt)0b0110'1100, 1) == 0b1101'1000 ); + static_assert( std::rotl((UInt)0b0110'1100, digits - 1) == 0b0011'0110 ); + + static_assert( std::rotl((UInt)0x01, 0 ) == 0x01 ); + static_assert( std::rotl((UInt)0x10, 0 ) == 0x10 ); + static_assert( std::rotl((UInt)0x10, 1 ) == 0x20 ); + static_assert( std::rotl((UInt)0x10, 2 ) == 0x40 ); + static_assert( std::rotl((UInt)0x10, 3 ) == 0x80 ); + static_assert( std::rotl((UInt)0x11, 1 ) == 0x22 ); + static_assert( std::rotl((UInt)0x11, 2 ) == 0x44 ); + + if constexpr (std::numeric_limits::digits > 8) + { + static_assert( std::rotl((UInt)0b0011'0111, 3) == 0b1'1011'1000 ); + static_assert( std::rotl((UInt)0b1010'0101, 4) == 0b1010'0101'0000 ); + } + + static_assert( test_negative_shifts() ); + + return true; +} + +static_assert( test( (unsigned char)0 ) ); +static_assert( test( (unsigned short)0 ) ); +static_assert( test( (unsigned int)0 ) ); +static_assert( test( (unsigned long)0 ) ); +static_assert( test( (unsigned long long)0 ) ); + +// std::rotl(T) shall not participate in overload resolution +// unless T is an unsigned integer type. +struct X { constexpr bool did_not_match() { return true; } }; +constexpr X test(...) { return X{}; } +static_assert( test( (bool)0 ).did_not_match() ); +static_assert( test( (char)0 ).did_not_match() ); +static_assert( test( (int)0 ).did_not_match() ); +static_assert( test( (char16_t)0 ).did_not_match() ); +static_assert( test( (float)0 ).did_not_match() ); +static_assert( test( (void*)0 ).did_not_match() ); +static_assert( test( X{} ).did_not_match() ); +enum E : unsigned { e }; +static_assert( test( e ).did_not_match() ); + +#if !defined(__STRICT_ANSI__) && defined _GLIBCXX_USE_INT128 +static_assert( test( (unsigned __int128)0 ) ); +static_assert( test( (__int128)0 ).did_not_match() ); +#endif +#if defined(__GLIBCXX_TYPE_INT_N_0) +static_assert( test( (unsigned __GLIBCXX_TYPE_INT_N_0)0 ) ); +static_assert( test( (__GLIBCXX_TYPE_INT_N_0)0 ).did_not_match() ); +#endif +#if defined(__GLIBCXX_TYPE_INT_N_1) +static_assert( test( (unsigned __GLIBCXX_TYPE_INT_N_1)0 ) ); +static_assert( test( (__GLIBCXX_TYPE_INT_N_1)0 ).did_not_match() ); +#endif +#if defined(__GLIBCXX_TYPE_INT_N_2) +static_assert( test( (unsigned __GLIBCXX_TYPE_INT_N_2)0 ) ); +static_assert( test( (__GLIBCXX_TYPE_INT_N_2)0 ).did_not_match() ); +#endif + +#include +static_assert( test( (std::byte)0 ).did_not_match() ); diff --git a/libstdc++-v3/testsuite/26_numerics/bit/bit.rotate/rotr.cc b/libstdc++-v3/testsuite/26_numerics/bit/bit.rotate/rotr.cc new file mode 100644 index 00000000000..f3bb94b1ef4 --- /dev/null +++ b/libstdc++-v3/testsuite/26_numerics/bit/bit.rotate/rotr.cc @@ -0,0 +1,126 @@ +// Copyright (C) 2018-2019 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License along +// with this library; see the file COPYING3. If not see +// . + +// { dg-options "-std=gnu++2a" } +// { dg-do compile { target c++2a } } + +#include + +template +constexpr bool +test_negative_shifts() +{ + constexpr unsigned digits = std::numeric_limits::digits; + + UInt xarr[] = { (UInt)-1, 0, 1, 3, 6, 7, 0x10, 0x11, 0x22, 0x44, 0x80 }; + int sarr[] = { 1, 4, 5, digits - 1, digits }; + for (UInt x : xarr) + for (int s : sarr) + if (std::rotr(x, -s) != std::rotl(x, s)) + return false; + return true; +} + +template +constexpr auto +test(UInt x) +-> decltype(std::rotr(x, 0)) +{ + static_assert( noexcept(std::rotr(x, 0)) ); + + constexpr unsigned digits = std::numeric_limits::digits; + + static_assert( std::rotr((UInt)0, 0) == 0 ); + static_assert( std::rotr((UInt)0, 1) == 0 ); + static_assert( std::rotr((UInt)0, 4) == 0 ); + static_assert( std::rotr((UInt)0, 8) == 0 ); + static_assert( std::rotr((UInt)-1, 0) == (UInt)-1 ); + static_assert( std::rotr((UInt)-1, 1) == (UInt)-1 ); + static_assert( std::rotr((UInt)-1, 4) == (UInt)-1 ); + static_assert( std::rotr((UInt)-1, 8) == (UInt)-1 ); + + static_assert( std::rotr((UInt)128, 0) == (UInt)128 >> 0 ); + static_assert( std::rotr((UInt)128, 1) == (UInt)128 >> 1 ); + static_assert( std::rotr((UInt)128, 4) == (UInt)128 >> 4 ); + static_assert( std::rotr((UInt)1, digits) == (UInt)1 ); + static_assert( std::rotr((UInt)7, digits) == (UInt)7 ); + static_assert( std::rotr((UInt)6, digits - 1) == (UInt)12 ); + static_assert( std::rotr((UInt)36, digits - 2) == (UInt)144 ); + + static_assert( std::rotr((UInt)0b0110'1100, 1) == 0b0011'0110 ); + static_assert( std::rotr((UInt)0b0110'1100, digits - 1) == 0b1101'1000 ); + + static_assert( std::rotr((UInt)0x01, 0 ) == 0x01 ); + static_assert( std::rotr((UInt)0x10, 0 ) == 0x10 ); + static_assert( std::rotr((UInt)0x10, 1 ) == 0x08 ); + static_assert( std::rotr((UInt)0x10, 2 ) == 0x04 ); + static_assert( std::rotr((UInt)0x10, 3 ) == 0x02 ); + static_assert( std::rotr((UInt)0x11, digits - 1 ) == 0x22 ); + static_assert( std::rotr((UInt)0x11, digits - 2 ) == 0x44 ); + + if constexpr (std::numeric_limits::digits > 8) + { + static_assert( std::rotr((UInt)0b0011'0111, 3) + == (0b0110 | ((UInt)0b0111 << digits - 3)) ); + static_assert( std::rotr((UInt)0b1010'0101, 4) + == (0b1010 | ((UInt)0b0101 << digits - 4)) ); + } + + static_assert( test_negative_shifts() ); + + return true; +} + +static_assert( test( (unsigned char)0 ) ); +static_assert( test( (unsigned short)0 ) ); +static_assert( test( (unsigned int)0 ) ); +static_assert( test( (unsigned long)0 ) ); +static_assert( test( (unsigned long long)0 ) ); + +// std::rotr(T) shall not participate in overload resolution +// unless T is an unsigned integer type. +struct X { constexpr bool did_not_match() { return true; } }; +constexpr X test(...) { return X{}; } +static_assert( test( (bool)0 ).did_not_match() ); +static_assert( test( (char)0 ).did_not_match() ); +static_assert( test( (int)0 ).did_not_match() ); +static_assert( test( (char16_t)0 ).did_not_match() ); +static_assert( test( (float)0 ).did_not_match() ); +static_assert( test( (void*)0 ).did_not_match() ); +static_assert( test( X{} ).did_not_match() ); +enum E : unsigned { e }; +static_assert( test( e ).did_not_match() ); + +#if !defined(__STRICT_ANSI__) && defined _GLIBCXX_USE_INT128 +static_assert( test( (unsigned __int128)0 ) ); +static_assert( test( (__int128)0 ).did_not_match() ); +#endif +#if defined(__GLIBCXX_TYPE_INT_N_0) +static_assert( test( (unsigned __GLIBCXX_TYPE_INT_N_0)0 ) ); +static_assert( test( (__GLIBCXX_TYPE_INT_N_0)0 ).did_not_match() ); +#endif +#if defined(__GLIBCXX_TYPE_INT_N_1) +static_assert( test( (unsigned __GLIBCXX_TYPE_INT_N_1)0 ) ); +static_assert( test( (__GLIBCXX_TYPE_INT_N_1)0 ).did_not_match() ); +#endif +#if defined(__GLIBCXX_TYPE_INT_N_2) +static_assert( test( (unsigned __GLIBCXX_TYPE_INT_N_2)0 ) ); +static_assert( test( (__GLIBCXX_TYPE_INT_N_2)0 ).did_not_match() ); +#endif + +#include +static_assert( test( (std::byte)0 ).did_not_match() ); diff --git a/libstdc++-v3/testsuite/26_numerics/bit/bitops.rot/rotl.cc b/libstdc++-v3/testsuite/26_numerics/bit/bitops.rot/rotl.cc deleted file mode 100644 index 2d97ae8c465..00000000000 --- a/libstdc++-v3/testsuite/26_numerics/bit/bitops.rot/rotl.cc +++ /dev/null @@ -1,107 +0,0 @@ -// Copyright (C) 2018-2019 Free Software Foundation, Inc. -// -// This file is part of the GNU ISO C++ Library. This library is free -// software; you can redistribute it and/or modify it under the -// terms of the GNU General Public License as published by the -// Free Software Foundation; either version 3, or (at your option) -// any later version. - -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License along -// with this library; see the file COPYING3. If not see -// . - -// { dg-options "-std=gnu++2a" } -// { dg-do compile { target c++2a } } - -#include - -template -constexpr auto -test(UInt x) --> decltype(std::rotl(x, 0u)) -{ - static_assert( noexcept(std::rotl(x, 0u)) ); - - constexpr unsigned digits = std::numeric_limits::digits; - - static_assert( std::rotl((UInt)0, 0) == 0 ); - static_assert( std::rotl((UInt)0, 1) == 0 ); - static_assert( std::rotl((UInt)0, 4) == 0 ); - static_assert( std::rotl((UInt)0, 8) == 0 ); - static_assert( std::rotl((UInt)-1, 0) == (UInt)-1 ); - static_assert( std::rotl((UInt)-1, 1) == (UInt)-1 ); - static_assert( std::rotl((UInt)-1, 4) == (UInt)-1 ); - static_assert( std::rotl((UInt)-1, 8) == (UInt)-1 ); - - static_assert( std::rotl((UInt)1, 0) == (UInt)1 << 0 ); - static_assert( std::rotl((UInt)1, 1) == (UInt)1 << 1 ); - static_assert( std::rotl((UInt)1, 4) == (UInt)1 << 4 ); - static_assert( std::rotl((UInt)1, digits) == (UInt)1 ); - static_assert( std::rotl((UInt)7, digits) == (UInt)7 ); - static_assert( std::rotl((UInt)6, digits - 1) == (UInt)3 ); - static_assert( std::rotl((UInt)3, 6) == (UInt)3 << 6 ); - - static_assert( std::rotl((UInt)0b0110'1100, 1) == 0b1101'1000 ); - static_assert( std::rotl((UInt)0b0110'1100, digits - 1) == 0b0011'0110 ); - - static_assert( std::rotl((UInt)0x01, 0 ) == 0x01 ); - static_assert( std::rotl((UInt)0x10, 0 ) == 0x10 ); - static_assert( std::rotl((UInt)0x10, 1 ) == 0x20 ); - static_assert( std::rotl((UInt)0x10, 2 ) == 0x40 ); - static_assert( std::rotl((UInt)0x10, 3 ) == 0x80 ); - static_assert( std::rotl((UInt)0x11, 1 ) == 0x22 ); - static_assert( std::rotl((UInt)0x11, 2 ) == 0x44 ); - - if constexpr (std::numeric_limits::digits > 8) - { - static_assert( std::rotl((UInt)0b0011'0111, 3) == 0b1'1011'1000 ); - static_assert( std::rotl((UInt)0b1010'0101, 4) == 0b1010'0101'0000 ); - } - - return true; -} - -static_assert( test( (unsigned char)0 ) ); -static_assert( test( (unsigned short)0 ) ); -static_assert( test( (unsigned int)0 ) ); -static_assert( test( (unsigned long)0 ) ); -static_assert( test( (unsigned long long)0 ) ); - -// std::rotl(T) shall not participate in overload resolution -// unless T is an unsigned integer type. -struct X { constexpr bool did_not_match() { return true; } }; -constexpr X test(...) { return X{}; } -static_assert( test( (bool)0 ).did_not_match() ); -static_assert( test( (char)0 ).did_not_match() ); -static_assert( test( (int)0 ).did_not_match() ); -static_assert( test( (char16_t)0 ).did_not_match() ); -static_assert( test( (float)0 ).did_not_match() ); -static_assert( test( (void*)0 ).did_not_match() ); -static_assert( test( X{} ).did_not_match() ); -enum E : unsigned { e }; -static_assert( test( e ).did_not_match() ); - -#if !defined(__STRICT_ANSI__) && defined _GLIBCXX_USE_INT128 -static_assert( test( (unsigned __int128)0 ) ); -static_assert( test( (__int128)0 ).did_not_match() ); -#endif -#if defined(__GLIBCXX_TYPE_INT_N_0) -static_assert( test( (unsigned __GLIBCXX_TYPE_INT_N_0)0 ) ); -static_assert( test( (__GLIBCXX_TYPE_INT_N_0)0 ).did_not_match() ); -#endif -#if defined(__GLIBCXX_TYPE_INT_N_1) -static_assert( test( (unsigned __GLIBCXX_TYPE_INT_N_1)0 ) ); -static_assert( test( (__GLIBCXX_TYPE_INT_N_1)0 ).did_not_match() ); -#endif -#if defined(__GLIBCXX_TYPE_INT_N_2) -static_assert( test( (unsigned __GLIBCXX_TYPE_INT_N_2)0 ) ); -static_assert( test( (__GLIBCXX_TYPE_INT_N_2)0 ).did_not_match() ); -#endif - -#include -static_assert( test( (std::byte)0 ).did_not_match() ); diff --git a/libstdc++-v3/testsuite/26_numerics/bit/bitops.rot/rotr.cc b/libstdc++-v3/testsuite/26_numerics/bit/bitops.rot/rotr.cc deleted file mode 100644 index c41c24d816a..00000000000 --- a/libstdc++-v3/testsuite/26_numerics/bit/bitops.rot/rotr.cc +++ /dev/null @@ -1,109 +0,0 @@ -// Copyright (C) 2018-2019 Free Software Foundation, Inc. -// -// This file is part of the GNU ISO C++ Library. This library is free -// software; you can redistribute it and/or modify it under the -// terms of the GNU General Public License as published by the -// Free Software Foundation; either version 3, or (at your option) -// any later version. - -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License along -// with this library; see the file COPYING3. If not see -// . - -// { dg-options "-std=gnu++2a" } -// { dg-do compile { target c++2a } } - -#include - -template -constexpr auto -test(UInt x) --> decltype(std::rotr(x, 0u)) -{ - static_assert( noexcept(std::rotr(x, 0u)) ); - - constexpr unsigned digits = std::numeric_limits::digits; - - static_assert( std::rotr((UInt)0, 0) == 0 ); - static_assert( std::rotr((UInt)0, 1) == 0 ); - static_assert( std::rotr((UInt)0, 4) == 0 ); - static_assert( std::rotr((UInt)0, 8) == 0 ); - static_assert( std::rotr((UInt)-1, 0) == (UInt)-1 ); - static_assert( std::rotr((UInt)-1, 1) == (UInt)-1 ); - static_assert( std::rotr((UInt)-1, 4) == (UInt)-1 ); - static_assert( std::rotr((UInt)-1, 8) == (UInt)-1 ); - - static_assert( std::rotr((UInt)128, 0) == (UInt)128 >> 0 ); - static_assert( std::rotr((UInt)128, 1) == (UInt)128 >> 1 ); - static_assert( std::rotr((UInt)128, 4) == (UInt)128 >> 4 ); - static_assert( std::rotr((UInt)1, digits) == (UInt)1 ); - static_assert( std::rotr((UInt)7, digits) == (UInt)7 ); - static_assert( std::rotr((UInt)6, digits - 1) == (UInt)12 ); - static_assert( std::rotr((UInt)36, digits - 2) == (UInt)144 ); - - static_assert( std::rotr((UInt)0b0110'1100, 1) == 0b0011'0110 ); - static_assert( std::rotr((UInt)0b0110'1100, digits - 1) == 0b1101'1000 ); - - static_assert( std::rotr((UInt)0x01, 0 ) == 0x01 ); - static_assert( std::rotr((UInt)0x10, 0 ) == 0x10 ); - static_assert( std::rotr((UInt)0x10, 1 ) == 0x08 ); - static_assert( std::rotr((UInt)0x10, 2 ) == 0x04 ); - static_assert( std::rotr((UInt)0x10, 3 ) == 0x02 ); - static_assert( std::rotr((UInt)0x11, digits - 1 ) == 0x22 ); - static_assert( std::rotr((UInt)0x11, digits - 2 ) == 0x44 ); - - if constexpr (std::numeric_limits::digits > 8) - { - static_assert( std::rotr((UInt)0b0011'0111, 3) - == (0b0110 | ((UInt)0b0111 << digits - 3)) ); - static_assert( std::rotr((UInt)0b1010'0101, 4) - == (0b1010 | ((UInt)0b0101 << digits - 4)) ); - } - - return true; -} - -static_assert( test( (unsigned char)0 ) ); -static_assert( test( (unsigned short)0 ) ); -static_assert( test( (unsigned int)0 ) ); -static_assert( test( (unsigned long)0 ) ); -static_assert( test( (unsigned long long)0 ) ); - -// std::rotr(T) shall not participate in overload resolution -// unless T is an unsigned integer type. -struct X { constexpr bool did_not_match() { return true; } }; -constexpr X test(...) { return X{}; } -static_assert( test( (bool)0 ).did_not_match() ); -static_assert( test( (char)0 ).did_not_match() ); -static_assert( test( (int)0 ).did_not_match() ); -static_assert( test( (char16_t)0 ).did_not_match() ); -static_assert( test( (float)0 ).did_not_match() ); -static_assert( test( (void*)0 ).did_not_match() ); -static_assert( test( X{} ).did_not_match() ); -enum E : unsigned { e }; -static_assert( test( e ).did_not_match() ); - -#if !defined(__STRICT_ANSI__) && defined _GLIBCXX_USE_INT128 -static_assert( test( (unsigned __int128)0 ) ); -static_assert( test( (__int128)0 ).did_not_match() ); -#endif -#if defined(__GLIBCXX_TYPE_INT_N_0) -static_assert( test( (unsigned __GLIBCXX_TYPE_INT_N_0)0 ) ); -static_assert( test( (__GLIBCXX_TYPE_INT_N_0)0 ).did_not_match() ); -#endif -#if defined(__GLIBCXX_TYPE_INT_N_1) -static_assert( test( (unsigned __GLIBCXX_TYPE_INT_N_1)0 ) ); -static_assert( test( (__GLIBCXX_TYPE_INT_N_1)0 ).did_not_match() ); -#endif -#if defined(__GLIBCXX_TYPE_INT_N_2) -static_assert( test( (unsigned __GLIBCXX_TYPE_INT_N_2)0 ) ); -static_assert( test( (__GLIBCXX_TYPE_INT_N_2)0 ).did_not_match() ); -#endif - -#include -static_assert( test( (std::byte)0 ).did_not_match() );