[libcxx-commits] [libcxx] P3793R2 Better shifting (PR #219389)
via libcxx-commits
libcxx-commits at lists.llvm.org
Thu Aug 27 23:47:25 PDT 2026
github-actions[bot] wrote:
<!--LLVM CODE FORMAT COMMENT: {clang-format}-->
:warning: C/C++ code formatter, clang-format found issues in your code. :warning:
<details>
<summary>
You can test this locally with the following command:
</summary>
``````````bash
git-clang-format --diff origin/main HEAD --extensions cpp,,h -- libcxx/include/__bit/shift.h libcxx/test/std/numerics/bit/bitops.shift/shl.pass.cpp libcxx/test/std/numerics/bit/bitops.shift/shr.pass.cpp libcxx/include/bit libcxx/include/version libcxx/test/std/language.support/support.limits/support.limits.general/bit.version.compile.pass.cpp libcxx/test/std/language.support/support.limits/support.limits.general/version.version.compile.pass.cpp --diff_from_common_commit
``````````
:warning:
The reproduction instructions above might return results for more than one PR
in a stack if you are using a stacked PR workflow. You can limit the results by
changing `origin/main` to the base branch/commit you want to compare against.
:warning:
</details>
<details>
<summary>
View the diff from clang-format here.
</summary>
``````````diff
diff --git a/libcxx/test/std/numerics/bit/bitops.shift/shl.pass.cpp b/libcxx/test/std/numerics/bit/bitops.shift/shl.pass.cpp
index d63a54722..dfe296f92 100644
--- a/libcxx/test/std/numerics/bit/bitops.shift/shl.pass.cpp
+++ b/libcxx/test/std/numerics/bit/bitops.shift/shl.pass.cpp
@@ -23,91 +23,89 @@
#include "test_macros.h"
struct A {};
-enum E1 : unsigned char { rEd };
+enum E1 : unsigned char { rEd };
enum class E2 : unsigned char { red };
template <class T>
-constexpr bool test()
-{
- ASSERT_SAME_TYPE(decltype(std::shl(T(), 0)), T);
- ASSERT_NOEXCEPT(std::shl(T(), 0));
-
- using U = std::make_unsigned_t<T>;
- constexpr int width = std::numeric_limits<U>::digits;
-
- // shl(1, n) for n = 0..7 — basic left shifts
- assert(std::shl(T(1), 0) == T(1));
- assert(std::shl(T(1), 1) == T(2));
- assert(std::shl(T(1), 2) == T(4));
- assert(std::shl(T(1), 3) == T(8));
- assert(std::shl(T(1), 4) == T(16));
- assert(std::shl(T(1), 5) == T(32));
- assert(std::shl(T(1), 6) == T(64));
- assert(std::shl(T(1), 7) == T(128));
-
- // Overlong shifts return 0
- assert(std::shl(T(1), width) == T(0));
- assert(std::shl(T(1), width + 1) == T(0));
- assert(std::shl(T(1), width + 100) == T(0));
- assert(std::shl(T(1), std::numeric_limits<int>::max()) == T(0));
-
- // Test all-ones pattern shifted out
- if constexpr (std::is_signed_v<T>) {
- assert(std::shl(T(-1), width) == T(0));
- assert(std::shl(T(-1), width + 5) == T(0));
- } else {
- assert(std::shl(T(~T(0)), width) == T(0));
- assert(std::shl(T(~T(0)), width + 5) == T(0));
- }
-
- // Negative shift amounts shift right (bidirectional)
- U highbit_u = U(1) << (width - 1);
- T highbit = static_cast<T>(highbit_u);
- assert(std::shl(highbit, -1) == static_cast<T>(highbit_u >> 1));
- assert(std::shl(highbit, -2) == static_cast<T>(highbit_u >> 2));
- assert(std::shl(highbit, -3) == static_cast<T>(highbit_u >> 3));
- assert(std::shl(highbit, -4) == static_cast<T>(highbit_u >> 4));
- assert(std::shl(highbit, -5) == static_cast<T>(highbit_u >> 5));
- assert(std::shl(highbit, -6) == static_cast<T>(highbit_u >> 6));
- assert(std::shl(highbit, -7) == static_cast<T>(highbit_u >> 7));
- assert(std::shl(highbit, -(width - 1)) == T(1));
-
- // Negative overlong shifts: 0 for unsigned, sign-extended for signed
- if constexpr (std::is_signed_v<T>) {
- assert(std::shl(T(-1), -width) == T(-1));
- assert(std::shl(T(-1), -(width + 1)) == T(-1));
- assert(std::shl(T(-1), std::numeric_limits<int>::min()) == T(-1));
- assert(std::shl(T(42), -width) == T(0));
- assert(std::shl(T(42), -(width + 1)) == T(0));
- } else {
- assert(std::shl(T(~T(0)), -width) == T(0));
- assert(std::shl(T(~T(0)), -(width + 1)) == T(0));
- assert(std::shl(T(1), std::numeric_limits<int>::min()) == T(0));
- }
+constexpr bool test() {
+ ASSERT_SAME_TYPE(decltype(std::shl(T(), 0)), T);
+ ASSERT_NOEXCEPT(std::shl(T(), 0));
+
+ using U = std::make_unsigned_t<T>;
+ constexpr int width = std::numeric_limits<U>::digits;
+
+ // shl(1, n) for n = 0..7 — basic left shifts
+ assert(std::shl(T(1), 0) == T(1));
+ assert(std::shl(T(1), 1) == T(2));
+ assert(std::shl(T(1), 2) == T(4));
+ assert(std::shl(T(1), 3) == T(8));
+ assert(std::shl(T(1), 4) == T(16));
+ assert(std::shl(T(1), 5) == T(32));
+ assert(std::shl(T(1), 6) == T(64));
+ assert(std::shl(T(1), 7) == T(128));
+
+ // Overlong shifts return 0
+ assert(std::shl(T(1), width) == T(0));
+ assert(std::shl(T(1), width + 1) == T(0));
+ assert(std::shl(T(1), width + 100) == T(0));
+ assert(std::shl(T(1), std::numeric_limits<int>::max()) == T(0));
+
+ // Test all-ones pattern shifted out
+ if constexpr (std::is_signed_v<T>) {
+ assert(std::shl(T(-1), width) == T(0));
+ assert(std::shl(T(-1), width + 5) == T(0));
+ } else {
+ assert(std::shl(T(~T(0)), width) == T(0));
+ assert(std::shl(T(~T(0)), width + 5) == T(0));
+ }
+
+ // Negative shift amounts shift right (bidirectional)
+ U highbit_u = U(1) << (width - 1);
+ T highbit = static_cast<T>(highbit_u);
+ assert(std::shl(highbit, -1) == static_cast<T>(highbit_u >> 1));
+ assert(std::shl(highbit, -2) == static_cast<T>(highbit_u >> 2));
+ assert(std::shl(highbit, -3) == static_cast<T>(highbit_u >> 3));
+ assert(std::shl(highbit, -4) == static_cast<T>(highbit_u >> 4));
+ assert(std::shl(highbit, -5) == static_cast<T>(highbit_u >> 5));
+ assert(std::shl(highbit, -6) == static_cast<T>(highbit_u >> 6));
+ assert(std::shl(highbit, -7) == static_cast<T>(highbit_u >> 7));
+ assert(std::shl(highbit, -(width - 1)) == T(1));
+
+ // Negative overlong shifts: 0 for unsigned, sign-extended for signed
+ if constexpr (std::is_signed_v<T>) {
+ assert(std::shl(T(-1), -width) == T(-1));
+ assert(std::shl(T(-1), -(width + 1)) == T(-1));
+ assert(std::shl(T(-1), std::numeric_limits<int>::min()) == T(-1));
+ assert(std::shl(T(42), -width) == T(0));
+ assert(std::shl(T(42), -(width + 1)) == T(0));
+ } else {
+ assert(std::shl(T(~T(0)), -width) == T(0));
+ assert(std::shl(T(~T(0)), -(width + 1)) == T(0));
+ assert(std::shl(T(1), std::numeric_limits<int>::min()) == T(0));
+ }
#ifndef TEST_HAS_NO_INT128
- if constexpr (std::is_same_v<T, __uint128_t>) {
- assert(std::shl(T(1), 0) == T(1));
- assert(std::shl(T(1), 64) == T(1) << 64);
- assert(std::shl(T(1), 127) == T(1) << 127);
- assert(std::shl(T(1), 128) == T(0));
- assert(std::shl(T(1), 200) == T(0));
- assert(std::shl(T(1) << 127, -1) == T(1) << 126);
- assert(std::shl(T(1) << 127, -127) == T(1));
- assert(std::shl(T(1) << 127, -128) == T(0));
- assert(std::shl(T(1) << 127, -200) == T(0));
- }
+ if constexpr (std::is_same_v<T, __uint128_t>) {
+ assert(std::shl(T(1), 0) == T(1));
+ assert(std::shl(T(1), 64) == T(1) << 64);
+ assert(std::shl(T(1), 127) == T(1) << 127);
+ assert(std::shl(T(1), 128) == T(0));
+ assert(std::shl(T(1), 200) == T(0));
+ assert(std::shl(T(1) << 127, -1) == T(1) << 126);
+ assert(std::shl(T(1) << 127, -127) == T(1));
+ assert(std::shl(T(1) << 127, -128) == T(0));
+ assert(std::shl(T(1) << 127, -200) == T(0));
+ }
#endif
- return true;
+ return true;
}
-int main(int, char**)
-{
- {
+int main(int, char**) {
+ {
// Constraint: T must be a signed or unsigned integer type
auto lambda = [](auto x) -> decltype(std::shl(x, 1U)) {};
- using L = decltype(lambda);
+ using L = decltype(lambda);
// Signed integer types are accepted
static_assert(std::is_invocable_v<L, signed char>);
@@ -148,11 +146,11 @@ int main(int, char**)
static_assert(!std::is_invocable_v<L, A*>);
static_assert(!std::is_invocable_v<L, E1>);
static_assert(!std::is_invocable_v<L, E2>);
- }
- {
+ }
+ {
// Constraint: S must be a signed or unsigned integer type
auto lambda_s = [](auto s) -> decltype(std::shl(1, s)) {};
- using LS = decltype(lambda_s);
+ using LS = decltype(lambda_s);
static_assert(std::is_invocable_v<LS, signed char>);
static_assert(std::is_invocable_v<LS, short>);
@@ -179,129 +177,129 @@ int main(int, char**)
static_assert(!std::is_invocable_v<LS, A*>);
static_assert(!std::is_invocable_v<LS, E1>);
static_assert(!std::is_invocable_v<LS, E2>);
- }
+ }
- static_assert(test<unsigned char>());
- static_assert(test<unsigned short>());
- static_assert(test<unsigned int>());
- static_assert(test<unsigned long>());
- static_assert(test<unsigned long long>());
+ static_assert(test<unsigned char>());
+ static_assert(test<unsigned short>());
+ static_assert(test<unsigned int>());
+ static_assert(test<unsigned long>());
+ static_assert(test<unsigned long long>());
#ifndef TEST_HAS_NO_INT128
- static_assert(test<__uint128_t>());
+ static_assert(test<__uint128_t>());
#endif
- static_assert(test<signed char>());
- static_assert(test<short>());
- static_assert(test<int>());
- static_assert(test<long>());
- static_assert(test<long long>());
-
- static_assert(test<std::uint8_t>());
- static_assert(test<std::uint16_t>());
- static_assert(test<std::uint32_t>());
- static_assert(test<std::uint64_t>());
- static_assert(test<std::uintmax_t>());
- static_assert(test<std::uintptr_t>());
- static_assert(test<std::size_t>());
-
- static_assert(test<std::int8_t>());
- static_assert(test<std::int16_t>());
- static_assert(test<std::int32_t>());
- static_assert(test<std::int64_t>());
- static_assert(test<std::intmax_t>());
- static_assert(test<std::intptr_t>());
- static_assert(test<std::ptrdiff_t>());
-
- test<unsigned char>();
- test<unsigned short>();
- test<unsigned int>();
- test<unsigned long>();
- test<unsigned long long>();
+ static_assert(test<signed char>());
+ static_assert(test<short>());
+ static_assert(test<int>());
+ static_assert(test<long>());
+ static_assert(test<long long>());
+
+ static_assert(test<std::uint8_t>());
+ static_assert(test<std::uint16_t>());
+ static_assert(test<std::uint32_t>());
+ static_assert(test<std::uint64_t>());
+ static_assert(test<std::uintmax_t>());
+ static_assert(test<std::uintptr_t>());
+ static_assert(test<std::size_t>());
+
+ static_assert(test<std::int8_t>());
+ static_assert(test<std::int16_t>());
+ static_assert(test<std::int32_t>());
+ static_assert(test<std::int64_t>());
+ static_assert(test<std::intmax_t>());
+ static_assert(test<std::intptr_t>());
+ static_assert(test<std::ptrdiff_t>());
+
+ test<unsigned char>();
+ test<unsigned short>();
+ test<unsigned int>();
+ test<unsigned long>();
+ test<unsigned long long>();
#ifndef TEST_HAS_NO_INT128
- test<__uint128_t>();
+ test<__uint128_t>();
#endif
- test<signed char>();
- test<short>();
- test<int>();
- test<long>();
- test<long long>();
-
- test<std::uint8_t>();
- test<std::uint16_t>();
- test<std::uint32_t>();
- test<std::uint64_t>();
- test<std::uintmax_t>();
- test<std::uintptr_t>();
- test<std::size_t>();
-
- test<std::int8_t>();
- test<std::int16_t>();
- test<std::int32_t>();
- test<std::int64_t>();
- test<std::intmax_t>();
- test<std::intptr_t>();
- test<std::ptrdiff_t>();
+ test<signed char>();
+ test<short>();
+ test<int>();
+ test<long>();
+ test<long long>();
+
+ test<std::uint8_t>();
+ test<std::uint16_t>();
+ test<std::uint32_t>();
+ test<std::uint64_t>();
+ test<std::uintmax_t>();
+ test<std::uintptr_t>();
+ test<std::size_t>();
+
+ test<std::int8_t>();
+ test<std::int16_t>();
+ test<std::int32_t>();
+ test<std::int64_t>();
+ test<std::intmax_t>();
+ test<std::intptr_t>();
+ test<std::ptrdiff_t>();
#if TEST_HAS_EXTENSION(bit_int)
- {
- using T32 = unsigned _BitInt(32);
- using T64 = unsigned _BitInt(64);
-
- assert(std::shl(T32(1), 0) == T32(1));
- assert(std::shl(T32(1), 1) == T32(2));
- assert(std::shl(T32(1), 4) == T32(16));
- assert(std::shl(T32(1), 7) == T32(128));
- assert(std::shl(T32(1), 31) == T32(1) << 31);
- // Overlong shift returns 0
- assert(std::shl(T32(1), 32) == T32(0));
- assert(std::shl(T32(~T32(0)), 32) == T32(0));
- // Negative shift (bidirectional)
- assert(std::shl(T32(1) << 31, -1) == T32(1) << 30);
- assert(std::shl(T32(1) << 31, -31) == T32(1));
- assert(std::shl(T32(1) << 31, -32) == T32(0));
-
- assert(std::shl(T64(1), 0) == T64(1));
- assert(std::shl(T64(1), 4) == T64(16));
- assert(std::shl(T64(1), 63) == T64(1) << 63);
- assert(std::shl(T64(1), 64) == T64(0));
- assert(std::shl(T64(1) << 63, -1) == T64(1) << 62);
- assert(std::shl(T64(1) << 63, -63) == T64(1));
- assert(std::shl(T64(1) << 63, -64) == T64(0));
- }
+ {
+ using T32 = unsigned _BitInt(32);
+ using T64 = unsigned _BitInt(64);
+
+ assert(std::shl(T32(1), 0) == T32(1));
+ assert(std::shl(T32(1), 1) == T32(2));
+ assert(std::shl(T32(1), 4) == T32(16));
+ assert(std::shl(T32(1), 7) == T32(128));
+ assert(std::shl(T32(1), 31) == T32(1) << 31);
+ // Overlong shift returns 0
+ assert(std::shl(T32(1), 32) == T32(0));
+ assert(std::shl(T32(~T32(0)), 32) == T32(0));
+ // Negative shift (bidirectional)
+ assert(std::shl(T32(1) << 31, -1) == T32(1) << 30);
+ assert(std::shl(T32(1) << 31, -31) == T32(1));
+ assert(std::shl(T32(1) << 31, -32) == T32(0));
+
+ assert(std::shl(T64(1), 0) == T64(1));
+ assert(std::shl(T64(1), 4) == T64(16));
+ assert(std::shl(T64(1), 63) == T64(1) << 63);
+ assert(std::shl(T64(1), 64) == T64(0));
+ assert(std::shl(T64(1) << 63, -1) == T64(1) << 62);
+ assert(std::shl(T64(1) << 63, -63) == T64(1));
+ assert(std::shl(T64(1) << 63, -64) == T64(0));
+ }
# if __BITINT_MAXWIDTH__ >= 128
- {
- using T128 = unsigned _BitInt(128);
- assert(std::shl(T128(1), 0) == T128(1));
- assert(std::shl(T128(1), 4) == T128(16));
- assert(std::shl(T128(1), 63) == T128(1) << 63);
- assert(std::shl(T128(1), 64) == T128(1) << 64);
- assert(std::shl(T128(1), 127) == T128(1) << 127);
- // Overlong shifts return 0
- assert(std::shl(T128(1), 128) == T128(0));
- assert(std::shl(T128(1), 200) == T128(0));
- // Negative shift (bidirectional)
- assert(std::shl(T128(1) << 127, -1) == T128(1) << 126);
- assert(std::shl(T128(1) << 127, -127) == T128(1));
- assert(std::shl(T128(1) << 127, -128) == T128(0));
- }
+ {
+ using T128 = unsigned _BitInt(128);
+ assert(std::shl(T128(1), 0) == T128(1));
+ assert(std::shl(T128(1), 4) == T128(16));
+ assert(std::shl(T128(1), 63) == T128(1) << 63);
+ assert(std::shl(T128(1), 64) == T128(1) << 64);
+ assert(std::shl(T128(1), 127) == T128(1) << 127);
+ // Overlong shifts return 0
+ assert(std::shl(T128(1), 128) == T128(0));
+ assert(std::shl(T128(1), 200) == T128(0));
+ // Negative shift (bidirectional)
+ assert(std::shl(T128(1) << 127, -1) == T128(1) << 126);
+ assert(std::shl(T128(1) << 127, -127) == T128(1));
+ assert(std::shl(T128(1) << 127, -128) == T128(0));
+ }
# endif
# if __BITINT_MAXWIDTH__ >= 256
- {
- using T256 = unsigned _BitInt(256);
- assert(std::shl(T256(1), 0) == T256(1));
- assert(std::shl(T256(1), 4) == T256(16));
- assert(std::shl(T256(1), 200) == T256(1) << 200);
- // Overlong shift returns 0
- assert(std::shl(T256(1), 256) == T256(0));
- assert(std::shl(T256(1), 300) == T256(0));
- // Negative shift (bidirectional)
- assert(std::shl(T256(1) << 255, -1) == T256(1) << 254);
- assert(std::shl(T256(1) << 255, -255) == T256(1));
- assert(std::shl(T256(1) << 255, -256) == T256(0));
- }
+ {
+ using T256 = unsigned _BitInt(256);
+ assert(std::shl(T256(1), 0) == T256(1));
+ assert(std::shl(T256(1), 4) == T256(16));
+ assert(std::shl(T256(1), 200) == T256(1) << 200);
+ // Overlong shift returns 0
+ assert(std::shl(T256(1), 256) == T256(0));
+ assert(std::shl(T256(1), 300) == T256(0));
+ // Negative shift (bidirectional)
+ assert(std::shl(T256(1) << 255, -1) == T256(1) << 254);
+ assert(std::shl(T256(1) << 255, -255) == T256(1));
+ assert(std::shl(T256(1) << 255, -256) == T256(0));
+ }
# endif
#endif // TEST_HAS_EXTENSION(bit_int)
- return 0;
+ return 0;
}
diff --git a/libcxx/test/std/numerics/bit/bitops.shift/shr.pass.cpp b/libcxx/test/std/numerics/bit/bitops.shift/shr.pass.cpp
index 5848c96fa..3108e0127 100644
--- a/libcxx/test/std/numerics/bit/bitops.shift/shr.pass.cpp
+++ b/libcxx/test/std/numerics/bit/bitops.shift/shr.pass.cpp
@@ -23,90 +23,88 @@
#include "test_macros.h"
struct A {};
-enum E1 : unsigned char { rEd };
+enum E1 : unsigned char { rEd };
enum class E2 : unsigned char { red };
template <class T>
-constexpr bool test()
-{
- ASSERT_SAME_TYPE(decltype(std::shr(T(), 0)), T);
- ASSERT_NOEXCEPT(std::shr(T(), 0));
-
- using U = std::make_unsigned_t<T>;
- constexpr int width = std::numeric_limits<U>::digits;
- constexpr U highbit_u = U(1) << (width - 1);
-
- // shr with small shift amounts
- T highbit = static_cast<T>(highbit_u);
- assert(std::shr(highbit, 0) == highbit);
- assert(std::shr(highbit, 1) == static_cast<T>(highbit_u >> 1));
- assert(std::shr(highbit, 2) == static_cast<T>(highbit_u >> 2));
- assert(std::shr(highbit, 3) == static_cast<T>(highbit_u >> 3));
- assert(std::shr(highbit, 4) == static_cast<T>(highbit_u >> 4));
- assert(std::shr(highbit, 5) == static_cast<T>(highbit_u >> 5));
- assert(std::shr(highbit, 6) == static_cast<T>(highbit_u >> 6));
- assert(std::shr(highbit, 7) == static_cast<T>(highbit_u >> 7));
- assert(std::shr(highbit, width - 1) == T(1));
-
- // Overlong right shifts: 0 for unsigned, sign-extended for signed
- if constexpr (std::is_signed_v<T>) {
- assert(std::shr(T(-1), width) == T(-1));
- assert(std::shr(T(-1), width + 1) == T(-1));
- assert(std::shr(T(-1), std::numeric_limits<int>::max()) == T(-1));
- assert(std::shr(T(42), width) == T(0));
- assert(std::shr(T(42), width + 1) == T(0));
- } else {
- assert(std::shr(T(~T(0)), width) == T(0));
- assert(std::shr(T(~T(0)), width + 1) == T(0));
- assert(std::shr(T(~T(0)), std::numeric_limits<int>::max()) == T(0));
- }
-
- // Negative shift amounts shift left (bidirectional)
- assert(std::shr(T(1), -1) == static_cast<T>(U(1) << 1));
- assert(std::shr(T(1), -2) == static_cast<T>(U(1) << 2));
- assert(std::shr(T(1), -3) == static_cast<T>(U(1) << 3));
- assert(std::shr(T(1), -4) == static_cast<T>(U(1) << 4));
- assert(std::shr(T(1), -5) == static_cast<T>(U(1) << 5));
- assert(std::shr(T(1), -6) == static_cast<T>(U(1) << 6));
- assert(std::shr(T(1), -7) == static_cast<T>(U(1) << 7));
- assert(std::shr(T(1), -(width - 1)) == static_cast<T>(U(1) << (width - 1)));
-
- // Negative overlong shifts: always return 0
- if constexpr (std::is_signed_v<T>) {
- assert(std::shr(T(-1), -width) == T(0));
- assert(std::shr(T(-1), -(width + 1)) == T(0));
- assert(std::shr(T(-1), std::numeric_limits<int>::min()) == T(0));
- } else {
- assert(std::shr(T(~T(0)), -width) == T(0));
- assert(std::shr(T(~T(0)), -(width + 1)) == T(0));
- }
- assert(std::shr(T(1), std::numeric_limits<int>::min()) == T(0));
+constexpr bool test() {
+ ASSERT_SAME_TYPE(decltype(std::shr(T(), 0)), T);
+ ASSERT_NOEXCEPT(std::shr(T(), 0));
+
+ using U = std::make_unsigned_t<T>;
+ constexpr int width = std::numeric_limits<U>::digits;
+ constexpr U highbit_u = U(1) << (width - 1);
+
+ // shr with small shift amounts
+ T highbit = static_cast<T>(highbit_u);
+ assert(std::shr(highbit, 0) == highbit);
+ assert(std::shr(highbit, 1) == static_cast<T>(highbit_u >> 1));
+ assert(std::shr(highbit, 2) == static_cast<T>(highbit_u >> 2));
+ assert(std::shr(highbit, 3) == static_cast<T>(highbit_u >> 3));
+ assert(std::shr(highbit, 4) == static_cast<T>(highbit_u >> 4));
+ assert(std::shr(highbit, 5) == static_cast<T>(highbit_u >> 5));
+ assert(std::shr(highbit, 6) == static_cast<T>(highbit_u >> 6));
+ assert(std::shr(highbit, 7) == static_cast<T>(highbit_u >> 7));
+ assert(std::shr(highbit, width - 1) == T(1));
+
+ // Overlong right shifts: 0 for unsigned, sign-extended for signed
+ if constexpr (std::is_signed_v<T>) {
+ assert(std::shr(T(-1), width) == T(-1));
+ assert(std::shr(T(-1), width + 1) == T(-1));
+ assert(std::shr(T(-1), std::numeric_limits<int>::max()) == T(-1));
+ assert(std::shr(T(42), width) == T(0));
+ assert(std::shr(T(42), width + 1) == T(0));
+ } else {
+ assert(std::shr(T(~T(0)), width) == T(0));
+ assert(std::shr(T(~T(0)), width + 1) == T(0));
+ assert(std::shr(T(~T(0)), std::numeric_limits<int>::max()) == T(0));
+ }
+
+ // Negative shift amounts shift left (bidirectional)
+ assert(std::shr(T(1), -1) == static_cast<T>(U(1) << 1));
+ assert(std::shr(T(1), -2) == static_cast<T>(U(1) << 2));
+ assert(std::shr(T(1), -3) == static_cast<T>(U(1) << 3));
+ assert(std::shr(T(1), -4) == static_cast<T>(U(1) << 4));
+ assert(std::shr(T(1), -5) == static_cast<T>(U(1) << 5));
+ assert(std::shr(T(1), -6) == static_cast<T>(U(1) << 6));
+ assert(std::shr(T(1), -7) == static_cast<T>(U(1) << 7));
+ assert(std::shr(T(1), -(width - 1)) == static_cast<T>(U(1) << (width - 1)));
+
+ // Negative overlong shifts: always return 0
+ if constexpr (std::is_signed_v<T>) {
+ assert(std::shr(T(-1), -width) == T(0));
+ assert(std::shr(T(-1), -(width + 1)) == T(0));
+ assert(std::shr(T(-1), std::numeric_limits<int>::min()) == T(0));
+ } else {
+ assert(std::shr(T(~T(0)), -width) == T(0));
+ assert(std::shr(T(~T(0)), -(width + 1)) == T(0));
+ }
+ assert(std::shr(T(1), std::numeric_limits<int>::min()) == T(0));
#ifndef TEST_HAS_NO_INT128
- if constexpr (std::is_same_v<T, __uint128_t>) {
- assert(std::shr(T(1) << 127, 0) == T(1) << 127);
- assert(std::shr(T(1) << 127, 1) == T(1) << 126);
- assert(std::shr(T(1) << 127, 64) == T(1) << 63);
- assert(std::shr(T(1) << 127, 127) == T(1));
- assert(std::shr(T(1) << 127, 128) == T(0));
- assert(std::shr(T(1) << 127, 200) == T(0));
- assert(std::shr(T(1), -1) == T(2));
- assert(std::shr(T(1), -64) == T(1) << 64);
- assert(std::shr(T(1), -127) == T(1) << 127);
- assert(std::shr(T(1), -128) == T(0));
- assert(std::shr(T(1), -200) == T(0));
- }
+ if constexpr (std::is_same_v<T, __uint128_t>) {
+ assert(std::shr(T(1) << 127, 0) == T(1) << 127);
+ assert(std::shr(T(1) << 127, 1) == T(1) << 126);
+ assert(std::shr(T(1) << 127, 64) == T(1) << 63);
+ assert(std::shr(T(1) << 127, 127) == T(1));
+ assert(std::shr(T(1) << 127, 128) == T(0));
+ assert(std::shr(T(1) << 127, 200) == T(0));
+ assert(std::shr(T(1), -1) == T(2));
+ assert(std::shr(T(1), -64) == T(1) << 64);
+ assert(std::shr(T(1), -127) == T(1) << 127);
+ assert(std::shr(T(1), -128) == T(0));
+ assert(std::shr(T(1), -200) == T(0));
+ }
#endif
- return true;
+ return true;
}
-int main(int, char**)
-{
- {
+int main(int, char**) {
+ {
// Constraint: T must be a signed or unsigned integer type
auto lambda = [](auto x) -> decltype(std::shr(x, 1U)) {};
- using L = decltype(lambda);
+ using L = decltype(lambda);
// Signed integer types are accepted
static_assert(std::is_invocable_v<L, signed char>);
@@ -147,11 +145,11 @@ int main(int, char**)
static_assert(!std::is_invocable_v<L, A*>);
static_assert(!std::is_invocable_v<L, E1>);
static_assert(!std::is_invocable_v<L, E2>);
- }
- {
+ }
+ {
// Constraint: S must be a signed or unsigned integer type
auto lambda_s = [](auto s) -> decltype(std::shr(1u, s)) {};
- using LS = decltype(lambda_s);
+ using LS = decltype(lambda_s);
static_assert(std::is_invocable_v<LS, signed char>);
static_assert(std::is_invocable_v<LS, short>);
@@ -178,133 +176,133 @@ int main(int, char**)
static_assert(!std::is_invocable_v<LS, A*>);
static_assert(!std::is_invocable_v<LS, E1>);
static_assert(!std::is_invocable_v<LS, E2>);
- }
+ }
- static_assert(test<unsigned char>());
- static_assert(test<unsigned short>());
- static_assert(test<unsigned int>());
- static_assert(test<unsigned long>());
- static_assert(test<unsigned long long>());
+ static_assert(test<unsigned char>());
+ static_assert(test<unsigned short>());
+ static_assert(test<unsigned int>());
+ static_assert(test<unsigned long>());
+ static_assert(test<unsigned long long>());
#ifndef TEST_HAS_NO_INT128
- static_assert(test<__uint128_t>());
+ static_assert(test<__uint128_t>());
#endif
- static_assert(test<signed char>());
- static_assert(test<short>());
- static_assert(test<int>());
- static_assert(test<long>());
- static_assert(test<long long>());
-
- static_assert(test<std::uint8_t>());
- static_assert(test<std::uint16_t>());
- static_assert(test<std::uint32_t>());
- static_assert(test<std::uint64_t>());
- static_assert(test<std::uintmax_t>());
- static_assert(test<std::uintptr_t>());
- static_assert(test<std::size_t>());
-
- static_assert(test<std::int8_t>());
- static_assert(test<std::int16_t>());
- static_assert(test<std::int32_t>());
- static_assert(test<std::int64_t>());
- static_assert(test<std::intmax_t>());
- static_assert(test<std::intptr_t>());
- static_assert(test<std::ptrdiff_t>());
-
- test<unsigned char>();
- test<unsigned short>();
- test<unsigned int>();
- test<unsigned long>();
- test<unsigned long long>();
+ static_assert(test<signed char>());
+ static_assert(test<short>());
+ static_assert(test<int>());
+ static_assert(test<long>());
+ static_assert(test<long long>());
+
+ static_assert(test<std::uint8_t>());
+ static_assert(test<std::uint16_t>());
+ static_assert(test<std::uint32_t>());
+ static_assert(test<std::uint64_t>());
+ static_assert(test<std::uintmax_t>());
+ static_assert(test<std::uintptr_t>());
+ static_assert(test<std::size_t>());
+
+ static_assert(test<std::int8_t>());
+ static_assert(test<std::int16_t>());
+ static_assert(test<std::int32_t>());
+ static_assert(test<std::int64_t>());
+ static_assert(test<std::intmax_t>());
+ static_assert(test<std::intptr_t>());
+ static_assert(test<std::ptrdiff_t>());
+
+ test<unsigned char>();
+ test<unsigned short>();
+ test<unsigned int>();
+ test<unsigned long>();
+ test<unsigned long long>();
#ifndef TEST_HAS_NO_INT128
- test<__uint128_t>();
+ test<__uint128_t>();
#endif
- test<signed char>();
- test<short>();
- test<int>();
- test<long>();
- test<long long>();
-
- test<std::uint8_t>();
- test<std::uint16_t>();
- test<std::uint32_t>();
- test<std::uint64_t>();
- test<std::uintmax_t>();
- test<std::uintptr_t>();
- test<std::size_t>();
-
- test<std::int8_t>();
- test<std::int16_t>();
- test<std::int32_t>();
- test<std::int64_t>();
- test<std::intmax_t>();
- test<std::intptr_t>();
- test<std::ptrdiff_t>();
+ test<signed char>();
+ test<short>();
+ test<int>();
+ test<long>();
+ test<long long>();
+
+ test<std::uint8_t>();
+ test<std::uint16_t>();
+ test<std::uint32_t>();
+ test<std::uint64_t>();
+ test<std::uintmax_t>();
+ test<std::uintptr_t>();
+ test<std::size_t>();
+
+ test<std::int8_t>();
+ test<std::int16_t>();
+ test<std::int32_t>();
+ test<std::int64_t>();
+ test<std::intmax_t>();
+ test<std::intptr_t>();
+ test<std::ptrdiff_t>();
#if TEST_HAS_EXTENSION(bit_int)
- {
- using T32 = unsigned _BitInt(32);
- using T64 = unsigned _BitInt(64);
-
- assert(std::shr(T32(1) << 31, 0) == T32(1) << 31);
- assert(std::shr(T32(1) << 31, 1) == T32(1) << 30);
- assert(std::shr(T32(1) << 31, 4) == T32(1) << 27);
- assert(std::shr(T32(1) << 31, 7) == T32(1) << 24);
- assert(std::shr(T32(1) << 31, 31) == T32(1));
- // Overlong shift
- assert(std::shr(T32(1) << 31, 32) == T32(0));
- assert(std::shr(T32(~T32(0)), 32) == T32(0));
- // Negative shift (bidirectional)
- assert(std::shr(T32(1), -1) == T32(2));
- assert(std::shr(T32(1), -4) == T32(16));
- assert(std::shr(T32(1), -31) == T32(1) << 31);
- assert(std::shr(T32(1), -32) == T32(0));
-
- assert(std::shr(T64(1) << 63, 0) == T64(1) << 63);
- assert(std::shr(T64(1) << 63, 1) == T64(1) << 62);
- assert(std::shr(T64(1) << 63, 4) == T64(1) << 59);
- assert(std::shr(T64(1) << 63, 63) == T64(1));
- assert(std::shr(T64(1) << 63, 64) == T64(0));
- assert(std::shr(T64(1), -1) == T64(2));
- assert(std::shr(T64(1), -4) == T64(16));
- assert(std::shr(T64(1), -63) == T64(1) << 63);
- assert(std::shr(T64(1), -64) == T64(0));
- }
+ {
+ using T32 = unsigned _BitInt(32);
+ using T64 = unsigned _BitInt(64);
+
+ assert(std::shr(T32(1) << 31, 0) == T32(1) << 31);
+ assert(std::shr(T32(1) << 31, 1) == T32(1) << 30);
+ assert(std::shr(T32(1) << 31, 4) == T32(1) << 27);
+ assert(std::shr(T32(1) << 31, 7) == T32(1) << 24);
+ assert(std::shr(T32(1) << 31, 31) == T32(1));
+ // Overlong shift
+ assert(std::shr(T32(1) << 31, 32) == T32(0));
+ assert(std::shr(T32(~T32(0)), 32) == T32(0));
+ // Negative shift (bidirectional)
+ assert(std::shr(T32(1), -1) == T32(2));
+ assert(std::shr(T32(1), -4) == T32(16));
+ assert(std::shr(T32(1), -31) == T32(1) << 31);
+ assert(std::shr(T32(1), -32) == T32(0));
+
+ assert(std::shr(T64(1) << 63, 0) == T64(1) << 63);
+ assert(std::shr(T64(1) << 63, 1) == T64(1) << 62);
+ assert(std::shr(T64(1) << 63, 4) == T64(1) << 59);
+ assert(std::shr(T64(1) << 63, 63) == T64(1));
+ assert(std::shr(T64(1) << 63, 64) == T64(0));
+ assert(std::shr(T64(1), -1) == T64(2));
+ assert(std::shr(T64(1), -4) == T64(16));
+ assert(std::shr(T64(1), -63) == T64(1) << 63);
+ assert(std::shr(T64(1), -64) == T64(0));
+ }
# if __BITINT_MAXWIDTH__ >= 128
- {
- using T128 = unsigned _BitInt(128);
- assert(std::shr(T128(1) << 127, 0) == T128(1) << 127);
- assert(std::shr(T128(1) << 127, 1) == T128(1) << 126);
- assert(std::shr(T128(1) << 127, 64) == T128(1) << 63);
- assert(std::shr(T128(1) << 127, 127) == T128(1));
- // Overlong shifts return 0
- assert(std::shr(T128(1) << 127, 128) == T128(0));
- assert(std::shr(T128(1) << 127, 200) == T128(0));
- // Negative shift (bidirectional)
- assert(std::shr(T128(1), -1) == T128(2));
- assert(std::shr(T128(1), -64) == T128(1) << 64);
- assert(std::shr(T128(1), -127) == T128(1) << 127);
- assert(std::shr(T128(1), -128) == T128(0));
- }
+ {
+ using T128 = unsigned _BitInt(128);
+ assert(std::shr(T128(1) << 127, 0) == T128(1) << 127);
+ assert(std::shr(T128(1) << 127, 1) == T128(1) << 126);
+ assert(std::shr(T128(1) << 127, 64) == T128(1) << 63);
+ assert(std::shr(T128(1) << 127, 127) == T128(1));
+ // Overlong shifts return 0
+ assert(std::shr(T128(1) << 127, 128) == T128(0));
+ assert(std::shr(T128(1) << 127, 200) == T128(0));
+ // Negative shift (bidirectional)
+ assert(std::shr(T128(1), -1) == T128(2));
+ assert(std::shr(T128(1), -64) == T128(1) << 64);
+ assert(std::shr(T128(1), -127) == T128(1) << 127);
+ assert(std::shr(T128(1), -128) == T128(0));
+ }
# endif
# if __BITINT_MAXWIDTH__ >= 256
- {
- using T256 = unsigned _BitInt(256);
- assert(std::shr(T256(1) << 255, 0) == T256(1) << 255);
- assert(std::shr(T256(1) << 255, 1) == T256(1) << 254);
- assert(std::shr(T256(1) << 255, 200) == T256(1) << 55);
- // Overlong shifts return 0
- assert(std::shr(T256(1) << 255, 256) == T256(0));
- assert(std::shr(T256(1) << 255, 300) == T256(0));
- // Negative shift (bidirectional)
- assert(std::shr(T256(1), -1) == T256(2));
- assert(std::shr(T256(1), -200) == T256(1) << 200);
- assert(std::shr(T256(1), -255) == T256(1) << 255);
- assert(std::shr(T256(1), -256) == T256(0));
- }
+ {
+ using T256 = unsigned _BitInt(256);
+ assert(std::shr(T256(1) << 255, 0) == T256(1) << 255);
+ assert(std::shr(T256(1) << 255, 1) == T256(1) << 254);
+ assert(std::shr(T256(1) << 255, 200) == T256(1) << 55);
+ // Overlong shifts return 0
+ assert(std::shr(T256(1) << 255, 256) == T256(0));
+ assert(std::shr(T256(1) << 255, 300) == T256(0));
+ // Negative shift (bidirectional)
+ assert(std::shr(T256(1), -1) == T256(2));
+ assert(std::shr(T256(1), -200) == T256(1) << 200);
+ assert(std::shr(T256(1), -255) == T256(1) << 255);
+ assert(std::shr(T256(1), -256) == T256(0));
+ }
# endif
#endif // TEST_HAS_EXTENSION(bit_int)
- return 0;
+ return 0;
}
``````````
</details>
https://github.com/llvm/llvm-project/pull/219389
More information about the libcxx-commits
mailing list