Skip to content

Commit 31741f5

Browse files
committed
[libc++] Refactor __next_prime to be const
1 parent 04518e7 commit 31741f5

File tree

6 files changed

+44
-17
lines changed

6 files changed

+44
-17
lines changed

libcxx/include/__configuration/availability.h

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,9 @@
8484
// in all versions of the library are available.
8585
#if !_LIBCPP_HAS_VENDOR_AVAILABILITY_ANNOTATIONS
8686

87+
# define _LIBCPP_INTRODUCED_IN_LLVM_22 1
88+
# define _LIBCPP_INTRODUCED_IN_LLVM_22_ATTRIBUTE /* nothing */
89+
8790
# define _LIBCPP_INTRODUCED_IN_LLVM_21 1
8891
# define _LIBCPP_INTRODUCED_IN_LLVM_21_ATTRIBUTE /* nothing */
8992

@@ -120,6 +123,11 @@
120123

121124
// clang-format off
122125

126+
// LLVM 22
127+
// TODO: Fill this in
128+
# define _LIBCPP_INTRODUCED_IN_LLVM_22 0
129+
# define _LIBCPP_INTRODUCED_IN_LLVM_22_ATTRIBUTE __attribute__((unavailable))
130+
123131
// LLVM 21
124132
// TODO: Fill this in
125133
# define _LIBCPP_INTRODUCED_IN_LLVM_21 0
@@ -355,6 +363,9 @@
355363
#define _LIBCPP_AVAILABILITY_HAS_BAD_FUNCTION_CALL_GOOD_WHAT_MESSAGE _LIBCPP_INTRODUCED_IN_LLVM_21
356364
// No attribute, since we've had bad_function_call::what() in the headers before
357365

366+
// This controls whether `std::__next_prime_impl` is available in the dylib, which is used for `__hash_table`.
367+
#define _LIBCPP_AVAILABILITY_HAS_NEXT_PRIME_IMPL _LIBCPP_INTRODUCED_IN_LLVM_22
368+
358369
// Define availability attributes that depend on both
359370
// _LIBCPP_HAS_EXCEPTIONS and _LIBCPP_HAS_RTTI.
360371
#if !_LIBCPP_HAS_EXCEPTIONS || !_LIBCPP_HAS_RTTI

libcxx/include/__hash_table

Lines changed: 25 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@
4747
#include <__utility/swap.h>
4848
#include <__utility/try_key_extraction.h>
4949
#include <limits>
50+
#include <stdexcept>
5051

5152
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
5253
# pragma GCC system_header
@@ -72,7 +73,28 @@ struct __is_hash_value_type : false_type {};
7273
template <class _One>
7374
struct __is_hash_value_type<_One> : __is_hash_value_type_imp<__remove_cvref_t<_One> > {};
7475

75-
_LIBCPP_EXPORTED_FROM_ABI size_t __next_prime(size_t __n);
76+
_LIBCPP_HIDE_FROM_ABI inline void __check_for_overflow(size_t __n) {
77+
if _LIBCPP_CONSTEXPR (sizeof(size_t) == 4) {
78+
if (__n > 0xFFFFFFFB)
79+
std::__throw_overflow_error("__next_prime overflow");
80+
} else {
81+
if (__n > 0xFFFFFFFFFFFFFFC5ull)
82+
std::__throw_overflow_error("__next_prime overflow");
83+
}
84+
}
85+
86+
#if _LIBCPP_AVAILABILITY_HAS_NEXT_PRIME_IMPL
87+
[[__gnu__::__const__]] _LIBCPP_EXPORTED_FROM_ABI size_t __next_prime_impl(size_t) _NOEXCEPT;
88+
89+
[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI inline size_t __get_next_prime(size_t __n) {
90+
__check_for_overflow(__n);
91+
return __next_prime_impl(__n);
92+
}
93+
#else
94+
_LIBCPP_EXPORTED_FROM_ABI size_t __next_prime(size_t);
95+
96+
[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI inline size_t __get_next_prime(size_t __n) { return __next_prime(__n); }
97+
#endif
7698

7799
template <class _NodePtr>
78100
struct __hash_node_base {
@@ -1764,15 +1786,15 @@ void __hash_table<_Tp, _Hash, _Equal, _Alloc>::__rehash(size_type __n) _LIBCPP_D
17641786
if (__n == 1)
17651787
__n = 2;
17661788
else if (__n & (__n - 1))
1767-
__n = std::__next_prime(__n);
1789+
__n = std::__get_next_prime(__n);
17681790
size_type __bc = bucket_count();
17691791
if (__n > __bc)
17701792
__do_rehash<_UniqueKeys>(__n);
17711793
else if (__n < __bc) {
17721794
__n = std::max<size_type>(
17731795
__n,
17741796
std::__is_hash_power2(__bc) ? std::__next_hash_pow2(size_t(__math::ceil(float(size()) / max_load_factor())))
1775-
: std::__next_prime(size_t(__math::ceil(float(size()) / max_load_factor()))));
1797+
: std::__get_next_prime(size_t(__math::ceil(float(size()) / max_load_factor()))));
17761798
if (__n < __bc)
17771799
__do_rehash<_UniqueKeys>(__n);
17781800
}

libcxx/lib/abi/x86_64-unknown-linux-gnu.libcxxabi.v1.stable.exceptions.nonew.abilist

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1147,6 +1147,7 @@
11471147
{'is_defined': True, 'name': '_ZNSt3__117__assoc_sub_state4waitEv', 'type': 'FUNC'}
11481148
{'is_defined': True, 'name': '_ZNSt3__117__assoc_sub_state9__executeEv', 'type': 'FUNC'}
11491149
{'is_defined': True, 'name': '_ZNSt3__117__assoc_sub_state9set_valueEv', 'type': 'FUNC'}
1150+
{'is_defined': True, 'name': '_ZNSt3__117__next_prime_implEm', 'type': 'FUNC'}
11501151
{'is_defined': True, 'name': '_ZNSt3__117__widen_from_utf8ILm16EED0Ev', 'type': 'FUNC'}
11511152
{'is_defined': True, 'name': '_ZNSt3__117__widen_from_utf8ILm16EED1Ev', 'type': 'FUNC'}
11521153
{'is_defined': True, 'name': '_ZNSt3__117__widen_from_utf8ILm16EED2Ev', 'type': 'FUNC'}

libcxx/src/hash.cpp

Lines changed: 3 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -51,17 +51,7 @@ const unsigned indices[] = {
5151
// are fewer potential primes to search, and fewer potential primes to divide
5252
// against.
5353

54-
inline void __check_for_overflow(size_t N) {
55-
if constexpr (sizeof(size_t) == 4) {
56-
if (N > 0xFFFFFFFB)
57-
std::__throw_overflow_error("__next_prime overflow");
58-
} else {
59-
if (N > 0xFFFFFFFFFFFFFFC5ull)
60-
std::__throw_overflow_error("__next_prime overflow");
61-
}
62-
}
63-
64-
size_t __next_prime(size_t n) {
54+
size_t __next_prime_impl(size_t n) noexcept {
6555
const size_t L = 210;
6656
const size_t N = sizeof(small_primes) / sizeof(small_primes[0]);
6757
// If n is small enough, search in small_primes
@@ -446,4 +436,6 @@ size_t __next_prime(size_t n) {
446436
}
447437
}
448438

439+
_LIBCPP_EXPORTED_FROM_ABI size_t __next_prime(size_t n) { return __get_next_prime(n); }
440+
449441
_LIBCPP_END_NAMESPACE_STD

libcxx/test/libcxx/containers/unord/next_prime.pass.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212

1313
// <__hash_table>
1414

15-
// size_t __next_prime(size_t n);
15+
// size_t __get_next_prime(size_t n);
1616

1717
// If n == 0, return 0, else return the lowest prime greater than or equal to n
1818

@@ -36,9 +36,9 @@ bool is_prime(std::size_t n) {
3636
}
3737

3838
int main(int, char**) {
39-
assert(std::__next_prime(0) == 0);
39+
assert(std::__get_next_prime(0) == 0);
4040
for (std::size_t n = 1; n <= 100000; ++n) {
41-
std::size_t p = std::__next_prime(n);
41+
std::size_t p = std::__get_next_prime(n);
4242
assert(p >= n);
4343
for (std::size_t i = n; i < p; ++i)
4444
assert(!is_prime(i));

libcxx/test/libcxx/transitive_includes/cxx26.csv

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1106,6 +1106,7 @@ unordered_set cstring
11061106
unordered_set initializer_list
11071107
unordered_set limits
11081108
unordered_set optional
1109+
unordered_set stdexcept
11091110
unordered_set tuple
11101111
unordered_set version
11111112
utility compare

0 commit comments

Comments
 (0)