[libcxx-commits] [libcxx] [libc++] Fix possible out of range access in bitset (PR #121348)
Peng Liu via libcxx-commits
libcxx-commits at lists.llvm.org
Sun Jun 1 10:50:28 PDT 2025
https://github.com/winner245 updated https://github.com/llvm/llvm-project/pull/121348
>From df5ae222d6890c653da1dddcc104a10aadfaaeb4 Mon Sep 17 00:00:00 2001
From: Peng Liu <winner245 at hotmail.com>
Date: Mon, 30 Dec 2024 12:19:19 -0500
Subject: [PATCH 1/9] Improve bitset::to_ullong Implementation
---
libcxx/include/bitset | 6 ++++--
1 file changed, 4 insertions(+), 2 deletions(-)
diff --git a/libcxx/include/bitset b/libcxx/include/bitset
index 88dc0e08c995d..29aebfe55f674 100644
--- a/libcxx/include/bitset
+++ b/libcxx/include/bitset
@@ -136,6 +136,7 @@ template <size_t N> struct hash<std::bitset<N>>;
# include <__algorithm/fill.h>
# include <__algorithm/fill_n.h>
# include <__algorithm/find.h>
+# include <__algorithm/min.h>
# include <__assert>
# include <__bit/countr.h>
# include <__bit/invert_if.h>
@@ -415,8 +416,9 @@ __bitset<_N_words, _Size>::to_ullong(true_type, true_type) const {
unsigned long long __r = __first_[0];
_LIBCPP_DIAGNOSTIC_PUSH
_LIBCPP_GCC_DIAGNOSTIC_IGNORED("-Wshift-count-overflow")
- for (size_t __i = 1; __i < sizeof(unsigned long long) / sizeof(__storage_type); ++__i)
- __r |= static_cast<unsigned long long>(__first_[__i]) << (sizeof(__storage_type) * CHAR_BIT);
+ size_t __n_words = std::min<size_t>(_N_words, sizeof(unsigned long long) / sizeof(__storage_type));
+ for (size_t __i = 1; __i < __n_words; ++__i)
+ __r |= static_cast<unsigned long long>(__first_[__i]) << (sizeof(__storage_type) * CHAR_BIT * __i);
_LIBCPP_DIAGNOSTIC_POP
return __r;
}
>From 1b3c15463039fed8469d6375a26d1e37e88f25ca Mon Sep 17 00:00:00 2001
From: Peng Liu <winner245 at hotmail.com>
Date: Tue, 31 Dec 2024 01:44:59 -0500
Subject: [PATCH 2/9] Make variable constant expression
---
libcxx/include/bitset | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/libcxx/include/bitset b/libcxx/include/bitset
index 29aebfe55f674..3464e3561ef83 100644
--- a/libcxx/include/bitset
+++ b/libcxx/include/bitset
@@ -416,7 +416,8 @@ __bitset<_N_words, _Size>::to_ullong(true_type, true_type) const {
unsigned long long __r = __first_[0];
_LIBCPP_DIAGNOSTIC_PUSH
_LIBCPP_GCC_DIAGNOSTIC_IGNORED("-Wshift-count-overflow")
- size_t __n_words = std::min<size_t>(_N_words, sizeof(unsigned long long) / sizeof(__storage_type));
+ const size_t __ull_words = sizeof(unsigned long long) / sizeof(__storage_type);
+ const size_t __n_words = _N_words < __ull_words ? _N_words : __ull_words;
for (size_t __i = 1; __i < __n_words; ++__i)
__r |= static_cast<unsigned long long>(__first_[__i]) << (sizeof(__storage_type) * CHAR_BIT * __i);
_LIBCPP_DIAGNOSTIC_POP
>From e1fb50d023c49c4fe4fe71fd3a1e0dfa2ce4d012 Mon Sep 17 00:00:00 2001
From: Peng Liu <winner245 at hotmail.com>
Date: Wed, 1 Jan 2025 18:06:08 -0500
Subject: [PATCH 3/9] Apply @frederick-vs-ja suggestions to support 16-bit
platforms
---
libcxx/include/bitset | 71 +++++++++++++++++++++++++++++++------------
1 file changed, 52 insertions(+), 19 deletions(-)
diff --git a/libcxx/include/bitset b/libcxx/include/bitset
index 3464e3561ef83..5c1d835a3e795 100644
--- a/libcxx/include/bitset
+++ b/libcxx/include/bitset
@@ -262,6 +262,8 @@ private:
# endif // _LIBCPP_CXX03_LANG
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 unsigned long to_ulong(false_type) const;
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 unsigned long to_ulong(true_type) const;
+ _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 unsigned long to_ulong(true_type, false_type) const;
+ _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 unsigned long to_ulong(true_type, true_type) const;
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 unsigned long long to_ullong(false_type) const;
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 unsigned long long to_ullong(true_type) const;
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 unsigned long long to_ullong(true_type, false_type) const;
@@ -317,14 +319,23 @@ inline _LIBCPP_HIDE_FROM_ABI void __bitset<_N_words, _Size>::__init(unsigned lon
template <size_t _N_words, size_t _Size>
inline _LIBCPP_CONSTEXPR __bitset<_N_words, _Size>::__bitset(unsigned long long __v) _NOEXCEPT
# ifndef _LIBCPP_CXX03_LANG
-# if __SIZEOF_SIZE_T__ == 8
- : __first_{__v}
-# elif __SIZEOF_SIZE_T__ == 4
+# if (__SIZEOF_LONG_LONG__ + __SIZEOF_SIZE_T__ - 1) / __SIZEOF_SIZE_T__ == 1
+ : __first_{static_cast<__storage_type>(__v)}
+# elif (__SIZEOF_LONG_LONG__ + __SIZEOF_SIZE_T__ - 1) / __SIZEOF_SIZE_T__ == 2
+ : __first_{static_cast<__storage_type>(__v), static_cast<__storage_type>(__v >> __bits_per_word)}
+# elif (__SIZEOF_LONG_LONG__ + __SIZEOF_SIZE_T__ - 1) / __SIZEOF_SIZE_T__ == 4
+# if _N_words == 2
+ : __first_{static_cast<__storage_type>(__v), static_cast<__storage_type>(__v >> __bits_per_word)}
+# elif _N_words == 3
: __first_{static_cast<__storage_type>(__v),
- _Size >= 2 * __bits_per_word
- ? static_cast<__storage_type>(__v >> __bits_per_word)
- : static_cast<__storage_type>((__v >> __bits_per_word) &
- (__storage_type(1) << (_Size - __bits_per_word)) - 1)}
+ static_cast<__storage_type>(__v >> __bits_per_word),
+ static_cast<__storage_type>(__v >> (__bits_per_word * 2))}
+# else
+ : __first_{static_cast<__storage_type>(__v),
+ static_cast<__storage_type>(__v >> __bits_per_word),
+ static_cast<__storage_type>(__v >> (__bits_per_word * 2)),
+ static_cast<__storage_type>(__v >> (__bits_per_word * 3))}
+# endif
# else
# error This constructor has not been ported to this platform
# endif
@@ -378,15 +389,34 @@ __bitset<_N_words, _Size>::to_ulong(false_type) const {
if (__i != __e)
std::__throw_overflow_error("bitset to_ulong overflow error");
- return __first_[0];
+ return to_ulong(true_type());
}
template <size_t _N_words, size_t _Size>
inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 unsigned long
__bitset<_N_words, _Size>::to_ulong(true_type) const {
- return __first_[0];
+ return to_ulong(true_type(), integral_constant<bool, sizeof(__storage_type) < sizeof(unsigned long)>());
+}
+
+template <size_t _N_words, size_t _Size>
+inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 unsigned long
+__bitset<_N_words, _Size>::to_ulong(true_type, false_type) const {
+ return static_cast<unsigned long>(__first_[0]);
}
+template <size_t _N_words, size_t _Size>
+_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 unsigned long
+__bitset<_N_words, _Size>::to_ulong(true_type, true_type) const {
+ unsigned long __r = static_cast<unsigned long>(__first_[0]);
+ _LIBCPP_DIAGNOSTIC_PUSH
+ _LIBCPP_GCC_DIAGNOSTIC_IGNORED("-Wshift-count-overflow")
+ const size_t __ul_words = sizeof(unsigned long) / sizeof(__storage_type);
+ const size_t __n_words = _N_words < __ul_words ? _N_words : __ul_words;
+ for (size_t __i = 1; __i < __n_words; ++__i)
+ __r |= static_cast<unsigned long>(__first_[__i]) << (__bits_per_word * __i);
+ _LIBCPP_DIAGNOSTIC_POP
+ return __r;
+}
template <size_t _N_words, size_t _Size>
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 unsigned long long
__bitset<_N_words, _Size>::to_ullong(false_type) const {
@@ -407,19 +437,19 @@ __bitset<_N_words, _Size>::to_ullong(true_type) const {
template <size_t _N_words, size_t _Size>
inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 unsigned long long
__bitset<_N_words, _Size>::to_ullong(true_type, false_type) const {
- return __first_[0];
+ return static_cast<unsigned long long>(__first_[0]);
}
template <size_t _N_words, size_t _Size>
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 unsigned long long
__bitset<_N_words, _Size>::to_ullong(true_type, true_type) const {
- unsigned long long __r = __first_[0];
+ unsigned long long __r = static_cast<unsigned long long>(__first_[0]);
_LIBCPP_DIAGNOSTIC_PUSH
_LIBCPP_GCC_DIAGNOSTIC_IGNORED("-Wshift-count-overflow")
const size_t __ull_words = sizeof(unsigned long long) / sizeof(__storage_type);
- const size_t __n_words = _N_words < __ull_words ? _N_words : __ull_words;
+ const size_t __n_words = _N_words < __ull_words ? _N_words : __ull_words;
for (size_t __i = 1; __i < __n_words; ++__i)
- __r |= static_cast<unsigned long long>(__first_[__i]) << (sizeof(__storage_type) * CHAR_BIT * __i);
+ __r |= static_cast<unsigned long long>(__first_[__i]) << (__bits_per_word * __i);
_LIBCPP_DIAGNOSTIC_POP
return __r;
}
@@ -510,8 +540,11 @@ inline _LIBCPP_CONSTEXPR __bitset<1, _Size>::__bitset() _NOEXCEPT : __first_(0)
template <size_t _Size>
inline _LIBCPP_CONSTEXPR __bitset<1, _Size>::__bitset(unsigned long long __v) _NOEXCEPT
- : __first_(_Size == __bits_per_word ? static_cast<__storage_type>(__v)
- : static_cast<__storage_type>(__v) & ((__storage_type(1) << _Size) - 1)) {}
+ : __first_(static_cast<__storage_type>(__v)) {
+ // Force __bits_per_word to be instantiated to avoid "gdb.error: There is no member or method named
+ // __bits_per_word"
+ (void)__bits_per_word;
+}
template <size_t _Size>
inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 void
@@ -538,12 +571,12 @@ inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 void __bitset<1, _Siz
template <size_t _Size>
inline _LIBCPP_CONSTEXPR_SINCE_CXX23 unsigned long __bitset<1, _Size>::to_ulong() const {
- return __first_;
+ return static_cast<unsigned long>(__first_);
}
template <size_t _Size>
inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 unsigned long long __bitset<1, _Size>::to_ullong() const {
- return __first_;
+ return static_cast<unsigned long long>(__first_);
}
template <size_t _Size>
@@ -607,8 +640,8 @@ protected:
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 void flip() _NOEXCEPT {}
- _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 unsigned long to_ulong() const { return 0; }
- _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 unsigned long long to_ullong() const { return 0; }
+ _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 unsigned long to_ulong() const { return 0UL; }
+ _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 unsigned long long to_ullong() const { return 0ULL; }
template <bool _Sparse, class _CharT, class _Traits, class _Allocator>
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 basic_string<_CharT, _Traits, _Allocator>
>From 89669647e04c7a92f9a173b5a68e051cdde4df37 Mon Sep 17 00:00:00 2001
From: Peng Liu <winner245 at hotmail.com>
Date: Fri, 3 Jan 2025 11:58:42 -0500
Subject: [PATCH 4/9] Fix gdb.error
---
libcxx/include/bitset | 33 +++++++++++----------------------
1 file changed, 11 insertions(+), 22 deletions(-)
diff --git a/libcxx/include/bitset b/libcxx/include/bitset
index 5c1d835a3e795..10e7ee76b4007 100644
--- a/libcxx/include/bitset
+++ b/libcxx/include/bitset
@@ -147,6 +147,7 @@ template <size_t N> struct hash<std::bitset<N>>;
# include <__functional/hash.h>
# include <__functional/identity.h>
# include <__functional/unary_function.h>
+# include <__type_traits/integral_constant.h>
# include <__type_traits/is_char_like_type.h>
# include <climits>
# include <stdexcept>
@@ -222,10 +223,10 @@ protected:
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 void flip() _NOEXCEPT;
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 unsigned long to_ulong() const {
- return to_ulong(integral_constant < bool, _Size< sizeof(unsigned long) * CHAR_BIT>());
+ return to_ulong(_BoolConstant < _Size< sizeof(unsigned long) * CHAR_BIT>());
}
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 unsigned long long to_ullong() const {
- return to_ullong(integral_constant < bool, _Size< sizeof(unsigned long long) * CHAR_BIT>());
+ return to_ullong(_BoolConstant < _Size< sizeof(unsigned long long) * CHAR_BIT>());
}
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 bool all() const _NOEXCEPT { return !__scan_bits(__bit_not()); }
@@ -342,7 +343,7 @@ inline _LIBCPP_CONSTEXPR __bitset<_N_words, _Size>::__bitset(unsigned long long
# endif
{
# ifdef _LIBCPP_CXX03_LANG
- __init(__v, integral_constant<bool, sizeof(unsigned long long) <= sizeof(__storage_type)>());
+ __init(__v, _BoolConstant<sizeof(unsigned long long) <= sizeof(__storage_type)>());
# endif
}
@@ -384,9 +385,7 @@ _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 void __bitset<_N_words, _Siz
template <size_t _N_words, size_t _Size>
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 unsigned long
__bitset<_N_words, _Size>::to_ulong(false_type) const {
- __const_iterator __e = __make_iter(_Size);
- __const_iterator __i = std::find(__make_iter(sizeof(unsigned long) * CHAR_BIT), __e, true);
- if (__i != __e)
+ if (auto __e = __make_iter(_Size); std::find(__make_iter(sizeof(unsigned long) * CHAR_BIT), __e, true) != __e)
std::__throw_overflow_error("bitset to_ulong overflow error");
return to_ulong(true_type());
@@ -395,7 +394,7 @@ __bitset<_N_words, _Size>::to_ulong(false_type) const {
template <size_t _N_words, size_t _Size>
inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 unsigned long
__bitset<_N_words, _Size>::to_ulong(true_type) const {
- return to_ulong(true_type(), integral_constant<bool, sizeof(__storage_type) < sizeof(unsigned long)>());
+ return to_ulong(true_type(), _BoolConstant<sizeof(__storage_type) < sizeof(unsigned long)>());
}
template <size_t _N_words, size_t _Size>
@@ -410,9 +409,7 @@ __bitset<_N_words, _Size>::to_ulong(true_type, true_type) const {
unsigned long __r = static_cast<unsigned long>(__first_[0]);
_LIBCPP_DIAGNOSTIC_PUSH
_LIBCPP_GCC_DIAGNOSTIC_IGNORED("-Wshift-count-overflow")
- const size_t __ul_words = sizeof(unsigned long) / sizeof(__storage_type);
- const size_t __n_words = _N_words < __ul_words ? _N_words : __ul_words;
- for (size_t __i = 1; __i < __n_words; ++__i)
+ for (size_t __i = 1; __i < _N_words; ++__i)
__r |= static_cast<unsigned long>(__first_[__i]) << (__bits_per_word * __i);
_LIBCPP_DIAGNOSTIC_POP
return __r;
@@ -420,9 +417,7 @@ __bitset<_N_words, _Size>::to_ulong(true_type, true_type) const {
template <size_t _N_words, size_t _Size>
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 unsigned long long
__bitset<_N_words, _Size>::to_ullong(false_type) const {
- __const_iterator __e = __make_iter(_Size);
- __const_iterator __i = std::find(__make_iter(sizeof(unsigned long long) * CHAR_BIT), __e, true);
- if (__i != __e)
+ if (auto __e = __make_iter(_Size); std::find(__make_iter(sizeof(unsigned long long) * CHAR_BIT), __e, true) != __e)
std::__throw_overflow_error("bitset to_ullong overflow error");
return to_ullong(true_type());
@@ -431,7 +426,7 @@ __bitset<_N_words, _Size>::to_ullong(false_type) const {
template <size_t _N_words, size_t _Size>
inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 unsigned long long
__bitset<_N_words, _Size>::to_ullong(true_type) const {
- return to_ullong(true_type(), integral_constant<bool, sizeof(__storage_type) < sizeof(unsigned long long)>());
+ return to_ullong(true_type(), _BoolConstant<sizeof(__storage_type) < sizeof(unsigned long long)>());
}
template <size_t _N_words, size_t _Size>
@@ -446,9 +441,7 @@ __bitset<_N_words, _Size>::to_ullong(true_type, true_type) const {
unsigned long long __r = static_cast<unsigned long long>(__first_[0]);
_LIBCPP_DIAGNOSTIC_PUSH
_LIBCPP_GCC_DIAGNOSTIC_IGNORED("-Wshift-count-overflow")
- const size_t __ull_words = sizeof(unsigned long long) / sizeof(__storage_type);
- const size_t __n_words = _N_words < __ull_words ? _N_words : __ull_words;
- for (size_t __i = 1; __i < __n_words; ++__i)
+ for (size_t __i = 1; __i < _N_words; ++__i)
__r |= static_cast<unsigned long long>(__first_[__i]) << (__bits_per_word * __i);
_LIBCPP_DIAGNOSTIC_POP
return __r;
@@ -540,11 +533,7 @@ inline _LIBCPP_CONSTEXPR __bitset<1, _Size>::__bitset() _NOEXCEPT : __first_(0)
template <size_t _Size>
inline _LIBCPP_CONSTEXPR __bitset<1, _Size>::__bitset(unsigned long long __v) _NOEXCEPT
- : __first_(static_cast<__storage_type>(__v)) {
- // Force __bits_per_word to be instantiated to avoid "gdb.error: There is no member or method named
- // __bits_per_word"
- (void)__bits_per_word;
-}
+ : __first_(_Size == __bits_per_word ? static_cast<__storage_type>(__v) : static_cast<__storage_type>(__v)) {}
template <size_t _Size>
inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 void
>From a27472cbb1db9569a4039063c21872e408307427 Mon Sep 17 00:00:00 2001
From: Peng Liu <winner245 at hotmail.com>
Date: Mon, 24 Feb 2025 13:22:31 -0500
Subject: [PATCH 5/9] Fix to_ulong to throw overflow_error as expected
---
libcxx/include/bitset | 71 ++++++++++++++++++++++++++++---------------
1 file changed, 46 insertions(+), 25 deletions(-)
diff --git a/libcxx/include/bitset b/libcxx/include/bitset
index 10e7ee76b4007..e02487ee0bf1d 100644
--- a/libcxx/include/bitset
+++ b/libcxx/include/bitset
@@ -223,10 +223,10 @@ protected:
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 void flip() _NOEXCEPT;
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 unsigned long to_ulong() const {
- return to_ulong(_BoolConstant < _Size< sizeof(unsigned long) * CHAR_BIT>());
+ return __to_ulong(_BoolConstant < _Size< sizeof(unsigned long) * CHAR_BIT>());
}
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 unsigned long long to_ullong() const {
- return to_ullong(_BoolConstant < _Size< sizeof(unsigned long long) * CHAR_BIT>());
+ return __to_ullong(_BoolConstant < _Size< sizeof(unsigned long long) * CHAR_BIT>());
}
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 bool all() const _NOEXCEPT { return !__scan_bits(__bit_not()); }
@@ -261,14 +261,6 @@ private:
void __init(unsigned long long __v, false_type) _NOEXCEPT;
_LIBCPP_HIDE_FROM_ABI void __init(unsigned long long __v, true_type) _NOEXCEPT;
# endif // _LIBCPP_CXX03_LANG
- _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 unsigned long to_ulong(false_type) const;
- _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 unsigned long to_ulong(true_type) const;
- _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 unsigned long to_ulong(true_type, false_type) const;
- _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 unsigned long to_ulong(true_type, true_type) const;
- _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 unsigned long long to_ullong(false_type) const;
- _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 unsigned long long to_ullong(true_type) const;
- _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 unsigned long long to_ullong(true_type, false_type) const;
- _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 unsigned long long to_ullong(true_type, true_type) const;
template <typename _Proj>
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 bool __scan_bits(_Proj __proj) const _NOEXCEPT {
@@ -286,6 +278,15 @@ private:
}
return false;
}
+
+ _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 unsigned long __to_ulong(false_type) const;
+ _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 unsigned long __to_ulong(true_type) const;
+ _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 unsigned long __to_ulong(true_type, false_type) const;
+ _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 unsigned long __to_ulong(true_type, true_type) const;
+ _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 unsigned long long __to_ullong(false_type) const;
+ _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 unsigned long long __to_ullong(true_type) const;
+ _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 unsigned long long __to_ullong(true_type, false_type) const;
+ _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 unsigned long long __to_ullong(true_type, true_type) const;
};
template <size_t _N_words, size_t _Size>
@@ -384,28 +385,28 @@ _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 void __bitset<_N_words, _Siz
template <size_t _N_words, size_t _Size>
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 unsigned long
-__bitset<_N_words, _Size>::to_ulong(false_type) const {
+__bitset<_N_words, _Size>::__to_ulong(false_type) const {
if (auto __e = __make_iter(_Size); std::find(__make_iter(sizeof(unsigned long) * CHAR_BIT), __e, true) != __e)
- std::__throw_overflow_error("bitset to_ulong overflow error");
+ std::__throw_overflow_error("bitset __to_ulong overflow error");
- return to_ulong(true_type());
+ return __to_ulong(true_type());
}
template <size_t _N_words, size_t _Size>
inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 unsigned long
-__bitset<_N_words, _Size>::to_ulong(true_type) const {
- return to_ulong(true_type(), _BoolConstant<sizeof(__storage_type) < sizeof(unsigned long)>());
+__bitset<_N_words, _Size>::__to_ulong(true_type) const {
+ return __to_ulong(true_type(), _BoolConstant<sizeof(__storage_type) < sizeof(unsigned long)>());
}
template <size_t _N_words, size_t _Size>
inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 unsigned long
-__bitset<_N_words, _Size>::to_ulong(true_type, false_type) const {
+__bitset<_N_words, _Size>::__to_ulong(true_type, false_type) const {
return static_cast<unsigned long>(__first_[0]);
}
template <size_t _N_words, size_t _Size>
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 unsigned long
-__bitset<_N_words, _Size>::to_ulong(true_type, true_type) const {
+__bitset<_N_words, _Size>::__to_ulong(true_type, true_type) const {
unsigned long __r = static_cast<unsigned long>(__first_[0]);
_LIBCPP_DIAGNOSTIC_PUSH
_LIBCPP_GCC_DIAGNOSTIC_IGNORED("-Wshift-count-overflow")
@@ -414,34 +415,37 @@ __bitset<_N_words, _Size>::to_ulong(true_type, true_type) const {
_LIBCPP_DIAGNOSTIC_POP
return __r;
}
+
template <size_t _N_words, size_t _Size>
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 unsigned long long
-__bitset<_N_words, _Size>::to_ullong(false_type) const {
+__bitset<_N_words, _Size>::__to_ullong(false_type) const {
if (auto __e = __make_iter(_Size); std::find(__make_iter(sizeof(unsigned long long) * CHAR_BIT), __e, true) != __e)
- std::__throw_overflow_error("bitset to_ullong overflow error");
+ std::__throw_overflow_error("bitset __to_ullong overflow error");
- return to_ullong(true_type());
+ return __to_ullong(true_type());
}
template <size_t _N_words, size_t _Size>
inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 unsigned long long
-__bitset<_N_words, _Size>::to_ullong(true_type) const {
- return to_ullong(true_type(), _BoolConstant<sizeof(__storage_type) < sizeof(unsigned long long)>());
+__bitset<_N_words, _Size>::__to_ullong(true_type) const {
+ return __to_ullong(true_type(), _BoolConstant<sizeof(__storage_type) < sizeof(unsigned long long)>());
}
template <size_t _N_words, size_t _Size>
inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 unsigned long long
-__bitset<_N_words, _Size>::to_ullong(true_type, false_type) const {
+__bitset<_N_words, _Size>::__to_ullong(true_type, false_type) const {
return static_cast<unsigned long long>(__first_[0]);
}
template <size_t _N_words, size_t _Size>
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 unsigned long long
-__bitset<_N_words, _Size>::to_ullong(true_type, true_type) const {
+__bitset<_N_words, _Size>::__to_ullong(true_type, true_type) const {
unsigned long long __r = static_cast<unsigned long long>(__first_[0]);
_LIBCPP_DIAGNOSTIC_PUSH
_LIBCPP_GCC_DIAGNOSTIC_IGNORED("-Wshift-count-overflow")
- for (size_t __i = 1; __i < _N_words; ++__i)
+ const size_t __ull_wrods = (sizeof(unsigned long long) - 1) / sizeof(__storage_type) + 1;
+ const size_t __n_words = _N_words < __ull_wrods ? _N_words : __ull_wrods;
+ for (size_t __i = 1; __i < __n_words; ++__i)
__r |= static_cast<unsigned long long>(__first_[__i]) << (__bits_per_word * __i);
_LIBCPP_DIAGNOSTIC_POP
return __r;
@@ -526,6 +530,10 @@ protected:
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 bool any() const _NOEXCEPT;
_LIBCPP_HIDE_FROM_ABI size_t __hash_code() const _NOEXCEPT;
+
+private:
+ _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 unsigned long __to_ulong(false_type) const;
+ _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 unsigned long __to_ulong(true_type) const;
};
template <size_t _Size>
@@ -560,6 +568,19 @@ inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 void __bitset<1, _Siz
template <size_t _Size>
inline _LIBCPP_CONSTEXPR_SINCE_CXX23 unsigned long __bitset<1, _Size>::to_ulong() const {
+ return __to_ulong(_BoolConstant < _Size< sizeof(unsigned long) * CHAR_BIT>());
+}
+
+template <size_t _Size>
+_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 unsigned long __bitset<1, _Size>::__to_ulong(false_type) const {
+ if (auto __e = __make_iter(_Size); std::find(__make_iter(sizeof(unsigned long) * CHAR_BIT), __e, true) != __e)
+ __throw_overflow_error("__bitset<1, _Size>::__to_ulong overflow error");
+
+ return static_cast<unsigned long>(__first_);
+}
+
+template <size_t _Size>
+_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 unsigned long __bitset<1, _Size>::__to_ulong(true_type) const {
return static_cast<unsigned long>(__first_);
}
>From 5b350a38e9f6f04bfaf9632b7d30bf40532155a2 Mon Sep 17 00:00:00 2001
From: Peng Liu <winner245 at hotmail.com>
Date: Wed, 14 May 2025 11:32:47 -0400
Subject: [PATCH 6/9] Address ldionne's review comments
---
libcxx/include/bitset | 10 +++++-----
1 file changed, 5 insertions(+), 5 deletions(-)
diff --git a/libcxx/include/bitset b/libcxx/include/bitset
index e02487ee0bf1d..171010d71eb82 100644
--- a/libcxx/include/bitset
+++ b/libcxx/include/bitset
@@ -223,10 +223,10 @@ protected:
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 void flip() _NOEXCEPT;
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 unsigned long to_ulong() const {
- return __to_ulong(_BoolConstant < _Size< sizeof(unsigned long) * CHAR_BIT>());
+ return __to_ulong(_BoolConstant<_Size < sizeof(unsigned long) * CHAR_BIT>());
}
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 unsigned long long to_ullong() const {
- return __to_ullong(_BoolConstant < _Size< sizeof(unsigned long long) * CHAR_BIT>());
+ return __to_ullong(_BoolConstant<_Size < sizeof(unsigned long long) * CHAR_BIT>());
}
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 bool all() const _NOEXCEPT { return !__scan_bits(__bit_not()); }
@@ -321,11 +321,11 @@ inline _LIBCPP_HIDE_FROM_ABI void __bitset<_N_words, _Size>::__init(unsigned lon
template <size_t _N_words, size_t _Size>
inline _LIBCPP_CONSTEXPR __bitset<_N_words, _Size>::__bitset(unsigned long long __v) _NOEXCEPT
# ifndef _LIBCPP_CXX03_LANG
-# if (__SIZEOF_LONG_LONG__ + __SIZEOF_SIZE_T__ - 1) / __SIZEOF_SIZE_T__ == 1
+# if __SIZEOF_LONG_LONG__ <= __SIZEOF_SIZE_T__
: __first_{static_cast<__storage_type>(__v)}
-# elif (__SIZEOF_LONG_LONG__ + __SIZEOF_SIZE_T__ - 1) / __SIZEOF_SIZE_T__ == 2
+# elif __SIZEOF_LONG_LONG__ <= 2 * __SIZEOF_SIZE_T__
: __first_{static_cast<__storage_type>(__v), static_cast<__storage_type>(__v >> __bits_per_word)}
-# elif (__SIZEOF_LONG_LONG__ + __SIZEOF_SIZE_T__ - 1) / __SIZEOF_SIZE_T__ == 4
+# elif __SIZEOF_LONG_LONG__ <= 4 * __SIZEOF_SIZE_T__
# if _N_words == 2
: __first_{static_cast<__storage_type>(__v), static_cast<__storage_type>(__v >> __bits_per_word)}
# elif _N_words == 3
>From 668d024accafac69cc1321e7484467fbec86042a Mon Sep 17 00:00:00 2001
From: Peng Liu <winner245 at hotmail.com>
Date: Thu, 15 May 2025 20:55:36 -0400
Subject: [PATCH 7/9] Fix preprocessing
---
libcxx/include/bitset | 92 +++++++++++++++++++++++++++++--------------
1 file changed, 62 insertions(+), 30 deletions(-)
diff --git a/libcxx/include/bitset b/libcxx/include/bitset
index 171010d71eb82..ea57aadd629c4 100644
--- a/libcxx/include/bitset
+++ b/libcxx/include/bitset
@@ -147,8 +147,10 @@ template <size_t N> struct hash<std::bitset<N>>;
# include <__functional/hash.h>
# include <__functional/identity.h>
# include <__functional/unary_function.h>
+# include <__type_traits/enable_if.h>
# include <__type_traits/integral_constant.h>
# include <__type_traits/is_char_like_type.h>
+# include <__utility/integer_sequence.h>
# include <climits>
# include <stdexcept>
# include <string_view>
@@ -223,10 +225,10 @@ protected:
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 void flip() _NOEXCEPT;
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 unsigned long to_ulong() const {
- return __to_ulong(_BoolConstant<_Size < sizeof(unsigned long) * CHAR_BIT>());
+ return __to_ulong(_BoolConstant<_Size <= sizeof(unsigned long) * CHAR_BIT>());
}
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 unsigned long long to_ullong() const {
- return __to_ullong(_BoolConstant<_Size < sizeof(unsigned long long) * CHAR_BIT>());
+ return __to_ullong(_BoolConstant<_Size <= sizeof(unsigned long long) * CHAR_BIT>());
}
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 bool all() const _NOEXCEPT { return !__scan_bits(__bit_not()); }
@@ -287,6 +289,11 @@ private:
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 unsigned long long __to_ullong(true_type) const;
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 unsigned long long __to_ullong(true_type, false_type) const;
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 unsigned long long __to_ullong(true_type, true_type) const;
+# if _LIBCPP_STD_VER >= 14
+ template <size_t... _Indices>
+ _LIBCPP_HIDE_FROM_ABI constexpr __bitset(unsigned long long __v, std::index_sequence<_Indices...>) _NOEXCEPT
+ : __first_{static_cast<__storage_type>(__v >> (_Indices * __bits_per_word))...} {}
+# endif
};
template <size_t _N_words, size_t _Size>
@@ -318,35 +325,47 @@ inline _LIBCPP_HIDE_FROM_ABI void __bitset<_N_words, _Size>::__init(unsigned lon
# endif // _LIBCPP_CXX03_LANG
+# ifdef _LIBCPP_CXX03_LANG
+template <size_t _N_words, size_t _Size>
+inline _LIBCPP_CONSTEXPR __bitset<_N_words, _Size>::__bitset(unsigned long long __v) _NOEXCEPT {
+ __init(__v, _BoolConstant<sizeof(unsigned long long) == sizeof(__storage_type)>());
+}
+# elif _LIBCPP_STD_VER >= 14
template <size_t _N_words, size_t _Size>
inline _LIBCPP_CONSTEXPR __bitset<_N_words, _Size>::__bitset(unsigned long long __v) _NOEXCEPT
-# ifndef _LIBCPP_CXX03_LANG
+ : __bitset{__v,
+ std::make_index_sequence<
+ std::min<size_t>(_N_words, (sizeof(unsigned long long) - 1) / sizeof(__storage_type) + 1)>{}} {}
+# else
# if __SIZEOF_LONG_LONG__ <= __SIZEOF_SIZE_T__
- : __first_{static_cast<__storage_type>(__v)}
-# elif __SIZEOF_LONG_LONG__ <= 2 * __SIZEOF_SIZE_T__
- : __first_{static_cast<__storage_type>(__v), static_cast<__storage_type>(__v >> __bits_per_word)}
-# elif __SIZEOF_LONG_LONG__ <= 4 * __SIZEOF_SIZE_T__
-# if _N_words == 2
- : __first_{static_cast<__storage_type>(__v), static_cast<__storage_type>(__v >> __bits_per_word)}
-# elif _N_words == 3
+template <size_t _N_words, size_t _Size>
+inline _LIBCPP_CONSTEXPR __bitset<_N_words, _Size>::__bitset(unsigned long long __v) _NOEXCEPT
+ : __first_{static_cast<__storage_type>(__v)} {}
+# elif __SIZEOF_LONG_LONG__ == 2 * __SIZEOF_SIZE_T__
+template <size_t _N_words, size_t _Size>
+inline _LIBCPP_CONSTEXPR __bitset<_N_words, _Size>::__bitset(unsigned long long __v) _NOEXCEPT
+ : __first_{static_cast<__storage_type>(__v), static_cast<__storage_type>(__v >> __bits_per_word)} {}
+# elif __SIZEOF_LONG_LONG__ == 4 * __SIZEOF_SIZE_T__
+template <size_t _N_words, size_t _Size, __enable_if_t<_N_words == 2, int> = 0>
+inline _LIBCPP_CONSTEXPR __bitset<_N_words, _Size>::__bitset(unsigned long long __v) _NOEXCEPT
+ : __first_{static_cast<__storage_type>(__v), static_cast<__storage_type>(__v >> __bits_per_word)} {}
+
+template <size_t _N_words, size_t _Size, __enable_if_t<_N_words == 3, int> = 0>
+inline _LIBCPP_CONSTEXPR __bitset<_N_words, _Size>::__bitset(unsigned long long __v) _NOEXCEPT
: __first_{static_cast<__storage_type>(__v),
static_cast<__storage_type>(__v >> __bits_per_word),
- static_cast<__storage_type>(__v >> (__bits_per_word * 2))}
-# else
+ static_cast<__storage_type>(__v >> (__bits_per_word * 2))} {}
+
+template <size_t _N_words, size_t _Size, __enable_if_t<_N_words >= 4, int> = 0>
+inline _LIBCPP_CONSTEXPR __bitset<_N_words, _Size>::__bitset(unsigned long long __v) _NOEXCEPT
: __first_{static_cast<__storage_type>(__v),
static_cast<__storage_type>(__v >> __bits_per_word),
static_cast<__storage_type>(__v >> (__bits_per_word * 2)),
- static_cast<__storage_type>(__v >> (__bits_per_word * 3))}
-# endif
+ static_cast<__storage_type>(__v >> (__bits_per_word * 3))} {}
# else
# error This constructor has not been ported to this platform
# endif
-# endif
-{
-# ifdef _LIBCPP_CXX03_LANG
- __init(__v, _BoolConstant<sizeof(unsigned long long) <= sizeof(__storage_type)>());
-# endif
-}
+# endif // _LIBCPP_CXX03_LANG
template <size_t _N_words, size_t _Size>
inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 void
@@ -407,12 +426,11 @@ __bitset<_N_words, _Size>::__to_ulong(true_type, false_type) const {
template <size_t _N_words, size_t _Size>
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 unsigned long
__bitset<_N_words, _Size>::__to_ulong(true_type, true_type) const {
- unsigned long __r = static_cast<unsigned long>(__first_[0]);
- _LIBCPP_DIAGNOSTIC_PUSH
- _LIBCPP_GCC_DIAGNOSTIC_IGNORED("-Wshift-count-overflow")
- for (size_t __i = 1; __i < _N_words; ++__i)
+ const size_t __ul_wrods = (sizeof(unsigned long) - 1) / sizeof(__storage_type) + 1;
+ const size_t __n_words = _N_words < __ul_wrods ? _N_words : __ul_wrods;
+ unsigned long __r = static_cast<unsigned long>(__first_[0]);
+ for (size_t __i = 1; __i < __n_words; ++__i)
__r |= static_cast<unsigned long>(__first_[__i]) << (__bits_per_word * __i);
- _LIBCPP_DIAGNOSTIC_POP
return __r;
}
@@ -440,14 +458,11 @@ __bitset<_N_words, _Size>::__to_ullong(true_type, false_type) const {
template <size_t _N_words, size_t _Size>
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 unsigned long long
__bitset<_N_words, _Size>::__to_ullong(true_type, true_type) const {
- unsigned long long __r = static_cast<unsigned long long>(__first_[0]);
- _LIBCPP_DIAGNOSTIC_PUSH
- _LIBCPP_GCC_DIAGNOSTIC_IGNORED("-Wshift-count-overflow")
const size_t __ull_wrods = (sizeof(unsigned long long) - 1) / sizeof(__storage_type) + 1;
const size_t __n_words = _N_words < __ull_wrods ? _N_words : __ull_wrods;
+ unsigned long long __r = static_cast<unsigned long long>(__first_[0]);
for (size_t __i = 1; __i < __n_words; ++__i)
__r |= static_cast<unsigned long long>(__first_[__i]) << (__bits_per_word * __i);
- _LIBCPP_DIAGNOSTIC_POP
return __r;
}
@@ -534,6 +549,8 @@ protected:
private:
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 unsigned long __to_ulong(false_type) const;
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 unsigned long __to_ulong(true_type) const;
+ _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 unsigned long long __to_ullong(false_type) const;
+ _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 unsigned long long __to_ullong(true_type) const;
};
template <size_t _Size>
@@ -568,7 +585,7 @@ inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 void __bitset<1, _Siz
template <size_t _Size>
inline _LIBCPP_CONSTEXPR_SINCE_CXX23 unsigned long __bitset<1, _Size>::to_ulong() const {
- return __to_ulong(_BoolConstant < _Size< sizeof(unsigned long) * CHAR_BIT>());
+ return __to_ulong(_BoolConstant<_Size <= sizeof(unsigned long) * CHAR_BIT>());
}
template <size_t _Size>
@@ -586,6 +603,21 @@ _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 unsigned long __bitset<1, _S
template <size_t _Size>
inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 unsigned long long __bitset<1, _Size>::to_ullong() const {
+ return __to_ullong(_BoolConstant<_Size <= sizeof(unsigned long long) * CHAR_BIT>());
+}
+
+template <size_t _Size>
+_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 unsigned long long
+__bitset<1, _Size>::__to_ullong(false_type) const {
+ if (auto __e = __make_iter(_Size); std::find(__make_iter(sizeof(unsigned long long) * CHAR_BIT), __e, true) != __e)
+ __throw_overflow_error("__bitset<1, _Size>::__to_ullong overflow error");
+
+ return static_cast<unsigned long long>(__first_);
+}
+
+template <size_t _Size>
+_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 unsigned long long
+__bitset<1, _Size>::__to_ullong(true_type) const {
return static_cast<unsigned long long>(__first_);
}
>From c11d29734fc105c27040037e2096bc602b1a4f66 Mon Sep 17 00:00:00 2001
From: Peng Liu <winner245 at hotmail.com>
Date: Wed, 21 May 2025 16:20:23 -0400
Subject: [PATCH 8/9] Address ldionne's comments
---
libcxx/include/bitset | 283 +++++++-----------
.../bitset.members/to_ullong.pass.cpp | 67 +++--
.../bitset.members/to_ulong.pass.cpp | 65 ++--
3 files changed, 195 insertions(+), 220 deletions(-)
diff --git a/libcxx/include/bitset b/libcxx/include/bitset
index ea57aadd629c4..5b23b94fc4f33 100644
--- a/libcxx/include/bitset
+++ b/libcxx/include/bitset
@@ -80,7 +80,7 @@ public:
constexpr bool operator[](size_t pos) const;
reference operator[](size_t pos); // constexpr since C++23
unsigned long to_ulong() const; // constexpr since C++23
- unsigned long long to_ullong() const; // constexpr since C++23
+ unsigned long long to_ullong() const; // since C++11, constexpr since C++23
template <class charT, class traits, class Allocator> // constexpr since C++23
basic_string<charT, traits, Allocator> to_string(charT zero = charT('0'), charT one = charT('1')) const;
template <class charT, class traits> // constexpr since C++23
@@ -147,6 +147,7 @@ template <size_t N> struct hash<std::bitset<N>>;
# include <__functional/hash.h>
# include <__functional/identity.h>
# include <__functional/unary_function.h>
+# include <__tuple/tuple_indices.h>
# include <__type_traits/enable_if.h>
# include <__type_traits/integral_constant.h>
# include <__type_traits/is_char_like_type.h>
@@ -224,12 +225,66 @@ protected:
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 void operator^=(const __bitset& __v) _NOEXCEPT;
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 void flip() _NOEXCEPT;
+
+ // unsigned long spans only one word
+ template <typename _StorageType = __storage_type,
+ __enable_if_t<sizeof(_StorageType) >= sizeof(unsigned long), int> = 0>
+ _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 unsigned long __to_ulong() const {
+ return static_cast<unsigned long>(__first_[0]);
+ }
+
+ // unsigned long may span multiple words which are concatenated to form the result
+ template <typename _StorageType = __storage_type,
+ __enable_if_t<sizeof(_StorageType) < sizeof(unsigned long), int> = 0>
+ _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 unsigned long __to_ulong() const {
+ const size_t __ul_words = (sizeof(unsigned long) - 1) / sizeof(__storage_type) + 1;
+ const size_t __n_words = _N_words < __ul_words ? _N_words : __ul_words;
+ unsigned long __r = static_cast<unsigned long>(__first_[0]);
+ for (size_t __i = 1; __i < __n_words; ++__i)
+ __r |= static_cast<unsigned long>(__first_[__i]) << (__bits_per_word * __i);
+ return __r;
+ }
+
+ // _Bit_size > sizeof(unsigned long) * CHAR_BIT: overflow check needed
+ template <size_t _Bit_size = _Size, __enable_if_t<(_Bit_size > sizeof(unsigned long) * CHAR_BIT), int> = 0>
+ _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 unsigned long to_ulong() const {
+ if (auto __e = __make_iter(_Bit_size); std::find(__make_iter(sizeof(unsigned long) * CHAR_BIT), __e, true) != __e)
+ std::__throw_overflow_error("__bitset<_N_words, _Size>::__to_ulong overflow error");
+
+ return __to_ulong();
+ }
+
+ // _Bit_size <= sizeof(unsigned long) * CHAR_BIT: no overflow check needed
+ template <size_t _Bit_size = _Size, __enable_if_t<(_Bit_size <= sizeof(unsigned long) * CHAR_BIT), int> = 0>
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 unsigned long to_ulong() const {
- return __to_ulong(_BoolConstant<_Size <= sizeof(unsigned long) * CHAR_BIT>());
+ return __to_ulong();
}
+
+# ifndef _LIBCPP_CXX03_LANG
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 unsigned long long to_ullong() const {
- return __to_ullong(_BoolConstant<_Size <= sizeof(unsigned long long) * CHAR_BIT>());
+ // Check for overflow if _Size does not fit in unsigned long long
+ if _LIBCPP_CONSTEXPR (_Size > sizeof(unsigned long long) * CHAR_BIT) {
+ if (auto __e = __make_iter(_Size);
+ std::find(__make_iter(sizeof(unsigned long long) * CHAR_BIT), __e, true) != __e)
+ std::__throw_overflow_error("__bitset<_N_words, _Size>::__to_ullong overflow error");
+ }
+
+ // At this point, the effective bitset size (excluding leading zeros) fits in unsigned long long
+
+ if _LIBCPP_CONSTEXPR (sizeof(__storage_type) >= sizeof(unsigned long long)) {
+ // If __storage_type is at least as large as unsigned long long, the result spans only one word
+ return static_cast<unsigned long long>(__first_[0]);
+ } else {
+ // Otherwise, the result spans multiple words which are concatenated
+ const size_t __ull_words = (sizeof(unsigned long long) - 1) / sizeof(__storage_type) + 1;
+ const size_t __n_words = _N_words < __ull_words ? _N_words : __ull_words;
+ unsigned long long __r = static_cast<unsigned long long>(__first_[0]);
+ for (size_t __i = 1; __i < __n_words; ++__i)
+ __r |= static_cast<unsigned long long>(__first_[__i]) << (__bits_per_word * __i);
+ return __r;
+ }
}
+# endif
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 bool all() const _NOEXCEPT { return !__scan_bits(__bit_not()); }
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 bool any() const _NOEXCEPT {
@@ -259,10 +314,6 @@ private:
return ~__x;
}
};
-# ifdef _LIBCPP_CXX03_LANG
- void __init(unsigned long long __v, false_type) _NOEXCEPT;
- _LIBCPP_HIDE_FROM_ABI void __init(unsigned long long __v, true_type) _NOEXCEPT;
-# endif // _LIBCPP_CXX03_LANG
template <typename _Proj>
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 bool __scan_bits(_Proj __proj) const _NOEXCEPT {
@@ -281,6 +332,10 @@ private:
return false;
}
+# ifdef _LIBCPP_CXX03_LANG
+ void __init(unsigned long long __v, false_type) _NOEXCEPT;
+ _LIBCPP_HIDE_FROM_ABI void __init(unsigned long long __v, true_type) _NOEXCEPT;
+
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 unsigned long __to_ulong(false_type) const;
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 unsigned long __to_ulong(true_type) const;
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 unsigned long __to_ulong(true_type, false_type) const;
@@ -289,11 +344,11 @@ private:
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 unsigned long long __to_ullong(true_type) const;
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 unsigned long long __to_ullong(true_type, false_type) const;
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 unsigned long long __to_ullong(true_type, true_type) const;
-# if _LIBCPP_STD_VER >= 14
+# else
template <size_t... _Indices>
- _LIBCPP_HIDE_FROM_ABI constexpr __bitset(unsigned long long __v, std::index_sequence<_Indices...>) _NOEXCEPT
+ _LIBCPP_HIDE_FROM_ABI constexpr __bitset(unsigned long long __v, std::__tuple_indices<_Indices...>) _NOEXCEPT
: __first_{static_cast<__storage_type>(__v >> (_Indices * __bits_per_word))...} {}
-# endif
+# endif // _LIBCPP_CXX03_LANG
};
template <size_t _N_words, size_t _Size>
@@ -325,47 +380,20 @@ inline _LIBCPP_HIDE_FROM_ABI void __bitset<_N_words, _Size>::__init(unsigned lon
# endif // _LIBCPP_CXX03_LANG
-# ifdef _LIBCPP_CXX03_LANG
template <size_t _N_words, size_t _Size>
-inline _LIBCPP_CONSTEXPR __bitset<_N_words, _Size>::__bitset(unsigned long long __v) _NOEXCEPT {
+inline _LIBCPP_CONSTEXPR __bitset<_N_words, _Size>::__bitset(unsigned long long __v) _NOEXCEPT
+# ifndef _LIBCPP_CXX03_LANG
+ : __bitset(__v,
+ std::__make_indices_imp< (_N_words < (sizeof(unsigned long long) - 1) / sizeof(__storage_type) + 1)
+ ? _N_words
+ : (sizeof(unsigned long long) - 1) / sizeof(__storage_type) + 1,
+ 0>{})
+# endif
+{
+# ifdef _LIBCPP_CXX03_LANG
__init(__v, _BoolConstant<sizeof(unsigned long long) == sizeof(__storage_type)>());
+# endif
}
-# elif _LIBCPP_STD_VER >= 14
-template <size_t _N_words, size_t _Size>
-inline _LIBCPP_CONSTEXPR __bitset<_N_words, _Size>::__bitset(unsigned long long __v) _NOEXCEPT
- : __bitset{__v,
- std::make_index_sequence<
- std::min<size_t>(_N_words, (sizeof(unsigned long long) - 1) / sizeof(__storage_type) + 1)>{}} {}
-# else
-# if __SIZEOF_LONG_LONG__ <= __SIZEOF_SIZE_T__
-template <size_t _N_words, size_t _Size>
-inline _LIBCPP_CONSTEXPR __bitset<_N_words, _Size>::__bitset(unsigned long long __v) _NOEXCEPT
- : __first_{static_cast<__storage_type>(__v)} {}
-# elif __SIZEOF_LONG_LONG__ == 2 * __SIZEOF_SIZE_T__
-template <size_t _N_words, size_t _Size>
-inline _LIBCPP_CONSTEXPR __bitset<_N_words, _Size>::__bitset(unsigned long long __v) _NOEXCEPT
- : __first_{static_cast<__storage_type>(__v), static_cast<__storage_type>(__v >> __bits_per_word)} {}
-# elif __SIZEOF_LONG_LONG__ == 4 * __SIZEOF_SIZE_T__
-template <size_t _N_words, size_t _Size, __enable_if_t<_N_words == 2, int> = 0>
-inline _LIBCPP_CONSTEXPR __bitset<_N_words, _Size>::__bitset(unsigned long long __v) _NOEXCEPT
- : __first_{static_cast<__storage_type>(__v), static_cast<__storage_type>(__v >> __bits_per_word)} {}
-
-template <size_t _N_words, size_t _Size, __enable_if_t<_N_words == 3, int> = 0>
-inline _LIBCPP_CONSTEXPR __bitset<_N_words, _Size>::__bitset(unsigned long long __v) _NOEXCEPT
- : __first_{static_cast<__storage_type>(__v),
- static_cast<__storage_type>(__v >> __bits_per_word),
- static_cast<__storage_type>(__v >> (__bits_per_word * 2))} {}
-
-template <size_t _N_words, size_t _Size, __enable_if_t<_N_words >= 4, int> = 0>
-inline _LIBCPP_CONSTEXPR __bitset<_N_words, _Size>::__bitset(unsigned long long __v) _NOEXCEPT
- : __first_{static_cast<__storage_type>(__v),
- static_cast<__storage_type>(__v >> __bits_per_word),
- static_cast<__storage_type>(__v >> (__bits_per_word * 2)),
- static_cast<__storage_type>(__v >> (__bits_per_word * 3))} {}
-# else
-# error This constructor has not been ported to this platform
-# endif
-# endif // _LIBCPP_CXX03_LANG
template <size_t _N_words, size_t _Size>
inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 void
@@ -402,70 +430,6 @@ _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 void __bitset<_N_words, _Siz
*__p ^= (__storage_type(1) << __n) - 1;
}
-template <size_t _N_words, size_t _Size>
-_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 unsigned long
-__bitset<_N_words, _Size>::__to_ulong(false_type) const {
- if (auto __e = __make_iter(_Size); std::find(__make_iter(sizeof(unsigned long) * CHAR_BIT), __e, true) != __e)
- std::__throw_overflow_error("bitset __to_ulong overflow error");
-
- return __to_ulong(true_type());
-}
-
-template <size_t _N_words, size_t _Size>
-inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 unsigned long
-__bitset<_N_words, _Size>::__to_ulong(true_type) const {
- return __to_ulong(true_type(), _BoolConstant<sizeof(__storage_type) < sizeof(unsigned long)>());
-}
-
-template <size_t _N_words, size_t _Size>
-inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 unsigned long
-__bitset<_N_words, _Size>::__to_ulong(true_type, false_type) const {
- return static_cast<unsigned long>(__first_[0]);
-}
-
-template <size_t _N_words, size_t _Size>
-_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 unsigned long
-__bitset<_N_words, _Size>::__to_ulong(true_type, true_type) const {
- const size_t __ul_wrods = (sizeof(unsigned long) - 1) / sizeof(__storage_type) + 1;
- const size_t __n_words = _N_words < __ul_wrods ? _N_words : __ul_wrods;
- unsigned long __r = static_cast<unsigned long>(__first_[0]);
- for (size_t __i = 1; __i < __n_words; ++__i)
- __r |= static_cast<unsigned long>(__first_[__i]) << (__bits_per_word * __i);
- return __r;
-}
-
-template <size_t _N_words, size_t _Size>
-_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 unsigned long long
-__bitset<_N_words, _Size>::__to_ullong(false_type) const {
- if (auto __e = __make_iter(_Size); std::find(__make_iter(sizeof(unsigned long long) * CHAR_BIT), __e, true) != __e)
- std::__throw_overflow_error("bitset __to_ullong overflow error");
-
- return __to_ullong(true_type());
-}
-
-template <size_t _N_words, size_t _Size>
-inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 unsigned long long
-__bitset<_N_words, _Size>::__to_ullong(true_type) const {
- return __to_ullong(true_type(), _BoolConstant<sizeof(__storage_type) < sizeof(unsigned long long)>());
-}
-
-template <size_t _N_words, size_t _Size>
-inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 unsigned long long
-__bitset<_N_words, _Size>::__to_ullong(true_type, false_type) const {
- return static_cast<unsigned long long>(__first_[0]);
-}
-
-template <size_t _N_words, size_t _Size>
-_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 unsigned long long
-__bitset<_N_words, _Size>::__to_ullong(true_type, true_type) const {
- const size_t __ull_wrods = (sizeof(unsigned long long) - 1) / sizeof(__storage_type) + 1;
- const size_t __n_words = _N_words < __ull_wrods ? _N_words : __ull_wrods;
- unsigned long long __r = static_cast<unsigned long long>(__first_[0]);
- for (size_t __i = 1; __i < __n_words; ++__i)
- __r |= static_cast<unsigned long long>(__first_[__i]) << (__bits_per_word * __i);
- return __r;
-}
-
template <size_t _N_words, size_t _Size>
inline size_t __bitset<_N_words, _Size>::__hash_code() const _NOEXCEPT {
size_t __h = 0;
@@ -524,8 +488,32 @@ protected:
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 void flip() _NOEXCEPT;
- _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 unsigned long to_ulong() const;
- _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 unsigned long long to_ullong() const;
+ template <size_t _Bit_size = _Size, __enable_if_t<(_Bit_size > sizeof(unsigned long) * CHAR_BIT), int> = 0>
+ _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 unsigned long to_ulong() const {
+ if (auto __e = __make_iter(_Bit_size); std::find(__make_iter(sizeof(unsigned long) * CHAR_BIT), __e, true) != __e)
+ __throw_overflow_error("__bitset<1, _Size>::to_ulong overflow error");
+
+ return static_cast<unsigned long>(__first_);
+ }
+
+ template <size_t _Bit_size = _Size, __enable_if_t<(_Bit_size <= sizeof(unsigned long) * CHAR_BIT), int> = 0>
+ _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 unsigned long to_ulong() const {
+ return static_cast<unsigned long>(__first_);
+ }
+
+# ifndef _LIBCPP_CXX03_LANG
+ _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 unsigned long long to_ullong() const {
+ // If _Size exceeds the size of unsigned long long, check for overflow
+ if _LIBCPP_CONSTEXPR (_Size > sizeof(unsigned long long) * CHAR_BIT) {
+ if (auto __e = __make_iter(_Size);
+ std::find(__make_iter(sizeof(unsigned long long) * CHAR_BIT), __e, true) != __e)
+ __throw_overflow_error("__bitset<1, _Size>::to_ullong overflow error");
+ }
+
+ // If _Size fits or no overflow, directly cast to unsigned long long
+ return static_cast<unsigned long long>(__first_);
+ }
+# endif
template <bool _Sparse, class _CharT, class _Traits, class _Allocator>
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 basic_string<_CharT, _Traits, _Allocator>
@@ -545,12 +533,6 @@ protected:
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 bool any() const _NOEXCEPT;
_LIBCPP_HIDE_FROM_ABI size_t __hash_code() const _NOEXCEPT;
-
-private:
- _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 unsigned long __to_ulong(false_type) const;
- _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 unsigned long __to_ulong(true_type) const;
- _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 unsigned long long __to_ullong(false_type) const;
- _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 unsigned long long __to_ullong(true_type) const;
};
template <size_t _Size>
@@ -558,6 +540,9 @@ inline _LIBCPP_CONSTEXPR __bitset<1, _Size>::__bitset() _NOEXCEPT : __first_(0)
template <size_t _Size>
inline _LIBCPP_CONSTEXPR __bitset<1, _Size>::__bitset(unsigned long long __v) _NOEXCEPT
+ // TODO: This is a workaround for a GCC bug causing stage1 CI (generic-gcc, gcc-14, g++-14)
+ // failure due to __bits_per_word lookup failure if not referenced here.
+ // See: https://github.com/llvm/llvm-project/actions/runs/15071518915/job/42368867929?pr=121348#logs
: __first_(_Size == __bits_per_word ? static_cast<__storage_type>(__v) : static_cast<__storage_type>(__v)) {}
template <size_t _Size>
@@ -583,44 +568,6 @@ inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 void __bitset<1, _Siz
__first_ ^= ~__storage_type(0) >> (__bits_per_word - _Size);
}
-template <size_t _Size>
-inline _LIBCPP_CONSTEXPR_SINCE_CXX23 unsigned long __bitset<1, _Size>::to_ulong() const {
- return __to_ulong(_BoolConstant<_Size <= sizeof(unsigned long) * CHAR_BIT>());
-}
-
-template <size_t _Size>
-_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 unsigned long __bitset<1, _Size>::__to_ulong(false_type) const {
- if (auto __e = __make_iter(_Size); std::find(__make_iter(sizeof(unsigned long) * CHAR_BIT), __e, true) != __e)
- __throw_overflow_error("__bitset<1, _Size>::__to_ulong overflow error");
-
- return static_cast<unsigned long>(__first_);
-}
-
-template <size_t _Size>
-_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 unsigned long __bitset<1, _Size>::__to_ulong(true_type) const {
- return static_cast<unsigned long>(__first_);
-}
-
-template <size_t _Size>
-inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 unsigned long long __bitset<1, _Size>::to_ullong() const {
- return __to_ullong(_BoolConstant<_Size <= sizeof(unsigned long long) * CHAR_BIT>());
-}
-
-template <size_t _Size>
-_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 unsigned long long
-__bitset<1, _Size>::__to_ullong(false_type) const {
- if (auto __e = __make_iter(_Size); std::find(__make_iter(sizeof(unsigned long long) * CHAR_BIT), __e, true) != __e)
- __throw_overflow_error("__bitset<1, _Size>::__to_ullong overflow error");
-
- return static_cast<unsigned long long>(__first_);
-}
-
-template <size_t _Size>
-_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 unsigned long long
-__bitset<1, _Size>::__to_ullong(true_type) const {
- return static_cast<unsigned long long>(__first_);
-}
-
template <size_t _Size>
inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 bool __bitset<1, _Size>::all() const _NOEXCEPT {
__storage_type __m = ~__storage_type(0) >> (__bits_per_word - _Size);
@@ -683,7 +630,9 @@ protected:
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 void flip() _NOEXCEPT {}
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 unsigned long to_ulong() const { return 0UL; }
+# ifndef _LIBCPP_CXX03_LANG
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 unsigned long long to_ullong() const { return 0ULL; }
+# endif
template <bool _Sparse, class _CharT, class _Traits, class _Allocator>
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 basic_string<_CharT, _Traits, _Allocator>
@@ -794,8 +743,12 @@ public:
_LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(__p < _Size, "bitset::operator[] index out of bounds");
return __base::__make_ref(__p);
}
- _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 unsigned long to_ulong() const;
- _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 unsigned long long to_ullong() const;
+ _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 unsigned long to_ulong() const { return __base::to_ulong(); }
+# ifndef _LIBCPP_CXX03_LANG
+ _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 unsigned long long to_ullong() const {
+ return __base::to_ullong();
+ }
+# endif
template <class _CharT, class _Traits, class _Allocator>
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 basic_string<_CharT, _Traits, _Allocator>
to_string(_CharT __zero = _CharT('0'), _CharT __one = _CharT('1')) const;
@@ -931,16 +884,6 @@ _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 bitset<_Size>& bitset<_Size>
return *this;
}
-template <size_t _Size>
-inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 unsigned long bitset<_Size>::to_ulong() const {
- return __base::to_ulong();
-}
-
-template <size_t _Size>
-inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 unsigned long long bitset<_Size>::to_ullong() const {
- return __base::to_ullong();
-}
-
template <size_t _Size>
template <class _CharT, class _Traits, class _Allocator>
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 basic_string<_CharT, _Traits, _Allocator>
diff --git a/libcxx/test/std/utilities/template.bitset/bitset.members/to_ullong.pass.cpp b/libcxx/test/std/utilities/template.bitset/bitset.members/to_ullong.pass.cpp
index cbc8da96be1b1..485ca9ccf8a34 100644
--- a/libcxx/test/std/utilities/template.bitset/bitset.members/to_ullong.pass.cpp
+++ b/libcxx/test/std/utilities/template.bitset/bitset.members/to_ullong.pass.cpp
@@ -6,6 +6,8 @@
//
//===----------------------------------------------------------------------===//
+// UNSUPPORTED: c++03, no-exceptions
+
// unsigned long long to_ullong() const; // constexpr since C++23
#include <bitset>
@@ -18,31 +20,32 @@
template <std::size_t N>
TEST_CONSTEXPR_CXX23 void test_to_ullong() {
- const std::size_t M = sizeof(unsigned long long) * CHAR_BIT < N ? sizeof(unsigned long long) * CHAR_BIT : N;
- const bool is_M_zero = std::integral_constant<bool, M == 0>::value; // avoid compiler warnings
- const std::size_t X = is_M_zero ? sizeof(unsigned long long) * CHAR_BIT - 1 : sizeof(unsigned long long) * CHAR_BIT - M;
- const unsigned long long max = is_M_zero ? 0 : (unsigned long long)(-1) >> X;
- unsigned long long tests[] = {
- 0,
- std::min<unsigned long long>(1, max),
- std::min<unsigned long long>(2, max),
- std::min<unsigned long long>(3, max),
- std::min(max, max-3),
- std::min(max, max-2),
- std::min(max, max-1),
- max
- };
- for (unsigned long long j : tests) {
- std::bitset<N> v(j);
- assert(j == v.to_ullong());
- }
- { // test values bigger than can fit into the bitset
- const unsigned long long val = 0x55AAAAFFFFAAAA55ULL;
- const bool canFit = N < sizeof(unsigned long long) * CHAR_BIT;
- const unsigned long long mask = canFit ? (1ULL << (canFit ? N : 0)) - 1 : (unsigned long long)(-1); // avoid compiler warnings
- std::bitset<N> v(val);
- assert(v.to_ullong() == (val & mask)); // we shouldn't return bit patterns from outside the limits of the bitset.
- }
+ const std::size_t M = sizeof(unsigned long long) * CHAR_BIT < N ? sizeof(unsigned long long) * CHAR_BIT : N;
+ const bool is_M_zero = std::integral_constant < bool, M == 0 > ::value; // avoid compiler warnings
+ const std::size_t X =
+ is_M_zero ? sizeof(unsigned long long) * CHAR_BIT - 1 : sizeof(unsigned long long) * CHAR_BIT - M;
+ const unsigned long long max = is_M_zero ? 0 : (unsigned long long)(-1) >> X;
+ unsigned long long tests[] = {
+ 0,
+ std::min<unsigned long long>(1, max),
+ std::min<unsigned long long>(2, max),
+ std::min<unsigned long long>(3, max),
+ std::min(max, max - 3),
+ std::min(max, max - 2),
+ std::min(max, max - 1),
+ max};
+ for (unsigned long long j : tests) {
+ std::bitset<N> v(j);
+ assert(j == v.to_ullong());
+ }
+ { // test values bigger than can fit into the bitset
+ const unsigned long long val = 0x55AAAAFFFFAAAA55ULL;
+ const bool canFit = N < sizeof(unsigned long long) * CHAR_BIT;
+ const unsigned long long mask =
+ canFit ? (1ULL << (canFit ? N : 0)) - 1 : (unsigned long long)(-1); // avoid compiler warnings
+ std::bitset<N> v(val);
+ assert(v.to_ullong() == (val & mask)); // we shouldn't return bit patterns from outside the limits of the bitset.
+ }
}
TEST_CONSTEXPR_CXX23 bool test() {
@@ -56,6 +59,20 @@ TEST_CONSTEXPR_CXX23 bool test() {
test_to_ullong<65>();
test_to_ullong<1000>();
+ if (!TEST_IS_CONSTANT_EVALUATED) {
+ // bitset has true bits beyond the size of unsigned long long
+ std::bitset<std::numeric_limits<unsigned long long>::digits + 1> q{0};
+ q.flip();
+ try {
+ q.to_ullong(); // throws
+ assert(false);
+ } catch (const std::overflow_error&) {
+ // expected
+ } catch (...) {
+ assert(false);
+ }
+ }
+
return true;
}
diff --git a/libcxx/test/std/utilities/template.bitset/bitset.members/to_ulong.pass.cpp b/libcxx/test/std/utilities/template.bitset/bitset.members/to_ulong.pass.cpp
index 17a5e7eb51aa2..977fa67dcd9bb 100644
--- a/libcxx/test/std/utilities/template.bitset/bitset.members/to_ulong.pass.cpp
+++ b/libcxx/test/std/utilities/template.bitset/bitset.members/to_ulong.pass.cpp
@@ -6,6 +6,8 @@
//
//===----------------------------------------------------------------------===//
+// UNSUPPORTED: no-exceptions
+
// unsigned long to_ulong() const; // constexpr since C++23
#include <bitset>
@@ -19,32 +21,31 @@
template <std::size_t N>
TEST_CONSTEXPR_CXX23 void test_to_ulong() {
- const std::size_t M = sizeof(unsigned long) * CHAR_BIT < N ? sizeof(unsigned long) * CHAR_BIT : N;
- const bool is_M_zero = std::integral_constant<bool, M == 0>::value; // avoid compiler warnings
- const std::size_t X = is_M_zero ? sizeof(unsigned long) * CHAR_BIT - 1 : sizeof(unsigned long) * CHAR_BIT - M;
- const std::size_t max = is_M_zero ? 0 : std::size_t(std::numeric_limits<unsigned long>::max()) >> X;
- std::size_t tests[] = {
- 0,
- std::min<std::size_t>(1, max),
- std::min<std::size_t>(2, max),
- std::min<std::size_t>(3, max),
- std::min(max, max-3),
- std::min(max, max-2),
- std::min(max, max-1),
- max
- };
- for (std::size_t j : tests) {
- std::bitset<N> v(j);
- assert(j == v.to_ulong());
- }
+ const std::size_t M = sizeof(unsigned long) * CHAR_BIT < N ? sizeof(unsigned long) * CHAR_BIT : N;
+ const bool is_M_zero = std::integral_constant < bool, M == 0 > ::value; // avoid compiler warnings
+ const std::size_t X = is_M_zero ? sizeof(unsigned long) * CHAR_BIT - 1 : sizeof(unsigned long) * CHAR_BIT - M;
+ const std::size_t max = is_M_zero ? 0 : std::size_t(std::numeric_limits<unsigned long>::max()) >> X;
+ std::size_t tests[] = {
+ 0,
+ std::min<std::size_t>(1, max),
+ std::min<std::size_t>(2, max),
+ std::min<std::size_t>(3, max),
+ std::min(max, max - 3),
+ std::min(max, max - 2),
+ std::min(max, max - 1),
+ max};
+ for (std::size_t j : tests) {
+ std::bitset<N> v(j);
+ assert(j == v.to_ulong());
+ }
- { // test values bigger than can fit into the bitset
- const unsigned long val = 0x5AFFFFA5UL;
- const bool canFit = N < sizeof(unsigned long) * CHAR_BIT;
- const unsigned long mask = canFit ? (1UL << (canFit ? N : 0)) - 1 : (unsigned long)(-1); // avoid compiler warnings
- std::bitset<N> v(val);
- assert(v.to_ulong() == (val & mask)); // we shouldn't return bit patterns from outside the limits of the bitset.
- }
+ { // test values bigger than can fit into the bitset
+ const unsigned long val = 0x5AFFFFA5UL;
+ const bool canFit = N < sizeof(unsigned long) * CHAR_BIT;
+ const unsigned long mask = canFit ? (1UL << (canFit ? N : 0)) - 1 : (unsigned long)(-1); // avoid compiler warnings
+ std::bitset<N> v(val);
+ assert(v.to_ulong() == (val & mask)); // we shouldn't return bit patterns from outside the limits of the bitset.
+ }
}
TEST_CONSTEXPR_CXX23 bool test() {
@@ -58,6 +59,20 @@ TEST_CONSTEXPR_CXX23 bool test() {
test_to_ulong<65>();
test_to_ulong<1000>();
+ if (!TEST_IS_CONSTANT_EVALUATED) {
+ // bitset has true bits beyond the size of unsigned long
+ std::bitset<std::numeric_limits<unsigned long>::digits + 1> q(0);
+ q.flip();
+ try {
+ q.to_ulong(); // throws
+ assert(false);
+ } catch (const std::overflow_error&) {
+ // expected
+ } catch (...) {
+ assert(false);
+ }
+ }
+
return true;
}
>From cf280254d19a3714e293aed0ffb29b1e16df49ee Mon Sep 17 00:00:00 2001
From: Peng Liu <winner245 at hotmail.com>
Date: Sun, 1 Jun 2025 08:42:30 -0400
Subject: [PATCH 9/9] Rebase
---
libcxx/include/bitset | 26 +++----------------
.../bitset.members/to_ullong.pass.cpp | 4 +--
2 files changed, 6 insertions(+), 24 deletions(-)
diff --git a/libcxx/include/bitset b/libcxx/include/bitset
index 5b23b94fc4f33..58a23e628a5f4 100644
--- a/libcxx/include/bitset
+++ b/libcxx/include/bitset
@@ -260,7 +260,6 @@ protected:
return __to_ulong();
}
-# ifndef _LIBCPP_CXX03_LANG
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 unsigned long long to_ullong() const {
// Check for overflow if _Size does not fit in unsigned long long
if _LIBCPP_CONSTEXPR (_Size > sizeof(unsigned long long) * CHAR_BIT) {
@@ -284,7 +283,6 @@ protected:
return __r;
}
}
-# endif
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 bool all() const _NOEXCEPT { return !__scan_bits(__bit_not()); }
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 bool any() const _NOEXCEPT {
@@ -335,15 +333,6 @@ private:
# ifdef _LIBCPP_CXX03_LANG
void __init(unsigned long long __v, false_type) _NOEXCEPT;
_LIBCPP_HIDE_FROM_ABI void __init(unsigned long long __v, true_type) _NOEXCEPT;
-
- _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 unsigned long __to_ulong(false_type) const;
- _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 unsigned long __to_ulong(true_type) const;
- _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 unsigned long __to_ulong(true_type, false_type) const;
- _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 unsigned long __to_ulong(true_type, true_type) const;
- _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 unsigned long long __to_ullong(false_type) const;
- _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 unsigned long long __to_ullong(true_type) const;
- _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 unsigned long long __to_ullong(true_type, false_type) const;
- _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 unsigned long long __to_ullong(true_type, true_type) const;
# else
template <size_t... _Indices>
_LIBCPP_HIDE_FROM_ABI constexpr __bitset(unsigned long long __v, std::__tuple_indices<_Indices...>) _NOEXCEPT
@@ -391,7 +380,7 @@ inline _LIBCPP_CONSTEXPR __bitset<_N_words, _Size>::__bitset(unsigned long long
# endif
{
# ifdef _LIBCPP_CXX03_LANG
- __init(__v, _BoolConstant<sizeof(unsigned long long) == sizeof(__storage_type)>());
+ __init(__v, _BoolConstant<sizeof(unsigned long long) <= sizeof(__storage_type)>());
# endif
}
@@ -501,7 +490,6 @@ protected:
return static_cast<unsigned long>(__first_);
}
-# ifndef _LIBCPP_CXX03_LANG
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 unsigned long long to_ullong() const {
// If _Size exceeds the size of unsigned long long, check for overflow
if _LIBCPP_CONSTEXPR (_Size > sizeof(unsigned long long) * CHAR_BIT) {
@@ -513,7 +501,6 @@ protected:
// If _Size fits or no overflow, directly cast to unsigned long long
return static_cast<unsigned long long>(__first_);
}
-# endif
template <bool _Sparse, class _CharT, class _Traits, class _Allocator>
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 basic_string<_CharT, _Traits, _Allocator>
@@ -540,8 +527,9 @@ inline _LIBCPP_CONSTEXPR __bitset<1, _Size>::__bitset() _NOEXCEPT : __first_(0)
template <size_t _Size>
inline _LIBCPP_CONSTEXPR __bitset<1, _Size>::__bitset(unsigned long long __v) _NOEXCEPT
- // TODO: This is a workaround for a GCC bug causing stage1 CI (generic-gcc, gcc-14, g++-14)
- // failure due to __bits_per_word lookup failure if not referenced here.
+ // TODO: This is a workaround for a gdb test failure (gdb_pretty_printer_test.sh.cpp) in
+ // stage1 CI (generic-gcc, gcc-14, g++-14), due to the __bits_per_word name lookup failure
+ // if not referenced in the constructor initializer list.
// See: https://github.com/llvm/llvm-project/actions/runs/15071518915/job/42368867929?pr=121348#logs
: __first_(_Size == __bits_per_word ? static_cast<__storage_type>(__v) : static_cast<__storage_type>(__v)) {}
@@ -630,9 +618,7 @@ protected:
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 void flip() _NOEXCEPT {}
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 unsigned long to_ulong() const { return 0UL; }
-# ifndef _LIBCPP_CXX03_LANG
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 unsigned long long to_ullong() const { return 0ULL; }
-# endif
template <bool _Sparse, class _CharT, class _Traits, class _Allocator>
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 basic_string<_CharT, _Traits, _Allocator>
@@ -660,8 +646,6 @@ class bitset : private __bitset<_Size == 0 ? 0 : (_Size - 1) / (sizeof(size_t) *
public:
static const unsigned __n_words = _Size == 0 ? 0 : (_Size - 1) / (sizeof(size_t) * CHAR_BIT) + 1;
typedef __bitset<__n_words, _Size> __base;
-
-public:
typedef typename __base::reference reference;
typedef typename __base::__const_reference __const_reference;
@@ -744,11 +728,9 @@ public:
return __base::__make_ref(__p);
}
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 unsigned long to_ulong() const { return __base::to_ulong(); }
-# ifndef _LIBCPP_CXX03_LANG
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 unsigned long long to_ullong() const {
return __base::to_ullong();
}
-# endif
template <class _CharT, class _Traits, class _Allocator>
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 basic_string<_CharT, _Traits, _Allocator>
to_string(_CharT __zero = _CharT('0'), _CharT __one = _CharT('1')) const;
diff --git a/libcxx/test/std/utilities/template.bitset/bitset.members/to_ullong.pass.cpp b/libcxx/test/std/utilities/template.bitset/bitset.members/to_ullong.pass.cpp
index 485ca9ccf8a34..84366c998f891 100644
--- a/libcxx/test/std/utilities/template.bitset/bitset.members/to_ullong.pass.cpp
+++ b/libcxx/test/std/utilities/template.bitset/bitset.members/to_ullong.pass.cpp
@@ -6,7 +6,7 @@
//
//===----------------------------------------------------------------------===//
-// UNSUPPORTED: c++03, no-exceptions
+// UNSUPPORTED: no-exceptions
// unsigned long long to_ullong() const; // constexpr since C++23
@@ -61,7 +61,7 @@ TEST_CONSTEXPR_CXX23 bool test() {
if (!TEST_IS_CONSTANT_EVALUATED) {
// bitset has true bits beyond the size of unsigned long long
- std::bitset<std::numeric_limits<unsigned long long>::digits + 1> q{0};
+ std::bitset<std::numeric_limits<unsigned long long>::digits + 1> q(0);
q.flip();
try {
q.to_ullong(); // throws
More information about the libcxx-commits
mailing list