[libcxx-commits] [libcxx] [libc++] Refactor __next_prime to be const (PR #157421)

Nikolas Klauser via libcxx-commits libcxx-commits at lists.llvm.org
Mon Sep 8 19:49:41 PDT 2025


https://github.com/philnik777 updated https://github.com/llvm/llvm-project/pull/157421

>From 96e46b97ef623872945ef693a783f86c0cc0f8ec Mon Sep 17 00:00:00 2001
From: Nikolas Klauser <nikolasklauser at berlin.de>
Date: Mon, 8 Sep 2025 12:39:18 +0200
Subject: [PATCH] [libc++] Refactor __next_prime to be const

---
 libcxx/include/__configuration/availability.h | 11 ++++++++
 libcxx/include/__hash_table                   | 28 +++++++++++++++++--
 libcxx/src/hash.cpp                           | 14 ++--------
 3 files changed, 39 insertions(+), 14 deletions(-)

diff --git a/libcxx/include/__configuration/availability.h b/libcxx/include/__configuration/availability.h
index 2fbc34a3cf8a2..e3903b610a3ec 100644
--- a/libcxx/include/__configuration/availability.h
+++ b/libcxx/include/__configuration/availability.h
@@ -84,6 +84,9 @@
 // in all versions of the library are available.
 #if !_LIBCPP_HAS_VENDOR_AVAILABILITY_ANNOTATIONS
 
+#  define _LIBCPP_INTRODUCED_IN_LLVM_22 1
+#  define _LIBCPP_INTRODUCED_IN_LLVM_22_ATTRIBUTE /* nothing */
+
 #  define _LIBCPP_INTRODUCED_IN_LLVM_21 1
 #  define _LIBCPP_INTRODUCED_IN_LLVM_21_ATTRIBUTE /* nothing */
 
@@ -120,6 +123,11 @@
 
 // clang-format off
 
+// LLVM 22
+// TODO: Fill this in
+#  define _LIBCPP_INTRODUCED_IN_LLVM_22 0
+#  define _LIBCPP_INTRODUCED_IN_LLVM_22_ATTRIBUTE __attribute__((unavailable))
+
 // LLVM 21
 // TODO: Fill this in
 #  define _LIBCPP_INTRODUCED_IN_LLVM_21 0
@@ -355,6 +363,9 @@
 #define _LIBCPP_AVAILABILITY_HAS_BAD_FUNCTION_CALL_GOOD_WHAT_MESSAGE _LIBCPP_INTRODUCED_IN_LLVM_21
 // No attribute, since we've had bad_function_call::what() in the headers before
 
+// This controls whether `std::__next_prime_impl` is available in the dylib, which is used for `__hash_table`.
+#define _LIBCPP_AVAILABILITY_HAS_NEXT_PRIME_IMPL _LIBCPP_INTRODUCED_IN_LLVM_22
+
 // Define availability attributes that depend on both
 // _LIBCPP_HAS_EXCEPTIONS and _LIBCPP_HAS_RTTI.
 #if !_LIBCPP_HAS_EXCEPTIONS || !_LIBCPP_HAS_RTTI
diff --git a/libcxx/include/__hash_table b/libcxx/include/__hash_table
index 91f660d3491e8..49c3c35181452 100644
--- a/libcxx/include/__hash_table
+++ b/libcxx/include/__hash_table
@@ -47,6 +47,7 @@
 #include <__utility/swap.h>
 #include <__utility/try_key_extraction.h>
 #include <limits>
+#include <stdexcept>
 
 #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
 #  pragma GCC system_header
@@ -72,7 +73,28 @@ struct __is_hash_value_type : false_type {};
 template <class _One>
 struct __is_hash_value_type<_One> : __is_hash_value_type_imp<__remove_cvref_t<_One> > {};
 
-_LIBCPP_EXPORTED_FROM_ABI size_t __next_prime(size_t __n);
+_LIBCPP_HIDE_FROM_ABI inline void __check_for_overflow(size_t __n) {
+  if _LIBCPP_CONSTEXPR (sizeof(size_t) == 4) {
+    if (__n > 0xFFFFFFFB)
+      std::__throw_overflow_error("__next_prime overflow");
+  } else {
+    if (__n > 0xFFFFFFFFFFFFFFC5ull)
+      std::__throw_overflow_error("__next_prime overflow");
+  }
+}
+
+#if _LIBCPP_AVAILABILITY_HAS_NEXT_PRIME_IMPL
+[[__gnu__::__const__]] _LIBCPP_EXPORTED_FROM_ABI size_t __next_prime_impl(size_t) _NOEXCEPT;
+
+[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI inline size_t __get_next_prime(size_t __n) {
+  __check_for_overflow(__n);
+  return __next_prime_impl(__n);
+}
+#else
+_LIBCPP_EXPORTED_FROM_ABI size_t __next_prime(size_t);
+
+[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI inline size_t __get_next_prime(size_t __n) { return __next_prime(__n); }
+#endif
 
 template <class _NodePtr>
 struct __hash_node_base {
@@ -1764,7 +1786,7 @@ void __hash_table<_Tp, _Hash, _Equal, _Alloc>::__rehash(size_type __n) _LIBCPP_D
   if (__n == 1)
     __n = 2;
   else if (__n & (__n - 1))
-    __n = std::__next_prime(__n);
+    __n = std::__get_next_prime(__n);
   size_type __bc = bucket_count();
   if (__n > __bc)
     __do_rehash<_UniqueKeys>(__n);
@@ -1772,7 +1794,7 @@ void __hash_table<_Tp, _Hash, _Equal, _Alloc>::__rehash(size_type __n) _LIBCPP_D
     __n = std::max<size_type>(
         __n,
         std::__is_hash_power2(__bc) ? std::__next_hash_pow2(size_t(__math::ceil(float(size()) / max_load_factor())))
-                                    : std::__next_prime(size_t(__math::ceil(float(size()) / max_load_factor()))));
+                                    : std::__get_next_prime(size_t(__math::ceil(float(size()) / max_load_factor()))));
     if (__n < __bc)
       __do_rehash<_UniqueKeys>(__n);
   }
diff --git a/libcxx/src/hash.cpp b/libcxx/src/hash.cpp
index e1e6d2b4c2bdb..76a2b7085d38b 100644
--- a/libcxx/src/hash.cpp
+++ b/libcxx/src/hash.cpp
@@ -51,17 +51,7 @@ const unsigned indices[] = {
 // are fewer potential primes to search, and fewer potential primes to divide
 // against.
 
-inline void __check_for_overflow(size_t N) {
-  if constexpr (sizeof(size_t) == 4) {
-    if (N > 0xFFFFFFFB)
-      std::__throw_overflow_error("__next_prime overflow");
-  } else {
-    if (N > 0xFFFFFFFFFFFFFFC5ull)
-      std::__throw_overflow_error("__next_prime overflow");
-  }
-}
-
-size_t __next_prime(size_t n) {
+size_t __next_prime_impl(size_t n) noexcept {
   const size_t L = 210;
   const size_t N = sizeof(small_primes) / sizeof(small_primes[0]);
   // If n is small enough, search in small_primes
@@ -446,4 +436,6 @@ size_t __next_prime(size_t n) {
   }
 }
 
+_LIBCPP_EXPORTED_FROM_ABI size_t __next_prime(size_t n) { return __get_next_prime(n); }
+
 _LIBCPP_END_NAMESPACE_STD



More information about the libcxx-commits mailing list