[libcxx-commits] [libcxx] [libc++] Implement `<bit>` parts of P3793R2 Better shifting (PR #219389)
Jan Schultke via libcxx-commits
libcxx-commits at lists.llvm.org
Fri Aug 28 01:04:32 PDT 2026
================
@@ -0,0 +1,299 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20, c++23, c++26
+
+// template <class T, class S>
+// constexpr T shl(T x, S s) noexcept;
+
+// Constraints: Each of T and S is a signed or unsigned integer type.
+
+#include <bit>
+#include <cassert>
+#include <cstddef>
+#include <cstdint>
+#include <limits>
+#include <type_traits>
+
+#include "test_macros.h"
+
+struct A {};
+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;
+
+ 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>) {
----------------
eisenwave wrote:
Done.
https://github.com/llvm/llvm-project/pull/219389
More information about the libcxx-commits
mailing list