@@ -136,6 +136,7 @@ template <size_t N> struct hash<std::bitset<N>>;
136136# include < __algorithm/fill.h>
137137# include < __algorithm/fill_n.h>
138138# include < __algorithm/find.h>
139+ # include < __algorithm/min.h>
139140# include < __assert>
140141# include < __bit/countr.h>
141142# include < __bit/invert_if.h>
@@ -146,7 +147,11 @@ template <size_t N> struct hash<std::bitset<N>>;
146147# include < __functional/hash.h>
147148# include < __functional/identity.h>
148149# include < __functional/unary_function.h>
150+ # include < __tuple/tuple_indices.h>
151+ # include < __type_traits/enable_if.h>
152+ # include < __type_traits/integral_constant.h>
149153# include < __type_traits/is_char_like_type.h>
154+ # include < __utility/integer_sequence.h>
150155# include < climits>
151156# include < stdexcept>
152157# include < string_view>
@@ -220,11 +225,42 @@ protected:
220225 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 void operator ^=(const __bitset& __v) _NOEXCEPT;
221226
222227 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 void flip () _NOEXCEPT;
228+
223229 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 unsigned long to_ulong () const {
224- return to_ulong (integral_constant < bool , _Size< sizeof (unsigned long ) * CHAR_BIT>());
230+ if _LIBCPP_CONSTEXPR (_Size > sizeof (unsigned long ) * CHAR_BIT) {
231+ if (auto __e = __make_iter (_Size); std::find (__make_iter (sizeof (unsigned long ) * CHAR_BIT), __e, true ) != __e)
232+ std::__throw_overflow_error (" __bitset<_N_words, _Size>::to_ulong overflow error" );
233+ }
234+
235+ static_assert (sizeof (__storage_type) >= sizeof (unsigned long ),
236+ " libc++ only supports platforms where sizeof(size_t) >= sizeof(unsigned long), such as 32-bit and "
237+ " 64-bit platforms. If you're interested in supporting a platform where that is not the case, please "
238+ " contact the libc++ developers." );
239+ return static_cast <unsigned long >(__first_[0 ]);
225240 }
241+
226242 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 unsigned long long to_ullong () const {
227- return to_ullong (integral_constant < bool , _Size< sizeof (unsigned long long ) * CHAR_BIT>());
243+ // Check for overflow if _Size does not fit in unsigned long long
244+ if _LIBCPP_CONSTEXPR (_Size > sizeof (unsigned long long ) * CHAR_BIT) {
245+ if (auto __e = __make_iter (_Size);
246+ std::find (__make_iter (sizeof (unsigned long long ) * CHAR_BIT), __e, true ) != __e)
247+ std::__throw_overflow_error (" __bitset<_N_words, _Size>::to_ullong overflow error" );
248+ }
249+
250+ // At this point, the effective bitset size (excluding leading zeros) fits in unsigned long long
251+
252+ if _LIBCPP_CONSTEXPR (sizeof (__storage_type) >= sizeof (unsigned long long )) {
253+ // If __storage_type is at least as large as unsigned long long, the result spans only one word
254+ return static_cast <unsigned long long >(__first_[0 ]);
255+ } else {
256+ // Otherwise, the result spans multiple words which are concatenated
257+ const size_t __ull_words = (sizeof (unsigned long long ) - 1 ) / sizeof (__storage_type) + 1 ;
258+ const size_t __n_words = _N_words < __ull_words ? _N_words : __ull_words;
259+ unsigned long long __r = static_cast <unsigned long long >(__first_[0 ]);
260+ for (size_t __i = 1 ; __i < __n_words; ++__i)
261+ __r |= static_cast <unsigned long long >(__first_[__i]) << (__bits_per_word * __i);
262+ return __r;
263+ }
228264 }
229265
230266 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 bool all () const _NOEXCEPT { return !__scan_bits (__bit_not ()); }
@@ -255,16 +291,6 @@ private:
255291 return ~__x;
256292 }
257293 };
258- # ifdef _LIBCPP_CXX03_LANG
259- void __init (unsigned long long __v, false_type) _NOEXCEPT;
260- _LIBCPP_HIDE_FROM_ABI void __init (unsigned long long __v, true_type) _NOEXCEPT;
261- # endif // _LIBCPP_CXX03_LANG
262- _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 unsigned long to_ulong (false_type) const ;
263- _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 unsigned long to_ulong (true_type) const ;
264- _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 unsigned long long to_ullong (false_type) const ;
265- _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 unsigned long long to_ullong (true_type) const ;
266- _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 unsigned long long to_ullong (true_type, false_type) const ;
267- _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 unsigned long long to_ullong (true_type, true_type) const ;
268294
269295 template <typename _Proj>
270296 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 bool __scan_bits (_Proj __proj) const _NOEXCEPT {
@@ -282,6 +308,15 @@ private:
282308 }
283309 return false ;
284310 }
311+
312+ # ifdef _LIBCPP_CXX03_LANG
313+ void __init (unsigned long long __v, false_type) _NOEXCEPT;
314+ _LIBCPP_HIDE_FROM_ABI void __init (unsigned long long __v, true_type) _NOEXCEPT;
315+ # else
316+ template <size_t ... _Indices>
317+ _LIBCPP_HIDE_FROM_ABI constexpr __bitset (unsigned long long __v, std::__tuple_indices<_Indices...>) _NOEXCEPT
318+ : __first_{static_cast <__storage_type>(__v >> (_Indices * __bits_per_word))...} {}
319+ # endif // _LIBCPP_CXX03_LANG
285320};
286321
287322template <size_t _N_words, size_t _Size>
@@ -316,21 +351,15 @@ inline _LIBCPP_HIDE_FROM_ABI void __bitset<_N_words, _Size>::__init(unsigned lon
316351template <size_t _N_words, size_t _Size>
317352inline _LIBCPP_CONSTEXPR __bitset<_N_words, _Size>::__bitset(unsigned long long __v) _NOEXCEPT
318353# ifndef _LIBCPP_CXX03_LANG
319- # if __SIZEOF_SIZE_T__ == 8
320- : __first_{__v}
321- # elif __SIZEOF_SIZE_T__ == 4
322- : __first_{static_cast <__storage_type>(__v),
323- _Size >= 2 * __bits_per_word
324- ? static_cast <__storage_type>(__v >> __bits_per_word)
325- : static_cast <__storage_type>((__v >> __bits_per_word) &
326- (__storage_type (1 ) << (_Size - __bits_per_word)) - 1 )}
327- # else
328- # error This constructor has not been ported to this platform
329- # endif
354+ : __bitset(__v,
355+ std::__make_indices_imp< (_N_words < (sizeof (unsigned long long ) - 1 ) / sizeof (__storage_type) + 1 )
356+ ? _N_words
357+ : (sizeof (unsigned long long ) - 1 ) / sizeof (__storage_type) + 1 ,
358+ 0 >{})
330359# endif
331360{
332361# ifdef _LIBCPP_CXX03_LANG
333- __init (__v, integral_constant< bool , sizeof (unsigned long long ) <= sizeof (__storage_type)>());
362+ __init (__v, _BoolConstant< sizeof (unsigned long long ) <= sizeof (__storage_type)>());
334363# endif
335364}
336365
@@ -369,58 +398,6 @@ _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 void __bitset<_N_words, _Siz
369398 *__p ^= (__storage_type (1 ) << __n) - 1 ;
370399}
371400
372- template <size_t _N_words, size_t _Size>
373- _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 unsigned long
374- __bitset<_N_words, _Size>::to_ulong(false_type) const {
375- __const_iterator __e = __make_iter (_Size);
376- __const_iterator __i = std::find (__make_iter (sizeof (unsigned long ) * CHAR_BIT), __e, true );
377- if (__i != __e)
378- std::__throw_overflow_error (" bitset to_ulong overflow error" );
379-
380- return __first_[0 ];
381- }
382-
383- template <size_t _N_words, size_t _Size>
384- inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 unsigned long
385- __bitset<_N_words, _Size>::to_ulong(true_type) const {
386- return __first_[0 ];
387- }
388-
389- template <size_t _N_words, size_t _Size>
390- _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 unsigned long long
391- __bitset<_N_words, _Size>::to_ullong(false_type) const {
392- __const_iterator __e = __make_iter (_Size);
393- __const_iterator __i = std::find (__make_iter (sizeof (unsigned long long ) * CHAR_BIT), __e, true );
394- if (__i != __e)
395- std::__throw_overflow_error (" bitset to_ullong overflow error" );
396-
397- return to_ullong (true_type ());
398- }
399-
400- template <size_t _N_words, size_t _Size>
401- inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 unsigned long long
402- __bitset<_N_words, _Size>::to_ullong(true_type) const {
403- return to_ullong (true_type (), integral_constant<bool , sizeof (__storage_type) < sizeof (unsigned long long )>());
404- }
405-
406- template <size_t _N_words, size_t _Size>
407- inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 unsigned long long
408- __bitset<_N_words, _Size>::to_ullong(true_type, false_type) const {
409- return __first_[0 ];
410- }
411-
412- template <size_t _N_words, size_t _Size>
413- _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 unsigned long long
414- __bitset<_N_words, _Size>::to_ullong(true_type, true_type) const {
415- unsigned long long __r = __first_[0 ];
416- _LIBCPP_DIAGNOSTIC_PUSH
417- _LIBCPP_GCC_DIAGNOSTIC_IGNORED (" -Wshift-count-overflow" )
418- for (size_t __i = 1 ; __i < sizeof (unsigned long long ) / sizeof (__storage_type); ++__i)
419- __r |= static_cast <unsigned long long >(__first_[__i]) << (sizeof (__storage_type) * CHAR_BIT);
420- _LIBCPP_DIAGNOSTIC_POP
421- return __r;
422- }
423-
424401template <size_t _N_words, size_t _Size>
425402inline size_t __bitset<_N_words, _Size>::__hash_code() const _NOEXCEPT {
426403 size_t __h = 0 ;
@@ -479,8 +456,25 @@ protected:
479456
480457 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 void flip () _NOEXCEPT;
481458
482- _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 unsigned long to_ulong () const ;
483- _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 unsigned long long to_ullong () const ;
459+ _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 unsigned long to_ulong () const {
460+ if _LIBCPP_CONSTEXPR (_Size > sizeof (unsigned long ) * CHAR_BIT) {
461+ if (auto __e = __make_iter (_Size); std::find (__make_iter (sizeof (unsigned long ) * CHAR_BIT), __e, true ) != __e)
462+ __throw_overflow_error (" __bitset<1, _Size>::to_ulong overflow error" );
463+ }
464+ return static_cast <unsigned long >(__first_);
465+ }
466+
467+ _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 unsigned long long to_ullong () const {
468+ // If _Size exceeds the size of unsigned long long, check for overflow
469+ if _LIBCPP_CONSTEXPR (_Size > sizeof (unsigned long long ) * CHAR_BIT) {
470+ if (auto __e = __make_iter (_Size);
471+ std::find (__make_iter (sizeof (unsigned long long ) * CHAR_BIT), __e, true ) != __e)
472+ __throw_overflow_error (" __bitset<1, _Size>::to_ullong overflow error" );
473+ }
474+
475+ // If _Size fits or no overflow, directly cast to unsigned long long
476+ return static_cast <unsigned long long >(__first_);
477+ }
484478
485479 template <bool _Sparse, class _CharT , class _Traits , class _Allocator >
486480 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 basic_string<_CharT, _Traits, _Allocator>
@@ -507,8 +501,10 @@ inline _LIBCPP_CONSTEXPR __bitset<1, _Size>::__bitset() _NOEXCEPT : __first_(0)
507501
508502template <size_t _Size>
509503inline _LIBCPP_CONSTEXPR __bitset<1 , _Size>::__bitset(unsigned long long __v) _NOEXCEPT
510- : __first_(_Size == __bits_per_word ? static_cast <__storage_type>(__v)
511- : static_cast <__storage_type>(__v) & ((__storage_type(1 ) << _Size) - 1 )) {}
504+ // TODO: We must refer to __bits_per_word in order to work around an issue with the GDB pretty-printers.
505+ // Without it, the pretty-printers complain about a missing __bits_per_word member. This needs to
506+ // be investigated further.
507+ : __first_(_Size == __bits_per_word ? static_cast <__storage_type>(__v) : static_cast <__storage_type>(__v)) {}
512508
513509template <size_t _Size>
514510inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 void
@@ -533,16 +529,6 @@ inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 void __bitset<1, _Siz
533529 __first_ ^= ~__storage_type (0 ) >> (__bits_per_word - _Size);
534530}
535531
536- template <size_t _Size>
537- inline _LIBCPP_CONSTEXPR_SINCE_CXX23 unsigned long __bitset<1 , _Size>::to_ulong() const {
538- return __first_;
539- }
540-
541- template <size_t _Size>
542- inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 unsigned long long __bitset<1 , _Size>::to_ullong() const {
543- return __first_;
544- }
545-
546532template <size_t _Size>
547533inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 bool __bitset<1 , _Size>::all() const _NOEXCEPT {
548534 __storage_type __m = ~__storage_type (0 ) >> (__bits_per_word - _Size);
@@ -633,8 +619,6 @@ class bitset : private __bitset<_Size == 0 ? 0 : (_Size - 1) / (sizeof(size_t) *
633619public:
634620 static const unsigned __n_words = _Size == 0 ? 0 : (_Size - 1 ) / (sizeof (size_t ) * CHAR_BIT) + 1 ;
635621 typedef __bitset<__n_words, _Size> __base;
636-
637- public:
638622 typedef typename __base::reference reference;
639623 typedef typename __base::__const_reference __const_reference;
640624
@@ -713,8 +697,10 @@ public:
713697 _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS (__p < _Size, " bitset::operator[] index out of bounds" );
714698 return __base::__make_ref (__p);
715699 }
716- _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 unsigned long to_ulong () const ;
717- _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 unsigned long long to_ullong () const ;
700+ _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 unsigned long to_ulong () const { return __base::to_ulong (); }
701+ _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 unsigned long long to_ullong () const {
702+ return __base::to_ullong ();
703+ }
718704 template <class _CharT , class _Traits , class _Allocator >
719705 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 basic_string<_CharT, _Traits, _Allocator>
720706 to_string (_CharT __zero = _CharT(' 0' ), _CharT __one = _CharT(' 1' )) const ;
@@ -850,16 +836,6 @@ _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 bitset<_Size>& bitset<_Size>
850836 return *this ;
851837}
852838
853- template <size_t _Size>
854- inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 unsigned long bitset<_Size>::to_ulong() const {
855- return __base::to_ulong ();
856- }
857-
858- template <size_t _Size>
859- inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 unsigned long long bitset<_Size>::to_ullong() const {
860- return __base::to_ullong ();
861- }
862-
863839template <size_t _Size>
864840template <class _CharT , class _Traits , class _Allocator >
865841_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 basic_string<_CharT, _Traits, _Allocator>
0 commit comments