[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