diff --git a/lib/libcxx/include/__algorithm/copy.h b/lib/libcxx/include/__algorithm/copy.h index 962aa90059..ea98031df1 100644 --- a/lib/libcxx/include/__algorithm/copy.h +++ b/lib/libcxx/include/__algorithm/copy.h @@ -13,8 +13,10 @@ #include <__algorithm/for_each_segment.h> #include <__algorithm/min.h> #include <__config> +#include <__fwd/bit_reference.h> #include <__iterator/iterator_traits.h> #include <__iterator/segmented_iterator.h> +#include <__memory/pointer_traits.h> #include <__type_traits/common_type.h> #include <__type_traits/enable_if.h> #include <__utility/move.h> @@ -29,9 +31,129 @@ _LIBCPP_PUSH_MACROS _LIBCPP_BEGIN_NAMESPACE_STD +template +inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _OutputIterator +copy(_InputIterator __first, _InputIterator __last, _OutputIterator __result); + template inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 pair<_InIter, _OutIter> __copy(_InIter, _Sent, _OutIter); +template +_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI __bit_iterator<_Cp, false> __copy_aligned( + __bit_iterator<_Cp, _IsConst> __first, __bit_iterator<_Cp, _IsConst> __last, __bit_iterator<_Cp, false> __result) { + using _In = __bit_iterator<_Cp, _IsConst>; + using difference_type = typename _In::difference_type; + using __storage_type = typename _In::__storage_type; + + const int __bits_per_word = _In::__bits_per_word; + difference_type __n = __last - __first; + if (__n > 0) { + // do first word + if (__first.__ctz_ != 0) { + unsigned __clz = __bits_per_word - __first.__ctz_; + difference_type __dn = std::min(static_cast(__clz), __n); + __n -= __dn; + __storage_type __m = std::__middle_mask<__storage_type>(__clz - __dn, __first.__ctz_); + __storage_type __b = *__first.__seg_ & __m; + *__result.__seg_ &= ~__m; + *__result.__seg_ |= __b; + __result.__seg_ += (__dn + __result.__ctz_) / __bits_per_word; + __result.__ctz_ = static_cast((__dn + __result.__ctz_) % __bits_per_word); + ++__first.__seg_; + // __first.__ctz_ = 0; + } + // __first.__ctz_ == 0; + // do middle words + __storage_type __nw = __n / __bits_per_word; + std::copy(std::__to_address(__first.__seg_), + std::__to_address(__first.__seg_ + __nw), + std::__to_address(__result.__seg_)); + __n -= __nw * __bits_per_word; + __result.__seg_ += __nw; + // do last word + if (__n > 0) { + __first.__seg_ += __nw; + __storage_type __m = std::__trailing_mask<__storage_type>(__bits_per_word - __n); + __storage_type __b = *__first.__seg_ & __m; + *__result.__seg_ &= ~__m; + *__result.__seg_ |= __b; + __result.__ctz_ = static_cast(__n); + } + } + return __result; +} + +template +_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI __bit_iterator<_Cp, false> __copy_unaligned( + __bit_iterator<_Cp, _IsConst> __first, __bit_iterator<_Cp, _IsConst> __last, __bit_iterator<_Cp, false> __result) { + using _In = __bit_iterator<_Cp, _IsConst>; + using difference_type = typename _In::difference_type; + using __storage_type = typename _In::__storage_type; + + const int __bits_per_word = _In::__bits_per_word; + difference_type __n = __last - __first; + if (__n > 0) { + // do first word + if (__first.__ctz_ != 0) { + unsigned __clz_f = __bits_per_word - __first.__ctz_; + difference_type __dn = std::min(static_cast(__clz_f), __n); + __n -= __dn; + __storage_type __m = std::__middle_mask<__storage_type>(__clz_f - __dn, __first.__ctz_); + __storage_type __b = *__first.__seg_ & __m; + unsigned __clz_r = __bits_per_word - __result.__ctz_; + __storage_type __ddn = std::min<__storage_type>(__dn, __clz_r); + __m = std::__middle_mask<__storage_type>(__clz_r - __ddn, __result.__ctz_); + *__result.__seg_ &= ~__m; + if (__result.__ctz_ > __first.__ctz_) + *__result.__seg_ |= __b << (__result.__ctz_ - __first.__ctz_); + else + *__result.__seg_ |= __b >> (__first.__ctz_ - __result.__ctz_); + __result.__seg_ += (__ddn + __result.__ctz_) / __bits_per_word; + __result.__ctz_ = static_cast((__ddn + __result.__ctz_) % __bits_per_word); + __dn -= __ddn; + if (__dn > 0) { + __m = std::__trailing_mask<__storage_type>(__bits_per_word - __dn); + *__result.__seg_ &= ~__m; + *__result.__seg_ |= __b >> (__first.__ctz_ + __ddn); + __result.__ctz_ = static_cast(__dn); + } + ++__first.__seg_; + // __first.__ctz_ = 0; + } + // __first.__ctz_ == 0; + // do middle words + unsigned __clz_r = __bits_per_word - __result.__ctz_; + __storage_type __m = std::__leading_mask<__storage_type>(__result.__ctz_); + for (; __n >= __bits_per_word; __n -= __bits_per_word, ++__first.__seg_) { + __storage_type __b = *__first.__seg_; + *__result.__seg_ &= ~__m; + *__result.__seg_ |= __b << __result.__ctz_; + ++__result.__seg_; + *__result.__seg_ &= __m; + *__result.__seg_ |= __b >> __clz_r; + } + // do last word + if (__n > 0) { + __m = std::__trailing_mask<__storage_type>(__bits_per_word - __n); + __storage_type __b = *__first.__seg_ & __m; + __storage_type __dn = std::min(__n, static_cast(__clz_r)); + __m = std::__middle_mask<__storage_type>(__clz_r - __dn, __result.__ctz_); + *__result.__seg_ &= ~__m; + *__result.__seg_ |= __b << __result.__ctz_; + __result.__seg_ += (__dn + __result.__ctz_) / __bits_per_word; + __result.__ctz_ = static_cast((__dn + __result.__ctz_) % __bits_per_word); + __n -= __dn; + if (__n > 0) { + __m = std::__trailing_mask<__storage_type>(__bits_per_word - __n); + *__result.__seg_ &= ~__m; + *__result.__seg_ |= __b >> __dn; + __result.__ctz_ = static_cast(__n); + } + } + } + return __result; +} + struct __copy_impl { template _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 pair<_InIter, _OutIter> @@ -95,6 +217,16 @@ struct __copy_impl { } } + template + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 pair<__bit_iterator<_Cp, _IsConst>, __bit_iterator<_Cp, false> > + operator()(__bit_iterator<_Cp, _IsConst> __first, + __bit_iterator<_Cp, _IsConst> __last, + __bit_iterator<_Cp, false> __result) const { + if (__first.__ctz_ == __result.__ctz_) + return std::make_pair(__last, std::__copy_aligned(__first, __last, __result)); + return std::make_pair(__last, std::__copy_unaligned(__first, __last, __result)); + } + // At this point, the iterators have been unwrapped so any `contiguous_iterator` has been unwrapped to a pointer. template ::value, int> = 0> _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 pair<_In*, _Out*> @@ -110,7 +242,7 @@ __copy(_InIter __first, _Sent __last, _OutIter __result) { } template -inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _OutputIterator +_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _OutputIterator copy(_InputIterator __first, _InputIterator __last, _OutputIterator __result) { return std::__copy(__first, __last, __result).second; } diff --git a/lib/libcxx/include/__algorithm/copy_backward.h b/lib/libcxx/include/__algorithm/copy_backward.h index 48a768f577..9f890645a4 100644 --- a/lib/libcxx/include/__algorithm/copy_backward.h +++ b/lib/libcxx/include/__algorithm/copy_backward.h @@ -10,11 +10,14 @@ #define _LIBCPP___ALGORITHM_COPY_BACKWARD_H #include <__algorithm/copy_move_common.h> +#include <__algorithm/copy_n.h> #include <__algorithm/iterator_operations.h> #include <__algorithm/min.h> #include <__config> +#include <__fwd/bit_reference.h> #include <__iterator/iterator_traits.h> #include <__iterator/segmented_iterator.h> +#include <__memory/pointer_traits.h> #include <__type_traits/common_type.h> #include <__type_traits/enable_if.h> #include <__type_traits/is_constructible.h> @@ -34,6 +37,124 @@ template _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 pair<_InIter, _OutIter> __copy_backward(_InIter __first, _Sent __last, _OutIter __result); +template +_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI __bit_iterator<_Cp, false> __copy_backward_aligned( + __bit_iterator<_Cp, _IsConst> __first, __bit_iterator<_Cp, _IsConst> __last, __bit_iterator<_Cp, false> __result) { + using _In = __bit_iterator<_Cp, _IsConst>; + using difference_type = typename _In::difference_type; + using __storage_type = typename _In::__storage_type; + + const int __bits_per_word = _In::__bits_per_word; + difference_type __n = __last - __first; + if (__n > 0) { + // do first word + if (__last.__ctz_ != 0) { + difference_type __dn = std::min(static_cast(__last.__ctz_), __n); + __n -= __dn; + unsigned __clz = __bits_per_word - __last.__ctz_; + __storage_type __m = std::__middle_mask<__storage_type>(__clz, __last.__ctz_ - __dn); + __storage_type __b = *__last.__seg_ & __m; + *__result.__seg_ &= ~__m; + *__result.__seg_ |= __b; + __result.__ctz_ = static_cast(((-__dn & (__bits_per_word - 1)) + __result.__ctz_) % __bits_per_word); + // __last.__ctz_ = 0 + } + // __last.__ctz_ == 0 || __n == 0 + // __result.__ctz_ == 0 || __n == 0 + // do middle words + __storage_type __nw = __n / __bits_per_word; + __result.__seg_ -= __nw; + __last.__seg_ -= __nw; + std::copy_n(std::__to_address(__last.__seg_), __nw, std::__to_address(__result.__seg_)); + __n -= __nw * __bits_per_word; + // do last word + if (__n > 0) { + __storage_type __m = std::__leading_mask<__storage_type>(__bits_per_word - __n); + __storage_type __b = *--__last.__seg_ & __m; + *--__result.__seg_ &= ~__m; + *__result.__seg_ |= __b; + __result.__ctz_ = static_cast(-__n & (__bits_per_word - 1)); + } + } + return __result; +} + +template +_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI __bit_iterator<_Cp, false> __copy_backward_unaligned( + __bit_iterator<_Cp, _IsConst> __first, __bit_iterator<_Cp, _IsConst> __last, __bit_iterator<_Cp, false> __result) { + using _In = __bit_iterator<_Cp, _IsConst>; + using difference_type = typename _In::difference_type; + using __storage_type = typename _In::__storage_type; + + const int __bits_per_word = _In::__bits_per_word; + difference_type __n = __last - __first; + if (__n > 0) { + // do first word + if (__last.__ctz_ != 0) { + difference_type __dn = std::min(static_cast(__last.__ctz_), __n); + __n -= __dn; + unsigned __clz_l = __bits_per_word - __last.__ctz_; + __storage_type __m = std::__middle_mask<__storage_type>(__clz_l, __last.__ctz_ - __dn); + __storage_type __b = *__last.__seg_ & __m; + unsigned __clz_r = __bits_per_word - __result.__ctz_; + __storage_type __ddn = std::min(__dn, static_cast(__result.__ctz_)); + if (__ddn > 0) { + __m = std::__middle_mask<__storage_type>(__clz_r, __result.__ctz_ - __ddn); + *__result.__seg_ &= ~__m; + if (__result.__ctz_ > __last.__ctz_) + *__result.__seg_ |= __b << (__result.__ctz_ - __last.__ctz_); + else + *__result.__seg_ |= __b >> (__last.__ctz_ - __result.__ctz_); + __result.__ctz_ = static_cast(((-__ddn & (__bits_per_word - 1)) + __result.__ctz_) % __bits_per_word); + __dn -= __ddn; + } + if (__dn > 0) { + // __result.__ctz_ == 0 + --__result.__seg_; + __result.__ctz_ = static_cast(-__dn & (__bits_per_word - 1)); + __m = std::__leading_mask<__storage_type>(__result.__ctz_); + *__result.__seg_ &= ~__m; + __last.__ctz_ -= __dn + __ddn; + *__result.__seg_ |= __b << (__result.__ctz_ - __last.__ctz_); + } + // __last.__ctz_ = 0 + } + // __last.__ctz_ == 0 || __n == 0 + // __result.__ctz_ != 0 || __n == 0 + // do middle words + unsigned __clz_r = __bits_per_word - __result.__ctz_; + __storage_type __m = std::__trailing_mask<__storage_type>(__clz_r); + for (; __n >= __bits_per_word; __n -= __bits_per_word) { + __storage_type __b = *--__last.__seg_; + *__result.__seg_ &= ~__m; + *__result.__seg_ |= __b >> __clz_r; + *--__result.__seg_ &= __m; + *__result.__seg_ |= __b << __result.__ctz_; + } + // do last word + if (__n > 0) { + __m = std::__leading_mask<__storage_type>(__bits_per_word - __n); + __storage_type __b = *--__last.__seg_ & __m; + __clz_r = __bits_per_word - __result.__ctz_; + __storage_type __dn = std::min(__n, static_cast(__result.__ctz_)); + __m = std::__middle_mask<__storage_type>(__clz_r, __result.__ctz_ - __dn); + *__result.__seg_ &= ~__m; + *__result.__seg_ |= __b >> (__bits_per_word - __result.__ctz_); + __result.__ctz_ = static_cast(((-__dn & (__bits_per_word - 1)) + __result.__ctz_) % __bits_per_word); + __n -= __dn; + if (__n > 0) { + // __result.__ctz_ == 0 + --__result.__seg_; + __result.__ctz_ = static_cast(-__n & (__bits_per_word - 1)); + __m = std::__leading_mask<__storage_type>(__result.__ctz_); + *__result.__seg_ &= ~__m; + *__result.__seg_ |= __b << (__result.__ctz_ - (__bits_per_word - __n - __dn)); + } + } + } + return __result; +} + template struct __copy_backward_impl { template @@ -107,6 +228,16 @@ struct __copy_backward_impl { } } + template + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 pair<__bit_iterator<_Cp, _IsConst>, __bit_iterator<_Cp, false> > + operator()(__bit_iterator<_Cp, _IsConst> __first, + __bit_iterator<_Cp, _IsConst> __last, + __bit_iterator<_Cp, false> __result) { + if (__last.__ctz_ == __result.__ctz_) + return std::make_pair(__last, std::__copy_backward_aligned(__first, __last, __result)); + return std::make_pair(__last, std::__copy_backward_unaligned(__first, __last, __result)); + } + // At this point, the iterators have been unwrapped so any `contiguous_iterator` has been unwrapped to a pointer. template ::value, int> = 0> _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 pair<_In*, _Out*> diff --git a/lib/libcxx/include/__algorithm/count.h b/lib/libcxx/include/__algorithm/count.h index cd9125779e..0cbe9b6e61 100644 --- a/lib/libcxx/include/__algorithm/count.h +++ b/lib/libcxx/include/__algorithm/count.h @@ -55,18 +55,18 @@ __count_bool(__bit_iterator<_Cp, _IsConst> __first, typename __size_difference_t if (__first.__ctz_ != 0) { __storage_type __clz_f = static_cast<__storage_type>(__bits_per_word - __first.__ctz_); __storage_type __dn = std::min(__clz_f, __n); - __storage_type __m = (~__storage_type(0) << __first.__ctz_) & (~__storage_type(0) >> (__clz_f - __dn)); - __r = std::__libcpp_popcount(std::__invert_if(*__first.__seg_) & __m); + __storage_type __m = std::__middle_mask<__storage_type>(__clz_f - __dn, __first.__ctz_); + __r = std::__popcount(__storage_type(std::__invert_if(*__first.__seg_) & __m)); __n -= __dn; ++__first.__seg_; } // do middle whole words for (; __n >= __bits_per_word; ++__first.__seg_, __n -= __bits_per_word) - __r += std::__libcpp_popcount(std::__invert_if(*__first.__seg_)); + __r += std::__popcount(std::__invert_if(*__first.__seg_)); // do last partial word if (__n > 0) { - __storage_type __m = ~__storage_type(0) >> (__bits_per_word - __n); - __r += std::__libcpp_popcount(std::__invert_if(*__first.__seg_) & __m); + __storage_type __m = std::__trailing_mask<__storage_type>(__bits_per_word - __n); + __r += std::__popcount(__storage_type(std::__invert_if(*__first.__seg_) & __m)); } return __r; } diff --git a/lib/libcxx/include/__algorithm/equal.h b/lib/libcxx/include/__algorithm/equal.h index a276bb9954..5a8c9504ed 100644 --- a/lib/libcxx/include/__algorithm/equal.h +++ b/lib/libcxx/include/__algorithm/equal.h @@ -11,16 +11,20 @@ #define _LIBCPP___ALGORITHM_EQUAL_H #include <__algorithm/comp.h> +#include <__algorithm/min.h> #include <__algorithm/unwrap_iter.h> #include <__config> #include <__functional/identity.h> +#include <__fwd/bit_reference.h> #include <__iterator/distance.h> #include <__iterator/iterator_traits.h> +#include <__memory/pointer_traits.h> #include <__string/constexpr_c_functions.h> #include <__type_traits/desugars_to.h> #include <__type_traits/enable_if.h> #include <__type_traits/invoke.h> #include <__type_traits/is_equality_comparable.h> +#include <__type_traits/is_same.h> #include <__type_traits/is_volatile.h> #include <__utility/move.h> @@ -33,6 +37,140 @@ _LIBCPP_PUSH_MACROS _LIBCPP_BEGIN_NAMESPACE_STD +template +[[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI bool +__equal_unaligned(__bit_iterator<_Cp, _IsConst1> __first1, + __bit_iterator<_Cp, _IsConst1> __last1, + __bit_iterator<_Cp, _IsConst2> __first2) { + using _It = __bit_iterator<_Cp, _IsConst1>; + using difference_type = typename _It::difference_type; + using __storage_type = typename _It::__storage_type; + + const int __bits_per_word = _It::__bits_per_word; + difference_type __n = __last1 - __first1; + if (__n > 0) { + // do first word + if (__first1.__ctz_ != 0) { + unsigned __clz_f = __bits_per_word - __first1.__ctz_; + difference_type __dn = std::min(static_cast(__clz_f), __n); + __n -= __dn; + __storage_type __m = std::__middle_mask<__storage_type>(__clz_f - __dn, __first1.__ctz_); + __storage_type __b = *__first1.__seg_ & __m; + unsigned __clz_r = __bits_per_word - __first2.__ctz_; + __storage_type __ddn = std::min<__storage_type>(__dn, __clz_r); + __m = std::__middle_mask<__storage_type>(__clz_r - __ddn, __first2.__ctz_); + if (__first2.__ctz_ > __first1.__ctz_) { + if (static_cast<__storage_type>(*__first2.__seg_ & __m) != + static_cast<__storage_type>(__b << (__first2.__ctz_ - __first1.__ctz_))) + return false; + } else { + if (static_cast<__storage_type>(*__first2.__seg_ & __m) != + static_cast<__storage_type>(__b >> (__first1.__ctz_ - __first2.__ctz_))) + return false; + } + __first2.__seg_ += (__ddn + __first2.__ctz_) / __bits_per_word; + __first2.__ctz_ = static_cast((__ddn + __first2.__ctz_) % __bits_per_word); + __dn -= __ddn; + if (__dn > 0) { + __m = std::__trailing_mask<__storage_type>(__bits_per_word - __n); + if (static_cast<__storage_type>(*__first2.__seg_ & __m) != + static_cast<__storage_type>(__b >> (__first1.__ctz_ + __ddn))) + return false; + __first2.__ctz_ = static_cast(__dn); + } + ++__first1.__seg_; + // __first1.__ctz_ = 0; + } + // __first1.__ctz_ == 0; + // do middle words + unsigned __clz_r = __bits_per_word - __first2.__ctz_; + __storage_type __m = std::__leading_mask<__storage_type>(__first2.__ctz_); + for (; __n >= __bits_per_word; __n -= __bits_per_word, ++__first1.__seg_) { + __storage_type __b = *__first1.__seg_; + if (static_cast<__storage_type>(*__first2.__seg_ & __m) != static_cast<__storage_type>(__b << __first2.__ctz_)) + return false; + ++__first2.__seg_; + if (static_cast<__storage_type>(*__first2.__seg_ & static_cast<__storage_type>(~__m)) != + static_cast<__storage_type>(__b >> __clz_r)) + return false; + } + // do last word + if (__n > 0) { + __m = std::__trailing_mask<__storage_type>(__bits_per_word - __n); + __storage_type __b = *__first1.__seg_ & __m; + __storage_type __dn = std::min(__n, static_cast(__clz_r)); + __m = std::__middle_mask<__storage_type>(__clz_r - __dn, __first2.__ctz_); + if (static_cast<__storage_type>(*__first2.__seg_ & __m) != static_cast<__storage_type>(__b << __first2.__ctz_)) + return false; + __first2.__seg_ += (__dn + __first2.__ctz_) / __bits_per_word; + __first2.__ctz_ = static_cast((__dn + __first2.__ctz_) % __bits_per_word); + __n -= __dn; + if (__n > 0) { + __m = std::__trailing_mask<__storage_type>(__bits_per_word - __n); + if (static_cast<__storage_type>(*__first2.__seg_ & __m) != static_cast<__storage_type>(__b >> __dn)) + return false; + } + } + } + return true; +} + +template +[[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI bool +__equal_aligned(__bit_iterator<_Cp, _IsConst1> __first1, + __bit_iterator<_Cp, _IsConst1> __last1, + __bit_iterator<_Cp, _IsConst2> __first2) { + using _It = __bit_iterator<_Cp, _IsConst1>; + using difference_type = typename _It::difference_type; + using __storage_type = typename _It::__storage_type; + + const int __bits_per_word = _It::__bits_per_word; + difference_type __n = __last1 - __first1; + if (__n > 0) { + // do first word + if (__first1.__ctz_ != 0) { + unsigned __clz = __bits_per_word - __first1.__ctz_; + difference_type __dn = std::min(static_cast(__clz), __n); + __n -= __dn; + __storage_type __m = std::__middle_mask<__storage_type>(__clz - __dn, __first1.__ctz_); + if ((*__first2.__seg_ & __m) != (*__first1.__seg_ & __m)) + return false; + ++__first2.__seg_; + ++__first1.__seg_; + // __first1.__ctz_ = 0; + // __first2.__ctz_ = 0; + } + // __first1.__ctz_ == 0; + // __first2.__ctz_ == 0; + // do middle words + for (; __n >= __bits_per_word; __n -= __bits_per_word, ++__first1.__seg_, ++__first2.__seg_) + if (*__first2.__seg_ != *__first1.__seg_) + return false; + // do last word + if (__n > 0) { + __storage_type __m = std::__trailing_mask<__storage_type>(__bits_per_word - __n); + if ((*__first2.__seg_ & __m) != (*__first1.__seg_ & __m)) + return false; + } + } + return true; +} + +template , int> = 0> +[[__nodiscard__]] inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 bool __equal_iter_impl( + __bit_iterator<_Cp, _IsConst1> __first1, + __bit_iterator<_Cp, _IsConst1> __last1, + __bit_iterator<_Cp, _IsConst2> __first2, + _BinaryPredicate) { + if (__first1.__ctz_ == __first2.__ctz_) + return std::__equal_aligned(__first1, __last1, __first2); + return std::__equal_unaligned(__first1, __last1, __first2); +} + template [[__nodiscard__]] inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 bool __equal_iter_impl( _InputIterator1 __first1, _InputIterator1 __last1, _InputIterator2 __first2, _BinaryPredicate& __pred) { @@ -94,6 +232,28 @@ __equal_impl(_Tp* __first1, _Tp* __last1, _Up* __first2, _Up*, _Pred&, _Proj1&, return std::__constexpr_memcmp_equal(__first1, __first2, __element_count(__last1 - __first1)); } +template && __is_identity<_Proj1>::value && + __is_identity<_Proj2>::value, + int> = 0> +[[__nodiscard__]] inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 bool __equal_impl( + __bit_iterator<_Cp, _IsConst1> __first1, + __bit_iterator<_Cp, _IsConst1> __last1, + __bit_iterator<_Cp, _IsConst2> __first2, + __bit_iterator<_Cp, _IsConst2>, + _Pred&, + _Proj1&, + _Proj2&) { + if (__first1.__ctz_ == __first2.__ctz_) + return std::__equal_aligned(__first1, __last1, __first2); + return std::__equal_unaligned(__first1, __last1, __first2); +} + template [[__nodiscard__]] inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 bool equal(_InputIterator1 __first1, diff --git a/lib/libcxx/include/__algorithm/fill_n.h b/lib/libcxx/include/__algorithm/fill_n.h index a7e01c45b9..0da78e1f38 100644 --- a/lib/libcxx/include/__algorithm/fill_n.h +++ b/lib/libcxx/include/__algorithm/fill_n.h @@ -41,11 +41,7 @@ __fill_n_bool(__bit_iterator<_Cp, false> __first, typename __size_difference_typ if (__first.__ctz_ != 0) { __storage_type __clz_f = static_cast<__storage_type>(__bits_per_word - __first.__ctz_); __storage_type __dn = std::min(__clz_f, __n); - __storage_type __m = (~__storage_type(0) << __first.__ctz_) & (~__storage_type(0) >> (__clz_f - __dn)); - if (_FillVal) - *__first.__seg_ |= __m; - else - *__first.__seg_ &= ~__m; + std::__fill_masked_range(std::__to_address(__first.__seg_), __clz_f - __dn, __first.__ctz_, _FillVal); __n -= __dn; ++__first.__seg_; } @@ -56,11 +52,7 @@ __fill_n_bool(__bit_iterator<_Cp, false> __first, typename __size_difference_typ // do last partial word if (__n > 0) { __first.__seg_ += __nw; - __storage_type __m = ~__storage_type(0) >> (__bits_per_word - __n); - if (_FillVal) - *__first.__seg_ |= __m; - else - *__first.__seg_ &= ~__m; + std::__fill_masked_range(std::__to_address(__first.__seg_), __bits_per_word - __n, 0u, _FillVal); } } diff --git a/lib/libcxx/include/__algorithm/find.h b/lib/libcxx/include/__algorithm/find.h index 24b8b2f964..a7d9374b3a 100644 --- a/lib/libcxx/include/__algorithm/find.h +++ b/lib/libcxx/include/__algorithm/find.h @@ -106,10 +106,10 @@ __find_bool(__bit_iterator<_Cp, _IsConst> __first, typename __size_difference_ty if (__first.__ctz_ != 0) { __storage_type __clz_f = static_cast<__storage_type>(__bits_per_word - __first.__ctz_); __storage_type __dn = std::min(__clz_f, __n); - __storage_type __m = (~__storage_type(0) << __first.__ctz_) & (~__storage_type(0) >> (__clz_f - __dn)); + __storage_type __m = std::__middle_mask<__storage_type>(__clz_f - __dn, __first.__ctz_); __storage_type __b = std::__invert_if(*__first.__seg_) & __m; if (__b) - return _It(__first.__seg_, static_cast(std::__libcpp_ctz(__b))); + return _It(__first.__seg_, static_cast(std::__countr_zero(__b))); if (__n == __dn) return __first + __n; __n -= __dn; @@ -119,14 +119,14 @@ __find_bool(__bit_iterator<_Cp, _IsConst> __first, typename __size_difference_ty for (; __n >= __bits_per_word; ++__first.__seg_, __n -= __bits_per_word) { __storage_type __b = std::__invert_if(*__first.__seg_); if (__b) - return _It(__first.__seg_, static_cast(std::__libcpp_ctz(__b))); + return _It(__first.__seg_, static_cast(std::__countr_zero(__b))); } // do last partial word if (__n > 0) { - __storage_type __m = ~__storage_type(0) >> (__bits_per_word - __n); + __storage_type __m = std::__trailing_mask<__storage_type>(__bits_per_word - __n); __storage_type __b = std::__invert_if(*__first.__seg_) & __m; if (__b) - return _It(__first.__seg_, static_cast(std::__libcpp_ctz(__b))); + return _It(__first.__seg_, static_cast(std::__countr_zero(__b))); } return _It(__first.__seg_, static_cast(__n)); } diff --git a/lib/libcxx/include/__algorithm/for_each.h b/lib/libcxx/include/__algorithm/for_each.h index e08f583504..4167eec350 100644 --- a/lib/libcxx/include/__algorithm/for_each.h +++ b/lib/libcxx/include/__algorithm/for_each.h @@ -12,9 +12,10 @@ #include <__algorithm/for_each_segment.h> #include <__config> +#include <__functional/identity.h> #include <__iterator/segmented_iterator.h> -#include <__ranges/movable_box.h> -#include <__utility/in_place.h> +#include <__type_traits/enable_if.h> +#include <__type_traits/invoke.h> #include <__utility/move.h> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) @@ -26,28 +27,36 @@ _LIBCPP_PUSH_MACROS _LIBCPP_BEGIN_NAMESPACE_STD -template -_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _Function -for_each(_InputIterator __first, _InputIterator __last, _Function __f) { +template +_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _InputIterator +__for_each(_InputIterator __first, _Sent __last, _Func& __f, _Proj& __proj) { for (; __first != __last; ++__first) - __f(*__first); - return __f; + std::__invoke(__f, std::__invoke(__proj, *__first)); + return __first; } -// __movable_box is available in C++20, but is actually a copyable-box, so optimization is only correct in C++23 -#if _LIBCPP_STD_VER >= 23 -template - requires __is_segmented_iterator<_SegmentedIterator>::value -_LIBCPP_HIDE_FROM_ABI constexpr _Function -for_each(_SegmentedIterator __first, _SegmentedIterator __last, _Function __func) { - ranges::__movable_box<_Function> __wrapped_func(in_place, std::move(__func)); - std::__for_each_segment(__first, __last, [&](auto __lfirst, auto __llast) { - __wrapped_func = - ranges::__movable_box<_Function>(in_place, std::for_each(__lfirst, __llast, std::move(*__wrapped_func))); +#ifndef _LIBCPP_CXX03_LANG +template ::value, int> = 0> +_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _SegmentedIterator +__for_each(_SegmentedIterator __first, _SegmentedIterator __last, _Func& __func, _Proj& __proj) { + using __local_iterator_t = typename __segmented_iterator_traits<_SegmentedIterator>::__local_iterator; + std::__for_each_segment(__first, __last, [&](__local_iterator_t __lfirst, __local_iterator_t __llast) { + std::__for_each(__lfirst, __llast, __func, __proj); }); - return std::move(*__wrapped_func); + return __last; +} +#endif // !_LIBCPP_CXX03_LANG + +template +_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _Func +for_each(_InputIterator __first, _InputIterator __last, _Func __f) { + __identity __proj; + std::__for_each(__first, __last, __f, __proj); + return __f; } -#endif // _LIBCPP_STD_VER >= 23 _LIBCPP_END_NAMESPACE_STD diff --git a/lib/libcxx/include/__algorithm/for_each_n.h b/lib/libcxx/include/__algorithm/for_each_n.h index fce380b49d..9a6c6bb517 100644 --- a/lib/libcxx/include/__algorithm/for_each_n.h +++ b/lib/libcxx/include/__algorithm/for_each_n.h @@ -10,32 +10,93 @@ #ifndef _LIBCPP___ALGORITHM_FOR_EACH_N_H #define _LIBCPP___ALGORITHM_FOR_EACH_N_H +#include <__algorithm/for_each.h> +#include <__algorithm/for_each_n_segment.h> #include <__config> +#include <__functional/identity.h> +#include <__iterator/iterator_traits.h> +#include <__iterator/segmented_iterator.h> +#include <__type_traits/disjunction.h> +#include <__type_traits/enable_if.h> +#include <__type_traits/invoke.h> +#include <__type_traits/negation.h> #include <__utility/convert_to_integral.h> +#include <__utility/move.h> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # pragma GCC system_header #endif +_LIBCPP_PUSH_MACROS +#include <__undef_macros> + _LIBCPP_BEGIN_NAMESPACE_STD -#if _LIBCPP_STD_VER >= 17 - -template -inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _InputIterator -for_each_n(_InputIterator __first, _Size __orig_n, _Function __f) { +template ::value && + _Or< _Not<__is_segmented_iterator<_InputIterator> >, + _Not<__has_random_access_local_iterator<_InputIterator> > >::value, + int> = 0> +_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _InputIterator +__for_each_n(_InputIterator __first, _Size __orig_n, _Func& __f, _Proj& __proj) { typedef decltype(std::__convert_to_integral(__orig_n)) _IntegralSize; _IntegralSize __n = __orig_n; while (__n > 0) { - __f(*__first); + std::__invoke(__f, std::__invoke(__proj, *__first)); ++__first; --__n; } - return __first; + return std::move(__first); } -#endif +template ::value, int> = 0> +_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _RandIter +__for_each_n(_RandIter __first, _Size __orig_n, _Func& __f, _Proj& __proj) { + typename std::iterator_traits<_RandIter>::difference_type __n = __orig_n; + auto __last = __first + __n; + std::__for_each(__first, __last, __f, __proj); + return __last; +} + +#ifndef _LIBCPP_CXX03_LANG +template ::value && + __is_segmented_iterator<_SegmentedIterator>::value && + __has_random_access_iterator_category< + typename __segmented_iterator_traits<_SegmentedIterator>::__local_iterator>::value, + int> = 0> +_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _SegmentedIterator +__for_each_n(_SegmentedIterator __first, _Size __orig_n, _Func& __f, _Proj& __proj) { + using __local_iterator_t = typename __segmented_iterator_traits<_SegmentedIterator>::__local_iterator; + return std::__for_each_n_segment(__first, __orig_n, [&](__local_iterator_t __lfirst, __local_iterator_t __llast) { + std::__for_each(__lfirst, __llast, __f, __proj); + }); +} +#endif // !_LIBCPP_CXX03_LANG + +#if _LIBCPP_STD_VER >= 17 + +template +inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _InputIterator +for_each_n(_InputIterator __first, _Size __orig_n, _Func __f) { + __identity __proj; + return std::__for_each_n(__first, __orig_n, __f, __proj); +} + +#endif // _LIBCPP_STD_VER >= 17 _LIBCPP_END_NAMESPACE_STD +_LIBCPP_POP_MACROS + #endif // _LIBCPP___ALGORITHM_FOR_EACH_N_H diff --git a/lib/libcxx/include/__algorithm/for_each_n_segment.h b/lib/libcxx/include/__algorithm/for_each_n_segment.h new file mode 100644 index 0000000000..1b522fb373 --- /dev/null +++ b/lib/libcxx/include/__algorithm/for_each_n_segment.h @@ -0,0 +1,63 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___ALGORITHM_FOR_EACH_N_SEGMENT_H +#define _LIBCPP___ALGORITHM_FOR_EACH_N_SEGMENT_H + +#include <__config> +#include <__iterator/iterator_traits.h> +#include <__iterator/segmented_iterator.h> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +// __for_each_n_segment optimizes linear iteration over segmented iterators. It processes a segmented +// input range [__first, __first + __n) by applying the functor __func to each element within the segment. +// The return value of __func is ignored, and the function returns an iterator pointing to one past the +// last processed element in the input range. + +template +_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 _SegmentedIterator +__for_each_n_segment(_SegmentedIterator __first, _Size __orig_n, _Functor __func) { + static_assert(__is_segmented_iterator<_SegmentedIterator>::value && + __has_random_access_iterator_category< + typename __segmented_iterator_traits<_SegmentedIterator>::__local_iterator>::value, + "__for_each_n_segment only works with segmented iterators with random-access local iterators"); + if (__orig_n <= 0) + return __first; + + using _Traits = __segmented_iterator_traits<_SegmentedIterator>; + using __local_iter_t = typename _Traits::__local_iterator; + using __difference_t = typename std::iterator_traits<__local_iter_t>::difference_type; + __difference_t __n = __orig_n; + auto __seg = _Traits::__segment(__first); + auto __local_first = _Traits::__local(__first); + __local_iter_t __local_last; + + while (__n > 0) { + __local_last = _Traits::__end(__seg); + auto __seg_size = __local_last - __local_first; + if (__n <= __seg_size) { + __local_last = __local_first + __n; + __func(__local_first, __local_last); + break; + } + __func(__local_first, __local_last); + __n -= __seg_size; + __local_first = _Traits::__begin(++__seg); + } + + return _Traits::__compose(__seg, __local_last); +} + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___ALGORITHM_FOR_EACH_N_SEGMENT_H diff --git a/lib/libcxx/include/__algorithm/inplace_merge.h b/lib/libcxx/include/__algorithm/inplace_merge.h index 1fc31b66f4..fbfe89936d 100644 --- a/lib/libcxx/include/__algorithm/inplace_merge.h +++ b/lib/libcxx/include/__algorithm/inplace_merge.h @@ -22,6 +22,7 @@ #include <__functional/identity.h> #include <__iterator/iterator_traits.h> #include <__iterator/reverse_iterator.h> +#include <__memory/construct_at.h> #include <__memory/destruct_n.h> #include <__memory/unique_ptr.h> #include <__memory/unique_temporary_buffer.h> @@ -106,13 +107,13 @@ _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 void __buffered_inplace_merg value_type* __p = __buff; for (_BidirectionalIterator __i = __first; __i != __middle; __d.template __incr(), (void)++__i, (void)++__p) - ::new ((void*)__p) value_type(_IterOps<_AlgPolicy>::__iter_move(__i)); + std::__construct_at(__p, _IterOps<_AlgPolicy>::__iter_move(__i)); std::__half_inplace_merge<_AlgPolicy>(__buff, __p, __middle, __last, __first, __comp); } else { value_type* __p = __buff; for (_BidirectionalIterator __i = __middle; __i != __last; __d.template __incr(), (void)++__i, (void)++__p) - ::new ((void*)__p) value_type(_IterOps<_AlgPolicy>::__iter_move(__i)); + std::__construct_at(__p, _IterOps<_AlgPolicy>::__iter_move(__i)); typedef reverse_iterator<_BidirectionalIterator> _RBi; typedef reverse_iterator _Rv; typedef __invert<_Compare> _Inverted; @@ -203,7 +204,7 @@ _LIBCPP_CONSTEXPR_SINCE_CXX26 void __inplace_merge( } template -_LIBCPP_HIDE_FROM_ABI void __inplace_merge( +_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 void __inplace_merge( _BidirectionalIterator __first, _BidirectionalIterator __middle, _BidirectionalIterator __last, _Compare&& __comp) { typedef typename iterator_traits<_BidirectionalIterator>::value_type value_type; typedef typename iterator_traits<_BidirectionalIterator>::difference_type difference_type; @@ -223,14 +224,14 @@ _LIBCPP_HIDE_FROM_ABI void __inplace_merge( } template -inline _LIBCPP_HIDE_FROM_ABI void inplace_merge( +inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 void inplace_merge( _BidirectionalIterator __first, _BidirectionalIterator __middle, _BidirectionalIterator __last, _Compare __comp) { std::__inplace_merge<_ClassicAlgPolicy>( std::move(__first), std::move(__middle), std::move(__last), static_cast<__comp_ref_type<_Compare> >(__comp)); } template -inline _LIBCPP_HIDE_FROM_ABI void +inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 void inplace_merge(_BidirectionalIterator __first, _BidirectionalIterator __middle, _BidirectionalIterator __last) { std::inplace_merge(std::move(__first), std::move(__middle), std::move(__last), __less<>()); } diff --git a/lib/libcxx/include/__algorithm/min_element.h b/lib/libcxx/include/__algorithm/min_element.h index db996365bf..fdab63aefe 100644 --- a/lib/libcxx/include/__algorithm/min_element.h +++ b/lib/libcxx/include/__algorithm/min_element.h @@ -29,7 +29,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD template inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 _Iter -__min_element(_Iter __first, _Sent __last, _Comp __comp, _Proj& __proj) { +__min_element(_Iter __first, _Sent __last, _Comp& __comp, _Proj& __proj) { if (__first == __last) return __first; diff --git a/lib/libcxx/include/__algorithm/move.h b/lib/libcxx/include/__algorithm/move.h index 6f3b0eb5d2..a3320e9f19 100644 --- a/lib/libcxx/include/__algorithm/move.h +++ b/lib/libcxx/include/__algorithm/move.h @@ -9,11 +9,13 @@ #ifndef _LIBCPP___ALGORITHM_MOVE_H #define _LIBCPP___ALGORITHM_MOVE_H +#include <__algorithm/copy.h> #include <__algorithm/copy_move_common.h> #include <__algorithm/for_each_segment.h> #include <__algorithm/iterator_operations.h> #include <__algorithm/min.h> #include <__config> +#include <__fwd/bit_reference.h> #include <__iterator/iterator_traits.h> #include <__iterator/segmented_iterator.h> #include <__type_traits/common_type.h> @@ -98,6 +100,14 @@ struct __move_impl { } } + template + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 pair<__bit_iterator<_Cp, _IsConst>, __bit_iterator<_Cp, false> > + operator()(__bit_iterator<_Cp, _IsConst> __first, + __bit_iterator<_Cp, _IsConst> __last, + __bit_iterator<_Cp, false> __result) { + return std::__copy(__first, __last, __result); + } + // At this point, the iterators have been unwrapped so any `contiguous_iterator` has been unwrapped to a pointer. template ::value, int> = 0> _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 pair<_In*, _Out*> diff --git a/lib/libcxx/include/__algorithm/move_backward.h b/lib/libcxx/include/__algorithm/move_backward.h index 24a8d9b245..14482fee18 100644 --- a/lib/libcxx/include/__algorithm/move_backward.h +++ b/lib/libcxx/include/__algorithm/move_backward.h @@ -9,10 +9,12 @@ #ifndef _LIBCPP___ALGORITHM_MOVE_BACKWARD_H #define _LIBCPP___ALGORITHM_MOVE_BACKWARD_H +#include <__algorithm/copy_backward.h> #include <__algorithm/copy_move_common.h> #include <__algorithm/iterator_operations.h> #include <__algorithm/min.h> #include <__config> +#include <__fwd/bit_reference.h> #include <__iterator/iterator_traits.h> #include <__iterator/segmented_iterator.h> #include <__type_traits/common_type.h> @@ -107,6 +109,14 @@ struct __move_backward_impl { } } + template + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 pair<__bit_iterator<_Cp, _IsConst>, __bit_iterator<_Cp, false> > + operator()(__bit_iterator<_Cp, _IsConst> __first, + __bit_iterator<_Cp, _IsConst> __last, + __bit_iterator<_Cp, false> __result) { + return std::__copy_backward<_ClassicAlgPolicy>(__first, __last, __result); + } + // At this point, the iterators have been unwrapped so any `contiguous_iterator` has been unwrapped to a pointer. template ::value, int> = 0> _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 pair<_In*, _Out*> diff --git a/lib/libcxx/include/__algorithm/out_value_result.h b/lib/libcxx/include/__algorithm/out_value_result.h new file mode 100644 index 0000000000..9e1e0e0728 --- /dev/null +++ b/lib/libcxx/include/__algorithm/out_value_result.h @@ -0,0 +1,56 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___ALGORITHM_OUT_VALUE_RESULT_H +#define _LIBCPP___ALGORITHM_OUT_VALUE_RESULT_H + +#include <__concepts/convertible_to.h> +#include <__config> +#include <__utility/move.h> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_PUSH_MACROS +#include <__undef_macros> + +_LIBCPP_BEGIN_NAMESPACE_STD + +#if _LIBCPP_STD_VER >= 23 + +namespace ranges { + +template +struct out_value_result { + _LIBCPP_NO_UNIQUE_ADDRESS _OutIter1 out; + _LIBCPP_NO_UNIQUE_ADDRESS _ValType1 value; + + template + requires convertible_to && convertible_to + _LIBCPP_HIDE_FROM_ABI constexpr operator out_value_result<_OutIter2, _ValType2>() const& { + return {out, value}; + } + + template + requires convertible_to<_OutIter1, _OutIter2> && convertible_to<_ValType1, _ValType2> + _LIBCPP_HIDE_FROM_ABI constexpr operator out_value_result<_OutIter2, _ValType2>() && { + return {std::move(out), std::move(value)}; + } +}; + +} // namespace ranges + +#endif // _LIBCPP_STD_VER >= 23 + +_LIBCPP_END_NAMESPACE_STD + +_LIBCPP_POP_MACROS + +#endif // _LIBCPP___ALGORITHM_OUT_VALUE_RESULT_H diff --git a/lib/libcxx/include/__algorithm/radix_sort.h b/lib/libcxx/include/__algorithm/radix_sort.h index de6927995e..055d8a0765 100644 --- a/lib/libcxx/include/__algorithm/radix_sort.h +++ b/lib/libcxx/include/__algorithm/radix_sort.h @@ -29,10 +29,12 @@ #include <__algorithm/for_each.h> #include <__algorithm/move.h> +#include <__bit/bit_cast.h> #include <__bit/bit_log2.h> -#include <__bit/countl.h> #include <__config> +#include <__cstddef/size_t.h> #include <__functional/identity.h> +#include <__iterator/access.h> #include <__iterator/distance.h> #include <__iterator/iterator_traits.h> #include <__iterator/move_iterator.h> @@ -43,9 +45,12 @@ #include <__type_traits/enable_if.h> #include <__type_traits/invoke.h> #include <__type_traits/is_assignable.h> +#include <__type_traits/is_enum.h> #include <__type_traits/is_integral.h> #include <__type_traits/is_unsigned.h> #include <__type_traits/make_unsigned.h> +#include <__type_traits/void_t.h> +#include <__utility/declval.h> #include <__utility/forward.h> #include <__utility/integer_sequence.h> #include <__utility/move.h> @@ -67,7 +72,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD #if _LIBCPP_STD_VER >= 14 template -_LIBCPP_HIDE_FROM_ABI pair<_OutputIterator, __iter_value_type<_InputIterator>> +_LIBCPP_HIDE_FROM_ABI constexpr pair<_OutputIterator, __iter_value_type<_InputIterator>> __partial_sum_max(_InputIterator __first, _InputIterator __last, _OutputIterator __result) { if (__first == __last) return {__result, 0}; @@ -109,7 +114,7 @@ struct __counting_sort_traits { }; template -_LIBCPP_HIDE_FROM_ABI auto __nth_radix(size_t __radix_number, _Radix __radix, _Integer __n) { +_LIBCPP_HIDE_FROM_ABI constexpr auto __nth_radix(size_t __radix_number, _Radix __radix, _Integer __n) { static_assert(is_unsigned<_Integer>::value); using __traits = __counting_sort_traits<_Integer, _Radix>; @@ -117,7 +122,7 @@ _LIBCPP_HIDE_FROM_ABI auto __nth_radix(size_t __radix_number, _Radix __radix, _I } template -_LIBCPP_HIDE_FROM_ABI void +_LIBCPP_HIDE_FROM_ABI constexpr void __collect(_ForwardIterator __first, _ForwardIterator __last, _Map __map, _RandomAccessIterator __counters) { using __value_type = __iter_value_type<_ForwardIterator>; using __traits = __counting_sort_traits<__value_type, _Map>; @@ -129,7 +134,7 @@ __collect(_ForwardIterator __first, _ForwardIterator __last, _Map __map, _Random } template -_LIBCPP_HIDE_FROM_ABI void +_LIBCPP_HIDE_FROM_ABI constexpr void __dispose(_ForwardIterator __first, _ForwardIterator __last, _RandomAccessIterator1 __result, @@ -147,7 +152,7 @@ template -_LIBCPP_HIDE_FROM_ABI bool __collect_impl( +_LIBCPP_HIDE_FROM_ABI constexpr bool __collect_impl( _ForwardIterator __first, _ForwardIterator __last, _Map __map, @@ -177,7 +182,7 @@ _LIBCPP_HIDE_FROM_ABI bool __collect_impl( } template -_LIBCPP_HIDE_FROM_ABI bool +_LIBCPP_HIDE_FROM_ABI constexpr bool __collect(_ForwardIterator __first, _ForwardIterator __last, _Map __map, @@ -191,7 +196,7 @@ __collect(_ForwardIterator __first, } template -_LIBCPP_HIDE_FROM_ABI void __dispose_backward( +_LIBCPP_HIDE_FROM_ABI constexpr void __dispose_backward( _BidirectionalIterator __first, _BidirectionalIterator __last, _RandomAccessIterator1 __result, @@ -206,7 +211,7 @@ _LIBCPP_HIDE_FROM_ABI void __dispose_backward( } template -_LIBCPP_HIDE_FROM_ABI _RandomAccessIterator +_LIBCPP_HIDE_FROM_ABI constexpr _RandomAccessIterator __counting_sort_impl(_ForwardIterator __first, _ForwardIterator __last, _RandomAccessIterator __result, _Map __map) { using __value_type = __iter_value_type<_ForwardIterator>; using __traits = __counting_sort_traits<__value_type, _Map>; @@ -225,7 +230,7 @@ template , _Map, _Radix>::__radix_count == 1, int> = 0> -_LIBCPP_HIDE_FROM_ABI void __radix_sort_impl( +_LIBCPP_HIDE_FROM_ABI constexpr void __radix_sort_impl( _RandomAccessIterator1 __first, _RandomAccessIterator1 __last, _RandomAccessIterator2 __buffer, @@ -245,7 +250,7 @@ template < class _Radix, enable_if_t< __radix_sort_traits<__iter_value_type<_RandomAccessIterator1>, _Map, _Radix>::__radix_count % 2 == 0, int> = 0 > -_LIBCPP_HIDE_FROM_ABI void __radix_sort_impl( +_LIBCPP_HIDE_FROM_ABI constexpr void __radix_sort_impl( _RandomAccessIterator1 __first, _RandomAccessIterator1 __last, _RandomAccessIterator2 __buffer_begin, @@ -297,6 +302,96 @@ _LIBCPP_HIDE_FROM_ABI constexpr auto __shift_to_unsigned(_Ip __n) { return static_cast >(__n ^ __min_value); } +template +struct __unsigned_integer_of_size; + +template <> +struct __unsigned_integer_of_size<1> { + using type _LIBCPP_NODEBUG = uint8_t; +}; + +template <> +struct __unsigned_integer_of_size<2> { + using type _LIBCPP_NODEBUG = uint16_t; +}; + +template <> +struct __unsigned_integer_of_size<4> { + using type _LIBCPP_NODEBUG = uint32_t; +}; + +template <> +struct __unsigned_integer_of_size<8> { + using type _LIBCPP_NODEBUG = uint64_t; +}; + +# if _LIBCPP_HAS_INT128 +template <> +struct __unsigned_integer_of_size<16> { + using type _LIBCPP_NODEBUG = unsigned __int128; +}; +# endif + +template +using __unsigned_integer_of_size_t _LIBCPP_NODEBUG = typename __unsigned_integer_of_size<_Size>::type; + +template +using __unsigned_representation_for_t _LIBCPP_NODEBUG = __unsigned_integer_of_size_t; + +// The function `__to_ordered_integral` is defined for integers and IEEE 754 floating-point numbers. +// Returns an integer representation such that for any `x` and `y` such that `x < y`, the expression +// `__to_ordered_integral(x) < __to_ordered_integral(y)` is true, where `x`, `y` are integers or IEEE 754 floats. +template ::value, int> = 0> +_LIBCPP_HIDE_FROM_ABI constexpr auto __to_ordered_integral(_Integral __n) { + return __n; +} + +// An overload for IEEE 754 floating-point numbers + +// For the floats conforming to IEEE 754 (IEC 559) standard, we know that: +// 1. The bit representation of positive floats directly reflects their order: +// When comparing floats by magnitude, the number with the larger exponent is greater, and if the exponents are +// equal, the one with the larger mantissa is greater. +// 2. The bit representation of negative floats reflects their reverse order (for the same reasons). +// 3. The most significant bit (sign bit) is zero for positive floats and one for negative floats. Therefore, in the raw +// bit representation, any negative number will be greater than any positive number. + +// The only exception from this rule is `NaN`, which is unordered by definition. + +// Based on the above, to obtain correctly ordered integral representation of floating-point numbers, we need to: +// 1. Invert the bit representation (including the sign bit) of negative floats to switch from reverse order to direct +// order; +// 2. Invert the sign bit for positive floats. + +// Thus, in final integral representation, we have reversed the order for negative floats and made all negative floats +// smaller than all positive numbers (by inverting the sign bit). +template ::is_iec559, int> = 0> +_LIBCPP_HIDE_FROM_ABI constexpr auto __to_ordered_integral(_Floating __f) { + using __integral_type = __unsigned_representation_for_t<_Floating>; + constexpr auto __bit_count = std::numeric_limits<__integral_type>::digits; + constexpr auto __sign_bit_mask = static_cast<__integral_type>(__integral_type{1} << (__bit_count - 1)); + + const auto __u = std::__bit_cast<__integral_type>(__f); + + return static_cast<__integral_type>(__u & __sign_bit_mask ? ~__u : __u ^ __sign_bit_mask); +} + +// There may exist user-defined comparison for enum, so we cannot compare enums just like integers. +template ::value, int> = 0> +_LIBCPP_HIDE_FROM_ABI constexpr auto __to_ordered_integral(_Enum __e) = delete; + +// `long double` varies significantly across platforms and compilers, making it practically +// impossible to determine its actual bit width for conversion to an ordered integer. +inline _LIBCPP_HIDE_FROM_ABI constexpr auto __to_ordered_integral(long double) = delete; + +template +inline const bool __is_ordered_integer_representable_v = false; + +template +inline const bool + __is_ordered_integer_representable_v<_Tp, __void_t()))>> = + true; + struct __low_byte_fn { template _LIBCPP_HIDE_FROM_ABI constexpr uint8_t operator()(_Ip __integer) const { @@ -307,18 +402,20 @@ struct __low_byte_fn { }; template -_LIBCPP_HIDE_FROM_ABI void +_LIBCPP_HIDE_FROM_ABI constexpr void __radix_sort(_RandomAccessIterator1 __first, _RandomAccessIterator1 __last, _RandomAccessIterator2 __buffer, _Map __map, _Radix __radix) { - auto __map_to_unsigned = [__map = std::move(__map)](const auto& __x) { return std::__shift_to_unsigned(__map(__x)); }; + auto __map_to_unsigned = [__map = std::move(__map)](const auto& __x) { + return std::__shift_to_unsigned(__map(std::__to_ordered_integral(__x))); + }; std::__radix_sort_impl(__first, __last, __buffer, __map_to_unsigned, __radix); } template -_LIBCPP_HIDE_FROM_ABI void +_LIBCPP_HIDE_FROM_ABI constexpr void __radix_sort(_RandomAccessIterator1 __first, _RandomAccessIterator1 __last, _RandomAccessIterator2 __buffer) { std::__radix_sort(__first, __last, __buffer, __identity{}, __low_byte_fn{}); } diff --git a/lib/libcxx/include/__algorithm/ranges_for_each.h b/lib/libcxx/include/__algorithm/ranges_for_each.h index de39bc5522..e9c84e8583 100644 --- a/lib/libcxx/include/__algorithm/ranges_for_each.h +++ b/lib/libcxx/include/__algorithm/ranges_for_each.h @@ -9,10 +9,12 @@ #ifndef _LIBCPP___ALGORITHM_RANGES_FOR_EACH_H #define _LIBCPP___ALGORITHM_RANGES_FOR_EACH_H +#include <__algorithm/for_each.h> +#include <__algorithm/for_each_n.h> #include <__algorithm/in_fun_result.h> +#include <__concepts/assignable.h> #include <__config> #include <__functional/identity.h> -#include <__functional/invoke.h> #include <__iterator/concepts.h> #include <__iterator/projected.h> #include <__ranges/access.h> @@ -41,9 +43,17 @@ private: template _LIBCPP_HIDE_FROM_ABI constexpr static for_each_result<_Iter, _Func> __for_each_impl(_Iter __first, _Sent __last, _Func& __func, _Proj& __proj) { - for (; __first != __last; ++__first) - std::invoke(__func, std::invoke(__proj, *__first)); - return {std::move(__first), std::move(__func)}; + // In the case where we have different iterator and sentinel types, the segmented iterator optimization + // in std::for_each will not kick in. Therefore, we prefer std::for_each_n in that case (whenever we can + // obtain the `n`). + if constexpr (!std::assignable_from<_Iter&, _Sent> && std::sized_sentinel_for<_Sent, _Iter>) { + auto __n = __last - __first; + auto __end = std::__for_each_n(std::move(__first), __n, __func, __proj); + return {std::move(__end), std::move(__func)}; + } else { + auto __end = std::__for_each(std::move(__first), std::move(__last), __func, __proj); + return {std::move(__end), std::move(__func)}; + } } public: diff --git a/lib/libcxx/include/__algorithm/ranges_for_each_n.h b/lib/libcxx/include/__algorithm/ranges_for_each_n.h index 603cb72323..3aab1b79c1 100644 --- a/lib/libcxx/include/__algorithm/ranges_for_each_n.h +++ b/lib/libcxx/include/__algorithm/ranges_for_each_n.h @@ -9,10 +9,10 @@ #ifndef _LIBCPP___ALGORITHM_RANGES_FOR_EACH_N_H #define _LIBCPP___ALGORITHM_RANGES_FOR_EACH_N_H +#include <__algorithm/for_each_n.h> #include <__algorithm/in_fun_result.h> #include <__config> #include <__functional/identity.h> -#include <__functional/invoke.h> #include <__iterator/concepts.h> #include <__iterator/incrementable_traits.h> #include <__iterator/iterator_traits.h> @@ -40,11 +40,8 @@ struct __for_each_n { template > _Func> _LIBCPP_HIDE_FROM_ABI constexpr for_each_n_result<_Iter, _Func> operator()(_Iter __first, iter_difference_t<_Iter> __count, _Func __func, _Proj __proj = {}) const { - while (__count-- > 0) { - std::invoke(__func, std::invoke(__proj, *__first)); - ++__first; - } - return {std::move(__first), std::move(__func)}; + auto __last = std::__for_each_n(std::move(__first), __count, __func, __proj); + return {std::move(__last), std::move(__func)}; } }; diff --git a/lib/libcxx/include/__algorithm/ranges_inplace_merge.h b/lib/libcxx/include/__algorithm/ranges_inplace_merge.h index 5879d0e7ef..54581aff39 100644 --- a/lib/libcxx/include/__algorithm/ranges_inplace_merge.h +++ b/lib/libcxx/include/__algorithm/ranges_inplace_merge.h @@ -41,7 +41,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD namespace ranges { struct __inplace_merge { template - _LIBCPP_HIDE_FROM_ABI static constexpr auto + _LIBCPP_HIDE_FROM_ABI static _LIBCPP_CONSTEXPR_SINCE_CXX26 auto __inplace_merge_impl(_Iter __first, _Iter __middle, _Sent __last, _Comp&& __comp, _Proj&& __proj) { auto __last_iter = ranges::next(__middle, __last); std::__inplace_merge<_RangeAlgPolicy>( @@ -51,7 +51,7 @@ struct __inplace_merge { template _Sent, class _Comp = ranges::less, class _Proj = identity> requires sortable<_Iter, _Comp, _Proj> - _LIBCPP_HIDE_FROM_ABI _Iter + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 _Iter operator()(_Iter __first, _Iter __middle, _Sent __last, _Comp __comp = {}, _Proj __proj = {}) const { return __inplace_merge_impl( std::move(__first), std::move(__middle), std::move(__last), std::move(__comp), std::move(__proj)); @@ -59,7 +59,7 @@ struct __inplace_merge { template requires sortable, _Comp, _Proj> - _LIBCPP_HIDE_FROM_ABI borrowed_iterator_t<_Range> + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 borrowed_iterator_t<_Range> operator()(_Range&& __range, iterator_t<_Range> __middle, _Comp __comp = {}, _Proj __proj = {}) const { return __inplace_merge_impl( ranges::begin(__range), std::move(__middle), ranges::end(__range), std::move(__comp), std::move(__proj)); diff --git a/lib/libcxx/include/__algorithm/ranges_iterator_concept.h b/lib/libcxx/include/__algorithm/ranges_iterator_concept.h index 58790e95aa..947dfa4811 100644 --- a/lib/libcxx/include/__algorithm/ranges_iterator_concept.h +++ b/lib/libcxx/include/__algorithm/ranges_iterator_concept.h @@ -44,7 +44,7 @@ consteval auto __get_iterator_concept() { } template -using __iterator_concept _LIBCPP_NODEBUG = decltype(__get_iterator_concept<_Iter>()); +using __iterator_concept _LIBCPP_NODEBUG = decltype(ranges::__get_iterator_concept<_Iter>()); } // namespace ranges _LIBCPP_END_NAMESPACE_STD diff --git a/lib/libcxx/include/__algorithm/ranges_max.h b/lib/libcxx/include/__algorithm/ranges_max.h index f631344422..a8fe13a734 100644 --- a/lib/libcxx/include/__algorithm/ranges_max.h +++ b/lib/libcxx/include/__algorithm/ranges_max.h @@ -9,7 +9,7 @@ #ifndef _LIBCPP___ALGORITHM_RANGES_MAX_H #define _LIBCPP___ALGORITHM_RANGES_MAX_H -#include <__algorithm/ranges_min_element.h> +#include <__algorithm/min_element.h> #include <__assert> #include <__concepts/copyable.h> #include <__config> @@ -57,7 +57,7 @@ struct __max { __il.begin() != __il.end(), "initializer_list must contain at least one element"); auto __comp_lhs_rhs_swapped = [&](auto&& __lhs, auto&& __rhs) -> bool { return std::invoke(__comp, __rhs, __lhs); }; - return *ranges::__min_element_impl(__il.begin(), __il.end(), __comp_lhs_rhs_swapped, __proj); + return *std::__min_element(__il.begin(), __il.end(), __comp_lhs_rhs_swapped, __proj); } template bool { return std::invoke(__comp, __rhs, __lhs); }; - return *ranges::__min_element_impl(std::move(__first), std::move(__last), __comp_lhs_rhs_swapped, __proj); + return *std::__min_element(std::move(__first), std::move(__last), __comp_lhs_rhs_swapped, __proj); } else { range_value_t<_Rp> __result = *__first; while (++__first != __last) { diff --git a/lib/libcxx/include/__algorithm/ranges_max_element.h b/lib/libcxx/include/__algorithm/ranges_max_element.h index 869f71ecc8..db6d5f6b9c 100644 --- a/lib/libcxx/include/__algorithm/ranges_max_element.h +++ b/lib/libcxx/include/__algorithm/ranges_max_element.h @@ -9,7 +9,7 @@ #ifndef _LIBCPP___ALGORITHM_RANGES_MAX_ELEMENT_H #define _LIBCPP___ALGORITHM_RANGES_MAX_ELEMENT_H -#include <__algorithm/ranges_min_element.h> +#include <__algorithm/min_element.h> #include <__config> #include <__functional/identity.h> #include <__functional/invoke.h> @@ -40,7 +40,7 @@ struct __max_element { [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr _Ip operator()(_Ip __first, _Sp __last, _Comp __comp = {}, _Proj __proj = {}) const { auto __comp_lhs_rhs_swapped = [&](auto&& __lhs, auto&& __rhs) -> bool { return std::invoke(__comp, __rhs, __lhs); }; - return ranges::__min_element_impl(__first, __last, __comp_lhs_rhs_swapped, __proj); + return std::__min_element(__first, __last, __comp_lhs_rhs_swapped, __proj); } template operator()(_Rp&& __r, _Comp __comp = {}, _Proj __proj = {}) const { auto __comp_lhs_rhs_swapped = [&](auto&& __lhs, auto&& __rhs) -> bool { return std::invoke(__comp, __rhs, __lhs); }; - return ranges::__min_element_impl(ranges::begin(__r), ranges::end(__r), __comp_lhs_rhs_swapped, __proj); + return std::__min_element(ranges::begin(__r), ranges::end(__r), __comp_lhs_rhs_swapped, __proj); } }; diff --git a/lib/libcxx/include/__algorithm/ranges_min.h b/lib/libcxx/include/__algorithm/ranges_min.h index 302b5d7975..9f1c78eaa9 100644 --- a/lib/libcxx/include/__algorithm/ranges_min.h +++ b/lib/libcxx/include/__algorithm/ranges_min.h @@ -9,7 +9,7 @@ #ifndef _LIBCPP___ALGORITHM_RANGES_MIN_H #define _LIBCPP___ALGORITHM_RANGES_MIN_H -#include <__algorithm/ranges_min_element.h> +#include <__algorithm/min_element.h> #include <__assert> #include <__concepts/copyable.h> #include <__config> @@ -54,7 +54,7 @@ struct __min { operator()(initializer_list<_Tp> __il, _Comp __comp = {}, _Proj __proj = {}) const { _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS( __il.begin() != __il.end(), "initializer_list must contain at least one element"); - return *ranges::__min_element_impl(__il.begin(), __il.end(), __comp, __proj); + return *std::__min_element(__il.begin(), __il.end(), __comp, __proj); } template && !__is_cheap_to_copy>) { - return *ranges::__min_element_impl(__first, __last, __comp, __proj); + return *std::__min_element(__first, __last, __comp, __proj); } else { range_value_t<_Rp> __result = *__first; while (++__first != __last) { diff --git a/lib/libcxx/include/__algorithm/ranges_min_element.h b/lib/libcxx/include/__algorithm/ranges_min_element.h index fb92ae56bc..5deb409ccd 100644 --- a/lib/libcxx/include/__algorithm/ranges_min_element.h +++ b/lib/libcxx/include/__algorithm/ranges_min_element.h @@ -9,6 +9,7 @@ #ifndef _LIBCPP___ALGORITHM_RANGES_MIN_ELEMENT_H #define _LIBCPP___ALGORITHM_RANGES_MIN_ELEMENT_H +#include <__algorithm/min_element.h> #include <__config> #include <__functional/identity.h> #include <__functional/invoke.h> @@ -32,20 +33,6 @@ _LIBCPP_PUSH_MACROS _LIBCPP_BEGIN_NAMESPACE_STD namespace ranges { - -// TODO(ranges): `ranges::min_element` can now simply delegate to `std::__min_element`. -template -_LIBCPP_HIDE_FROM_ABI constexpr _Ip __min_element_impl(_Ip __first, _Sp __last, _Comp& __comp, _Proj& __proj) { - if (__first == __last) - return __first; - - _Ip __i = __first; - while (++__i != __last) - if (std::invoke(__comp, std::invoke(__proj, *__i), std::invoke(__proj, *__first))) - __first = __i; - return __first; -} - struct __min_element { template _Sp, @@ -53,7 +40,7 @@ struct __min_element { indirect_strict_weak_order> _Comp = ranges::less> [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr _Ip operator()(_Ip __first, _Sp __last, _Comp __comp = {}, _Proj __proj = {}) const { - return ranges::__min_element_impl(__first, __last, __comp, __proj); + return std::__min_element(__first, __last, __comp, __proj); } template , _Proj>> _Comp = ranges::less> [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr borrowed_iterator_t<_Rp> operator()(_Rp&& __r, _Comp __comp = {}, _Proj __proj = {}) const { - return ranges::__min_element_impl(ranges::begin(__r), ranges::end(__r), __comp, __proj); + return std::__min_element(ranges::begin(__r), ranges::end(__r), __comp, __proj); } }; diff --git a/lib/libcxx/include/__algorithm/ranges_stable_partition.h b/lib/libcxx/include/__algorithm/ranges_stable_partition.h index cfc02e1e97..d8cfc8d941 100644 --- a/lib/libcxx/include/__algorithm/ranges_stable_partition.h +++ b/lib/libcxx/include/__algorithm/ranges_stable_partition.h @@ -44,7 +44,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD namespace ranges { struct __stable_partition { template - _LIBCPP_HIDE_FROM_ABI static subrange<__remove_cvref_t<_Iter>> + _LIBCPP_HIDE_FROM_ABI static _LIBCPP_CONSTEXPR_SINCE_CXX26 subrange<__remove_cvref_t<_Iter>> __stable_partition_fn_impl(_Iter&& __first, _Sent&& __last, _Pred&& __pred, _Proj&& __proj) { auto __last_iter = ranges::next(__first, __last); @@ -60,7 +60,8 @@ struct __stable_partition { class _Proj = identity, indirect_unary_predicate> _Pred> requires permutable<_Iter> - _LIBCPP_HIDE_FROM_ABI subrange<_Iter> operator()(_Iter __first, _Sent __last, _Pred __pred, _Proj __proj = {}) const { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 subrange<_Iter> + operator()(_Iter __first, _Sent __last, _Pred __pred, _Proj __proj = {}) const { return __stable_partition_fn_impl(__first, __last, __pred, __proj); } @@ -68,7 +69,7 @@ struct __stable_partition { class _Proj = identity, indirect_unary_predicate, _Proj>> _Pred> requires permutable> - _LIBCPP_HIDE_FROM_ABI borrowed_subrange_t<_Range> + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 borrowed_subrange_t<_Range> operator()(_Range&& __range, _Pred __pred, _Proj __proj = {}) const { return __stable_partition_fn_impl(ranges::begin(__range), ranges::end(__range), __pred, __proj); } diff --git a/lib/libcxx/include/__algorithm/ranges_stable_sort.h b/lib/libcxx/include/__algorithm/ranges_stable_sort.h index 9c7df80ae9..6e17d0d0c7 100644 --- a/lib/libcxx/include/__algorithm/ranges_stable_sort.h +++ b/lib/libcxx/include/__algorithm/ranges_stable_sort.h @@ -41,7 +41,8 @@ _LIBCPP_BEGIN_NAMESPACE_STD namespace ranges { struct __stable_sort { template - _LIBCPP_HIDE_FROM_ABI static _Iter __stable_sort_fn_impl(_Iter __first, _Sent __last, _Comp& __comp, _Proj& __proj) { + _LIBCPP_HIDE_FROM_ABI static _LIBCPP_CONSTEXPR_SINCE_CXX26 _Iter + __stable_sort_fn_impl(_Iter __first, _Sent __last, _Comp& __comp, _Proj& __proj) { auto __last_iter = ranges::next(__first, __last); auto&& __projected_comp = std::__make_projected(__comp, __proj); @@ -52,13 +53,14 @@ struct __stable_sort { template _Sent, class _Comp = ranges::less, class _Proj = identity> requires sortable<_Iter, _Comp, _Proj> - _LIBCPP_HIDE_FROM_ABI _Iter operator()(_Iter __first, _Sent __last, _Comp __comp = {}, _Proj __proj = {}) const { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 _Iter + operator()(_Iter __first, _Sent __last, _Comp __comp = {}, _Proj __proj = {}) const { return __stable_sort_fn_impl(std::move(__first), std::move(__last), __comp, __proj); } template requires sortable, _Comp, _Proj> - _LIBCPP_HIDE_FROM_ABI borrowed_iterator_t<_Range> + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 borrowed_iterator_t<_Range> operator()(_Range&& __r, _Comp __comp = {}, _Proj __proj = {}) const { return __stable_sort_fn_impl(ranges::begin(__r), ranges::end(__r), __comp, __proj); } diff --git a/lib/libcxx/include/__algorithm/rotate.h b/lib/libcxx/include/__algorithm/rotate.h index df4ca95aac..c676980f0c 100644 --- a/lib/libcxx/include/__algorithm/rotate.h +++ b/lib/libcxx/include/__algorithm/rotate.h @@ -9,12 +9,19 @@ #ifndef _LIBCPP___ALGORITHM_ROTATE_H #define _LIBCPP___ALGORITHM_ROTATE_H +#include <__algorithm/copy.h> +#include <__algorithm/copy_backward.h> #include <__algorithm/iterator_operations.h> #include <__algorithm/move.h> #include <__algorithm/move_backward.h> #include <__algorithm/swap_ranges.h> #include <__config> +#include <__cstddef/size_t.h> +#include <__fwd/bit_reference.h> #include <__iterator/iterator_traits.h> +#include <__memory/construct_at.h> +#include <__memory/pointer_traits.h> +#include <__type_traits/is_constant_evaluated.h> #include <__type_traits/is_trivially_assignable.h> #include <__utility/move.h> #include <__utility/pair.h> @@ -185,6 +192,44 @@ __rotate(_Iterator __first, _Iterator __middle, _Sentinel __last) { return _Ret(std::move(__result), std::move(__last_iter)); } +template +_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 pair<__bit_iterator<_Cp, false>, __bit_iterator<_Cp, false> > +__rotate(__bit_iterator<_Cp, false> __first, __bit_iterator<_Cp, false> __middle, __bit_iterator<_Cp, false> __last) { + using _I1 = __bit_iterator<_Cp, false>; + using difference_type = typename _I1::difference_type; + difference_type __d1 = __middle - __first; + difference_type __d2 = __last - __middle; + _I1 __r = __first + __d2; + while (__d1 != 0 && __d2 != 0) { + if (__d1 <= __d2) { + if (__d1 <= __bit_array<_Cp>::capacity()) { + __bit_array<_Cp> __b(__d1); + std::copy(__first, __middle, __b.begin()); + std::copy(__b.begin(), __b.end(), std::copy(__middle, __last, __first)); + break; + } else { + __bit_iterator<_Cp, false> __mp = std::swap_ranges(__first, __middle, __middle); + __first = __middle; + __middle = __mp; + __d2 -= __d1; + } + } else { + if (__d2 <= __bit_array<_Cp>::capacity()) { + __bit_array<_Cp> __b(__d2); + std::copy(__middle, __last, __b.begin()); + std::copy_backward(__b.begin(), __b.end(), std::copy_backward(__first, __middle, __last)); + break; + } else { + __bit_iterator<_Cp, false> __mp = __first + __d2; + std::swap_ranges(__first, __mp, __middle); + __first = __mp; + __d1 -= __d2; + } + } + } + return std::make_pair(__r, __last); +} + template inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _ForwardIterator rotate(_ForwardIterator __first, _ForwardIterator __middle, _ForwardIterator __last) { diff --git a/lib/libcxx/include/__algorithm/simd_utils.h b/lib/libcxx/include/__algorithm/simd_utils.h index 4e03723a32..47942a09e6 100644 --- a/lib/libcxx/include/__algorithm/simd_utils.h +++ b/lib/libcxx/include/__algorithm/simd_utils.h @@ -15,8 +15,6 @@ #include <__bit/countr.h> #include <__config> #include <__cstddef/size_t.h> -#include <__type_traits/is_arithmetic.h> -#include <__type_traits/is_same.h> #include <__utility/integer_sequence.h> #include @@ -28,7 +26,9 @@ _LIBCPP_PUSH_MACROS #include <__undef_macros> // TODO: Find out how altivec changes things and allow vectorizations there too. -#if _LIBCPP_STD_VER >= 14 && defined(_LIBCPP_CLANG_VER) && !defined(__ALTIVEC__) +// TODO: Simplify this condition once we stop building with AppleClang 15 in the CI. +#if _LIBCPP_STD_VER >= 14 && defined(_LIBCPP_COMPILER_CLANG_BASED) && !defined(__ALTIVEC__) && \ + !(defined(_LIBCPP_APPLE_CLANG_VER) && _LIBCPP_APPLE_CLANG_VER < 1600) # define _LIBCPP_HAS_ALGORITHM_VECTOR_UTILS 1 #else # define _LIBCPP_HAS_ALGORITHM_VECTOR_UTILS 0 @@ -53,20 +53,20 @@ struct __get_as_integer_type_impl; template <> struct __get_as_integer_type_impl<1> { - using type = uint8_t; + using type _LIBCPP_NODEBUG = uint8_t; }; template <> struct __get_as_integer_type_impl<2> { - using type = uint16_t; + using type _LIBCPP_NODEBUG = uint16_t; }; template <> struct __get_as_integer_type_impl<4> { - using type = uint32_t; + using type _LIBCPP_NODEBUG = uint32_t; }; template <> struct __get_as_integer_type_impl<8> { - using type = uint64_t; + using type _LIBCPP_NODEBUG = uint64_t; }; template @@ -78,7 +78,7 @@ using __get_as_integer_type_t _LIBCPP_NODEBUG = typename __get_as_integer_type_i # if defined(__AVX__) || defined(__MVS__) template inline constexpr size_t __native_vector_size = 32 / sizeof(_Tp); -# elif defined(__SSE__) || defined(__ARM_NEON__) +# elif defined(__SSE__) || defined(__ARM_NEON) template inline constexpr size_t __native_vector_size = 16 / sizeof(_Tp); # elif defined(__MMX__) diff --git a/lib/libcxx/include/__algorithm/sort.h b/lib/libcxx/include/__algorithm/sort.h index 8dd0721f2c..06cb5b8ce7 100644 --- a/lib/libcxx/include/__algorithm/sort.h +++ b/lib/libcxx/include/__algorithm/sort.h @@ -17,6 +17,7 @@ #include <__algorithm/partial_sort.h> #include <__algorithm/unwrap_iter.h> #include <__assert> +#include <__bit/bit_log2.h> #include <__bit/blsr.h> #include <__bit/countl.h> #include <__bit/countr.h> @@ -34,7 +35,7 @@ #include <__type_traits/is_constant_evaluated.h> #include <__type_traits/is_same.h> #include <__type_traits/is_trivially_copyable.h> -#include <__type_traits/remove_cvref.h> +#include <__type_traits/make_unsigned.h> #include <__utility/move.h> #include <__utility/pair.h> #include @@ -52,8 +53,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD template ::value_type> inline const bool __use_branchless_sort = __libcpp_is_contiguous_iterator<_Iter>::value && __is_cheap_to_copy<_Tp> && is_arithmetic<_Tp>::value && - (__desugars_to_v<__less_tag, __remove_cvref_t<_Compare>, _Tp, _Tp> || - __desugars_to_v<__greater_tag, __remove_cvref_t<_Compare>, _Tp, _Tp>); + (__desugars_to_v<__less_tag, _Compare, _Tp, _Tp> || __desugars_to_v<__greater_tag, _Compare, _Tp, _Tp>); namespace __detail { @@ -359,10 +359,10 @@ inline _LIBCPP_HIDE_FROM_ABI void __swap_bitmap_pos( // Swap one pair on each iteration as long as both bitsets have at least one // element for swapping. while (__left_bitset != 0 && __right_bitset != 0) { - difference_type __tz_left = __libcpp_ctz(__left_bitset); - __left_bitset = __libcpp_blsr(__left_bitset); - difference_type __tz_right = __libcpp_ctz(__right_bitset); - __right_bitset = __libcpp_blsr(__right_bitset); + difference_type __tz_left = std::__countr_zero(__left_bitset); + __left_bitset = std::__libcpp_blsr(__left_bitset); + difference_type __tz_right = std::__countr_zero(__right_bitset); + __right_bitset = std::__libcpp_blsr(__right_bitset); _Ops::iter_swap(__first + __tz_left, __last - __tz_right); } } @@ -458,7 +458,7 @@ inline _LIBCPP_HIDE_FROM_ABI void __swap_bitmap_pos_within( // Swap within the left side. Need to find set positions in the reverse // order. while (__left_bitset != 0) { - difference_type __tz_left = __detail::__block_size - 1 - __libcpp_clz(__left_bitset); + difference_type __tz_left = __detail::__block_size - 1 - std::__countl_zero(__left_bitset); __left_bitset &= (static_cast(1) << __tz_left) - 1; _RandomAccessIterator __it = __first + __tz_left; if (__it != __lm1) { @@ -471,7 +471,7 @@ inline _LIBCPP_HIDE_FROM_ABI void __swap_bitmap_pos_within( // Swap within the right side. Need to find set positions in the reverse // order. while (__right_bitset != 0) { - difference_type __tz_right = __detail::__block_size - 1 - __libcpp_clz(__right_bitset); + difference_type __tz_right = __detail::__block_size - 1 - std::__countl_zero(__right_bitset); __right_bitset &= (static_cast(1) << __tz_right) - 1; _RandomAccessIterator __it = __lm1 - __tz_right; if (__it != __first) { @@ -828,25 +828,6 @@ void __introsort(_RandomAccessIterator __first, } } -template -inline _LIBCPP_HIDE_FROM_ABI _Number __log2i(_Number __n) { - if (__n == 0) - return 0; - if (sizeof(__n) <= sizeof(unsigned)) - return sizeof(unsigned) * CHAR_BIT - 1 - __libcpp_clz(static_cast(__n)); - if (sizeof(__n) <= sizeof(unsigned long)) - return sizeof(unsigned long) * CHAR_BIT - 1 - __libcpp_clz(static_cast(__n)); - if (sizeof(__n) <= sizeof(unsigned long long)) - return sizeof(unsigned long long) * CHAR_BIT - 1 - __libcpp_clz(static_cast(__n)); - - _Number __log2 = 0; - while (__n > 1) { - __log2++; - __n >>= 1; - } - return __log2; -} - template void __sort(_RandomAccessIterator, _RandomAccessIterator, _Comp); @@ -880,7 +861,7 @@ template _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void __sort_dispatch(_RandomAccessIterator __first, _RandomAccessIterator __last, _Comp& __comp) { typedef typename iterator_traits<_RandomAccessIterator>::difference_type difference_type; - difference_type __depth_limit = 2 * std::__log2i(__last - __first); + difference_type __depth_limit = 2 * std::__bit_log2(std::__to_unsigned_like(__last - __first)); // Only use bitset partitioning for arithmetic types. We should also check // that the default comparator is in use so that we are sure that there are no diff --git a/lib/libcxx/include/__algorithm/stable_partition.h b/lib/libcxx/include/__algorithm/stable_partition.h index 2ba7239a3a..b389ae2508 100644 --- a/lib/libcxx/include/__algorithm/stable_partition.h +++ b/lib/libcxx/include/__algorithm/stable_partition.h @@ -16,6 +16,7 @@ #include <__iterator/advance.h> #include <__iterator/distance.h> #include <__iterator/iterator_traits.h> +#include <__memory/construct_at.h> #include <__memory/destruct_n.h> #include <__memory/unique_ptr.h> #include <__memory/unique_temporary_buffer.h> @@ -33,7 +34,7 @@ _LIBCPP_PUSH_MACROS _LIBCPP_BEGIN_NAMESPACE_STD template -_LIBCPP_HIDE_FROM_ABI _ForwardIterator __stable_partition_impl( +_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 _ForwardIterator __stable_partition_impl( _ForwardIterator __first, _ForwardIterator __last, _Predicate __pred, @@ -61,7 +62,7 @@ _LIBCPP_HIDE_FROM_ABI _ForwardIterator __stable_partition_impl( // Move the falses into the temporary buffer, and the trues to the front of the line // Update __first to always point to the end of the trues value_type* __t = __p.first; - ::new ((void*)__t) value_type(_Ops::__iter_move(__first)); + std::__construct_at(__t, _Ops::__iter_move(__first)); __d.template __incr(); ++__t; _ForwardIterator __i = __first; @@ -70,7 +71,7 @@ _LIBCPP_HIDE_FROM_ABI _ForwardIterator __stable_partition_impl( *__first = _Ops::__iter_move(__i); ++__first; } else { - ::new ((void*)__t) value_type(_Ops::__iter_move(__i)); + std::__construct_at(__t, _Ops::__iter_move(__i)); __d.template __incr(); ++__t; } @@ -116,7 +117,7 @@ __second_half_done: } template -_LIBCPP_HIDE_FROM_ABI _ForwardIterator +_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 _ForwardIterator __stable_partition_impl(_ForwardIterator __first, _ForwardIterator __last, _Predicate __pred, forward_iterator_tag) { typedef typename iterator_traits<_ForwardIterator>::difference_type difference_type; typedef typename iterator_traits<_ForwardIterator>::value_type value_type; @@ -145,7 +146,7 @@ __stable_partition_impl(_ForwardIterator __first, _ForwardIterator __last, _Pred } template -_BidirectionalIterator __stable_partition_impl( +_LIBCPP_CONSTEXPR_SINCE_CXX26 _BidirectionalIterator __stable_partition_impl( _BidirectionalIterator __first, _BidirectionalIterator __last, _Predicate __pred, @@ -179,7 +180,7 @@ _BidirectionalIterator __stable_partition_impl( // Move the falses into the temporary buffer, and the trues to the front of the line // Update __first to always point to the end of the trues value_type* __t = __p.first; - ::new ((void*)__t) value_type(_Ops::__iter_move(__first)); + std::__construct_at(__t, _Ops::__iter_move(__first)); __d.template __incr(); ++__t; _BidirectionalIterator __i = __first; @@ -188,7 +189,7 @@ _BidirectionalIterator __stable_partition_impl( *__first = _Ops::__iter_move(__i); ++__first; } else { - ::new ((void*)__t) value_type(_Ops::__iter_move(__i)); + std::__construct_at(__t, _Ops::__iter_move(__i)); __d.template __incr(); ++__t; } @@ -247,7 +248,7 @@ __second_half_done: } template -_LIBCPP_HIDE_FROM_ABI _BidirectionalIterator __stable_partition_impl( +_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 _BidirectionalIterator __stable_partition_impl( _BidirectionalIterator __first, _BidirectionalIterator __last, _Predicate __pred, bidirectional_iterator_tag) { typedef typename iterator_traits<_BidirectionalIterator>::difference_type difference_type; typedef typename iterator_traits<_BidirectionalIterator>::value_type value_type; @@ -283,14 +284,14 @@ _LIBCPP_HIDE_FROM_ABI _BidirectionalIterator __stable_partition_impl( } template -_LIBCPP_HIDE_FROM_ABI _ForwardIterator __stable_partition( +_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 _ForwardIterator __stable_partition( _ForwardIterator __first, _ForwardIterator __last, _Predicate&& __pred, _IterCategory __iter_category) { return std::__stable_partition_impl<_AlgPolicy, __remove_cvref_t<_Predicate>&>( std::move(__first), std::move(__last), __pred, __iter_category); } template -inline _LIBCPP_HIDE_FROM_ABI _ForwardIterator +_LIBCPP_HIDE_FROM_ABI inline _LIBCPP_CONSTEXPR_SINCE_CXX26 _ForwardIterator stable_partition(_ForwardIterator __first, _ForwardIterator __last, _Predicate __pred) { using _IterCategory = typename iterator_traits<_ForwardIterator>::iterator_category; return std::__stable_partition<_ClassicAlgPolicy, _Predicate&>( diff --git a/lib/libcxx/include/__algorithm/stable_sort.h b/lib/libcxx/include/__algorithm/stable_sort.h index 3cfbcf08d2..1ca66f6a51 100644 --- a/lib/libcxx/include/__algorithm/stable_sort.h +++ b/lib/libcxx/include/__algorithm/stable_sort.h @@ -25,10 +25,9 @@ #include <__memory/unique_temporary_buffer.h> #include <__type_traits/desugars_to.h> #include <__type_traits/enable_if.h> -#include <__type_traits/is_integral.h> +#include <__type_traits/is_constant_evaluated.h> #include <__type_traits/is_same.h> #include <__type_traits/is_trivially_assignable.h> -#include <__type_traits/remove_cvref.h> #include <__utility/move.h> #include <__utility/pair.h> @@ -201,7 +200,7 @@ struct __stable_sort_switch { #if _LIBCPP_STD_VER >= 17 template _LIBCPP_HIDE_FROM_ABI constexpr unsigned __radix_sort_min_bound() { - static_assert(is_integral<_Tp>::value); + static_assert(__is_ordered_integer_representable_v<_Tp>); if constexpr (sizeof(_Tp) == 1) { return 1 << 8; } @@ -211,7 +210,7 @@ _LIBCPP_HIDE_FROM_ABI constexpr unsigned __radix_sort_min_bound() { template _LIBCPP_HIDE_FROM_ABI constexpr unsigned __radix_sort_max_bound() { - static_assert(is_integral<_Tp>::value); + static_assert(__is_ordered_integer_representable_v<_Tp>); if constexpr (sizeof(_Tp) >= 8) { return 1 << 15; } @@ -245,14 +244,19 @@ _LIBCPP_CONSTEXPR_SINCE_CXX26 void __stable_sort( } #if _LIBCPP_STD_VER >= 17 - constexpr auto __default_comp = - __desugars_to_v<__totally_ordered_less_tag, __remove_cvref_t<_Compare>, value_type, value_type >; - constexpr auto __integral_value = - is_integral_v && is_same_v< value_type&, __iter_reference<_RandomAccessIterator>>; - constexpr auto __allowed_radix_sort = __default_comp && __integral_value; - if constexpr (__allowed_radix_sort) { - if (__len <= __buff_size && __len >= static_cast(__radix_sort_min_bound()) && - __len <= static_cast(__radix_sort_max_bound())) { + constexpr auto __default_comp = __desugars_to_v<__less_tag, _Compare, value_type, value_type >; + constexpr auto __radix_sortable = + __is_ordered_integer_representable_v && + is_same_v< value_type&, __iter_reference<_RandomAccessIterator>>; + if constexpr (__default_comp && __radix_sortable) { + if (__len <= __buff_size && __len >= static_cast(std::__radix_sort_min_bound()) && + __len <= static_cast(std::__radix_sort_max_bound())) { + if (__libcpp_is_constant_evaluated()) { + for (auto* __p = __buff; __p < __buff + __buff_size; ++__p) { + std::__construct_at(__p); + } + } + std::__radix_sort(__first, __last, __buff); return; } diff --git a/lib/libcxx/include/__algorithm/swap_ranges.h b/lib/libcxx/include/__algorithm/swap_ranges.h index 54b453b723..2731d4feaa 100644 --- a/lib/libcxx/include/__algorithm/swap_ranges.h +++ b/lib/libcxx/include/__algorithm/swap_ranges.h @@ -10,9 +10,12 @@ #define _LIBCPP___ALGORITHM_SWAP_RANGES_H #include <__algorithm/iterator_operations.h> +#include <__algorithm/min.h> #include <__config> +#include <__fwd/bit_reference.h> #include <__utility/move.h> #include <__utility/pair.h> +#include <__utility/swap.h> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # pragma GCC system_header @@ -23,6 +26,165 @@ _LIBCPP_PUSH_MACROS _LIBCPP_BEGIN_NAMESPACE_STD +template +_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 __bit_iterator<_Cr, false> __swap_ranges_aligned( + __bit_iterator<_Cl, false> __first, __bit_iterator<_Cl, false> __last, __bit_iterator<_Cr, false> __result) { + using _I1 = __bit_iterator<_Cl, false>; + using difference_type = typename _I1::difference_type; + using __storage_type = typename _I1::__storage_type; + + const int __bits_per_word = _I1::__bits_per_word; + difference_type __n = __last - __first; + if (__n > 0) { + // do first word + if (__first.__ctz_ != 0) { + unsigned __clz = __bits_per_word - __first.__ctz_; + difference_type __dn = std::min(static_cast(__clz), __n); + __n -= __dn; + __storage_type __m = (~__storage_type(0) << __first.__ctz_) & (~__storage_type(0) >> (__clz - __dn)); + __storage_type __b1 = *__first.__seg_ & __m; + *__first.__seg_ &= ~__m; + __storage_type __b2 = *__result.__seg_ & __m; + *__result.__seg_ &= ~__m; + *__result.__seg_ |= __b1; + *__first.__seg_ |= __b2; + __result.__seg_ += (__dn + __result.__ctz_) / __bits_per_word; + __result.__ctz_ = static_cast((__dn + __result.__ctz_) % __bits_per_word); + ++__first.__seg_; + // __first.__ctz_ = 0; + } + // __first.__ctz_ == 0; + // do middle words + for (; __n >= __bits_per_word; __n -= __bits_per_word, ++__first.__seg_, ++__result.__seg_) + swap(*__first.__seg_, *__result.__seg_); + // do last word + if (__n > 0) { + __storage_type __m = ~__storage_type(0) >> (__bits_per_word - __n); + __storage_type __b1 = *__first.__seg_ & __m; + *__first.__seg_ &= ~__m; + __storage_type __b2 = *__result.__seg_ & __m; + *__result.__seg_ &= ~__m; + *__result.__seg_ |= __b1; + *__first.__seg_ |= __b2; + __result.__ctz_ = static_cast(__n); + } + } + return __result; +} + +template +_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 __bit_iterator<_Cr, false> __swap_ranges_unaligned( + __bit_iterator<_Cl, false> __first, __bit_iterator<_Cl, false> __last, __bit_iterator<_Cr, false> __result) { + using _I1 = __bit_iterator<_Cl, false>; + using difference_type = typename _I1::difference_type; + using __storage_type = typename _I1::__storage_type; + + const int __bits_per_word = _I1::__bits_per_word; + difference_type __n = __last - __first; + if (__n > 0) { + // do first word + if (__first.__ctz_ != 0) { + unsigned __clz_f = __bits_per_word - __first.__ctz_; + difference_type __dn = std::min(static_cast(__clz_f), __n); + __n -= __dn; + __storage_type __m = (~__storage_type(0) << __first.__ctz_) & (~__storage_type(0) >> (__clz_f - __dn)); + __storage_type __b1 = *__first.__seg_ & __m; + *__first.__seg_ &= ~__m; + unsigned __clz_r = __bits_per_word - __result.__ctz_; + __storage_type __ddn = std::min<__storage_type>(__dn, __clz_r); + __m = (~__storage_type(0) << __result.__ctz_) & (~__storage_type(0) >> (__clz_r - __ddn)); + __storage_type __b2 = *__result.__seg_ & __m; + *__result.__seg_ &= ~__m; + if (__result.__ctz_ > __first.__ctz_) { + unsigned __s = __result.__ctz_ - __first.__ctz_; + *__result.__seg_ |= __b1 << __s; + *__first.__seg_ |= __b2 >> __s; + } else { + unsigned __s = __first.__ctz_ - __result.__ctz_; + *__result.__seg_ |= __b1 >> __s; + *__first.__seg_ |= __b2 << __s; + } + __result.__seg_ += (__ddn + __result.__ctz_) / __bits_per_word; + __result.__ctz_ = static_cast((__ddn + __result.__ctz_) % __bits_per_word); + __dn -= __ddn; + if (__dn > 0) { + __m = ~__storage_type(0) >> (__bits_per_word - __dn); + __b2 = *__result.__seg_ & __m; + *__result.__seg_ &= ~__m; + unsigned __s = __first.__ctz_ + __ddn; + *__result.__seg_ |= __b1 >> __s; + *__first.__seg_ |= __b2 << __s; + __result.__ctz_ = static_cast(__dn); + } + ++__first.__seg_; + // __first.__ctz_ = 0; + } + // __first.__ctz_ == 0; + // do middle words + __storage_type __m = ~__storage_type(0) << __result.__ctz_; + unsigned __clz_r = __bits_per_word - __result.__ctz_; + for (; __n >= __bits_per_word; __n -= __bits_per_word, ++__first.__seg_) { + __storage_type __b1 = *__first.__seg_; + __storage_type __b2 = *__result.__seg_ & __m; + *__result.__seg_ &= ~__m; + *__result.__seg_ |= __b1 << __result.__ctz_; + *__first.__seg_ = __b2 >> __result.__ctz_; + ++__result.__seg_; + __b2 = *__result.__seg_ & ~__m; + *__result.__seg_ &= __m; + *__result.__seg_ |= __b1 >> __clz_r; + *__first.__seg_ |= __b2 << __clz_r; + } + // do last word + if (__n > 0) { + __m = ~__storage_type(0) >> (__bits_per_word - __n); + __storage_type __b1 = *__first.__seg_ & __m; + *__first.__seg_ &= ~__m; + __storage_type __dn = std::min<__storage_type>(__n, __clz_r); + __m = (~__storage_type(0) << __result.__ctz_) & (~__storage_type(0) >> (__clz_r - __dn)); + __storage_type __b2 = *__result.__seg_ & __m; + *__result.__seg_ &= ~__m; + *__result.__seg_ |= __b1 << __result.__ctz_; + *__first.__seg_ |= __b2 >> __result.__ctz_; + __result.__seg_ += (__dn + __result.__ctz_) / __bits_per_word; + __result.__ctz_ = static_cast((__dn + __result.__ctz_) % __bits_per_word); + __n -= __dn; + if (__n > 0) { + __m = ~__storage_type(0) >> (__bits_per_word - __n); + __b2 = *__result.__seg_ & __m; + *__result.__seg_ &= ~__m; + *__result.__seg_ |= __b1 >> __dn; + *__first.__seg_ |= __b2 << __dn; + __result.__ctz_ = static_cast(__n); + } + } + } + return __result; +} + +// 2+1 iterators: size2 >= size1; used by std::swap_ranges. +template +_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 pair<__bit_iterator<_Cl, false>, __bit_iterator<_Cr, false> > +__swap_ranges(__bit_iterator<_Cl, false> __first1, + __bit_iterator<_Cl, false> __last1, + __bit_iterator<_Cr, false> __first2) { + if (__first1.__ctz_ == __first2.__ctz_) + return std::make_pair(__last1, std::__swap_ranges_aligned(__first1, __last1, __first2)); + return std::make_pair(__last1, std::__swap_ranges_unaligned(__first1, __last1, __first2)); +} + +// 2+2 iterators: used by std::ranges::swap_ranges. +template +_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 pair<__bit_iterator<_Cl, false>, __bit_iterator<_Cr, false> > +__swap_ranges(__bit_iterator<_Cl, false> __first1, + __bit_iterator<_Cl, false> __last1, + __bit_iterator<_Cr, false> __first2, + __bit_iterator<_Cr, false> __last2) { + if (__last1 - __first1 < __last2 - __first2) + return std::make_pair(__last1, std::__swap_ranges<_AlgPolicy>(__first1, __last1, __first2).second); + return std::make_pair(std::__swap_ranges<_AlgPolicy>(__first2, __last2, __first1).second, __last2); +} + // 2+2 iterators: the shorter size will be used. template _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 pair<_ForwardIterator1, _ForwardIterator2> diff --git a/lib/libcxx/include/__assert b/lib/libcxx/include/__assert index 90eaa60235..a9451daf47 100644 --- a/lib/libcxx/include/__assert +++ b/lib/libcxx/include/__assert @@ -20,8 +20,8 @@ #define _LIBCPP_ASSERT(expression, message) \ (__builtin_expect(static_cast(expression), 1) \ ? (void)0 \ - : _LIBCPP_ASSERTION_HANDLER(__FILE__ ":" _LIBCPP_TOSTRING(__LINE__) ": assertion " _LIBCPP_TOSTRING( \ - expression) " failed: " message "\n")) + : _LIBCPP_ASSERTION_HANDLER(__FILE__ ":" _LIBCPP_TOSTRING( \ + __LINE__) ": libc++ Hardening assertion " _LIBCPP_TOSTRING(expression) " failed: " message "\n")) // WARNING: __builtin_assume can currently inhibit optimizations. Only add assumptions with a clear // optimization intent. See https://discourse.llvm.org/t/llvm-assume-blocks-optimization/71609 for a diff --git a/lib/libcxx/include/__assertion_handler b/lib/libcxx/include/__assertion_handler index 1d6b21fc6b..f115658f9f 100644 --- a/lib/libcxx/include/__assertion_handler +++ b/lib/libcxx/include/__assertion_handler @@ -13,9 +13,11 @@ #if __cplusplus < 201103L && defined(_LIBCPP_USE_FROZEN_CXX03_HEADERS) # include <__cxx03/__config> # include <__cxx03/__verbose_abort> +# include <__cxx03/__verbose_trap> #else # include <__config> # include <__verbose_abort> +# include <__verbose_trap> #endif #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) @@ -28,18 +30,7 @@ #else -# if __has_builtin(__builtin_verbose_trap) -// AppleClang shipped a slightly different version of __builtin_verbose_trap from the upstream -// version before upstream Clang actually got the builtin. -// TODO: Remove once AppleClang supports the two-arguments version of the builtin. -# if defined(_LIBCPP_APPLE_CLANG_VER) && _LIBCPP_APPLE_CLANG_VER < 1700 -# define _LIBCPP_ASSERTION_HANDLER(message) __builtin_verbose_trap(message) -# else -# define _LIBCPP_ASSERTION_HANDLER(message) __builtin_verbose_trap("libc++", message) -# endif -# else -# define _LIBCPP_ASSERTION_HANDLER(message) ((void)message, __builtin_trap()) -# endif +# define _LIBCPP_ASSERTION_HANDLER(message) _LIBCPP_VERBOSE_TRAP(message) #endif // _LIBCPP_HARDENING_MODE == _LIBCPP_HARDENING_MODE_DEBUG diff --git a/lib/libcxx/include/__atomic/atomic.h b/lib/libcxx/include/__atomic/atomic.h index 975a479e20..eead49dde6 100644 --- a/lib/libcxx/include/__atomic/atomic.h +++ b/lib/libcxx/include/__atomic/atomic.h @@ -23,6 +23,7 @@ #include <__type_traits/is_integral.h> #include <__type_traits/is_nothrow_constructible.h> #include <__type_traits/is_same.h> +#include <__type_traits/is_trivially_copyable.h> #include <__type_traits/remove_const.h> #include <__type_traits/remove_pointer.h> #include <__type_traits/remove_volatile.h> @@ -40,6 +41,8 @@ struct __atomic_base // false { mutable __cxx_atomic_impl<_Tp> __a_; + using value_type = _Tp; + #if _LIBCPP_STD_VER >= 17 static constexpr bool is_always_lock_free = __libcpp_is_always_lock_free<__cxx_atomic_impl<_Tp> >::__value; #endif @@ -145,6 +148,8 @@ template struct __atomic_base<_Tp, true> : public __atomic_base<_Tp, false> { using __base _LIBCPP_NODEBUG = __atomic_base<_Tp, false>; + using difference_type = typename __base::value_type; + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 __atomic_base() _NOEXCEPT = default; _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR __atomic_base(_Tp __d) _NOEXCEPT : __base(__d) {} @@ -226,11 +231,15 @@ struct __atomic_waitable_traits<__atomic_base<_Tp, _IsIntegral> > { } }; +template +struct __check_atomic_mandates { + using type _LIBCPP_NODEBUG = _Tp; + static_assert(is_trivially_copyable<_Tp>::value, "std::atomic requires that 'T' be a trivially copyable type"); +}; + template -struct atomic : public __atomic_base<_Tp> { +struct atomic : public __atomic_base::type> { using __base _LIBCPP_NODEBUG = __atomic_base<_Tp>; - using value_type = _Tp; - using difference_type = value_type; #if _LIBCPP_STD_VER >= 20 _LIBCPP_HIDE_FROM_ABI atomic() = default; @@ -258,8 +267,8 @@ struct atomic : public __atomic_base<_Tp> { template struct atomic<_Tp*> : public __atomic_base<_Tp*> { using __base _LIBCPP_NODEBUG = __atomic_base<_Tp*>; - using value_type = _Tp*; - using difference_type = ptrdiff_t; + + using difference_type = ptrdiff_t; _LIBCPP_HIDE_FROM_ABI atomic() _NOEXCEPT = default; @@ -361,7 +370,7 @@ private: // https://github.com/llvm/llvm-project/issues/47978 // clang bug: __old is not updated on failure for atomic::compare_exchange_weak // Note __old = __self.load(memory_order_relaxed) will not work - std::__cxx_atomic_load_inplace(std::addressof(__self.__a_), &__old, memory_order_relaxed); + std::__cxx_atomic_load_inplace(std::addressof(__self.__a_), std::addressof(__old), memory_order_relaxed); } # endif __new = __operation(__old, __operand); diff --git a/lib/libcxx/include/__atomic/atomic_ref.h b/lib/libcxx/include/__atomic/atomic_ref.h index 177ea646b6..b5493662c5 100644 --- a/lib/libcxx/include/__atomic/atomic_ref.h +++ b/lib/libcxx/include/__atomic/atomic_ref.h @@ -119,7 +119,7 @@ public: // that the pointer is going to be aligned properly at runtime because that is a (checked) precondition // of atomic_ref's constructor. static constexpr bool is_always_lock_free = - __atomic_always_lock_free(sizeof(_Tp), &__get_aligner_instance::__instance); + __atomic_always_lock_free(sizeof(_Tp), std::addressof(__get_aligner_instance::__instance)); _LIBCPP_HIDE_FROM_ABI bool is_lock_free() const noexcept { return __atomic_is_lock_free(sizeof(_Tp), __ptr_); } diff --git a/lib/libcxx/include/__atomic/memory_order.h b/lib/libcxx/include/__atomic/memory_order.h index 44790fe888..355804312b 100644 --- a/lib/libcxx/include/__atomic/memory_order.h +++ b/lib/libcxx/include/__atomic/memory_order.h @@ -24,7 +24,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD // to pin the underlying type in C++20. enum __legacy_memory_order { __mo_relaxed, __mo_consume, __mo_acquire, __mo_release, __mo_acq_rel, __mo_seq_cst }; -using __memory_order_underlying_t _LIBCPP_NODEBUG = underlying_type<__legacy_memory_order>::type; +using __memory_order_underlying_t _LIBCPP_NODEBUG = __underlying_type_t<__legacy_memory_order>; #if _LIBCPP_STD_VER >= 20 @@ -37,7 +37,7 @@ enum class memory_order : __memory_order_underlying_t { seq_cst = __mo_seq_cst }; -static_assert(is_same::type, __memory_order_underlying_t>::value, +static_assert(is_same<__underlying_type_t, __memory_order_underlying_t>::value, "unexpected underlying type for std::memory_order"); inline constexpr auto memory_order_relaxed = memory_order::relaxed; diff --git a/lib/libcxx/include/__atomic/support.h b/lib/libcxx/include/__atomic/support.h index 4b555ab483..99d0f6aa54 100644 --- a/lib/libcxx/include/__atomic/support.h +++ b/lib/libcxx/include/__atomic/support.h @@ -10,7 +10,6 @@ #define _LIBCPP___ATOMIC_SUPPORT_H #include <__config> -#include <__type_traits/is_trivially_copyable.h> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # pragma GCC system_header @@ -113,8 +112,6 @@ _LIBCPP_BEGIN_NAMESPACE_STD template > struct __cxx_atomic_impl : public _Base { - static_assert(is_trivially_copyable<_Tp>::value, "std::atomic requires that 'T' be a trivially copyable type"); - _LIBCPP_HIDE_FROM_ABI __cxx_atomic_impl() _NOEXCEPT = default; _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR explicit __cxx_atomic_impl(_Tp __value) _NOEXCEPT : _Base(__value) {} }; diff --git a/lib/libcxx/include/__atomic/support/c11.h b/lib/libcxx/include/__atomic/support/c11.h index 177a075be4..1ad299882a 100644 --- a/lib/libcxx/include/__atomic/support/c11.h +++ b/lib/libcxx/include/__atomic/support/c11.h @@ -35,7 +35,7 @@ struct __cxx_atomic_base_impl { } #endif // _LIBCPP_CXX03_LANG _LIBCPP_CONSTEXPR explicit __cxx_atomic_base_impl(_Tp __value) _NOEXCEPT : __a_value(__value) {} - _LIBCPP_DISABLE_EXTENSION_WARNING _Atomic(_Tp) __a_value; + _Atomic(_Tp) __a_value; }; #define __cxx_atomic_is_lock_free(__s) __c11_atomic_is_lock_free(__s) diff --git a/lib/libcxx/include/__bit/bit_ceil.h b/lib/libcxx/include/__bit/bit_ceil.h index cfd792dc2e..99881a8538 100644 --- a/lib/libcxx/include/__bit/bit_ceil.h +++ b/lib/libcxx/include/__bit/bit_ceil.h @@ -11,8 +11,8 @@ #include <__assert> #include <__bit/countl.h> -#include <__concepts/arithmetic.h> #include <__config> +#include <__type_traits/integer_traits.h> #include #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) @@ -41,7 +41,7 @@ template # if _LIBCPP_STD_VER >= 20 -template <__libcpp_unsigned_integer _Tp> +template <__unsigned_integer _Tp> [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr _Tp bit_ceil(_Tp __t) noexcept { return std::__bit_ceil(__t); } diff --git a/lib/libcxx/include/__bit/bit_floor.h b/lib/libcxx/include/__bit/bit_floor.h index 133e369504..799a064130 100644 --- a/lib/libcxx/include/__bit/bit_floor.h +++ b/lib/libcxx/include/__bit/bit_floor.h @@ -10,9 +10,8 @@ #define _LIBCPP___BIT_BIT_FLOOR_H #include <__bit/bit_log2.h> -#include <__concepts/arithmetic.h> #include <__config> -#include +#include <__type_traits/integer_traits.h> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # pragma GCC system_header @@ -22,7 +21,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD #if _LIBCPP_STD_VER >= 20 -template <__libcpp_unsigned_integer _Tp> +template <__unsigned_integer _Tp> [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr _Tp bit_floor(_Tp __t) noexcept { return __t == 0 ? 0 : _Tp{1} << std::__bit_log2(__t); } diff --git a/lib/libcxx/include/__bit/bit_log2.h b/lib/libcxx/include/__bit/bit_log2.h index 94ee6c3b2b..8077cd91d6 100644 --- a/lib/libcxx/include/__bit/bit_log2.h +++ b/lib/libcxx/include/__bit/bit_log2.h @@ -11,7 +11,7 @@ #include <__bit/countl.h> #include <__config> -#include <__type_traits/is_unsigned_integer.h> +#include <__type_traits/integer_traits.h> #include #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) @@ -20,16 +20,12 @@ _LIBCPP_BEGIN_NAMESPACE_STD -#if _LIBCPP_STD_VER >= 14 - template -_LIBCPP_HIDE_FROM_ABI constexpr _Tp __bit_log2(_Tp __t) noexcept { - static_assert(__libcpp_is_unsigned_integer<_Tp>::value, "__bit_log2 requires an unsigned integer type"); +_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 _Tp __bit_log2(_Tp __t) _NOEXCEPT { + static_assert(__is_unsigned_integer_v<_Tp>, "__bit_log2 requires an unsigned integer type"); return numeric_limits<_Tp>::digits - 1 - std::__countl_zero(__t); } -#endif // _LIBCPP_STD_VER >= 14 - _LIBCPP_END_NAMESPACE_STD #endif // _LIBCPP___BIT_BIT_LOG2_H diff --git a/lib/libcxx/include/__bit/bit_width.h b/lib/libcxx/include/__bit/bit_width.h index 853e481776..75050acabb 100644 --- a/lib/libcxx/include/__bit/bit_width.h +++ b/lib/libcxx/include/__bit/bit_width.h @@ -10,8 +10,8 @@ #define _LIBCPP___BIT_BIT_WIDTH_H #include <__bit/bit_log2.h> -#include <__concepts/arithmetic.h> #include <__config> +#include <__type_traits/integer_traits.h> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # pragma GCC system_header @@ -21,7 +21,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD -template <__libcpp_unsigned_integer _Tp> +template <__unsigned_integer _Tp> [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr int bit_width(_Tp __t) noexcept { return __t == 0 ? 0 : std::__bit_log2(__t) + 1; } diff --git a/lib/libcxx/include/__bit/countl.h b/lib/libcxx/include/__bit/countl.h index d4df1d049b..0759140208 100644 --- a/lib/libcxx/include/__bit/countl.h +++ b/lib/libcxx/include/__bit/countl.h @@ -6,16 +6,11 @@ // //===----------------------------------------------------------------------===// -// TODO: __builtin_clzg is available since Clang 19 and GCC 14. When support for older versions is dropped, we can -// refactor this code to exclusively use __builtin_clzg. - #ifndef _LIBCPP___BIT_COUNTL_H #define _LIBCPP___BIT_COUNTL_H -#include <__bit/rotate.h> -#include <__concepts/arithmetic.h> #include <__config> -#include <__type_traits/is_unsigned_integer.h> +#include <__type_traits/integer_traits.h> #include #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) @@ -27,79 +22,20 @@ _LIBCPP_PUSH_MACROS _LIBCPP_BEGIN_NAMESPACE_STD -[[__nodiscard__]] inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR int __libcpp_clz(unsigned __x) _NOEXCEPT { - return __builtin_clz(__x); -} - -[[__nodiscard__]] inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR int __libcpp_clz(unsigned long __x) _NOEXCEPT { - return __builtin_clzl(__x); -} - -[[__nodiscard__]] inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR int __libcpp_clz(unsigned long long __x) _NOEXCEPT { - return __builtin_clzll(__x); -} - -#if _LIBCPP_HAS_INT128 -inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR int __libcpp_clz(__uint128_t __x) _NOEXCEPT { -# if __has_builtin(__builtin_clzg) - return __builtin_clzg(__x); -# else - // The function is written in this form due to C++ constexpr limitations. - // The algorithm: - // - Test whether any bit in the high 64-bits is set - // - No bits set: - // - The high 64-bits contain 64 leading zeros, - // - Add the result of the low 64-bits. - // - Any bits set: - // - The number of leading zeros of the input is the number of leading - // zeros in the high 64-bits. - return ((__x >> 64) == 0) ? (64 + __builtin_clzll(static_cast(__x))) - : __builtin_clzll(static_cast(__x >> 64)); -# endif -} -#endif // _LIBCPP_HAS_INT128 - template _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 int __countl_zero(_Tp __t) _NOEXCEPT { - static_assert(__libcpp_is_unsigned_integer<_Tp>::value, "__countl_zero requires an unsigned integer type"); -#if __has_builtin(__builtin_clzg) + static_assert(__is_unsigned_integer_v<_Tp>, "__countl_zero requires an unsigned integer type"); return __builtin_clzg(__t, numeric_limits<_Tp>::digits); -#else // __has_builtin(__builtin_clzg) - if (__t == 0) - return numeric_limits<_Tp>::digits; - - if (sizeof(_Tp) <= sizeof(unsigned int)) - return std::__libcpp_clz(static_cast(__t)) - - (numeric_limits::digits - numeric_limits<_Tp>::digits); - else if (sizeof(_Tp) <= sizeof(unsigned long)) - return std::__libcpp_clz(static_cast(__t)) - - (numeric_limits::digits - numeric_limits<_Tp>::digits); - else if (sizeof(_Tp) <= sizeof(unsigned long long)) - return std::__libcpp_clz(static_cast(__t)) - - (numeric_limits::digits - numeric_limits<_Tp>::digits); - else { - int __ret = 0; - int __iter = 0; - const unsigned int __ulldigits = numeric_limits::digits; - while (true) { - __t = std::__rotl(__t, __ulldigits); - if ((__iter = std::__countl_zero(static_cast(__t))) != __ulldigits) - break; - __ret += __iter; - } - return __ret + __iter; - } -#endif // __has_builtin(__builtin_clzg) } #if _LIBCPP_STD_VER >= 20 -template <__libcpp_unsigned_integer _Tp> +template <__unsigned_integer _Tp> [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr int countl_zero(_Tp __t) noexcept { return std::__countl_zero(__t); } -template <__libcpp_unsigned_integer _Tp> +template <__unsigned_integer _Tp> [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr int countl_one(_Tp __t) noexcept { return __t != numeric_limits<_Tp>::max() ? std::countl_zero(static_cast<_Tp>(~__t)) : numeric_limits<_Tp>::digits; } diff --git a/lib/libcxx/include/__bit/countr.h b/lib/libcxx/include/__bit/countr.h index 2f7571133b..f6c98695d3 100644 --- a/lib/libcxx/include/__bit/countr.h +++ b/lib/libcxx/include/__bit/countr.h @@ -6,15 +6,11 @@ // //===----------------------------------------------------------------------===// -// TODO: __builtin_ctzg is available since Clang 19 and GCC 14. When support for older versions is dropped, we can -// refactor this code to exclusively use __builtin_ctzg. - #ifndef _LIBCPP___BIT_COUNTR_H #define _LIBCPP___BIT_COUNTR_H -#include <__bit/rotate.h> -#include <__concepts/arithmetic.h> #include <__config> +#include <__type_traits/integer_traits.h> #include #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) @@ -26,51 +22,20 @@ _LIBCPP_PUSH_MACROS _LIBCPP_BEGIN_NAMESPACE_STD -[[__nodiscard__]] inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR int __libcpp_ctz(unsigned __x) _NOEXCEPT { - return __builtin_ctz(__x); -} - -[[__nodiscard__]] inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR int __libcpp_ctz(unsigned long __x) _NOEXCEPT { - return __builtin_ctzl(__x); -} - -[[__nodiscard__]] inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR int __libcpp_ctz(unsigned long long __x) _NOEXCEPT { - return __builtin_ctzll(__x); -} - template -[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 int __countr_zero(_Tp __t) _NOEXCEPT { -#if __has_builtin(__builtin_ctzg) +[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR int __countr_zero(_Tp __t) _NOEXCEPT { + static_assert(__is_unsigned_integer_v<_Tp>, "__countr_zero only works with unsigned types"); return __builtin_ctzg(__t, numeric_limits<_Tp>::digits); -#else // __has_builtin(__builtin_ctzg) - if (__t == 0) - return numeric_limits<_Tp>::digits; - if (sizeof(_Tp) <= sizeof(unsigned int)) - return std::__libcpp_ctz(static_cast(__t)); - else if (sizeof(_Tp) <= sizeof(unsigned long)) - return std::__libcpp_ctz(static_cast(__t)); - else if (sizeof(_Tp) <= sizeof(unsigned long long)) - return std::__libcpp_ctz(static_cast(__t)); - else { - int __ret = 0; - const unsigned int __ulldigits = numeric_limits::digits; - while (static_cast(__t) == 0uLL) { - __ret += __ulldigits; - __t >>= __ulldigits; - } - return __ret + std::__libcpp_ctz(static_cast(__t)); - } -#endif // __has_builtin(__builtin_ctzg) } #if _LIBCPP_STD_VER >= 20 -template <__libcpp_unsigned_integer _Tp> +template <__unsigned_integer _Tp> [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr int countr_zero(_Tp __t) noexcept { return std::__countr_zero(__t); } -template <__libcpp_unsigned_integer _Tp> +template <__unsigned_integer _Tp> [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr int countr_one(_Tp __t) noexcept { return __t != numeric_limits<_Tp>::max() ? std::countr_zero(static_cast<_Tp>(~__t)) : numeric_limits<_Tp>::digits; } diff --git a/lib/libcxx/include/__bit/has_single_bit.h b/lib/libcxx/include/__bit/has_single_bit.h index 52f5853a1b..b43e69323e 100644 --- a/lib/libcxx/include/__bit/has_single_bit.h +++ b/lib/libcxx/include/__bit/has_single_bit.h @@ -9,8 +9,8 @@ #ifndef _LIBCPP___BIT_HAS_SINGLE_BIT_H #define _LIBCPP___BIT_HAS_SINGLE_BIT_H -#include <__concepts/arithmetic.h> #include <__config> +#include <__type_traits/integer_traits.h> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # pragma GCC system_header @@ -23,7 +23,7 @@ _LIBCPP_PUSH_MACROS _LIBCPP_BEGIN_NAMESPACE_STD -template <__libcpp_unsigned_integer _Tp> +template <__unsigned_integer _Tp> [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr bool has_single_bit(_Tp __t) noexcept { return __t != 0 && (((__t & (__t - 1)) == 0)); } diff --git a/lib/libcxx/include/__bit/popcount.h b/lib/libcxx/include/__bit/popcount.h index 5cf0a01d07..8d9ba09938 100644 --- a/lib/libcxx/include/__bit/popcount.h +++ b/lib/libcxx/include/__bit/popcount.h @@ -6,16 +6,11 @@ // //===----------------------------------------------------------------------===// -// TODO: __builtin_popcountg is available since Clang 19 and GCC 14. When support for older versions is dropped, we can -// refactor this code to exclusively use __builtin_popcountg. - #ifndef _LIBCPP___BIT_POPCOUNT_H #define _LIBCPP___BIT_POPCOUNT_H -#include <__bit/rotate.h> -#include <__concepts/arithmetic.h> #include <__config> -#include +#include <__type_traits/integer_traits.h> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # pragma GCC system_header @@ -26,43 +21,20 @@ _LIBCPP_PUSH_MACROS _LIBCPP_BEGIN_NAMESPACE_STD -inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR int __libcpp_popcount(unsigned __x) _NOEXCEPT { - return __builtin_popcount(__x); -} - -inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR int __libcpp_popcount(unsigned long __x) _NOEXCEPT { - return __builtin_popcountl(__x); -} - -inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR int __libcpp_popcount(unsigned long long __x) _NOEXCEPT { - return __builtin_popcountll(__x); +template +[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR int __popcount(_Tp __t) _NOEXCEPT { + static_assert(__is_unsigned_integer_v<_Tp>, "__popcount only works with unsigned types"); + return __builtin_popcountg(__t); } #if _LIBCPP_STD_VER >= 20 -template <__libcpp_unsigned_integer _Tp> +template <__unsigned_integer _Tp> [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr int popcount(_Tp __t) noexcept { -# if __has_builtin(__builtin_popcountg) - return __builtin_popcountg(__t); -# else // __has_builtin(__builtin_popcountg) - if (sizeof(_Tp) <= sizeof(unsigned int)) - return std::__libcpp_popcount(static_cast(__t)); - else if (sizeof(_Tp) <= sizeof(unsigned long)) - return std::__libcpp_popcount(static_cast(__t)); - else if (sizeof(_Tp) <= sizeof(unsigned long long)) - return std::__libcpp_popcount(static_cast(__t)); - else { - int __ret = 0; - while (__t != 0) { - __ret += std::__libcpp_popcount(static_cast(__t)); - __t >>= numeric_limits::digits; - } - return __ret; - } -# endif // __has_builtin(__builtin_popcountg) + return std::__popcount(__t); } -#endif // _LIBCPP_STD_VER >= 20 +#endif _LIBCPP_END_NAMESPACE_STD diff --git a/lib/libcxx/include/__bit/rotate.h b/lib/libcxx/include/__bit/rotate.h index d79d98de29..c6f34bdaf6 100644 --- a/lib/libcxx/include/__bit/rotate.h +++ b/lib/libcxx/include/__bit/rotate.h @@ -9,9 +9,8 @@ #ifndef _LIBCPP___BIT_ROTATE_H #define _LIBCPP___BIT_ROTATE_H -#include <__concepts/arithmetic.h> #include <__config> -#include <__type_traits/is_unsigned_integer.h> +#include <__type_traits/integer_traits.h> #include #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) @@ -25,7 +24,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD // the rotr function becomes the ROR instruction. template _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 _Tp __rotl(_Tp __x, int __s) _NOEXCEPT { - static_assert(__libcpp_is_unsigned_integer<_Tp>::value, "__rotl requires an unsigned integer type"); + static_assert(__is_unsigned_integer_v<_Tp>, "__rotl requires an unsigned integer type"); const int __n = numeric_limits<_Tp>::digits; int __r = __s % __n; @@ -40,7 +39,7 @@ _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 _Tp __rotl(_Tp __x, int __s) template _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 _Tp __rotr(_Tp __x, int __s) _NOEXCEPT { - static_assert(__libcpp_is_unsigned_integer<_Tp>::value, "__rotr requires an unsigned integer type"); + static_assert(__is_unsigned_integer_v<_Tp>, "__rotr requires an unsigned integer type"); const int __n = numeric_limits<_Tp>::digits; int __r = __s % __n; @@ -55,12 +54,12 @@ _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 _Tp __rotr(_Tp __x, int __s) #if _LIBCPP_STD_VER >= 20 -template <__libcpp_unsigned_integer _Tp> +template <__unsigned_integer _Tp> [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr _Tp rotl(_Tp __t, int __cnt) noexcept { return std::__rotl(__t, __cnt); } -template <__libcpp_unsigned_integer _Tp> +template <__unsigned_integer _Tp> [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr _Tp rotr(_Tp __t, int __cnt) noexcept { return std::__rotr(__t, __cnt); } diff --git a/lib/libcxx/include/__bit_reference b/lib/libcxx/include/__bit_reference index 67abb02312..a3e6defd40 100644 --- a/lib/libcxx/include/__bit_reference +++ b/lib/libcxx/include/__bit_reference @@ -10,21 +10,35 @@ #ifndef _LIBCPP___BIT_REFERENCE #define _LIBCPP___BIT_REFERENCE +#include <__algorithm/comp.h> +#include <__algorithm/copy.h> +#include <__algorithm/copy_backward.h> #include <__algorithm/copy_n.h> +#include <__algorithm/equal.h> #include <__algorithm/min.h> +#include <__algorithm/rotate.h> +#include <__algorithm/swap_ranges.h> +#include <__assert> #include <__bit/countr.h> #include <__compare/ordering.h> #include <__config> #include <__cstddef/ptrdiff_t.h> #include <__cstddef/size_t.h> +#include <__functional/identity.h> #include <__fwd/bit_reference.h> #include <__iterator/iterator_traits.h> #include <__memory/construct_at.h> #include <__memory/pointer_traits.h> #include <__type_traits/conditional.h> +#include <__type_traits/desugars_to.h> +#include <__type_traits/enable_if.h> #include <__type_traits/is_constant_evaluated.h> +#include <__type_traits/is_same.h> +#include <__type_traits/is_unsigned.h> #include <__type_traits/void_t.h> +#include <__utility/pair.h> #include <__utility/swap.h> +#include #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # pragma GCC system_header @@ -55,6 +69,53 @@ struct __size_difference_type_traits<_Cp, __void_t +_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _StorageType __trailing_mask(unsigned __clz) { + static_assert(is_unsigned<_StorageType>::value, "__trailing_mask only works with unsigned types"); + return static_cast<_StorageType>(~static_cast<_StorageType>(0)) >> __clz; +} + +// Creates a mask of type `_StorageType` with a specified number of trailing zeros (__ctz) and sets all remaining +// bits to one. +template +_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _StorageType __leading_mask(unsigned __ctz) { + static_assert(is_unsigned<_StorageType>::value, "__leading_mask only works with unsigned types"); + return static_cast<_StorageType>(~static_cast<_StorageType>(0)) << __ctz; +} + +// Creates a mask of type `_StorageType` with a specified number of leading zeros (__clz), a specified number of +// trailing zeros (__ctz), and sets all bits in between to one. +template +_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _StorageType __middle_mask(unsigned __clz, unsigned __ctz) { + static_assert(is_unsigned<_StorageType>::value, "__middle_mask only works with unsigned types"); + return std::__leading_mask<_StorageType>(__ctz) & std::__trailing_mask<_StorageType>(__clz); +} + +// This function is designed to operate correctly even for smaller integral types like `uint8_t`, `uint16_t`, +// or `unsigned short`. +// See https://github.com/llvm/llvm-project/pull/122410. +template +_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 void +__fill_masked_range(_StoragePointer __word, unsigned __clz, unsigned __ctz, bool __fill_val) { + static_assert(is_unsigned::element_type>::value, + "__fill_masked_range must be called with unsigned type"); + using _StorageType = typename pointer_traits<_StoragePointer>::element_type; + _LIBCPP_ASSERT_VALID_INPUT_RANGE( + __ctz + __clz < sizeof(_StorageType) * CHAR_BIT, "__fill_masked_range called with invalid range"); + _StorageType __m = std::__middle_mask<_StorageType>(__clz, __ctz); + if (__fill_val) + *__word |= __m; + else + *__word &= ~__m; +} + template ::value> class __bit_reference { using __storage_type _LIBCPP_NODEBUG = typename _Cp::__storage_type; @@ -104,7 +165,7 @@ public: _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void flip() _NOEXCEPT { *__seg_ ^= __mask_; } _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 __bit_iterator<_Cp, false> operator&() const _NOEXCEPT { - return __bit_iterator<_Cp, false>(__seg_, static_cast(std::__libcpp_ctz(__mask_))); + return __bit_iterator<_Cp, false>(__seg_, static_cast(std::__countr_zero(__mask_))); } private: @@ -173,7 +234,7 @@ public: } _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 __bit_iterator<_Cp, true> operator&() const _NOEXCEPT { - return __bit_iterator<_Cp, true>(__seg_, static_cast(std::__libcpp_ctz(__mask_))); + return __bit_iterator<_Cp, true>(__seg_, static_cast(std::__countr_zero(__mask_))); } private: @@ -183,422 +244,6 @@ private: __mask_(__m) {} }; -// copy - -template -_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI __bit_iterator<_Cp, false> __copy_aligned( - __bit_iterator<_Cp, _IsConst> __first, __bit_iterator<_Cp, _IsConst> __last, __bit_iterator<_Cp, false> __result) { - using _In = __bit_iterator<_Cp, _IsConst>; - using difference_type = typename _In::difference_type; - using __storage_type = typename _In::__storage_type; - - const int __bits_per_word = _In::__bits_per_word; - difference_type __n = __last - __first; - if (__n > 0) { - // do first word - if (__first.__ctz_ != 0) { - unsigned __clz = __bits_per_word - __first.__ctz_; - difference_type __dn = std::min(static_cast(__clz), __n); - __n -= __dn; - __storage_type __m = (~__storage_type(0) << __first.__ctz_) & (~__storage_type(0) >> (__clz - __dn)); - __storage_type __b = *__first.__seg_ & __m; - *__result.__seg_ &= ~__m; - *__result.__seg_ |= __b; - __result.__seg_ += (__dn + __result.__ctz_) / __bits_per_word; - __result.__ctz_ = static_cast((__dn + __result.__ctz_) % __bits_per_word); - ++__first.__seg_; - // __first.__ctz_ = 0; - } - // __first.__ctz_ == 0; - // do middle words - __storage_type __nw = __n / __bits_per_word; - std::copy_n(std::__to_address(__first.__seg_), __nw, std::__to_address(__result.__seg_)); - __n -= __nw * __bits_per_word; - __result.__seg_ += __nw; - // do last word - if (__n > 0) { - __first.__seg_ += __nw; - __storage_type __m = ~__storage_type(0) >> (__bits_per_word - __n); - __storage_type __b = *__first.__seg_ & __m; - *__result.__seg_ &= ~__m; - *__result.__seg_ |= __b; - __result.__ctz_ = static_cast(__n); - } - } - return __result; -} - -template -_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI __bit_iterator<_Cp, false> __copy_unaligned( - __bit_iterator<_Cp, _IsConst> __first, __bit_iterator<_Cp, _IsConst> __last, __bit_iterator<_Cp, false> __result) { - using _In = __bit_iterator<_Cp, _IsConst>; - using difference_type = typename _In::difference_type; - using __storage_type = typename _In::__storage_type; - - const int __bits_per_word = _In::__bits_per_word; - difference_type __n = __last - __first; - if (__n > 0) { - // do first word - if (__first.__ctz_ != 0) { - unsigned __clz_f = __bits_per_word - __first.__ctz_; - difference_type __dn = std::min(static_cast(__clz_f), __n); - __n -= __dn; - __storage_type __m = (~__storage_type(0) << __first.__ctz_) & (~__storage_type(0) >> (__clz_f - __dn)); - __storage_type __b = *__first.__seg_ & __m; - unsigned __clz_r = __bits_per_word - __result.__ctz_; - __storage_type __ddn = std::min<__storage_type>(__dn, __clz_r); - __m = (~__storage_type(0) << __result.__ctz_) & (~__storage_type(0) >> (__clz_r - __ddn)); - *__result.__seg_ &= ~__m; - if (__result.__ctz_ > __first.__ctz_) - *__result.__seg_ |= __b << (__result.__ctz_ - __first.__ctz_); - else - *__result.__seg_ |= __b >> (__first.__ctz_ - __result.__ctz_); - __result.__seg_ += (__ddn + __result.__ctz_) / __bits_per_word; - __result.__ctz_ = static_cast((__ddn + __result.__ctz_) % __bits_per_word); - __dn -= __ddn; - if (__dn > 0) { - __m = ~__storage_type(0) >> (__bits_per_word - __dn); - *__result.__seg_ &= ~__m; - *__result.__seg_ |= __b >> (__first.__ctz_ + __ddn); - __result.__ctz_ = static_cast(__dn); - } - ++__first.__seg_; - // __first.__ctz_ = 0; - } - // __first.__ctz_ == 0; - // do middle words - unsigned __clz_r = __bits_per_word - __result.__ctz_; - __storage_type __m = ~__storage_type(0) << __result.__ctz_; - for (; __n >= __bits_per_word; __n -= __bits_per_word, ++__first.__seg_) { - __storage_type __b = *__first.__seg_; - *__result.__seg_ &= ~__m; - *__result.__seg_ |= __b << __result.__ctz_; - ++__result.__seg_; - *__result.__seg_ &= __m; - *__result.__seg_ |= __b >> __clz_r; - } - // do last word - if (__n > 0) { - __m = ~__storage_type(0) >> (__bits_per_word - __n); - __storage_type __b = *__first.__seg_ & __m; - __storage_type __dn = std::min(__n, static_cast(__clz_r)); - __m = (~__storage_type(0) << __result.__ctz_) & (~__storage_type(0) >> (__clz_r - __dn)); - *__result.__seg_ &= ~__m; - *__result.__seg_ |= __b << __result.__ctz_; - __result.__seg_ += (__dn + __result.__ctz_) / __bits_per_word; - __result.__ctz_ = static_cast((__dn + __result.__ctz_) % __bits_per_word); - __n -= __dn; - if (__n > 0) { - __m = ~__storage_type(0) >> (__bits_per_word - __n); - *__result.__seg_ &= ~__m; - *__result.__seg_ |= __b >> __dn; - __result.__ctz_ = static_cast(__n); - } - } - } - return __result; -} - -template -inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 __bit_iterator<_Cp, false> -copy(__bit_iterator<_Cp, _IsConst> __first, __bit_iterator<_Cp, _IsConst> __last, __bit_iterator<_Cp, false> __result) { - if (__first.__ctz_ == __result.__ctz_) - return std::__copy_aligned(__first, __last, __result); - return std::__copy_unaligned(__first, __last, __result); -} - -// copy_backward - -template -_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI __bit_iterator<_Cp, false> __copy_backward_aligned( - __bit_iterator<_Cp, _IsConst> __first, __bit_iterator<_Cp, _IsConst> __last, __bit_iterator<_Cp, false> __result) { - using _In = __bit_iterator<_Cp, _IsConst>; - using difference_type = typename _In::difference_type; - using __storage_type = typename _In::__storage_type; - - const int __bits_per_word = _In::__bits_per_word; - difference_type __n = __last - __first; - if (__n > 0) { - // do first word - if (__last.__ctz_ != 0) { - difference_type __dn = std::min(static_cast(__last.__ctz_), __n); - __n -= __dn; - unsigned __clz = __bits_per_word - __last.__ctz_; - __storage_type __m = (~__storage_type(0) << (__last.__ctz_ - __dn)) & (~__storage_type(0) >> __clz); - __storage_type __b = *__last.__seg_ & __m; - *__result.__seg_ &= ~__m; - *__result.__seg_ |= __b; - __result.__ctz_ = static_cast(((-__dn & (__bits_per_word - 1)) + __result.__ctz_) % __bits_per_word); - // __last.__ctz_ = 0 - } - // __last.__ctz_ == 0 || __n == 0 - // __result.__ctz_ == 0 || __n == 0 - // do middle words - __storage_type __nw = __n / __bits_per_word; - __result.__seg_ -= __nw; - __last.__seg_ -= __nw; - std::copy_n(std::__to_address(__last.__seg_), __nw, std::__to_address(__result.__seg_)); - __n -= __nw * __bits_per_word; - // do last word - if (__n > 0) { - __storage_type __m = ~__storage_type(0) << (__bits_per_word - __n); - __storage_type __b = *--__last.__seg_ & __m; - *--__result.__seg_ &= ~__m; - *__result.__seg_ |= __b; - __result.__ctz_ = static_cast(-__n & (__bits_per_word - 1)); - } - } - return __result; -} - -template -_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI __bit_iterator<_Cp, false> __copy_backward_unaligned( - __bit_iterator<_Cp, _IsConst> __first, __bit_iterator<_Cp, _IsConst> __last, __bit_iterator<_Cp, false> __result) { - using _In = __bit_iterator<_Cp, _IsConst>; - using difference_type = typename _In::difference_type; - using __storage_type = typename _In::__storage_type; - - const int __bits_per_word = _In::__bits_per_word; - difference_type __n = __last - __first; - if (__n > 0) { - // do first word - if (__last.__ctz_ != 0) { - difference_type __dn = std::min(static_cast(__last.__ctz_), __n); - __n -= __dn; - unsigned __clz_l = __bits_per_word - __last.__ctz_; - __storage_type __m = (~__storage_type(0) << (__last.__ctz_ - __dn)) & (~__storage_type(0) >> __clz_l); - __storage_type __b = *__last.__seg_ & __m; - unsigned __clz_r = __bits_per_word - __result.__ctz_; - __storage_type __ddn = std::min(__dn, static_cast(__result.__ctz_)); - if (__ddn > 0) { - __m = (~__storage_type(0) << (__result.__ctz_ - __ddn)) & (~__storage_type(0) >> __clz_r); - *__result.__seg_ &= ~__m; - if (__result.__ctz_ > __last.__ctz_) - *__result.__seg_ |= __b << (__result.__ctz_ - __last.__ctz_); - else - *__result.__seg_ |= __b >> (__last.__ctz_ - __result.__ctz_); - __result.__ctz_ = static_cast(((-__ddn & (__bits_per_word - 1)) + __result.__ctz_) % __bits_per_word); - __dn -= __ddn; - } - if (__dn > 0) { - // __result.__ctz_ == 0 - --__result.__seg_; - __result.__ctz_ = static_cast(-__dn & (__bits_per_word - 1)); - __m = ~__storage_type(0) << __result.__ctz_; - *__result.__seg_ &= ~__m; - __last.__ctz_ -= __dn + __ddn; - *__result.__seg_ |= __b << (__result.__ctz_ - __last.__ctz_); - } - // __last.__ctz_ = 0 - } - // __last.__ctz_ == 0 || __n == 0 - // __result.__ctz_ != 0 || __n == 0 - // do middle words - unsigned __clz_r = __bits_per_word - __result.__ctz_; - __storage_type __m = ~__storage_type(0) >> __clz_r; - for (; __n >= __bits_per_word; __n -= __bits_per_word) { - __storage_type __b = *--__last.__seg_; - *__result.__seg_ &= ~__m; - *__result.__seg_ |= __b >> __clz_r; - *--__result.__seg_ &= __m; - *__result.__seg_ |= __b << __result.__ctz_; - } - // do last word - if (__n > 0) { - __m = ~__storage_type(0) << (__bits_per_word - __n); - __storage_type __b = *--__last.__seg_ & __m; - __clz_r = __bits_per_word - __result.__ctz_; - __storage_type __dn = std::min(__n, static_cast(__result.__ctz_)); - __m = (~__storage_type(0) << (__result.__ctz_ - __dn)) & (~__storage_type(0) >> __clz_r); - *__result.__seg_ &= ~__m; - *__result.__seg_ |= __b >> (__bits_per_word - __result.__ctz_); - __result.__ctz_ = static_cast(((-__dn & (__bits_per_word - 1)) + __result.__ctz_) % __bits_per_word); - __n -= __dn; - if (__n > 0) { - // __result.__ctz_ == 0 - --__result.__seg_; - __result.__ctz_ = static_cast(-__n & (__bits_per_word - 1)); - __m = ~__storage_type(0) << __result.__ctz_; - *__result.__seg_ &= ~__m; - *__result.__seg_ |= __b << (__result.__ctz_ - (__bits_per_word - __n - __dn)); - } - } - } - return __result; -} - -template -inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 __bit_iterator<_Cp, false> copy_backward( - __bit_iterator<_Cp, _IsConst> __first, __bit_iterator<_Cp, _IsConst> __last, __bit_iterator<_Cp, false> __result) { - if (__last.__ctz_ == __result.__ctz_) - return std::__copy_backward_aligned(__first, __last, __result); - return std::__copy_backward_unaligned(__first, __last, __result); -} - -// move - -template -inline _LIBCPP_HIDE_FROM_ABI __bit_iterator<_Cp, false> -move(__bit_iterator<_Cp, _IsConst> __first, __bit_iterator<_Cp, _IsConst> __last, __bit_iterator<_Cp, false> __result) { - return std::copy(__first, __last, __result); -} - -// move_backward - -template -inline _LIBCPP_HIDE_FROM_ABI __bit_iterator<_Cp, false> move_backward( - __bit_iterator<_Cp, _IsConst> __first, __bit_iterator<_Cp, _IsConst> __last, __bit_iterator<_Cp, false> __result) { - return std::copy_backward(__first, __last, __result); -} - -// swap_ranges - -template -_LIBCPP_HIDE_FROM_ABI __bit_iterator<_Cr, false> __swap_ranges_aligned( - __bit_iterator<_Cl, false> __first, __bit_iterator<_Cl, false> __last, __bit_iterator<_Cr, false> __result) { - using _I1 = __bit_iterator<_Cl, false>; - using difference_type = typename _I1::difference_type; - using __storage_type = typename _I1::__storage_type; - - const int __bits_per_word = _I1::__bits_per_word; - difference_type __n = __last - __first; - if (__n > 0) { - // do first word - if (__first.__ctz_ != 0) { - unsigned __clz = __bits_per_word - __first.__ctz_; - difference_type __dn = std::min(static_cast(__clz), __n); - __n -= __dn; - __storage_type __m = (~__storage_type(0) << __first.__ctz_) & (~__storage_type(0) >> (__clz - __dn)); - __storage_type __b1 = *__first.__seg_ & __m; - *__first.__seg_ &= ~__m; - __storage_type __b2 = *__result.__seg_ & __m; - *__result.__seg_ &= ~__m; - *__result.__seg_ |= __b1; - *__first.__seg_ |= __b2; - __result.__seg_ += (__dn + __result.__ctz_) / __bits_per_word; - __result.__ctz_ = static_cast((__dn + __result.__ctz_) % __bits_per_word); - ++__first.__seg_; - // __first.__ctz_ = 0; - } - // __first.__ctz_ == 0; - // do middle words - for (; __n >= __bits_per_word; __n -= __bits_per_word, ++__first.__seg_, ++__result.__seg_) - swap(*__first.__seg_, *__result.__seg_); - // do last word - if (__n > 0) { - __storage_type __m = ~__storage_type(0) >> (__bits_per_word - __n); - __storage_type __b1 = *__first.__seg_ & __m; - *__first.__seg_ &= ~__m; - __storage_type __b2 = *__result.__seg_ & __m; - *__result.__seg_ &= ~__m; - *__result.__seg_ |= __b1; - *__first.__seg_ |= __b2; - __result.__ctz_ = static_cast(__n); - } - } - return __result; -} - -template -_LIBCPP_HIDE_FROM_ABI __bit_iterator<_Cr, false> __swap_ranges_unaligned( - __bit_iterator<_Cl, false> __first, __bit_iterator<_Cl, false> __last, __bit_iterator<_Cr, false> __result) { - using _I1 = __bit_iterator<_Cl, false>; - using difference_type = typename _I1::difference_type; - using __storage_type = typename _I1::__storage_type; - - const int __bits_per_word = _I1::__bits_per_word; - difference_type __n = __last - __first; - if (__n > 0) { - // do first word - if (__first.__ctz_ != 0) { - unsigned __clz_f = __bits_per_word - __first.__ctz_; - difference_type __dn = std::min(static_cast(__clz_f), __n); - __n -= __dn; - __storage_type __m = (~__storage_type(0) << __first.__ctz_) & (~__storage_type(0) >> (__clz_f - __dn)); - __storage_type __b1 = *__first.__seg_ & __m; - *__first.__seg_ &= ~__m; - unsigned __clz_r = __bits_per_word - __result.__ctz_; - __storage_type __ddn = std::min<__storage_type>(__dn, __clz_r); - __m = (~__storage_type(0) << __result.__ctz_) & (~__storage_type(0) >> (__clz_r - __ddn)); - __storage_type __b2 = *__result.__seg_ & __m; - *__result.__seg_ &= ~__m; - if (__result.__ctz_ > __first.__ctz_) { - unsigned __s = __result.__ctz_ - __first.__ctz_; - *__result.__seg_ |= __b1 << __s; - *__first.__seg_ |= __b2 >> __s; - } else { - unsigned __s = __first.__ctz_ - __result.__ctz_; - *__result.__seg_ |= __b1 >> __s; - *__first.__seg_ |= __b2 << __s; - } - __result.__seg_ += (__ddn + __result.__ctz_) / __bits_per_word; - __result.__ctz_ = static_cast((__ddn + __result.__ctz_) % __bits_per_word); - __dn -= __ddn; - if (__dn > 0) { - __m = ~__storage_type(0) >> (__bits_per_word - __dn); - __b2 = *__result.__seg_ & __m; - *__result.__seg_ &= ~__m; - unsigned __s = __first.__ctz_ + __ddn; - *__result.__seg_ |= __b1 >> __s; - *__first.__seg_ |= __b2 << __s; - __result.__ctz_ = static_cast(__dn); - } - ++__first.__seg_; - // __first.__ctz_ = 0; - } - // __first.__ctz_ == 0; - // do middle words - __storage_type __m = ~__storage_type(0) << __result.__ctz_; - unsigned __clz_r = __bits_per_word - __result.__ctz_; - for (; __n >= __bits_per_word; __n -= __bits_per_word, ++__first.__seg_) { - __storage_type __b1 = *__first.__seg_; - __storage_type __b2 = *__result.__seg_ & __m; - *__result.__seg_ &= ~__m; - *__result.__seg_ |= __b1 << __result.__ctz_; - *__first.__seg_ = __b2 >> __result.__ctz_; - ++__result.__seg_; - __b2 = *__result.__seg_ & ~__m; - *__result.__seg_ &= __m; - *__result.__seg_ |= __b1 >> __clz_r; - *__first.__seg_ |= __b2 << __clz_r; - } - // do last word - if (__n > 0) { - __m = ~__storage_type(0) >> (__bits_per_word - __n); - __storage_type __b1 = *__first.__seg_ & __m; - *__first.__seg_ &= ~__m; - __storage_type __dn = std::min<__storage_type>(__n, __clz_r); - __m = (~__storage_type(0) << __result.__ctz_) & (~__storage_type(0) >> (__clz_r - __dn)); - __storage_type __b2 = *__result.__seg_ & __m; - *__result.__seg_ &= ~__m; - *__result.__seg_ |= __b1 << __result.__ctz_; - *__first.__seg_ |= __b2 >> __result.__ctz_; - __result.__seg_ += (__dn + __result.__ctz_) / __bits_per_word; - __result.__ctz_ = static_cast((__dn + __result.__ctz_) % __bits_per_word); - __n -= __dn; - if (__n > 0) { - __m = ~__storage_type(0) >> (__bits_per_word - __n); - __b2 = *__result.__seg_ & __m; - *__result.__seg_ &= ~__m; - *__result.__seg_ |= __b1 >> __dn; - *__first.__seg_ |= __b2 << __dn; - __result.__ctz_ = static_cast(__n); - } - } - } - return __result; -} - -template -inline _LIBCPP_HIDE_FROM_ABI __bit_iterator<_Cr, false> swap_ranges( - __bit_iterator<_Cl, false> __first1, __bit_iterator<_Cl, false> __last1, __bit_iterator<_Cr, false> __first2) { - if (__first1.__ctz_ == __first2.__ctz_) - return std::__swap_ranges_aligned(__first1, __last1, __first2); - return std::__swap_ranges_unaligned(__first1, __last1, __first2); -} - -// rotate - template struct __bit_array { using difference_type _LIBCPP_NODEBUG = typename __size_difference_type_traits<_Cp>::difference_type; @@ -630,166 +275,6 @@ struct __bit_array { } }; -template -_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI __bit_iterator<_Cp, false> -rotate(__bit_iterator<_Cp, false> __first, __bit_iterator<_Cp, false> __middle, __bit_iterator<_Cp, false> __last) { - using _I1 = __bit_iterator<_Cp, false>; - using difference_type = typename _I1::difference_type; - - difference_type __d1 = __middle - __first; - difference_type __d2 = __last - __middle; - _I1 __r = __first + __d2; - while (__d1 != 0 && __d2 != 0) { - if (__d1 <= __d2) { - if (__d1 <= __bit_array<_Cp>::capacity()) { - __bit_array<_Cp> __b(__d1); - std::copy(__first, __middle, __b.begin()); - std::copy(__b.begin(), __b.end(), std::copy(__middle, __last, __first)); - break; - } else { - __bit_iterator<_Cp, false> __mp = std::swap_ranges(__first, __middle, __middle); - __first = __middle; - __middle = __mp; - __d2 -= __d1; - } - } else { - if (__d2 <= __bit_array<_Cp>::capacity()) { - __bit_array<_Cp> __b(__d2); - std::copy(__middle, __last, __b.begin()); - std::copy_backward(__b.begin(), __b.end(), std::copy_backward(__first, __middle, __last)); - break; - } else { - __bit_iterator<_Cp, false> __mp = __first + __d2; - std::swap_ranges(__first, __mp, __middle); - __first = __mp; - __d1 -= __d2; - } - } - } - return __r; -} - -// equal - -template -_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI bool __equal_unaligned( - __bit_iterator<_Cp, _IC1> __first1, __bit_iterator<_Cp, _IC1> __last1, __bit_iterator<_Cp, _IC2> __first2) { - using _It = __bit_iterator<_Cp, _IC1>; - using difference_type = typename _It::difference_type; - using __storage_type = typename _It::__storage_type; - - const int __bits_per_word = _It::__bits_per_word; - difference_type __n = __last1 - __first1; - if (__n > 0) { - // do first word - if (__first1.__ctz_ != 0) { - unsigned __clz_f = __bits_per_word - __first1.__ctz_; - difference_type __dn = std::min(static_cast(__clz_f), __n); - __n -= __dn; - __storage_type __m = (~__storage_type(0) << __first1.__ctz_) & (~__storage_type(0) >> (__clz_f - __dn)); - __storage_type __b = *__first1.__seg_ & __m; - unsigned __clz_r = __bits_per_word - __first2.__ctz_; - __storage_type __ddn = std::min<__storage_type>(__dn, __clz_r); - __m = (~__storage_type(0) << __first2.__ctz_) & (~__storage_type(0) >> (__clz_r - __ddn)); - if (__first2.__ctz_ > __first1.__ctz_) { - if ((*__first2.__seg_ & __m) != (__b << (__first2.__ctz_ - __first1.__ctz_))) - return false; - } else { - if ((*__first2.__seg_ & __m) != (__b >> (__first1.__ctz_ - __first2.__ctz_))) - return false; - } - __first2.__seg_ += (__ddn + __first2.__ctz_) / __bits_per_word; - __first2.__ctz_ = static_cast((__ddn + __first2.__ctz_) % __bits_per_word); - __dn -= __ddn; - if (__dn > 0) { - __m = ~__storage_type(0) >> (__bits_per_word - __dn); - if ((*__first2.__seg_ & __m) != (__b >> (__first1.__ctz_ + __ddn))) - return false; - __first2.__ctz_ = static_cast(__dn); - } - ++__first1.__seg_; - // __first1.__ctz_ = 0; - } - // __first1.__ctz_ == 0; - // do middle words - unsigned __clz_r = __bits_per_word - __first2.__ctz_; - __storage_type __m = ~__storage_type(0) << __first2.__ctz_; - for (; __n >= __bits_per_word; __n -= __bits_per_word, ++__first1.__seg_) { - __storage_type __b = *__first1.__seg_; - if ((*__first2.__seg_ & __m) != (__b << __first2.__ctz_)) - return false; - ++__first2.__seg_; - if ((*__first2.__seg_ & ~__m) != (__b >> __clz_r)) - return false; - } - // do last word - if (__n > 0) { - __m = ~__storage_type(0) >> (__bits_per_word - __n); - __storage_type __b = *__first1.__seg_ & __m; - __storage_type __dn = std::min(__n, static_cast(__clz_r)); - __m = (~__storage_type(0) << __first2.__ctz_) & (~__storage_type(0) >> (__clz_r - __dn)); - if ((*__first2.__seg_ & __m) != (__b << __first2.__ctz_)) - return false; - __first2.__seg_ += (__dn + __first2.__ctz_) / __bits_per_word; - __first2.__ctz_ = static_cast((__dn + __first2.__ctz_) % __bits_per_word); - __n -= __dn; - if (__n > 0) { - __m = ~__storage_type(0) >> (__bits_per_word - __n); - if ((*__first2.__seg_ & __m) != (__b >> __dn)) - return false; - } - } - } - return true; -} - -template -_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI bool __equal_aligned( - __bit_iterator<_Cp, _IC1> __first1, __bit_iterator<_Cp, _IC1> __last1, __bit_iterator<_Cp, _IC2> __first2) { - using _It = __bit_iterator<_Cp, _IC1>; - using difference_type = typename _It::difference_type; - using __storage_type = typename _It::__storage_type; - - const int __bits_per_word = _It::__bits_per_word; - difference_type __n = __last1 - __first1; - if (__n > 0) { - // do first word - if (__first1.__ctz_ != 0) { - unsigned __clz = __bits_per_word - __first1.__ctz_; - difference_type __dn = std::min(static_cast(__clz), __n); - __n -= __dn; - __storage_type __m = (~__storage_type(0) << __first1.__ctz_) & (~__storage_type(0) >> (__clz - __dn)); - if ((*__first2.__seg_ & __m) != (*__first1.__seg_ & __m)) - return false; - ++__first2.__seg_; - ++__first1.__seg_; - // __first1.__ctz_ = 0; - // __first2.__ctz_ = 0; - } - // __first1.__ctz_ == 0; - // __first2.__ctz_ == 0; - // do middle words - for (; __n >= __bits_per_word; __n -= __bits_per_word, ++__first1.__seg_, ++__first2.__seg_) - if (*__first2.__seg_ != *__first1.__seg_) - return false; - // do last word - if (__n > 0) { - __storage_type __m = ~__storage_type(0) >> (__bits_per_word - __n); - if ((*__first2.__seg_ & __m) != (*__first1.__seg_ & __m)) - return false; - } - } - return true; -} - -template -inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 bool -equal(__bit_iterator<_Cp, _IC1> __first1, __bit_iterator<_Cp, _IC1> __last1, __bit_iterator<_Cp, _IC2> __first2) { - if (__first1.__ctz_ == __first2.__ctz_) - return std::__equal_aligned(__first1, __last1, __first2); - return std::__equal_unaligned(__first1, __last1, __first2); -} - template class __bit_iterator { public: @@ -844,6 +329,7 @@ public: } _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 reference operator*() const _NOEXCEPT { + _LIBCPP_ASSERT_INTERNAL(__ctz_ < __bits_per_word, "Dereferencing an invalid __bit_iterator."); return __conditional_t<_IsConst, __bit_const_reference<_Cp>, __bit_reference<_Cp> >( __seg_, __storage_type(1) << __ctz_); } @@ -968,7 +454,10 @@ private: _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 explicit __bit_iterator(__storage_pointer __s, unsigned __ctz) _NOEXCEPT : __seg_(__s), - __ctz_(__ctz) {} + __ctz_(__ctz) { + _LIBCPP_ASSERT_INTERNAL( + __ctz_ < __bits_per_word, "__bit_iterator initialized with an invalid number of trailing zeros."); + } friend typename _Cp::__self; @@ -989,38 +478,59 @@ private: _LIBCPP_CONSTEXPR_SINCE_CXX20 friend __bit_iterator<_Dp, false> __copy_unaligned( __bit_iterator<_Dp, _IC> __first, __bit_iterator<_Dp, _IC> __last, __bit_iterator<_Dp, false> __result); template - _LIBCPP_CONSTEXPR_SINCE_CXX20 friend __bit_iterator<_Dp, false> - copy(__bit_iterator<_Dp, _IC> __first, __bit_iterator<_Dp, _IC> __last, __bit_iterator<_Dp, false> __result); + _LIBCPP_CONSTEXPR_SINCE_CXX20 friend pair<__bit_iterator<_Dp, _IC>, __bit_iterator<_Dp, false> > + __copy_impl::operator()( + __bit_iterator<_Dp, _IC> __first, __bit_iterator<_Dp, _IC> __last, __bit_iterator<_Dp, false> __result) const; template _LIBCPP_CONSTEXPR_SINCE_CXX20 friend __bit_iterator<_Dp, false> __copy_backward_aligned( __bit_iterator<_Dp, _IC> __first, __bit_iterator<_Dp, _IC> __last, __bit_iterator<_Dp, false> __result); template _LIBCPP_CONSTEXPR_SINCE_CXX20 friend __bit_iterator<_Dp, false> __copy_backward_unaligned( __bit_iterator<_Dp, _IC> __first, __bit_iterator<_Dp, _IC> __last, __bit_iterator<_Dp, false> __result); - template - _LIBCPP_CONSTEXPR_SINCE_CXX20 friend __bit_iterator<_Dp, false> - copy_backward(__bit_iterator<_Dp, _IC> __first, __bit_iterator<_Dp, _IC> __last, __bit_iterator<_Dp, false> __result); + template + friend struct __copy_backward_impl; template - friend __bit_iterator<_Cr, false> + _LIBCPP_CONSTEXPR_SINCE_CXX20 friend __bit_iterator<_Cr, false> __swap_ranges_aligned(__bit_iterator<_Cl, false>, __bit_iterator<_Cl, false>, __bit_iterator<_Cr, false>); template - friend __bit_iterator<_Cr, false> + _LIBCPP_CONSTEXPR_SINCE_CXX20 friend __bit_iterator<_Cr, false> __swap_ranges_unaligned(__bit_iterator<_Cl, false>, __bit_iterator<_Cl, false>, __bit_iterator<_Cr, false>); - template - friend __bit_iterator<_Cr, false> - swap_ranges(__bit_iterator<_Cl, false>, __bit_iterator<_Cl, false>, __bit_iterator<_Cr, false>); - template - _LIBCPP_CONSTEXPR_SINCE_CXX20 friend __bit_iterator<_Dp, false> - rotate(__bit_iterator<_Dp, false>, __bit_iterator<_Dp, false>, __bit_iterator<_Dp, false>); - template + template + _LIBCPP_CONSTEXPR_SINCE_CXX20 friend pair<__bit_iterator<_Cl, false>, __bit_iterator<_Cr, false> > + __swap_ranges(__bit_iterator<_Cl, false>, __bit_iterator<_Cl, false>, __bit_iterator<_Cr, false>); + template + _LIBCPP_CONSTEXPR_SINCE_CXX20 friend pair<__bit_iterator<_Dp, false>, __bit_iterator<_Dp, false> > + __rotate(__bit_iterator<_Dp, false>, __bit_iterator<_Dp, false>, __bit_iterator<_Dp, false>); + template _LIBCPP_CONSTEXPR_SINCE_CXX20 friend bool - __equal_aligned(__bit_iterator<_Dp, _IC1>, __bit_iterator<_Dp, _IC1>, __bit_iterator<_Dp, _IC2>); - template + __equal_aligned(__bit_iterator<_Dp, _IsConst1>, __bit_iterator<_Dp, _IsConst1>, __bit_iterator<_Dp, _IsConst2>); + template _LIBCPP_CONSTEXPR_SINCE_CXX20 friend bool - __equal_unaligned(__bit_iterator<_Dp, _IC1>, __bit_iterator<_Dp, _IC1>, __bit_iterator<_Dp, _IC2>); - template - _LIBCPP_CONSTEXPR_SINCE_CXX20 friend bool - equal(__bit_iterator<_Dp, _IC1>, __bit_iterator<_Dp, _IC1>, __bit_iterator<_Dp, _IC2>); + __equal_unaligned(__bit_iterator<_Dp, _IsConst1>, __bit_iterator<_Dp, _IsConst1>, __bit_iterator<_Dp, _IsConst2>); + template , int> > + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 friend bool __equal_iter_impl( + __bit_iterator<_Dp, _IsConst1>, __bit_iterator<_Dp, _IsConst1>, __bit_iterator<_Dp, _IsConst2>, _BinaryPredicate); + template && __is_identity<_Proj1>::value && + __is_identity<_Proj2>::value, + int> > + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 friend bool __equal_impl( + __bit_iterator<_Dp, _IsConst1> __first1, + __bit_iterator<_Dp, _IsConst1> __last1, + __bit_iterator<_Dp, _IsConst2> __first2, + __bit_iterator<_Dp, _IsConst2>, + _Pred&, + _Proj1&, + _Proj2&); template _LIBCPP_CONSTEXPR_SINCE_CXX20 friend __bit_iterator<_Dp, _IC> __find_bool(__bit_iterator<_Dp, _IC>, typename __size_difference_type_traits<_Dp>::size_type); diff --git a/lib/libcxx/include/__charconv/tables.h b/lib/libcxx/include/__charconv/tables.h index 9568bf841c..b8c6fd8af0 100644 --- a/lib/libcxx/include/__charconv/tables.h +++ b/lib/libcxx/include/__charconv/tables.h @@ -19,16 +19,14 @@ _LIBCPP_BEGIN_NAMESPACE_STD -#if _LIBCPP_STD_VER >= 17 - namespace __itoa { -inline constexpr char __base_2_lut[64] = { +inline _LIBCPP_CONSTEXPR const char __base_2_lut[64] = { '0', '0', '0', '0', '0', '0', '0', '1', '0', '0', '1', '0', '0', '0', '1', '1', '0', '1', '0', '0', '0', '1', '0', '1', '0', '1', '1', '0', '0', '1', '1', '1', '1', '0', '0', '0', '1', '0', '0', '1', '1', '0', '1', '0', '1', '0', '1', '1', '1', '1', '0', '0', '1', '1', '0', '1', '1', '1', '1', '0', '1', '1', '1', '1'}; -inline constexpr char __base_8_lut[128] = { +inline _LIBCPP_CONSTEXPR const char __base_8_lut[128] = { '0', '0', '0', '1', '0', '2', '0', '3', '0', '4', '0', '5', '0', '6', '0', '7', '1', '0', '1', '1', '1', '2', '1', '3', '1', '4', '1', '5', '1', '6', '1', '7', '2', '0', '2', '1', '2', '2', '2', '3', '2', '4', '2', '5', '2', '6', '2', '7', '3', '0', '3', '1', '3', '2', '3', '3', '3', '4', '3', '5', '3', '6', '3', '7', '4', '0', @@ -36,7 +34,7 @@ inline constexpr char __base_8_lut[128] = { '5', '4', '5', '5', '5', '6', '5', '7', '6', '0', '6', '1', '6', '2', '6', '3', '6', '4', '6', '5', '6', '6', '6', '7', '7', '0', '7', '1', '7', '2', '7', '3', '7', '4', '7', '5', '7', '6', '7', '7'}; -inline constexpr char __base_16_lut[512] = { +inline _LIBCPP_CONSTEXPR const char __base_16_lut[512] = { '0', '0', '0', '1', '0', '2', '0', '3', '0', '4', '0', '5', '0', '6', '0', '7', '0', '8', '0', '9', '0', 'a', '0', 'b', '0', 'c', '0', 'd', '0', 'e', '0', 'f', '1', '0', '1', '1', '1', '2', '1', '3', '1', '4', '1', '5', '1', '6', '1', '7', '1', '8', '1', '9', '1', 'a', '1', 'b', '1', 'c', '1', 'd', '1', 'e', '1', 'f', '2', '0', '2', '1', '2', @@ -61,7 +59,7 @@ inline constexpr char __base_16_lut[512] = { '1', 'f', '2', 'f', '3', 'f', '4', 'f', '5', 'f', '6', 'f', '7', 'f', '8', 'f', '9', 'f', 'a', 'f', 'b', 'f', 'c', 'f', 'd', 'f', 'e', 'f', 'f'}; -inline constexpr uint32_t __pow10_32[10] = { +inline _LIBCPP_CONSTEXPR const uint32_t __pow10_32[10] = { UINT32_C(0), UINT32_C(10), UINT32_C(100), @@ -73,7 +71,7 @@ inline constexpr uint32_t __pow10_32[10] = { UINT32_C(100000000), UINT32_C(1000000000)}; -inline constexpr uint64_t __pow10_64[20] = { +inline _LIBCPP_CONSTEXPR const uint64_t __pow10_64[20] = { UINT64_C(0), UINT64_C(10), UINT64_C(100), @@ -96,8 +94,8 @@ inline constexpr uint64_t __pow10_64[20] = { UINT64_C(10000000000000000000)}; # if _LIBCPP_HAS_INT128 -inline constexpr int __pow10_128_offset = 0; -inline constexpr __uint128_t __pow10_128[40] = { +inline _LIBCPP_CONSTEXPR const int __pow10_128_offset = 0; +inline _LIBCPP_CONSTEXPR const __uint128_t __pow10_128[40] = { UINT64_C(0), UINT64_C(10), UINT64_C(100), @@ -140,7 +138,7 @@ inline constexpr __uint128_t __pow10_128[40] = { (__uint128_t(UINT64_C(10000000000000000000)) * UINT64_C(10000000000000000000)) * 10}; # endif -inline constexpr char __digits_base_10[200] = { +inline _LIBCPP_CONSTEXPR const char __digits_base_10[200] = { // clang-format off '0', '0', '0', '1', '0', '2', '0', '3', '0', '4', '0', '5', '0', '6', '0', '7', '0', '8', '0', '9', '1', '0', '1', '1', '1', '2', '1', '3', '1', '4', '1', '5', '1', '6', '1', '7', '1', '8', '1', '9', @@ -156,8 +154,6 @@ inline constexpr char __digits_base_10[200] = { } // namespace __itoa -#endif // _LIBCPP_STD_VER >= 17 - _LIBCPP_END_NAMESPACE_STD #endif // _LIBCPP___CHARCONV_TABLES diff --git a/lib/libcxx/include/__charconv/to_chars_base_10.h b/lib/libcxx/include/__charconv/to_chars_base_10.h index 06e4e69233..d90952ea71 100644 --- a/lib/libcxx/include/__charconv/to_chars_base_10.h +++ b/lib/libcxx/include/__charconv/to_chars_base_10.h @@ -26,55 +26,53 @@ _LIBCPP_PUSH_MACROS _LIBCPP_BEGIN_NAMESPACE_STD -#if _LIBCPP_STD_VER >= 17 - namespace __itoa { -_LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI inline char* __append1(char* __first, uint32_t __value) noexcept { +_LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI inline char* __append1(char* __first, uint32_t __value) _NOEXCEPT { *__first = '0' + static_cast(__value); return __first + 1; } -_LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI inline char* __append2(char* __first, uint32_t __value) noexcept { +_LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI inline char* __append2(char* __first, uint32_t __value) _NOEXCEPT { return std::copy_n(&__digits_base_10[__value * 2], 2, __first); } -_LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI inline char* __append3(char* __first, uint32_t __value) noexcept { +_LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI inline char* __append3(char* __first, uint32_t __value) _NOEXCEPT { return __itoa::__append2(__itoa::__append1(__first, __value / 100), __value % 100); } -_LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI inline char* __append4(char* __first, uint32_t __value) noexcept { +_LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI inline char* __append4(char* __first, uint32_t __value) _NOEXCEPT { return __itoa::__append2(__itoa::__append2(__first, __value / 100), __value % 100); } -_LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI inline char* __append5(char* __first, uint32_t __value) noexcept { +_LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI inline char* __append5(char* __first, uint32_t __value) _NOEXCEPT { return __itoa::__append4(__itoa::__append1(__first, __value / 10000), __value % 10000); } -_LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI inline char* __append6(char* __first, uint32_t __value) noexcept { +_LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI inline char* __append6(char* __first, uint32_t __value) _NOEXCEPT { return __itoa::__append4(__itoa::__append2(__first, __value / 10000), __value % 10000); } -_LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI inline char* __append7(char* __first, uint32_t __value) noexcept { +_LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI inline char* __append7(char* __first, uint32_t __value) _NOEXCEPT { return __itoa::__append6(__itoa::__append1(__first, __value / 1000000), __value % 1000000); } -_LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI inline char* __append8(char* __first, uint32_t __value) noexcept { +_LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI inline char* __append8(char* __first, uint32_t __value) _NOEXCEPT { return __itoa::__append6(__itoa::__append2(__first, __value / 1000000), __value % 1000000); } -_LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI inline char* __append9(char* __first, uint32_t __value) noexcept { +_LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI inline char* __append9(char* __first, uint32_t __value) _NOEXCEPT { return __itoa::__append8(__itoa::__append1(__first, __value / 100000000), __value % 100000000); } template -_LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI char* __append10(char* __first, _Tp __value) noexcept { +_LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI char* __append10(char* __first, _Tp __value) _NOEXCEPT { return __itoa::__append8(__itoa::__append2(__first, static_cast(__value / 100000000)), static_cast(__value % 100000000)); } _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI inline char* -__base_10_u32(char* __first, uint32_t __value) noexcept { +__base_10_u32(char* __first, uint32_t __value) _NOEXCEPT { if (__value < 1000000) { if (__value < 10000) { if (__value < 100) { @@ -110,7 +108,7 @@ __base_10_u32(char* __first, uint32_t __value) noexcept { } _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI inline char* -__base_10_u64(char* __buffer, uint64_t __value) noexcept { +__base_10_u64(char* __buffer, uint64_t __value) _NOEXCEPT { if (__value <= UINT32_MAX) return __itoa::__base_10_u32(__buffer, static_cast(__value)); @@ -132,13 +130,13 @@ __base_10_u64(char* __buffer, uint64_t __value) noexcept { /// \note The lookup table contains a partial set of exponents limiting the /// range that can be used. However the range is sufficient for /// \ref __base_10_u128. -_LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI inline __uint128_t __pow_10(int __exp) noexcept { +_LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI inline __uint128_t __pow_10(int __exp) _NOEXCEPT { _LIBCPP_ASSERT_INTERNAL(__exp >= __pow10_128_offset, "Index out of bounds"); return __pow10_128[__exp - __pow10_128_offset]; } _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI inline char* -__base_10_u128(char* __buffer, __uint128_t __value) noexcept { +__base_10_u128(char* __buffer, __uint128_t __value) _NOEXCEPT { _LIBCPP_ASSERT_INTERNAL( __value > numeric_limits::max(), "The optimizations for this algorithm fails when this isn't true."); @@ -179,8 +177,6 @@ __base_10_u128(char* __buffer, __uint128_t __value) noexcept { # endif } // namespace __itoa -#endif // _LIBCPP_STD_VER >= 17 - _LIBCPP_END_NAMESPACE_STD _LIBCPP_POP_MACROS diff --git a/lib/libcxx/include/__charconv/to_chars_integral.h b/lib/libcxx/include/__charconv/to_chars_integral.h index 710299df9b..f10cc35668 100644 --- a/lib/libcxx/include/__charconv/to_chars_integral.h +++ b/lib/libcxx/include/__charconv/to_chars_integral.h @@ -39,16 +39,12 @@ _LIBCPP_PUSH_MACROS _LIBCPP_BEGIN_NAMESPACE_STD -#if _LIBCPP_STD_VER >= 17 - -to_chars_result to_chars(char*, char*, bool, int = 10) = delete; - template -inline _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI to_chars_result +inline _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI __to_chars_result __to_chars_itoa(char* __first, char* __last, _Tp __value, false_type); template -inline _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI to_chars_result +inline _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI __to_chars_result __to_chars_itoa(char* __first, char* __last, _Tp __value, true_type) { auto __x = std::__to_unsigned_like(__value); if (__value < 0 && __first != __last) { @@ -60,7 +56,7 @@ __to_chars_itoa(char* __first, char* __last, _Tp __value, true_type) { } template -inline _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI to_chars_result +inline _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI __to_chars_result __to_chars_itoa(char* __first, char* __last, _Tp __value, false_type) { using __tx = __itoa::__traits<_Tp>; auto __diff = __last - __first; @@ -73,7 +69,7 @@ __to_chars_itoa(char* __first, char* __last, _Tp __value, false_type) { # if _LIBCPP_HAS_INT128 template <> -inline _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI to_chars_result +inline _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI __to_chars_result __to_chars_itoa(char* __first, char* __last, __uint128_t __value, false_type) { // When the value fits in 64-bits use the 64-bit code path. This reduces // the number of expensive calculations on 128-bit values. @@ -92,20 +88,20 @@ __to_chars_itoa(char* __first, char* __last, __uint128_t __value, false_type) { } # endif -template -inline _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI to_chars_result -__to_chars_integral(char* __first, char* __last, _Tp __value, int __base, false_type); +template ::value, int> = 0> +inline _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI __to_chars_result +__to_chars_integral(char* __first, char* __last, _Tp __value, int __base); -template -inline _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI to_chars_result -__to_chars_integral(char* __first, char* __last, _Tp __value, int __base, true_type) { +template ::value, int> = 0> +inline _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI __to_chars_result +__to_chars_integral(char* __first, char* __last, _Tp __value, int __base) { auto __x = std::__to_unsigned_like(__value); if (__value < 0 && __first != __last) { *__first++ = '-'; __x = std::__complement(__x); } - return std::__to_chars_integral(__first, __last, __x, __base, false_type()); + return std::__to_chars_integral(__first, __last, __x, __base); } namespace __itoa { @@ -116,15 +112,14 @@ struct _LIBCPP_HIDDEN __integral; template <> struct _LIBCPP_HIDDEN __integral<2> { template - _LIBCPP_HIDE_FROM_ABI static constexpr int __width(_Tp __value) noexcept { + _LIBCPP_HIDE_FROM_ABI static _LIBCPP_CONSTEXPR int __width(_Tp __value) _NOEXCEPT { // If value == 0 still need one digit. If the value != this has no - // effect since the code scans for the most significant bit set. (Note - // that __libcpp_clz doesn't work for 0.) - return numeric_limits<_Tp>::digits - std::__libcpp_clz(__value | 1); + // effect since the code scans for the most significant bit set. + return numeric_limits<_Tp>::digits - std::__countl_zero(__value | 1); } template - _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI static to_chars_result + _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI static __to_chars_result __to_chars(char* __first, char* __last, _Tp __value) { ptrdiff_t __cap = __last - __first; int __n = __width(__value); @@ -152,15 +147,14 @@ struct _LIBCPP_HIDDEN __integral<2> { template <> struct _LIBCPP_HIDDEN __integral<8> { template - _LIBCPP_HIDE_FROM_ABI static constexpr int __width(_Tp __value) noexcept { + _LIBCPP_HIDE_FROM_ABI static _LIBCPP_CONSTEXPR int __width(_Tp __value) _NOEXCEPT { // If value == 0 still need one digit. If the value != this has no - // effect since the code scans for the most significat bit set. (Note - // that __libcpp_clz doesn't work for 0.) - return ((numeric_limits<_Tp>::digits - std::__libcpp_clz(__value | 1)) + 2) / 3; + // effect since the code scans for the most significat bit set. + return ((numeric_limits<_Tp>::digits - std::__countl_zero(__value | 1)) + 2) / 3; } template - _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI static to_chars_result + _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI static __to_chars_result __to_chars(char* __first, char* __last, _Tp __value) { ptrdiff_t __cap = __last - __first; int __n = __width(__value); @@ -188,15 +182,14 @@ struct _LIBCPP_HIDDEN __integral<8> { template <> struct _LIBCPP_HIDDEN __integral<16> { template - _LIBCPP_HIDE_FROM_ABI static constexpr int __width(_Tp __value) noexcept { + _LIBCPP_HIDE_FROM_ABI static _LIBCPP_CONSTEXPR int __width(_Tp __value) _NOEXCEPT { // If value == 0 still need one digit. If the value != this has no - // effect since the code scans for the most significat bit set. (Note - // that __libcpp_clz doesn't work for 0.) - return (numeric_limits<_Tp>::digits - std::__libcpp_clz(__value | 1) + 3) / 4; + // effect since the code scans for the most significat bit set. + return (numeric_limits<_Tp>::digits - std::__countl_zero(__value | 1) + 3) / 4; } template - _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI static to_chars_result + _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI static __to_chars_result __to_chars(char* __first, char* __last, _Tp __value) { ptrdiff_t __cap = __last - __first; int __n = __width(__value); @@ -235,13 +228,13 @@ _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI int __to_chars_integral_widt } template = sizeof(unsigned)), int> = 0> -_LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI to_chars_result +_LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI __to_chars_result __to_chars_integral(char* __first, char* __last, _Tp __value) { return __itoa::__integral<_Base>::__to_chars(__first, __last, __value); } template = 0> -_LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI to_chars_result +_LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI __to_chars_result __to_chars_integral(char* __first, char* __last, _Tp __value) { return std::__to_chars_integral<_Base>(__first, __last, static_cast(__value)); } @@ -272,9 +265,9 @@ _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI int __to_chars_integral_widt __libcpp_unreachable(); } -template -inline _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI to_chars_result -__to_chars_integral(char* __first, char* __last, _Tp __value, int __base, false_type) { +template ::value, int> > +inline _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI __to_chars_result +__to_chars_integral(char* __first, char* __last, _Tp __value, int __base) { if (__base == 10) [[likely]] return std::__to_chars_itoa(__first, __last, __value, false_type()); @@ -302,6 +295,28 @@ __to_chars_integral(char* __first, char* __last, _Tp __value, int __base, false_ return {__last, errc(0)}; } +_LIBCPP_HIDE_FROM_ABI inline _LIBCPP_CONSTEXPR_SINCE_CXX14 char __hex_to_upper(char __c) { + switch (__c) { + case 'a': + return 'A'; + case 'b': + return 'B'; + case 'c': + return 'C'; + case 'd': + return 'D'; + case 'e': + return 'E'; + case 'f': + return 'F'; + } + return __c; +} + +#if _LIBCPP_STD_VER >= 17 + +to_chars_result to_chars(char*, char*, bool, int = 10) = delete; + template ::value, int> = 0> inline _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI to_chars_result to_chars(char* __first, char* __last, _Tp __value) { @@ -316,7 +331,7 @@ to_chars(char* __first, char* __last, _Tp __value, int __base) { _LIBCPP_ASSERT_UNCATEGORIZED(2 <= __base && __base <= 36, "base not in [2, 36]"); using _Type = __make_32_64_or_128_bit_t<_Tp>; - return std::__to_chars_integral(__first, __last, static_cast<_Type>(__value), __base, is_signed<_Tp>()); + return std::__to_chars_integral(__first, __last, static_cast<_Type>(__value), __base); } #endif // _LIBCPP_STD_VER >= 17 diff --git a/lib/libcxx/include/__charconv/to_chars_result.h b/lib/libcxx/include/__charconv/to_chars_result.h index 8df0897a49..41dea4ab14 100644 --- a/lib/libcxx/include/__charconv/to_chars_result.h +++ b/lib/libcxx/include/__charconv/to_chars_result.h @@ -34,6 +34,15 @@ struct _LIBCPP_EXPORTED_FROM_ABI to_chars_result { #endif // _LIBCPP_STD_VER >= 17 +struct __to_chars_result { + char* __ptr; + errc __ec; + +#if _LIBCPP_STD_VER >= 17 + _LIBCPP_HIDE_FROM_ABI constexpr operator to_chars_result() { return {__ptr, __ec}; } +#endif +}; + _LIBCPP_END_NAMESPACE_STD #endif // _LIBCPP___CHARCONV_TO_CHARS_RESULT_H diff --git a/lib/libcxx/include/__charconv/traits.h b/lib/libcxx/include/__charconv/traits.h index 2cb37c8cfb..9fd0092ca7 100644 --- a/lib/libcxx/include/__charconv/traits.h +++ b/lib/libcxx/include/__charconv/traits.h @@ -15,6 +15,7 @@ #include <__charconv/tables.h> #include <__charconv/to_chars_base_10.h> #include <__config> +#include <__memory/addressof.h> #include <__type_traits/enable_if.h> #include <__type_traits/is_unsigned.h> #include @@ -29,27 +30,22 @@ _LIBCPP_PUSH_MACROS _LIBCPP_BEGIN_NAMESPACE_STD -#if _LIBCPP_STD_VER >= 17 - namespace __itoa { template struct _LIBCPP_HIDDEN __traits_base; template -struct _LIBCPP_HIDDEN __traits_base<_Tp, __enable_if_t> { +struct _LIBCPP_HIDDEN __traits_base<_Tp, __enable_if_t > { using type = uint32_t; /// The width estimation using a log10 algorithm. /// /// The algorithm is based on /// http://graphics.stanford.edu/~seander/bithacks.html#IntegerLog10 - /// Instead of using IntegerLogBase2 it uses __libcpp_clz. Since that - /// function requires its input to have at least one bit set the value of - /// zero is set to one. This means the first element of the lookup table is - /// zero. + /// Instead of using IntegerLogBase2 it uses __countl_zero. static _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI int __width(_Tp __v) { - auto __t = (32 - std::__libcpp_clz(static_cast(__v | 1))) * 1233 >> 12; + auto __t = (32 - std::__countl_zero(static_cast(__v | 1))) * 1233 >> 12; return __t - (__v < __itoa::__pow10_32[__t]) + 1; } @@ -63,19 +59,16 @@ struct _LIBCPP_HIDDEN __traits_base<_Tp, __enable_if_t -struct _LIBCPP_HIDDEN __traits_base<_Tp, __enable_if_t> { +struct _LIBCPP_HIDDEN __traits_base<_Tp, __enable_if_t > { using type = uint64_t; /// The width estimation using a log10 algorithm. /// /// The algorithm is based on /// http://graphics.stanford.edu/~seander/bithacks.html#IntegerLog10 - /// Instead of using IntegerLogBase2 it uses __libcpp_clz. Since that - /// function requires its input to have at least one bit set the value of - /// zero is set to one. This means the first element of the lookup table is - /// zero. + /// Instead of using IntegerLogBase2 it uses __countl_zero. static _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI int __width(_Tp __v) { - auto __t = (64 - std::__libcpp_clz(static_cast(__v | 1))) * 1233 >> 12; + auto __t = (64 - std::__countl_zero(static_cast(__v | 1))) * 1233 >> 12; return __t - (__v < __itoa::__pow10_64[__t]) + 1; } @@ -97,15 +90,12 @@ struct _LIBCPP_HIDDEN __traits_base<_Tp, __enable_if_t numeric_limits::max(), "The optimizations for this algorithm fail when this isn't true."); // There's always a bit set in the upper 64-bits. - auto __t = (128 - std::__libcpp_clz(static_cast(__v >> 64))) * 1233 >> 12; + auto __t = (128 - std::__countl_zero(static_cast(__v >> 64))) * 1233 >> 12; _LIBCPP_ASSERT_INTERNAL(__t >= __itoa::__pow10_128_offset, "Index out of bounds"); // __t is adjusted since the lookup table misses the lower entries. return __t - (__v < __itoa::__pow10_128[__t - __itoa::__pow10_128_offset]) + 1; @@ -142,7 +132,7 @@ __mul_overflowed(unsigned short __a, _Tp __b, unsigned short& __r) { template inline _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI bool __mul_overflowed(_Tp __a, _Tp __b, _Tp& __r) { static_assert(is_unsigned<_Tp>::value, ""); - return __builtin_mul_overflow(__a, __b, &__r); + return __builtin_mul_overflow(__a, __b, std::addressof(__r)); } template @@ -152,7 +142,7 @@ inline _LIBCPP_HIDE_FROM_ABI bool _LIBCPP_CONSTEXPR_SINCE_CXX23 __mul_overflowed template struct _LIBCPP_HIDDEN __traits : __traits_base<_Tp> { - static constexpr int digits = numeric_limits<_Tp>::digits10 + 1; + static _LIBCPP_CONSTEXPR const int digits = numeric_limits<_Tp>::digits10 + 1; using __traits_base<_Tp>::__pow; using typename __traits_base<_Tp>::type; @@ -191,8 +181,6 @@ inline _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI _Tp __complement(_Tp return _Tp(~__x + 1); } -#endif // _LIBCPP_STD_VER >= 17 - _LIBCPP_END_NAMESPACE_STD _LIBCPP_POP_MACROS diff --git a/lib/libcxx/include/__chrono/convert_to_tm.h b/lib/libcxx/include/__chrono/convert_to_tm.h index 7d06a38d87..817e6747a7 100644 --- a/lib/libcxx/include/__chrono/convert_to_tm.h +++ b/lib/libcxx/include/__chrono/convert_to_tm.h @@ -15,6 +15,7 @@ #include <__chrono/day.h> #include <__chrono/duration.h> #include <__chrono/file_clock.h> +#include <__chrono/gps_clock.h> #include <__chrono/hh_mm_ss.h> #include <__chrono/local_info.h> #include <__chrono/month.h> @@ -23,6 +24,7 @@ #include <__chrono/statically_widen.h> #include <__chrono/sys_info.h> #include <__chrono/system_clock.h> +#include <__chrono/tai_clock.h> #include <__chrono/time_point.h> #include <__chrono/utc_clock.h> #include <__chrono/weekday.h> @@ -35,6 +37,7 @@ #include <__config> #include <__format/format_error.h> #include <__memory/addressof.h> +#include <__type_traits/common_type.h> #include <__type_traits/is_convertible.h> #include <__type_traits/is_specialization.h> #include @@ -112,6 +115,21 @@ _LIBCPP_HIDE_FROM_ABI _Tm __convert_to_tm(chrono::utc_time<_Duration> __tp) { return __result; } +template +_LIBCPP_HIDE_FROM_ABI _Tm __convert_to_tm(chrono::tai_time<_Duration> __tp) { + using _Rp = common_type_t<_Duration, chrono::seconds>; + // The time between the TAI epoch (1958-01-01) and UNIX epoch (1970-01-01). + // This avoids leap second conversion when going from TAI to UTC. + // (It also avoids issues when the date is before the UTC epoch.) + constexpr chrono::seconds __offset{4383 * 24 * 60 * 60}; + return std::__convert_to_tm<_Tm>(chrono::sys_time<_Rp>{__tp.time_since_epoch() - __offset}); +} + +template +_LIBCPP_HIDE_FROM_ABI _Tm __convert_to_tm(chrono::gps_time<_Duration> __tp) { + return std::__convert_to_tm<_Tm>(chrono::utc_clock::to_sys(chrono::gps_clock::to_utc(__tp))); +} + # endif // _LIBCPP_HAS_EXPERIMENTAL_TZDB # endif // _LIBCPP_HAS_TIME_ZONE_DATABASE && _LIBCPP_HAS_FILESYSTEM && _LIBCPP_HAS_LOCALIZATION @@ -125,20 +143,16 @@ _LIBCPP_HIDE_FROM_ABI _Tm __convert_to_tm(const _ChronoT& __value) { # endif if constexpr (__is_time_point<_ChronoT>) { - if constexpr (same_as) - return std::__convert_to_tm<_Tm>(__value); -# if _LIBCPP_HAS_TIME_ZONE_DATABASE && _LIBCPP_HAS_FILESYSTEM && _LIBCPP_HAS_LOCALIZATION -# if _LIBCPP_HAS_EXPERIMENTAL_TZDB - else if constexpr (same_as) - return std::__convert_to_tm<_Tm>(__value); -# endif // _LIBCPP_HAS_EXPERIMENTAL_TZDB -# endif // _LIBCPP_HAS_TIME_ZONE_DATABASE && _LIBCPP_HAS_FILESYSTEM && _LIBCPP_HAS_LOCALIZATION - else if constexpr (same_as) + if constexpr (same_as) return std::__convert_to_tm<_Tm>(_ChronoT::clock::to_sys(__value)); else if constexpr (same_as) return std::__convert_to_tm<_Tm>(chrono::sys_time{__value.time_since_epoch()}); - else + else { + // Note that some clocks have specializations __convert_to_tm for their + // time_point. These don't need to be added here. They do not trigger + // this assert. static_assert(sizeof(_ChronoT) == 0, "TODO: Add the missing clock specialization"); + } } else if constexpr (chrono::__is_duration_v<_ChronoT>) { // [time.format]/6 // ... However, if a flag refers to a "time of day" (e.g. %H, %I, %p, diff --git a/lib/libcxx/include/__chrono/duration.h b/lib/libcxx/include/__chrono/duration.h index 941aca6009..57fa64d650 100644 --- a/lib/libcxx/include/__chrono/duration.h +++ b/lib/libcxx/include/__chrono/duration.h @@ -32,7 +32,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD namespace chrono { template > -class _LIBCPP_TEMPLATE_VIS duration; +class duration; template inline const bool __is_duration_v = false; @@ -52,7 +52,7 @@ inline const bool __is_duration_v > = tru } // namespace chrono template -struct _LIBCPP_TEMPLATE_VIS common_type, chrono::duration<_Rep2, _Period2> > { +struct common_type, chrono::duration<_Rep2, _Period2> > { typedef chrono::duration::type, __ratio_gcd<_Period1, _Period2> > type; }; @@ -107,7 +107,7 @@ inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR _ToDuration duration_cast(const d } template -struct _LIBCPP_TEMPLATE_VIS treat_as_floating_point : is_floating_point<_Rep> {}; +struct treat_as_floating_point : is_floating_point<_Rep> {}; #if _LIBCPP_STD_VER >= 17 template @@ -115,7 +115,7 @@ inline constexpr bool treat_as_floating_point_v = treat_as_floating_point<_Rep>: #endif template -struct _LIBCPP_TEMPLATE_VIS duration_values { +struct duration_values { public: _LIBCPP_HIDE_FROM_ABI static _LIBCPP_CONSTEXPR _Rep zero() _NOEXCEPT { return _Rep(0); } _LIBCPP_HIDE_FROM_ABI static _LIBCPP_CONSTEXPR _Rep max() _NOEXCEPT { return numeric_limits<_Rep>::max(); } @@ -156,7 +156,7 @@ inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR _ToDuration round(const duration< // duration template -class _LIBCPP_TEMPLATE_VIS duration { +class duration { static_assert(!__is_duration_v<_Rep>, "A duration representation can not be a duration"); static_assert(__is_ratio_v<_Period>, "Second template parameter of duration must be a std::ratio"); static_assert(_Period::num > 0, "duration period must be positive"); diff --git a/lib/libcxx/include/__chrono/formatter.h b/lib/libcxx/include/__chrono/formatter.h index d17acd274e..49758397f6 100644 --- a/lib/libcxx/include/__chrono/formatter.h +++ b/lib/libcxx/include/__chrono/formatter.h @@ -21,6 +21,7 @@ # include <__chrono/day.h> # include <__chrono/duration.h> # include <__chrono/file_clock.h> +# include <__chrono/gps_clock.h> # include <__chrono/hh_mm_ss.h> # include <__chrono/local_info.h> # include <__chrono/month.h> @@ -31,6 +32,7 @@ # include <__chrono/statically_widen.h> # include <__chrono/sys_info.h> # include <__chrono/system_clock.h> +# include <__chrono/tai_clock.h> # include <__chrono/time_point.h> # include <__chrono/utc_clock.h> # include <__chrono/weekday.h> @@ -48,12 +50,14 @@ # include <__format/formatter.h> # include <__format/parser_std_format_spec.h> # include <__format/write_escaped.h> +# include <__iterator/istreambuf_iterator.h> +# include <__iterator/ostreambuf_iterator.h> +# include <__locale_dir/time.h> # include <__memory/addressof.h> # include <__type_traits/is_specialization.h> # include # include # include -# include # include # include @@ -232,9 +236,13 @@ _LIBCPP_HIDE_FROM_ABI __time_zone __convert_to_time_zone([[maybe_unused]] const if constexpr (same_as<_Tp, chrono::sys_info>) return {__value.abbrev, __value.offset}; # if _LIBCPP_HAS_TIME_ZONE_DATABASE && _LIBCPP_HAS_FILESYSTEM + else if constexpr (__is_time_point<_Tp> && requires { requires same_as; }) + return {"TAI", chrono::seconds{0}}; + else if constexpr (__is_time_point<_Tp> && requires { requires same_as; }) + return {"GPS", chrono::seconds{0}}; else if constexpr (__is_specialization_v<_Tp, chrono::zoned_time>) return __formatter::__convert_to_time_zone(__value.get_info()); -# endif +# endif // _LIBCPP_HAS_TIME_ZONE_DATABASE && _LIBCPP_HAS_FILESYSTEM else # endif // _LIBCPP_HAS_EXPERIMENTAL_TZDB return {"UTC", chrono::seconds{0}}; @@ -312,7 +320,7 @@ _LIBCPP_HIDE_FROM_ABI void __format_chrono_using_chrono_specs( case _CharT('T'): __facet.put( {__sstr}, __sstr, _CharT(' '), std::addressof(__t), std::to_address(__s), std::to_address(__it + 1)); - if constexpr (__use_fraction<_Tp>()) + if constexpr (__formatter::__use_fraction<_Tp>()) __formatter::__format_sub_seconds(__sstr, __value); break; @@ -375,7 +383,7 @@ _LIBCPP_HIDE_FROM_ABI void __format_chrono_using_chrono_specs( break; case _CharT('O'): - if constexpr (__use_fraction<_Tp>()) { + if constexpr (__formatter::__use_fraction<_Tp>()) { // Handle OS using the normal representation for the non-fractional // part. There seems to be no locale information regarding how the // fractional part should be formatted. @@ -692,7 +700,7 @@ __format_chrono(const _Tp& __value, } // namespace __formatter template <__fmt_char_type _CharT> -struct _LIBCPP_TEMPLATE_VIS __formatter_chrono { +struct __formatter_chrono { public: template _LIBCPP_HIDE_FROM_ABI constexpr typename _ParseContext::iterator @@ -710,7 +718,7 @@ public: }; template -struct _LIBCPP_TEMPLATE_VIS formatter, _CharT> : public __formatter_chrono<_CharT> { +struct formatter, _CharT> : public __formatter_chrono<_CharT> { public: using _Base _LIBCPP_NODEBUG = __formatter_chrono<_CharT>; @@ -724,7 +732,29 @@ public: # if _LIBCPP_HAS_EXPERIMENTAL_TZDB template -struct _LIBCPP_TEMPLATE_VIS formatter, _CharT> : public __formatter_chrono<_CharT> { +struct formatter, _CharT> : public __formatter_chrono<_CharT> { +public: + using _Base _LIBCPP_NODEBUG = __formatter_chrono<_CharT>; + + template + _LIBCPP_HIDE_FROM_ABI constexpr typename _ParseContext::iterator parse(_ParseContext& __ctx) { + return _Base::__parse(__ctx, __format_spec::__fields_chrono, __format_spec::__flags::__clock); + } +}; + +template +struct formatter, _CharT> : public __formatter_chrono<_CharT> { +public: + using _Base _LIBCPP_NODEBUG = __formatter_chrono<_CharT>; + + template + _LIBCPP_HIDE_FROM_ABI constexpr typename _ParseContext::iterator parse(_ParseContext& __ctx) { + return _Base::__parse(__ctx, __format_spec::__fields_chrono, __format_spec::__flags::__clock); + } +}; + +template +struct formatter, _CharT> : public __formatter_chrono<_CharT> { public: using _Base _LIBCPP_NODEBUG = __formatter_chrono<_CharT>; @@ -738,7 +768,7 @@ public: # endif // _LIBCPP_HAS_TIME_ZONE_DATABASE && _LIBCPP_HAS_FILESYSTEM template -struct _LIBCPP_TEMPLATE_VIS formatter, _CharT> : public __formatter_chrono<_CharT> { +struct formatter, _CharT> : public __formatter_chrono<_CharT> { public: using _Base _LIBCPP_NODEBUG = __formatter_chrono<_CharT>; @@ -749,7 +779,7 @@ public: }; template -struct _LIBCPP_TEMPLATE_VIS formatter, _CharT> : public __formatter_chrono<_CharT> { +struct formatter, _CharT> : public __formatter_chrono<_CharT> { public: using _Base _LIBCPP_NODEBUG = __formatter_chrono<_CharT>; @@ -783,7 +813,7 @@ public: }; template <__fmt_char_type _CharT> -struct _LIBCPP_TEMPLATE_VIS formatter : public __formatter_chrono<_CharT> { +struct formatter : public __formatter_chrono<_CharT> { public: using _Base _LIBCPP_NODEBUG = __formatter_chrono<_CharT>; @@ -794,7 +824,7 @@ public: }; template <__fmt_char_type _CharT> -struct _LIBCPP_TEMPLATE_VIS formatter : public __formatter_chrono<_CharT> { +struct formatter : public __formatter_chrono<_CharT> { public: using _Base _LIBCPP_NODEBUG = __formatter_chrono<_CharT>; @@ -805,7 +835,7 @@ public: }; template <__fmt_char_type _CharT> -struct _LIBCPP_TEMPLATE_VIS formatter : public __formatter_chrono<_CharT> { +struct formatter : public __formatter_chrono<_CharT> { public: using _Base _LIBCPP_NODEBUG = __formatter_chrono<_CharT>; @@ -816,7 +846,7 @@ public: }; template <__fmt_char_type _CharT> -struct _LIBCPP_TEMPLATE_VIS formatter : public __formatter_chrono<_CharT> { +struct formatter : public __formatter_chrono<_CharT> { public: using _Base _LIBCPP_NODEBUG = __formatter_chrono<_CharT>; @@ -827,7 +857,7 @@ public: }; template <__fmt_char_type _CharT> -struct _LIBCPP_TEMPLATE_VIS formatter : public __formatter_chrono<_CharT> { +struct formatter : public __formatter_chrono<_CharT> { public: using _Base _LIBCPP_NODEBUG = __formatter_chrono<_CharT>; @@ -838,7 +868,7 @@ public: }; template <__fmt_char_type _CharT> -struct _LIBCPP_TEMPLATE_VIS formatter : public __formatter_chrono<_CharT> { +struct formatter : public __formatter_chrono<_CharT> { public: using _Base _LIBCPP_NODEBUG = __formatter_chrono<_CharT>; @@ -849,7 +879,7 @@ public: }; template <__fmt_char_type _CharT> -struct _LIBCPP_TEMPLATE_VIS formatter : public __formatter_chrono<_CharT> { +struct formatter : public __formatter_chrono<_CharT> { public: using _Base _LIBCPP_NODEBUG = __formatter_chrono<_CharT>; @@ -860,7 +890,7 @@ public: }; template <__fmt_char_type _CharT> -struct _LIBCPP_TEMPLATE_VIS formatter : public __formatter_chrono<_CharT> { +struct formatter : public __formatter_chrono<_CharT> { public: using _Base _LIBCPP_NODEBUG = __formatter_chrono<_CharT>; @@ -871,7 +901,7 @@ public: }; template <__fmt_char_type _CharT> -struct _LIBCPP_TEMPLATE_VIS formatter : public __formatter_chrono<_CharT> { +struct formatter : public __formatter_chrono<_CharT> { public: using _Base _LIBCPP_NODEBUG = __formatter_chrono<_CharT>; @@ -882,7 +912,7 @@ public: }; template <__fmt_char_type _CharT> -struct _LIBCPP_TEMPLATE_VIS formatter : public __formatter_chrono<_CharT> { +struct formatter : public __formatter_chrono<_CharT> { public: using _Base _LIBCPP_NODEBUG = __formatter_chrono<_CharT>; @@ -893,7 +923,7 @@ public: }; template <__fmt_char_type _CharT> -struct _LIBCPP_TEMPLATE_VIS formatter : public __formatter_chrono<_CharT> { +struct formatter : public __formatter_chrono<_CharT> { public: using _Base _LIBCPP_NODEBUG = __formatter_chrono<_CharT>; @@ -904,7 +934,7 @@ public: }; template <__fmt_char_type _CharT> -struct _LIBCPP_TEMPLATE_VIS formatter : public __formatter_chrono<_CharT> { +struct formatter : public __formatter_chrono<_CharT> { public: using _Base _LIBCPP_NODEBUG = __formatter_chrono<_CharT>; @@ -915,7 +945,7 @@ public: }; template <__fmt_char_type _CharT> -struct _LIBCPP_TEMPLATE_VIS formatter : public __formatter_chrono<_CharT> { +struct formatter : public __formatter_chrono<_CharT> { public: using _Base _LIBCPP_NODEBUG = __formatter_chrono<_CharT>; @@ -926,7 +956,7 @@ public: }; template <__fmt_char_type _CharT> -struct _LIBCPP_TEMPLATE_VIS formatter : public __formatter_chrono<_CharT> { +struct formatter : public __formatter_chrono<_CharT> { public: using _Base _LIBCPP_NODEBUG = __formatter_chrono<_CharT>; @@ -937,7 +967,7 @@ public: }; template <__fmt_char_type _CharT> -struct _LIBCPP_TEMPLATE_VIS formatter : public __formatter_chrono<_CharT> { +struct formatter : public __formatter_chrono<_CharT> { public: using _Base _LIBCPP_NODEBUG = __formatter_chrono<_CharT>; diff --git a/lib/libcxx/include/__chrono/gps_clock.h b/lib/libcxx/include/__chrono/gps_clock.h new file mode 100644 index 0000000000..2e220cab94 --- /dev/null +++ b/lib/libcxx/include/__chrono/gps_clock.h @@ -0,0 +1,90 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___CHRONO_GPS_CLOCK_H +#define _LIBCPP___CHRONO_GPS_CLOCK_H + +#include +// Enable the contents of the header only when libc++ was built with experimental features enabled. +#if _LIBCPP_HAS_EXPERIMENTAL_TZDB + +# include <__assert> +# include <__chrono/duration.h> +# include <__chrono/time_point.h> +# include <__chrono/utc_clock.h> +# include <__config> +# include <__type_traits/common_type.h> + +# if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +# endif + +_LIBCPP_PUSH_MACROS +# include <__undef_macros> + +_LIBCPP_BEGIN_NAMESPACE_STD + +# if _LIBCPP_STD_VER >= 20 && _LIBCPP_HAS_TIME_ZONE_DATABASE && _LIBCPP_HAS_FILESYSTEM && _LIBCPP_HAS_LOCALIZATION + +namespace chrono { + +class gps_clock; + +template +using gps_time = time_point; +using gps_seconds = gps_time; + +class gps_clock { +public: + using rep = utc_clock::rep; + using period = utc_clock::period; + using duration = chrono::duration; + using time_point = chrono::time_point; + static constexpr bool is_steady = false; // The utc_clock is not steady. + + // The static difference between UTC and GPS time as specified in the Standard. + static constexpr chrono::seconds __offset{315964809}; + + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI static time_point now() { return from_utc(utc_clock::now()); } + + template + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI static utc_time> + to_utc(const gps_time<_Duration>& __time) noexcept { + using _Rp = common_type_t<_Duration, seconds>; + _Duration __time_since_epoch = __time.time_since_epoch(); + _LIBCPP_ASSERT_ARGUMENT_WITHIN_DOMAIN(__time_since_epoch >= utc_time<_Rp>::min().time_since_epoch() + __offset, + "the GPS to UTC conversion would underflow"); + + return utc_time<_Rp>{__time_since_epoch + __offset}; + } + + template + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI static gps_time> + from_utc(const utc_time<_Duration>& __time) noexcept { + using _Rp = common_type_t<_Duration, seconds>; + _Duration __time_since_epoch = __time.time_since_epoch(); + _LIBCPP_ASSERT_ARGUMENT_WITHIN_DOMAIN(__time_since_epoch <= utc_time<_Rp>::max().time_since_epoch() - __offset, + "the UTC to GPS conversion would overflow"); + + return gps_time<_Rp>{__time_since_epoch - __offset}; + } +}; + +} // namespace chrono + +# endif // _LIBCPP_STD_VER >= 20 && _LIBCPP_HAS_TIME_ZONE_DATABASE && _LIBCPP_HAS_FILESYSTEM && + // _LIBCPP_HAS_LOCALIZATION + +_LIBCPP_END_NAMESPACE_STD + +_LIBCPP_POP_MACROS + +#endif // _LIBCPP_HAS_EXPERIMENTAL_TZDB + +#endif // _LIBCPP___CHRONO_GPS_CLOCK_H diff --git a/lib/libcxx/include/__chrono/ostream.h b/lib/libcxx/include/__chrono/ostream.h index ed9ad8e346..7a01b18678 100644 --- a/lib/libcxx/include/__chrono/ostream.h +++ b/lib/libcxx/include/__chrono/ostream.h @@ -18,6 +18,7 @@ # include <__chrono/day.h> # include <__chrono/duration.h> # include <__chrono/file_clock.h> +# include <__chrono/gps_clock.h> # include <__chrono/hh_mm_ss.h> # include <__chrono/local_info.h> # include <__chrono/month.h> @@ -26,6 +27,7 @@ # include <__chrono/statically_widen.h> # include <__chrono/sys_info.h> # include <__chrono/system_clock.h> +# include <__chrono/tai_clock.h> # include <__chrono/utc_clock.h> # include <__chrono/weekday.h> # include <__chrono/year.h> @@ -71,6 +73,18 @@ operator<<(basic_ostream<_CharT, _Traits>& __os, const utc_time<_Duration>& __tp return __os << std::format(__os.getloc(), _LIBCPP_STATICALLY_WIDEN(_CharT, "{:L%F %T}"), __tp); } +template +_LIBCPP_HIDE_FROM_ABI basic_ostream<_CharT, _Traits>& +operator<<(basic_ostream<_CharT, _Traits>& __os, const tai_time<_Duration>& __tp) { + return __os << std::format(__os.getloc(), _LIBCPP_STATICALLY_WIDEN(_CharT, "{:L%F %T}"), __tp); +} + +template +_LIBCPP_HIDE_FROM_ABI basic_ostream<_CharT, _Traits>& +operator<<(basic_ostream<_CharT, _Traits>& __os, const gps_time<_Duration>& __tp) { + return __os << std::format(__os.getloc(), _LIBCPP_STATICALLY_WIDEN(_CharT, "{:L%F %T}"), __tp); +} + # endif // _LIBCPP_HAS_EXPERIMENTAL_TZDB # endif // _LIBCPP_HAS_TIME_ZONE_DATABASE && _LIBCPP_HAS_FILESYSTEM diff --git a/lib/libcxx/include/__chrono/parser_std_format_spec.h b/lib/libcxx/include/__chrono/parser_std_format_spec.h index 4df8e603c6..8ecc19f3c7 100644 --- a/lib/libcxx/include/__chrono/parser_std_format_spec.h +++ b/lib/libcxx/include/__chrono/parser_std_format_spec.h @@ -139,7 +139,7 @@ _LIBCPP_HIDE_FROM_ABI constexpr void __validate_time_zone(__flags __flags) { } template -class _LIBCPP_TEMPLATE_VIS __parser_chrono { +class __parser_chrono { using _ConstIterator _LIBCPP_NODEBUG = typename basic_format_parse_context<_CharT>::const_iterator; public: diff --git a/lib/libcxx/include/__chrono/tai_clock.h b/lib/libcxx/include/__chrono/tai_clock.h new file mode 100644 index 0000000000..14c8b70a94 --- /dev/null +++ b/lib/libcxx/include/__chrono/tai_clock.h @@ -0,0 +1,108 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___CHRONO_TAI_CLOCK_H +#define _LIBCPP___CHRONO_TAI_CLOCK_H + +#include +// Enable the contents of the header only when libc++ was built with experimental features enabled. +#if _LIBCPP_HAS_EXPERIMENTAL_TZDB + +# include <__assert> +# include <__chrono/duration.h> +# include <__chrono/time_point.h> +# include <__chrono/utc_clock.h> +# include <__config> +# include <__type_traits/common_type.h> + +# if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +# endif + +_LIBCPP_PUSH_MACROS +# include <__undef_macros> + +_LIBCPP_BEGIN_NAMESPACE_STD + +# if _LIBCPP_STD_VER >= 20 && _LIBCPP_HAS_TIME_ZONE_DATABASE && _LIBCPP_HAS_FILESYSTEM && _LIBCPP_HAS_LOCALIZATION + +namespace chrono { + +class tai_clock; + +template +using tai_time = time_point; +using tai_seconds = tai_time; + +// [time.clock.tai.overview]/1 +// The clock tai_clock measures seconds since 1958-01-01 00:00:00 and is +// offset 10s ahead of UTC at this date. That is, 1958-01-01 00:00:00 TAI is +// equivalent to 1957-12-31 23:59:50 UTC. Leap seconds are not inserted into +// TAI. Therefore every time a leap second is inserted into UTC, UTC shifts +// another second with respect to TAI. For example by 2000-01-01 there had +// been 22 positive and 0 negative leap seconds inserted so 2000-01-01 +// 00:00:00 UTC is equivalent to 2000-01-01 00:00:32 TAI (22s plus the +// initial 10s offset). +// +// Note this does not specify what the UTC offset before 1958-01-01 00:00:00 +// TAI is, nor does it follow the "real" TAI clock between 1958-01-01 and the +// start of the UTC epoch. So while the member functions are fully specified in +// the standard, they do not technically follow the "real-world" TAI clock with +// 100% accuracy. +// +// https://koka-lang.github.io/koka/doc/std_time_utc.html contains more +// information and references. +class tai_clock { +public: + using rep = utc_clock::rep; + using period = utc_clock::period; + using duration = chrono::duration; + using time_point = chrono::time_point; + static constexpr bool is_steady = false; // The utc_clock is not steady. + + // The static difference between UTC and TAI time. + static constexpr chrono::seconds __offset{378691210}; + + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI static time_point now() { return from_utc(utc_clock::now()); } + + template + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI static utc_time> + to_utc(const tai_time<_Duration>& __time) noexcept { + using _Rp = common_type_t<_Duration, seconds>; + _Duration __time_since_epoch = __time.time_since_epoch(); + _LIBCPP_ASSERT_ARGUMENT_WITHIN_DOMAIN(__time_since_epoch >= utc_time<_Rp>::min().time_since_epoch() + __offset, + "the TAI to UTC conversion would underflow"); + + return utc_time<_Rp>{__time_since_epoch - __offset}; + } + + template + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI static tai_time> + from_utc(const utc_time<_Duration>& __time) noexcept { + using _Rp = common_type_t<_Duration, seconds>; + _Duration __time_since_epoch = __time.time_since_epoch(); + _LIBCPP_ASSERT_ARGUMENT_WITHIN_DOMAIN(__time_since_epoch <= utc_time<_Rp>::max().time_since_epoch() - __offset, + "the UTC to TAI conversion would overflow"); + + return tai_time<_Rp>{__time_since_epoch + __offset}; + } +}; + +} // namespace chrono + +# endif // _LIBCPP_STD_VER >= 20 && _LIBCPP_HAS_TIME_ZONE_DATABASE && _LIBCPP_HAS_FILESYSTEM && + // _LIBCPP_HAS_LOCALIZATION + +_LIBCPP_END_NAMESPACE_STD + +_LIBCPP_POP_MACROS + +#endif // _LIBCPP_HAS_EXPERIMENTAL_TZDB + +#endif // _LIBCPP___CHRONO_TAI_CLOCK_H diff --git a/lib/libcxx/include/__chrono/time_point.h b/lib/libcxx/include/__chrono/time_point.h index 5e79fa5d25..fc4408d23d 100644 --- a/lib/libcxx/include/__chrono/time_point.h +++ b/lib/libcxx/include/__chrono/time_point.h @@ -31,7 +31,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD namespace chrono { template -class _LIBCPP_TEMPLATE_VIS time_point { +class time_point { static_assert(__is_duration_v<_Duration>, "Second template parameter of time_point must be a std::chrono::duration"); public: @@ -58,6 +58,19 @@ public: // arithmetic +#if _LIBCPP_STD_VER >= 20 + _LIBCPP_HIDE_FROM_ABI constexpr time_point& operator++() { + ++__d_; + return *this; + } + _LIBCPP_HIDE_FROM_ABI constexpr time_point operator++(int) { return time_point{__d_++}; } + _LIBCPP_HIDE_FROM_ABI constexpr time_point& operator--() { + --__d_; + return *this; + } + _LIBCPP_HIDE_FROM_ABI constexpr time_point operator--(int) { return time_point{__d_--}; } +#endif // _LIBCPP_STD_VER >= 20 + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX17 time_point& operator+=(const duration& __d) { __d_ += __d; return *this; @@ -76,8 +89,7 @@ public: } // namespace chrono template -struct _LIBCPP_TEMPLATE_VIS -common_type, chrono::time_point<_Clock, _Duration2> > { +struct common_type, chrono::time_point<_Clock, _Duration2> > { typedef chrono::time_point<_Clock, typename common_type<_Duration1, _Duration2>::type> type; }; diff --git a/lib/libcxx/include/__compare/common_comparison_category.h b/lib/libcxx/include/__compare/common_comparison_category.h index 215922abad..eae2ef0062 100644 --- a/lib/libcxx/include/__compare/common_comparison_category.h +++ b/lib/libcxx/include/__compare/common_comparison_category.h @@ -55,7 +55,7 @@ __compute_comp_type(const _ClassifyCompCategory (&__types)[_Size]) { template _LIBCPP_HIDE_FROM_ABI constexpr auto __get_comp_type() { using _CCC = _ClassifyCompCategory; - constexpr _CCC __type_kinds[] = {_StrongOrd, __type_to_enum<_Ts>()...}; + constexpr _CCC __type_kinds[] = {_StrongOrd, __comp_detail::__type_to_enum<_Ts>()...}; constexpr _CCC __cat = __comp_detail::__compute_comp_type(__type_kinds); if constexpr (__cat == _None) return void(); @@ -72,8 +72,8 @@ _LIBCPP_HIDE_FROM_ABI constexpr auto __get_comp_type() { // [cmp.common], common comparison category type template -struct _LIBCPP_TEMPLATE_VIS common_comparison_category { - using type = decltype(__comp_detail::__get_comp_type<_Ts...>()); +struct common_comparison_category { + using type _LIBCPP_NODEBUG = decltype(__comp_detail::__get_comp_type<_Ts...>()); }; template diff --git a/lib/libcxx/include/__compare/compare_three_way.h b/lib/libcxx/include/__compare/compare_three_way.h index 01c12076c0..852c5874c6 100644 --- a/lib/libcxx/include/__compare/compare_three_way.h +++ b/lib/libcxx/include/__compare/compare_three_way.h @@ -22,7 +22,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD #if _LIBCPP_STD_VER >= 20 -struct _LIBCPP_TEMPLATE_VIS compare_three_way { +struct compare_three_way { template requires three_way_comparable_with<_T1, _T2> constexpr _LIBCPP_HIDE_FROM_ABI auto operator()(_T1&& __t, _T2&& __u) const diff --git a/lib/libcxx/include/__compare/compare_three_way_result.h b/lib/libcxx/include/__compare/compare_three_way_result.h index 6ee2eff003..264a4d603c 100644 --- a/lib/libcxx/include/__compare/compare_three_way_result.h +++ b/lib/libcxx/include/__compare/compare_three_way_result.h @@ -29,12 +29,12 @@ struct _LIBCPP_HIDE_FROM_ABI __compare_three_way_result< _Tp, _Up, decltype(std::declval<__make_const_lvalue_ref<_Tp>>() <=> std::declval<__make_const_lvalue_ref<_Up>>(), void())> { - using type = decltype(std::declval<__make_const_lvalue_ref<_Tp>>() <=> std::declval<__make_const_lvalue_ref<_Up>>()); + using type _LIBCPP_NODEBUG = + decltype(std::declval<__make_const_lvalue_ref<_Tp>>() <=> std::declval<__make_const_lvalue_ref<_Up>>()); }; template -struct _LIBCPP_TEMPLATE_VIS _LIBCPP_NO_SPECIALIZATIONS compare_three_way_result - : __compare_three_way_result<_Tp, _Up, void> {}; +struct _LIBCPP_NO_SPECIALIZATIONS compare_three_way_result : __compare_three_way_result<_Tp, _Up, void> {}; template using compare_three_way_result_t = typename compare_three_way_result<_Tp, _Up>::type; diff --git a/lib/libcxx/include/__concepts/arithmetic.h b/lib/libcxx/include/__concepts/arithmetic.h index 0c44f11780..64c0200783 100644 --- a/lib/libcxx/include/__concepts/arithmetic.h +++ b/lib/libcxx/include/__concepts/arithmetic.h @@ -13,8 +13,6 @@ #include <__type_traits/is_floating_point.h> #include <__type_traits/is_integral.h> #include <__type_traits/is_signed.h> -#include <__type_traits/is_signed_integer.h> -#include <__type_traits/is_unsigned_integer.h> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # pragma GCC system_header @@ -38,17 +36,6 @@ concept unsigned_integral = integral<_Tp> && !signed_integral<_Tp>; template concept floating_point = is_floating_point_v<_Tp>; -// Concept helpers for the internal type traits for the fundamental types. - -template -concept __libcpp_unsigned_integer = __libcpp_is_unsigned_integer<_Tp>::value; - -template -concept __libcpp_signed_integer = __libcpp_is_signed_integer<_Tp>::value; - -template -concept __libcpp_integer = __libcpp_unsigned_integer<_Tp> || __libcpp_signed_integer<_Tp>; - #endif // _LIBCPP_STD_VER >= 20 _LIBCPP_END_NAMESPACE_STD diff --git a/lib/libcxx/include/__concepts/class_or_enum.h b/lib/libcxx/include/__concepts/class_or_enum.h index 2739e31e14..9fceed034c 100644 --- a/lib/libcxx/include/__concepts/class_or_enum.h +++ b/lib/libcxx/include/__concepts/class_or_enum.h @@ -13,7 +13,6 @@ #include <__type_traits/is_class.h> #include <__type_traits/is_enum.h> #include <__type_traits/is_union.h> -#include <__type_traits/remove_cvref.h> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # pragma GCC system_header diff --git a/lib/libcxx/include/__concepts/common_with.h b/lib/libcxx/include/__concepts/common_with.h index 85abb05efb..09082b2295 100644 --- a/lib/libcxx/include/__concepts/common_with.h +++ b/lib/libcxx/include/__concepts/common_with.h @@ -12,7 +12,7 @@ #include <__concepts/common_reference_with.h> #include <__concepts/same_as.h> #include <__config> -#include <__type_traits/add_lvalue_reference.h> +#include <__type_traits/add_reference.h> #include <__type_traits/common_reference.h> #include <__type_traits/common_type.h> #include <__utility/declval.h> diff --git a/lib/libcxx/include/__concepts/swappable.h b/lib/libcxx/include/__concepts/swappable.h index 985c733021..c691d3ab1e 100644 --- a/lib/libcxx/include/__concepts/swappable.h +++ b/lib/libcxx/include/__concepts/swappable.h @@ -22,7 +22,6 @@ #include <__utility/exchange.h> #include <__utility/forward.h> #include <__utility/move.h> -#include <__utility/swap.h> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # pragma GCC system_header diff --git a/lib/libcxx/include/__condition_variable/condition_variable.h b/lib/libcxx/include/__condition_variable/condition_variable.h index 4521fe2746..1e8edd5dcb 100644 --- a/lib/libcxx/include/__condition_variable/condition_variable.h +++ b/lib/libcxx/include/__condition_variable/condition_variable.h @@ -39,60 +39,6 @@ _LIBCPP_BEGIN_NAMESPACE_STD _LIBCPP_DECLARE_STRONG_ENUM(cv_status){no_timeout, timeout}; _LIBCPP_DECLARE_STRONG_ENUM_EPILOG(cv_status) -class _LIBCPP_EXPORTED_FROM_ABI condition_variable { - __libcpp_condvar_t __cv_ = _LIBCPP_CONDVAR_INITIALIZER; - -public: - _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR condition_variable() _NOEXCEPT = default; - -# if _LIBCPP_HAS_TRIVIAL_CONDVAR_DESTRUCTION - ~condition_variable() = default; -# else - ~condition_variable(); -# endif - - condition_variable(const condition_variable&) = delete; - condition_variable& operator=(const condition_variable&) = delete; - - void notify_one() _NOEXCEPT; - void notify_all() _NOEXCEPT; - - void wait(unique_lock& __lk) _NOEXCEPT; - template - _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS void wait(unique_lock& __lk, _Predicate __pred); - - template - _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS cv_status - wait_until(unique_lock& __lk, const chrono::time_point<_Clock, _Duration>& __t); - - template - _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS bool - wait_until(unique_lock& __lk, const chrono::time_point<_Clock, _Duration>& __t, _Predicate __pred); - - template - _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS cv_status - wait_for(unique_lock& __lk, const chrono::duration<_Rep, _Period>& __d); - - template - bool _LIBCPP_HIDE_FROM_ABI - wait_for(unique_lock& __lk, const chrono::duration<_Rep, _Period>& __d, _Predicate __pred); - - typedef __libcpp_condvar_t* native_handle_type; - _LIBCPP_HIDE_FROM_ABI native_handle_type native_handle() { return &__cv_; } - -private: - void - __do_timed_wait(unique_lock& __lk, chrono::time_point) _NOEXCEPT; -# if _LIBCPP_HAS_COND_CLOCKWAIT - _LIBCPP_HIDE_FROM_ABI void - __do_timed_wait(unique_lock& __lk, chrono::time_point) _NOEXCEPT; -# endif - template - _LIBCPP_HIDE_FROM_ABI void - __do_timed_wait(unique_lock& __lk, chrono::time_point<_Clock, chrono::nanoseconds>) _NOEXCEPT; -}; -#endif // _LIBCPP_HAS_THREADS - template ::value, int> = 0> inline _LIBCPP_HIDE_FROM_ABI chrono::nanoseconds __safe_nanosecond_cast(chrono::duration<_Rep, _Period> __d) { using namespace chrono; @@ -140,64 +86,106 @@ inline _LIBCPP_HIDE_FROM_ABI chrono::nanoseconds __safe_nanosecond_cast(chrono:: return nanoseconds(__result); } -#if _LIBCPP_HAS_THREADS -template -void condition_variable::wait(unique_lock& __lk, _Predicate __pred) { - while (!__pred()) - wait(__lk); -} +class _LIBCPP_EXPORTED_FROM_ABI condition_variable { + __libcpp_condvar_t __cv_ = _LIBCPP_CONDVAR_INITIALIZER; -template -cv_status condition_variable::wait_until(unique_lock& __lk, const chrono::time_point<_Clock, _Duration>& __t) { - using namespace chrono; - using __clock_tp_ns = time_point<_Clock, nanoseconds>; +public: + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR condition_variable() _NOEXCEPT = default; - typename _Clock::time_point __now = _Clock::now(); - if (__t <= __now) - return cv_status::timeout; - - __clock_tp_ns __t_ns = __clock_tp_ns(std::__safe_nanosecond_cast(__t.time_since_epoch())); - - __do_timed_wait(__lk, __t_ns); - return _Clock::now() < __t ? cv_status::no_timeout : cv_status::timeout; -} - -template -bool condition_variable::wait_until( - unique_lock& __lk, const chrono::time_point<_Clock, _Duration>& __t, _Predicate __pred) { - while (!__pred()) { - if (wait_until(__lk, __t) == cv_status::timeout) - return __pred(); - } - return true; -} - -template -cv_status condition_variable::wait_for(unique_lock& __lk, const chrono::duration<_Rep, _Period>& __d) { - using namespace chrono; - if (__d <= __d.zero()) - return cv_status::timeout; - using __ns_rep = nanoseconds::rep; - steady_clock::time_point __c_now = steady_clock::now(); - -# if _LIBCPP_HAS_COND_CLOCKWAIT - using __clock_tp_ns = time_point; - __ns_rep __now_count_ns = std::__safe_nanosecond_cast(__c_now.time_since_epoch()).count(); +# if _LIBCPP_HAS_TRIVIAL_CONDVAR_DESTRUCTION + ~condition_variable() = default; # else - using __clock_tp_ns = time_point; - __ns_rep __now_count_ns = std::__safe_nanosecond_cast(system_clock::now().time_since_epoch()).count(); + ~condition_variable(); # endif - __ns_rep __d_ns_count = std::__safe_nanosecond_cast(__d).count(); + condition_variable(const condition_variable&) = delete; + condition_variable& operator=(const condition_variable&) = delete; - if (__now_count_ns > numeric_limits<__ns_rep>::max() - __d_ns_count) { - __do_timed_wait(__lk, __clock_tp_ns::max()); - } else { - __do_timed_wait(__lk, __clock_tp_ns(nanoseconds(__now_count_ns + __d_ns_count))); + void notify_one() _NOEXCEPT; + void notify_all() _NOEXCEPT; + + void wait(unique_lock& __lk) _NOEXCEPT; + + template + _LIBCPP_HIDE_FROM_ABI void wait(unique_lock& __lk, _Predicate __pred) { + while (!__pred()) + wait(__lk); } - return steady_clock::now() - __c_now < __d ? cv_status::no_timeout : cv_status::timeout; -} + template + _LIBCPP_HIDE_FROM_ABI cv_status + wait_until(unique_lock& __lk, const chrono::time_point<_Clock, _Duration>& __t) { + using namespace chrono; + using __clock_tp_ns = time_point<_Clock, nanoseconds>; + + typename _Clock::time_point __now = _Clock::now(); + if (__t <= __now) + return cv_status::timeout; + + __clock_tp_ns __t_ns = __clock_tp_ns(std::__safe_nanosecond_cast(__t.time_since_epoch())); + + __do_timed_wait(__lk, __t_ns); + return _Clock::now() < __t ? cv_status::no_timeout : cv_status::timeout; + } + + template + _LIBCPP_HIDE_FROM_ABI bool + wait_until(unique_lock& __lk, const chrono::time_point<_Clock, _Duration>& __t, _Predicate __pred) { + while (!__pred()) { + if (wait_until(__lk, __t) == cv_status::timeout) + return __pred(); + } + return true; + } + + template + _LIBCPP_HIDE_FROM_ABI cv_status wait_for(unique_lock& __lk, const chrono::duration<_Rep, _Period>& __d) { + using namespace chrono; + if (__d <= __d.zero()) + return cv_status::timeout; + using __ns_rep = nanoseconds::rep; + steady_clock::time_point __c_now = steady_clock::now(); + +# if _LIBCPP_HAS_COND_CLOCKWAIT + using __clock_tp_ns = time_point; + __ns_rep __now_count_ns = std::__safe_nanosecond_cast(__c_now.time_since_epoch()).count(); +# else + using __clock_tp_ns = time_point; + __ns_rep __now_count_ns = std::__safe_nanosecond_cast(system_clock::now().time_since_epoch()).count(); +# endif + + __ns_rep __d_ns_count = std::__safe_nanosecond_cast(__d).count(); + + if (__now_count_ns > numeric_limits<__ns_rep>::max() - __d_ns_count) { + __do_timed_wait(__lk, __clock_tp_ns::max()); + } else { + __do_timed_wait(__lk, __clock_tp_ns(nanoseconds(__now_count_ns + __d_ns_count))); + } + + return steady_clock::now() - __c_now < __d ? cv_status::no_timeout : cv_status::timeout; + } + + template + bool _LIBCPP_HIDE_FROM_ABI + wait_for(unique_lock& __lk, const chrono::duration<_Rep, _Period>& __d, _Predicate __pred); + + typedef __libcpp_condvar_t* native_handle_type; + _LIBCPP_HIDE_FROM_ABI native_handle_type native_handle() { return &__cv_; } + +private: + void + __do_timed_wait(unique_lock& __lk, chrono::time_point) _NOEXCEPT; +# if _LIBCPP_HAS_COND_CLOCKWAIT + _LIBCPP_HIDE_FROM_ABI void + __do_timed_wait(unique_lock& __lk, chrono::time_point) _NOEXCEPT; +# endif + template + _LIBCPP_HIDE_FROM_ABI void + __do_timed_wait(unique_lock& __lk, chrono::time_point<_Clock, chrono::nanoseconds>) _NOEXCEPT; +}; +#endif // _LIBCPP_HAS_THREADS + +#if _LIBCPP_HAS_THREADS template inline bool @@ -210,7 +198,7 @@ inline void condition_variable::__do_timed_wait( unique_lock& __lk, chrono::time_point __tp) _NOEXCEPT { using namespace chrono; if (!__lk.owns_lock()) - __throw_system_error(EPERM, "condition_variable::timed wait: mutex not locked"); + std::__throw_system_error(EPERM, "condition_variable::timed wait: mutex not locked"); nanoseconds __d = __tp.time_since_epoch(); timespec __ts; seconds __s = duration_cast(__d); @@ -225,7 +213,7 @@ inline void condition_variable::__do_timed_wait( } int __ec = pthread_cond_clockwait(&__cv_, __lk.mutex()->native_handle(), CLOCK_MONOTONIC, &__ts); if (__ec != 0 && __ec != ETIMEDOUT) - __throw_system_error(__ec, "condition_variable timed_wait failed"); + std::__throw_system_error(__ec, "condition_variable timed_wait failed"); } # endif // _LIBCPP_HAS_COND_CLOCKWAIT diff --git a/lib/libcxx/include/__config b/lib/libcxx/include/__config index fec323f812..41cb6ac3b6 100644 --- a/lib/libcxx/include/__config +++ b/lib/libcxx/include/__config @@ -28,7 +28,7 @@ // _LIBCPP_VERSION represents the version of libc++, which matches the version of LLVM. // Given a LLVM release LLVM XX.YY.ZZ (e.g. LLVM 17.0.1 == 17.00.01), _LIBCPP_VERSION is // defined to XXYYZZ. -# define _LIBCPP_VERSION 200100 +# define _LIBCPP_VERSION 210100 # define _LIBCPP_CONCAT_IMPL(_X, _Y) _X##_Y # define _LIBCPP_CONCAT(_X, _Y) _LIBCPP_CONCAT_IMPL(_X, _Y) @@ -38,11 +38,47 @@ # define _LIBCPP_FREESTANDING # endif +// NOLINTNEXTLINE(libcpp-cpp-version-check) +# if __cplusplus < 201103L +# define _LIBCPP_CXX03_LANG +# endif + +# if __has_feature(experimental_library) +# ifndef _LIBCPP_ENABLE_EXPERIMENTAL +# define _LIBCPP_ENABLE_EXPERIMENTAL +# endif +# endif + +// Incomplete features get their own specific disabling flags. This makes it +// easier to grep for target specific flags once the feature is complete. +# if defined(_LIBCPP_ENABLE_EXPERIMENTAL) || defined(_LIBCPP_BUILDING_LIBRARY) +# define _LIBCPP_HAS_EXPERIMENTAL_LIBRARY 1 +# else +# define _LIBCPP_HAS_EXPERIMENTAL_LIBRARY 0 +# endif + +# define _LIBCPP_HAS_EXPERIMENTAL_PSTL _LIBCPP_HAS_EXPERIMENTAL_LIBRARY +# define _LIBCPP_HAS_EXPERIMENTAL_TZDB _LIBCPP_HAS_EXPERIMENTAL_LIBRARY +# define _LIBCPP_HAS_EXPERIMENTAL_SYNCSTREAM _LIBCPP_HAS_EXPERIMENTAL_LIBRARY +# define _LIBCPP_HAS_EXPERIMENTAL_HARDENING_OBSERVE_SEMANTIC _LIBCPP_HAS_EXPERIMENTAL_LIBRARY + // HARDENING { -// TODO: Remove in LLVM 21. We're making this an error to catch folks who might not have migrated. -# ifdef _LIBCPP_ENABLE_ASSERTIONS -# error "_LIBCPP_ENABLE_ASSERTIONS has been removed, please use _LIBCPP_HARDENING_MODE instead" +// TODO(LLVM 23): Remove this. We're making these an error to catch folks who might not have migrated. +// Since hardening went through several changes (many of which impacted user-facing macros), +// we're keeping these checks around for a bit longer than usual. Failure to properly configure +// hardening results in checks being dropped silently, which is a pretty big deal. +# if defined(_LIBCPP_ENABLE_ASSERTIONS) +# error "_LIBCPP_ENABLE_ASSERTIONS has been removed, please use _LIBCPP_HARDENING_MODE= instead (see docs)" +# endif +# if defined(_LIBCPP_ENABLE_HARDENED_MODE) +# error "_LIBCPP_ENABLE_HARDENED_MODE has been removed, please use _LIBCPP_HARDENING_MODE= instead (see docs)" +# endif +# if defined(_LIBCPP_ENABLE_SAFE_MODE) +# error "_LIBCPP_ENABLE_SAFE_MODE has been removed, please use _LIBCPP_HARDENING_MODE= instead (see docs)" +# endif +# if defined(_LIBCPP_ENABLE_DEBUG_MODE) +# error "_LIBCPP_ENABLE_DEBUG_MODE has been removed, please use _LIBCPP_HARDENING_MODE= instead (see docs)" # endif // The library provides the macro `_LIBCPP_HARDENING_MODE` which can be set to one of the following values: @@ -147,16 +183,53 @@ _LIBCPP_HARDENING_MODE_EXTENSIVE, \ _LIBCPP_HARDENING_MODE_DEBUG # endif +// Hardening assertion semantics generally mirror the evaluation semantics of C++26 Contracts: +// - `ignore` evaluates the assertion but doesn't do anything if it fails (note that it differs from the Contracts +// `ignore` semantic which wouldn't evaluate the assertion at all); +// - `observe` logs an error (indicating, if possible, that the error is fatal) and continues execution; +// - `quick-enforce` terminates the program as fast as possible (via trapping); +// - `enforce` logs an error and then terminates the program. +// +// Notes: +// - Continuing execution after a hardening check fails results in undefined behavior; the `observe` semantic is meant +// to make adopting hardening easier but should not be used outside of this scenario; +// - C++26 wording for Library Hardening precludes a conforming Hardened implementation from using the Contracts +// `ignore` semantic when evaluating hardened preconditions in the Library. Libc++ allows using this semantic for +// hardened preconditions, however, be aware that using `ignore` does not produce a conforming "Hardened" +// implementation, unlike the other semantics above. +// clang-format off +# define _LIBCPP_ASSERTION_SEMANTIC_IGNORE (1 << 1) +# define _LIBCPP_ASSERTION_SEMANTIC_OBSERVE (1 << 2) +# define _LIBCPP_ASSERTION_SEMANTIC_QUICK_ENFORCE (1 << 3) +# define _LIBCPP_ASSERTION_SEMANTIC_ENFORCE (1 << 4) +// clang-format on + +// Allow users to define an arbitrary assertion semantic; otherwise, use the default mapping from modes to semantics. +// The default is for production-capable modes to use `quick-enforce` (i.e., trap) and for the `debug` mode to use +// `enforce` (i.e., log and abort). +# ifndef _LIBCPP_ASSERTION_SEMANTIC + +# if _LIBCPP_HARDENING_MODE == _LIBCPP_HARDENING_MODE_DEBUG +# define _LIBCPP_ASSERTION_SEMANTIC _LIBCPP_ASSERTION_SEMANTIC_ENFORCE +# else +# define _LIBCPP_ASSERTION_SEMANTIC _LIBCPP_ASSERTION_SEMANTIC_QUICK_ENFORCE +# endif + +# else +# if !_LIBCPP_HAS_EXPERIMENTAL_LIBRARY +# error "Assertion semantics are an experimental feature." +# endif +# if defined(_LIBCPP_CXX03_LANG) +# error "Assertion semantics are not available in the C++03 mode." +# endif + +# endif // _LIBCPP_ASSERTION_SEMANTIC + // } HARDENING # define _LIBCPP_TOSTRING2(x) #x # define _LIBCPP_TOSTRING(x) _LIBCPP_TOSTRING2(x) -// NOLINTNEXTLINE(libcpp-cpp-version-check) -# if __cplusplus < 201103L -# define _LIBCPP_CXX03_LANG -# endif - # ifndef __has_constexpr_builtin # define __has_constexpr_builtin(x) 0 # endif @@ -190,24 +263,6 @@ _LIBCPP_HARDENING_MODE_DEBUG # define _LIBCPP_ABI_VCRUNTIME # endif -# if __has_feature(experimental_library) -# ifndef _LIBCPP_ENABLE_EXPERIMENTAL -# define _LIBCPP_ENABLE_EXPERIMENTAL -# endif -# endif - -// Incomplete features get their own specific disabling flags. This makes it -// easier to grep for target specific flags once the feature is complete. -# if defined(_LIBCPP_ENABLE_EXPERIMENTAL) || defined(_LIBCPP_BUILDING_LIBRARY) -# define _LIBCPP_HAS_EXPERIMENTAL_LIBRARY 1 -# else -# define _LIBCPP_HAS_EXPERIMENTAL_LIBRARY 0 -# endif - -# define _LIBCPP_HAS_EXPERIMENTAL_PSTL _LIBCPP_HAS_EXPERIMENTAL_LIBRARY -# define _LIBCPP_HAS_EXPERIMENTAL_TZDB _LIBCPP_HAS_EXPERIMENTAL_LIBRARY -# define _LIBCPP_HAS_EXPERIMENTAL_SYNCSTREAM _LIBCPP_HAS_EXPERIMENTAL_LIBRARY - # if defined(__MVS__) # include // for __NATIVE_ASCII_F # endif @@ -319,41 +374,14 @@ typedef __char32_t char32_t; # define _LIBCPP_PREFERRED_ALIGNOF(_Tp) __alignof(_Tp) -// Objective-C++ features (opt-in) -# if __has_feature(objc_arc) -# define _LIBCPP_HAS_OBJC_ARC 1 -# else -# define _LIBCPP_HAS_OBJC_ARC 0 -# endif - -# if __has_feature(objc_arc_weak) -# define _LIBCPP_HAS_OBJC_ARC_WEAK 1 -# else -# define _LIBCPP_HAS_OBJC_ARC_WEAK 0 -# endif - -# if __has_extension(blocks) -# define _LIBCPP_HAS_EXTENSION_BLOCKS 1 -# else -# define _LIBCPP_HAS_EXTENSION_BLOCKS 0 -# endif - -# if _LIBCPP_HAS_EXTENSION_BLOCKS && defined(__APPLE__) +# if __has_extension(blocks) && defined(__APPLE__) # define _LIBCPP_HAS_BLOCKS_RUNTIME 1 # else # define _LIBCPP_HAS_BLOCKS_RUNTIME 0 # endif -# if __has_feature(address_sanitizer) -# define _LIBCPP_HAS_ASAN 1 -# else -# define _LIBCPP_HAS_ASAN 0 -# endif - # define _LIBCPP_ALWAYS_INLINE __attribute__((__always_inline__)) -# define _LIBCPP_DISABLE_EXTENSION_WARNING __extension__ - # if defined(_LIBCPP_OBJECT_FORMAT_COFF) # ifdef _DLL @@ -363,35 +391,30 @@ typedef __char32_t char32_t; # endif # if defined(_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS) || (defined(__MINGW32__) && !defined(_LIBCPP_BUILDING_LIBRARY)) -# define _LIBCPP_DLL_VIS # define _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS # define _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS # define _LIBCPP_OVERRIDABLE_FUNC_VIS # define _LIBCPP_EXPORTED_FROM_ABI # elif defined(_LIBCPP_BUILDING_LIBRARY) -# define _LIBCPP_DLL_VIS __declspec(dllexport) # if defined(__MINGW32__) -# define _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS _LIBCPP_DLL_VIS +# define _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS __declspec(dllexport) # define _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS # else # define _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS -# define _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS _LIBCPP_DLL_VIS +# define _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS __declspec(dllexport) # endif -# define _LIBCPP_OVERRIDABLE_FUNC_VIS _LIBCPP_DLL_VIS +# define _LIBCPP_OVERRIDABLE_FUNC_VIS __declspec(dllexport) # define _LIBCPP_EXPORTED_FROM_ABI __declspec(dllexport) # else -# define _LIBCPP_DLL_VIS __declspec(dllimport) -# define _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS _LIBCPP_DLL_VIS +# define _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS __declspec(dllimport) # define _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS # define _LIBCPP_OVERRIDABLE_FUNC_VIS # define _LIBCPP_EXPORTED_FROM_ABI __declspec(dllimport) # endif # define _LIBCPP_HIDDEN -# define _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS -# define _LIBCPP_TEMPLATE_VIS # define _LIBCPP_TEMPLATE_DATA_VIS -# define _LIBCPP_TYPE_VISIBILITY_DEFAULT +# define _LIBCPP_NAMESPACE_VISIBILITY # else @@ -412,24 +435,12 @@ typedef __char32_t char32_t; # define _LIBCPP_OVERRIDABLE_FUNC_VIS _LIBCPP_VISIBILITY("default") # endif -# if !defined(_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS) -// The inline should be removed once PR32114 is resolved -# define _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS inline _LIBCPP_HIDDEN -# else -# define _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS -# endif - -// GCC doesn't support the type_visibility attribute, so we have to keep the visibility attribute on templates -# if !defined(_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS) && !__has_attribute(__type_visibility__) -# define _LIBCPP_TEMPLATE_VIS __attribute__((__visibility__("default"))) -# else -# define _LIBCPP_TEMPLATE_VIS -# endif - # if !defined(_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS) && __has_attribute(__type_visibility__) -# define _LIBCPP_TYPE_VISIBILITY_DEFAULT __attribute__((__type_visibility__("default"))) +# define _LIBCPP_NAMESPACE_VISIBILITY __attribute__((__type_visibility__("default"))) +# elif !defined(_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS) +# define _LIBCPP_NAMESPACE_VISIBILITY __attribute__((__visibility__("default"))) # else -# define _LIBCPP_TYPE_VISIBILITY_DEFAULT +# define _LIBCPP_NAMESPACE_VISIBILITY # endif # endif // defined(_LIBCPP_OBJECT_FORMAT_COFF) @@ -549,24 +560,17 @@ typedef __char32_t char32_t; # define _LIBCPP_HIDE_FROM_ABI_AFTER_V1 _LIBCPP_HIDE_FROM_ABI # endif -// TODO: Remove this workaround once we drop support for Clang 16 -# if __has_warning("-Wc++23-extensions") -# define _LIBCPP_CLANG_DIAGNOSTIC_IGNORED_CXX23_EXTENSION _LIBCPP_CLANG_DIAGNOSTIC_IGNORED("-Wc++23-extensions") -# else -# define _LIBCPP_CLANG_DIAGNOSTIC_IGNORED_CXX23_EXTENSION _LIBCPP_CLANG_DIAGNOSTIC_IGNORED("-Wc++2b-extensions") -# endif - // Clang modules take a significant compile time hit when pushing and popping diagnostics. -// Since all the headers are marked as system headers in the modulemap, we can simply disable this -// pushing and popping when building with clang modules. -# if !__has_feature(modules) +// Since all the headers are marked as system headers unless _LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER is defined, we can +// simply disable this pushing and popping when _LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER isn't defined. +# ifdef _LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER # define _LIBCPP_PUSH_EXTENSION_DIAGNOSTICS \ _LIBCPP_DIAGNOSTIC_PUSH \ _LIBCPP_CLANG_DIAGNOSTIC_IGNORED("-Wc++11-extensions") \ _LIBCPP_CLANG_DIAGNOSTIC_IGNORED("-Wc++14-extensions") \ _LIBCPP_CLANG_DIAGNOSTIC_IGNORED("-Wc++17-extensions") \ _LIBCPP_CLANG_DIAGNOSTIC_IGNORED("-Wc++20-extensions") \ - _LIBCPP_CLANG_DIAGNOSTIC_IGNORED_CXX23_EXTENSION \ + _LIBCPP_CLANG_DIAGNOSTIC_IGNORED("-Wc++23-extensions") \ _LIBCPP_GCC_DIAGNOSTIC_IGNORED("-Wc++14-extensions") \ _LIBCPP_GCC_DIAGNOSTIC_IGNORED("-Wc++17-extensions") \ _LIBCPP_GCC_DIAGNOSTIC_IGNORED("-Wc++20-extensions") \ @@ -577,15 +581,27 @@ typedef __char32_t char32_t; # define _LIBCPP_POP_EXTENSION_DIAGNOSTICS # endif -// Inline namespaces are available in Clang/GCC/MSVC regardless of C++ dialect. // clang-format off -# define _LIBCPP_BEGIN_NAMESPACE_STD _LIBCPP_PUSH_EXTENSION_DIAGNOSTICS \ - namespace _LIBCPP_TYPE_VISIBILITY_DEFAULT std { \ - inline namespace _LIBCPP_ABI_NAMESPACE { -# define _LIBCPP_END_NAMESPACE_STD }} _LIBCPP_POP_EXTENSION_DIAGNOSTICS -#define _LIBCPP_BEGIN_NAMESPACE_EXPERIMENTAL namespace std { namespace experimental { -#define _LIBCPP_END_NAMESPACE_EXPERIMENTAL }} +// The unversioned namespace is used when we want to be ABI compatible with other standard libraries in some way. There +// are two main categories where that's the case: +// - Historically, we have made exception types ABI compatible with libstdc++ to allow throwing them between libstdc++ +// and libc++. This is not used anymore for new exception types, since there is no use-case for it anymore. +// - Types and functions which are used by the compiler are in the unversioned namespace, since the compiler has to know +// their mangling without the appropriate declaration in some cases. +// If it's not clear whether using the unversioned namespace is the correct thing to do, it's not. The versioned +// namespace (_LIBCPP_BEGIN_NAMESPACE_STD) should almost always be used. +# define _LIBCPP_BEGIN_UNVERSIONED_NAMESPACE_STD \ + _LIBCPP_PUSH_EXTENSION_DIAGNOSTICS namespace _LIBCPP_NAMESPACE_VISIBILITY std { + +# define _LIBCPP_END_UNVERSIONED_NAMESPACE_STD } _LIBCPP_POP_EXTENSION_DIAGNOSTICS + +# define _LIBCPP_BEGIN_NAMESPACE_STD _LIBCPP_BEGIN_UNVERSIONED_NAMESPACE_STD inline namespace _LIBCPP_ABI_NAMESPACE { +# define _LIBCPP_END_NAMESPACE_STD } _LIBCPP_END_UNVERSIONED_NAMESPACE_STD + +// TODO: This should really be in the versioned namespace +#define _LIBCPP_BEGIN_NAMESPACE_EXPERIMENTAL _LIBCPP_BEGIN_UNVERSIONED_NAMESPACE_STD namespace experimental { +#define _LIBCPP_END_NAMESPACE_EXPERIMENTAL } _LIBCPP_END_UNVERSIONED_NAMESPACE_STD #define _LIBCPP_BEGIN_NAMESPACE_LFTS _LIBCPP_BEGIN_NAMESPACE_EXPERIMENTAL inline namespace fundamentals_v1 { #define _LIBCPP_END_NAMESPACE_LFTS } _LIBCPP_END_NAMESPACE_EXPERIMENTAL @@ -663,7 +679,10 @@ typedef __char32_t char32_t; # if (defined(__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__) && \ __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ < 101500) || \ (defined(__ENVIRONMENT_IPHONE_OS_VERSION_MIN_REQUIRED__) && \ - __ENVIRONMENT_IPHONE_OS_VERSION_MIN_REQUIRED__ < 130000) + __ENVIRONMENT_IPHONE_OS_VERSION_MIN_REQUIRED__ < 130000) || \ + (defined(__ENVIRONMENT_WATCH_OS_VERSION_MIN_REQUIRED__) && \ + __ENVIRONMENT_WATCH_OS_VERSION_MIN_REQUIRED__ < 60000) || \ + (defined(__ENVIRONMENT_TV_OS_VERSION_MIN_REQUIRED__) && __ENVIRONMENT_TV_OS_VERSION_MIN_REQUIRED__ < 130000) # define _LIBCPP_HAS_C11_ALIGNED_ALLOC 0 # else # define _LIBCPP_HAS_C11_ALIGNED_ALLOC 1 @@ -675,10 +694,6 @@ typedef __char32_t char32_t; # define _LIBCPP_HAS_C11_ALIGNED_ALLOC 1 # endif -# if defined(__APPLE__) || defined(__FreeBSD__) -# define _LIBCPP_HAS_DEFAULTRUNELOCALE -# endif - # if defined(__APPLE__) || defined(__FreeBSD__) # define _LIBCPP_WCTYPE_IS_MASK # endif @@ -741,8 +756,10 @@ typedef __char32_t char32_t; # if _LIBCPP_STD_VER >= 26 # define _LIBCPP_DEPRECATED_IN_CXX26 _LIBCPP_DEPRECATED +# define _LIBCPP_DEPRECATED_IN_CXX26_(m) _LIBCPP_DEPRECATED_(m) # else # define _LIBCPP_DEPRECATED_IN_CXX26 +# define _LIBCPP_DEPRECATED_IN_CXX26_(m) # endif # if _LIBCPP_HAS_CHAR8_T @@ -937,23 +954,6 @@ typedef __char32_t char32_t; # define _LIBCPP_NO_THREAD_SAFETY_ANALYSIS # endif -// Work around the attribute handling in clang. When both __declspec and -// __attribute__ are present, the processing goes awry preventing the definition -// of the types. In MinGW mode, __declspec evaluates to __attribute__, and thus -// combining the two does work. -# if defined(_LIBCPP_ENABLE_THREAD_SAFETY_ANNOTATIONS) && defined(__clang__) && \ - __has_attribute(acquire_capability) && !defined(_MSC_VER) -# define _LIBCPP_HAS_THREAD_SAFETY_ANNOTATIONS 1 -# else -# define _LIBCPP_HAS_THREAD_SAFETY_ANNOTATIONS 0 -# endif - -# if _LIBCPP_HAS_THREAD_SAFETY_ANNOTATIONS -# define _LIBCPP_THREAD_SAFETY_ANNOTATION(x) __attribute__((x)) -# else -# define _LIBCPP_THREAD_SAFETY_ANNOTATION(x) -# endif - # if _LIBCPP_STD_VER >= 20 # define _LIBCPP_CONSTINIT constinit # elif __has_attribute(__require_constant_initialization__) @@ -1064,9 +1064,8 @@ typedef __char32_t char32_t; # define _LIBCPP_CTAD_SUPPORTED_FOR_TYPE(_ClassName) static_assert(true, "") # endif -// TODO(varconst): currently, there are bugs in Clang's intrinsics when handling Objective-C++ `id`, so don't use -// compiler intrinsics in the Objective-C++ mode. -# ifdef __OBJC__ +// TODO(LLVM 22): Remove the workaround +# if defined(__OBJC__) && (!defined(_LIBCPP_CLANG_VER) || _LIBCPP_CLANG_VER < 2001) # define _LIBCPP_WORKAROUND_OBJCXX_COMPILER_INTRINSICS # endif @@ -1119,26 +1118,28 @@ typedef __char32_t char32_t; // Optional attributes - these are useful for a better QoI, but not required to be available +# define _LIBCPP_NOALIAS __attribute__((__malloc__)) +# define _LIBCPP_NODEBUG [[__gnu__::__nodebug__]] +# define _LIBCPP_NO_SANITIZE(...) __attribute__((__no_sanitize__(__VA_ARGS__))) +# define _LIBCPP_INIT_PRIORITY_MAX __attribute__((__init_priority__(100))) +# define _LIBCPP_ATTRIBUTE_FORMAT(archetype, format_string_index, first_format_arg_index) \ + __attribute__((__format__(archetype, format_string_index, first_format_arg_index))) +# define _LIBCPP_PACKED __attribute__((__packed__)) + # if __has_attribute(__no_sanitize__) && !defined(_LIBCPP_COMPILER_GCC) # define _LIBCPP_NO_CFI __attribute__((__no_sanitize__("cfi"))) # else # define _LIBCPP_NO_CFI # endif -# if __has_attribute(__malloc__) -# define _LIBCPP_NOALIAS __attribute__((__malloc__)) -# else -# define _LIBCPP_NOALIAS -# endif - # if __has_attribute(__using_if_exists__) # define _LIBCPP_USING_IF_EXISTS __attribute__((__using_if_exists__)) # else # define _LIBCPP_USING_IF_EXISTS # endif -# if __has_attribute(__no_destroy__) -# define _LIBCPP_NO_DESTROY __attribute__((__no_destroy__)) +# if __has_cpp_attribute(_Clang::__no_destroy__) +# define _LIBCPP_NO_DESTROY [[_Clang::__no_destroy__]] # else # define _LIBCPP_NO_DESTROY # endif @@ -1149,15 +1150,6 @@ typedef __char32_t char32_t; # define _LIBCPP_DIAGNOSE_WARNING(...) # endif -// Use a function like macro to imply that it must be followed by a semicolon -# if __has_cpp_attribute(fallthrough) -# define _LIBCPP_FALLTHROUGH() [[fallthrough]] -# elif __has_attribute(__fallthrough__) -# define _LIBCPP_FALLTHROUGH() __attribute__((__fallthrough__)) -# else -# define _LIBCPP_FALLTHROUGH() ((void)0) -# endif - # if __has_cpp_attribute(_Clang::__lifetimebound__) # define _LIBCPP_LIFETIMEBOUND [[_Clang::__lifetimebound__]] # else @@ -1170,8 +1162,6 @@ typedef __char32_t char32_t; # define _LIBCPP_NOESCAPE # endif -# define _LIBCPP_NODEBUG [[__gnu__::__nodebug__]] - # if __has_cpp_attribute(_Clang::__no_specializations__) # define _LIBCPP_NO_SPECIALIZATIONS \ [[_Clang::__no_specializations__("Users are not allowed to specialize this standard library entity")]] @@ -1179,43 +1169,70 @@ typedef __char32_t char32_t; # define _LIBCPP_NO_SPECIALIZATIONS # endif -# if __has_attribute(__standalone_debug__) -# define _LIBCPP_STANDALONE_DEBUG __attribute__((__standalone_debug__)) +# if __has_cpp_attribute(_Clang::__standalone_debug__) +# define _LIBCPP_STANDALONE_DEBUG [[_Clang::__standalone_debug__]] # else # define _LIBCPP_STANDALONE_DEBUG # endif -# if __has_attribute(__preferred_name__) -# define _LIBCPP_PREFERRED_NAME(x) __attribute__((__preferred_name__(x))) +# if __has_cpp_attribute(_Clang::__preferred_name__) +# define _LIBCPP_PREFERRED_NAME(x) [[_Clang::__preferred_name__(x)]] # else # define _LIBCPP_PREFERRED_NAME(x) # endif -# if __has_attribute(__no_sanitize__) -# define _LIBCPP_NO_SANITIZE(...) __attribute__((__no_sanitize__(__VA_ARGS__))) +# if __has_cpp_attribute(_Clang::__scoped_lockable__) +# define _LIBCPP_SCOPED_LOCKABLE [[_Clang::__scoped_lockable__]] # else -# define _LIBCPP_NO_SANITIZE(...) +# define _LIBCPP_SCOPED_LOCKABLE # endif -# if __has_attribute(__init_priority__) -# define _LIBCPP_INIT_PRIORITY_MAX __attribute__((__init_priority__(100))) +# if __has_cpp_attribute(_Clang::__capability__) +# define _LIBCPP_CAPABILITY(...) [[_Clang::__capability__(__VA_ARGS__)]] # else -# define _LIBCPP_INIT_PRIORITY_MAX +# define _LIBCPP_CAPABILITY(...) # endif -# if __has_attribute(__format__) -// The attribute uses 1-based indices for ordinary and static member functions. -// The attribute uses 2-based indices for non-static member functions. -# define _LIBCPP_ATTRIBUTE_FORMAT(archetype, format_string_index, first_format_arg_index) \ - __attribute__((__format__(archetype, format_string_index, first_format_arg_index))) +# if __has_attribute(__acquire_capability__) +# define _LIBCPP_ACQUIRE_CAPABILITY(...) __attribute__((__acquire_capability__(__VA_ARGS__))) # else -# define _LIBCPP_ATTRIBUTE_FORMAT(archetype, format_string_index, first_format_arg_index) /* nothing */ +# define _LIBCPP_ACQUIRE_CAPABILITY(...) # endif -# if __has_attribute(__packed__) -# define _LIBCPP_PACKED __attribute__((__packed__)) +# if __has_cpp_attribute(_Clang::__try_acquire_capability__) +# define _LIBCPP_TRY_ACQUIRE_CAPABILITY(...) [[_Clang::__try_acquire_capability__(__VA_ARGS__)]] # else -# define _LIBCPP_PACKED +# define _LIBCPP_TRY_ACQUIRE_CAPABILITY(...) +# endif + +# if __has_cpp_attribute(_Clang::__acquire_shared_capability__) +# define _LIBCPP_ACQUIRE_SHARED_CAPABILITY [[_Clang::__acquire_shared_capability__]] +# else +# define _LIBCPP_ACQUIRE_SHARED_CAPABILITY +# endif + +# if __has_cpp_attribute(_Clang::__try_acquire_shared_capability__) +# define _LIBCPP_TRY_ACQUIRE_SHARED_CAPABILITY(...) [[_Clang::__try_acquire_shared_capability__(__VA_ARGS__)]] +# else +# define _LIBCPP_TRY_ACQUIRE_SHARED_CAPABILITY(...) +# endif + +# if __has_cpp_attribute(_Clang::__release_capability__) +# define _LIBCPP_RELEASE_CAPABILITY [[_Clang::__release_capability__]] +# else +# define _LIBCPP_RELEASE_CAPABILITY +# endif + +# if __has_cpp_attribute(_Clang::__release_shared_capability__) +# define _LIBCPP_RELEASE_SHARED_CAPABILITY [[_Clang::__release_shared_capability__]] +# else +# define _LIBCPP_RELEASE_SHARED_CAPABILITY +# endif + +# if __has_attribute(__requires_capability__) +# define _LIBCPP_REQUIRES_CAPABILITY(...) __attribute__((__requires_capability__(__VA_ARGS__))) +# else +# define _LIBCPP_REQUIRES_CAPABILITY(...) # endif # if defined(_LIBCPP_ABI_MICROSOFT) && __has_declspec_attribute(empty_bases) @@ -1231,6 +1248,13 @@ typedef __char32_t char32_t; # define _LIBCPP_DISABLE_UBSAN_UNSIGNED_INTEGER_CHECK # endif +# if __has_feature(nullability) +# define _LIBCPP_DIAGNOSE_NULLPTR _Nonnull +# else +# define _LIBCPP_DIAGNOSE_NULLPTR +# endif + +// TODO(LLVM 22): Remove this macro once LLVM19 support ends. __cpp_explicit_this_parameter has been set in LLVM20. // Clang-18 has support for deducing this, but it does not set the FTM. # if defined(__cpp_explicit_this_parameter) || (defined(_LIBCPP_CLANG_VER) && _LIBCPP_CLANG_VER >= 1800) # define _LIBCPP_HAS_EXPLICIT_THIS_PARAMETER 1 diff --git a/lib/libcxx/include/__configuration/abi.h b/lib/libcxx/include/__configuration/abi.h index 1806dbc7c1..fb82613ea0 100644 --- a/lib/libcxx/include/__configuration/abi.h +++ b/lib/libcxx/include/__configuration/abi.h @@ -38,92 +38,47 @@ #endif #if _LIBCPP_ABI_VERSION >= 2 -// Change short string representation so that string data starts at offset 0, -// improving its alignment in some cases. -# define _LIBCPP_ABI_ALTERNATE_STRING_LAYOUT -// Fix deque iterator type in order to support incomplete types. -# define _LIBCPP_ABI_INCOMPLETE_TYPES_IN_DEQUE -// Fix undefined behavior in how std::list stores its linked nodes. -# define _LIBCPP_ABI_LIST_REMOVE_NODE_POINTER_UB -// Fix undefined behavior in how __tree stores its end and parent nodes. -# define _LIBCPP_ABI_TREE_REMOVE_NODE_POINTER_UB -// Fix undefined behavior in how __hash_table stores its pointer types. -# define _LIBCPP_ABI_FIX_UNORDERED_NODE_POINTER_UB -# define _LIBCPP_ABI_FORWARD_LIST_REMOVE_NODE_POINTER_UB -# define _LIBCPP_ABI_FIX_UNORDERED_CONTAINER_SIZE_TYPE +// TODO: Move the description of the remaining ABI flags to ABIGuarantees.rst or remove them. + // Override the default return value of exception::what() for bad_function_call::what() // with a string that is specific to bad_function_call (see http://wg21.link/LWG2233). // This is an ABI break on platforms that sign and authenticate vtable function pointers // because it changes the mangling of the virtual function located in the vtable, which // changes how it gets signed. # define _LIBCPP_ABI_BAD_FUNCTION_CALL_GOOD_WHAT_MESSAGE -// Enable optimized version of __do_get_(un)signed which avoids redundant copies. -# define _LIBCPP_ABI_OPTIMIZED_LOCALE_NUM_GET -// Give reverse_iterator one data member of type T, not two. -// Also, in C++17 and later, don't derive iterator types from std::iterator. -# define _LIBCPP_ABI_NO_ITERATOR_BASES -// Use the smallest possible integer type to represent the index of the variant. -// Previously libc++ used "unsigned int" exclusively. -# define _LIBCPP_ABI_VARIANT_INDEX_TYPE_OPTIMIZATION -// Unstable attempt to provide a more optimized std::function -# define _LIBCPP_ABI_OPTIMIZED_FUNCTION -// All the regex constants must be distinct and nonzero. -# define _LIBCPP_ABI_REGEX_CONSTANTS_NONZERO -// Re-worked external template instantiations for std::string with a focus on -// performance and fast-path inlining. -# define _LIBCPP_ABI_STRING_OPTIMIZED_EXTERNAL_INSTANTIATION -// Enable clang::trivial_abi on std::unique_ptr. -# define _LIBCPP_ABI_ENABLE_UNIQUE_PTR_TRIVIAL_ABI -// Enable clang::trivial_abi on std::shared_ptr and std::weak_ptr -# define _LIBCPP_ABI_ENABLE_SHARED_PTR_TRIVIAL_ABI -// std::random_device holds some state when it uses an implementation that gets -// entropy from a file (see _LIBCPP_USING_DEV_RANDOM). When switching from this -// implementation to another one on a platform that has already shipped -// std::random_device, one needs to retain the same object layout to remain ABI -// compatible. This switch removes these workarounds for platforms that don't care -// about ABI compatibility. -# define _LIBCPP_ABI_NO_RANDOM_DEVICE_COMPATIBILITY_LAYOUT -// Don't export the legacy __basic_string_common class and its methods from the built library. -# define _LIBCPP_ABI_DO_NOT_EXPORT_BASIC_STRING_COMMON -// Don't export the legacy __vector_base_common class and its methods from the built library. -# define _LIBCPP_ABI_DO_NOT_EXPORT_VECTOR_BASE_COMMON // According to the Standard, `bitset::operator[] const` returns bool # define _LIBCPP_ABI_BITSET_VECTOR_BOOL_CONST_SUBSCRIPT_RETURN_BOOL -// Fix the implementation of CityHash used for std::hash. -// This is an ABI break because `std::hash` will return a different result, -// which means that hashing the same object in translation units built against -// different versions of libc++ can return inconsistent results. This is especially -// tricky since std::hash is used in the implementation of unordered containers. -// -// The incorrect implementation of CityHash has the problem that it drops some -// bits on the floor. -# define _LIBCPP_ABI_FIX_CITYHASH_IMPLEMENTATION -// Remove the base 10 implementation of std::to_chars from the dylib. -// The implementation moved to the header, but we still export the symbols from -// the dylib for backwards compatibility. + +// In LLVM 20, we've changed to take these ABI breaks unconditionally. These flags only exist in case someone is running +// into the static_asserts we added to catch the ABI break and don't care that it is one. +// TODO(LLVM 22): Remove these flags +# define _LIBCPP_ABI_LIST_REMOVE_NODE_POINTER_UB +# define _LIBCPP_ABI_TREE_REMOVE_NODE_POINTER_UB +# define _LIBCPP_ABI_FIX_UNORDERED_NODE_POINTER_UB +# define _LIBCPP_ABI_FORWARD_LIST_REMOVE_NODE_POINTER_UB + +// These flags are documented in ABIGuarantees.rst +# define _LIBCPP_ABI_ALTERNATE_STRING_LAYOUT +# define _LIBCPP_ABI_DO_NOT_EXPORT_BASIC_STRING_COMMON +# define _LIBCPP_ABI_DO_NOT_EXPORT_VECTOR_BASE_COMMON # define _LIBCPP_ABI_DO_NOT_EXPORT_TO_CHARS_BASE_10 -// Define std::array/std::string_view iterators to be __wrap_iters instead of raw -// pointers, which prevents people from relying on a non-portable implementation -// detail. This is especially useful because enabling bounded iterators hardening -// requires code not to make these assumptions. +# define _LIBCPP_ABI_ENABLE_SHARED_PTR_TRIVIAL_ABI +# define _LIBCPP_ABI_ENABLE_UNIQUE_PTR_TRIVIAL_ABI +# define _LIBCPP_ABI_FIX_CITYHASH_IMPLEMENTATION +# define _LIBCPP_ABI_FIX_UNORDERED_CONTAINER_SIZE_TYPE +# define _LIBCPP_ABI_INCOMPLETE_TYPES_IN_DEQUE +# define _LIBCPP_ABI_IOS_ALLOW_ARBITRARY_FILL_VALUE +# define _LIBCPP_ABI_NO_COMPRESSED_PAIR_PADDING +# define _LIBCPP_ABI_NO_FILESYSTEM_INLINE_NAMESPACE +# define _LIBCPP_ABI_NO_ITERATOR_BASES +# define _LIBCPP_ABI_NO_RANDOM_DEVICE_COMPATIBILITY_LAYOUT +# define _LIBCPP_ABI_OPTIMIZED_FUNCTION +# define _LIBCPP_ABI_REGEX_CONSTANTS_NONZERO +# define _LIBCPP_ABI_STRING_OPTIMIZED_EXTERNAL_INSTANTIATION # define _LIBCPP_ABI_USE_WRAP_ITER_IN_STD_ARRAY # define _LIBCPP_ABI_USE_WRAP_ITER_IN_STD_STRING_VIEW -// Dont' add an inline namespace for `std::filesystem` -# define _LIBCPP_ABI_NO_FILESYSTEM_INLINE_NAMESPACE -// std::basic_ios uses WEOF to indicate that the fill value is -// uninitialized. However, on platforms where the size of char_type is -// equal to or greater than the size of int_type and char_type is unsigned, -// std::char_traits::eq_int_type() cannot distinguish between WEOF -// and WCHAR_MAX. This ABI setting determines whether we should instead track whether the fill -// value has been initialized using a separate boolean, which changes the ABI. -# define _LIBCPP_ABI_IOS_ALLOW_ARBITRARY_FILL_VALUE -// Historically, libc++ used a type called `__compressed_pair` to reduce storage needs in cases of empty types (e.g. an -// empty allocator in std::vector). We switched to using `[[no_unique_address]]`. However, for ABI compatibility reasons -// we had to add artificial padding in a few places. -// -// This setting disables the addition of such artificial padding, leading to a more optimal -// representation for several types. -# define _LIBCPP_ABI_NO_COMPRESSED_PAIR_PADDING +# define _LIBCPP_ABI_VARIANT_INDEX_TYPE_OPTIMIZATION + #elif _LIBCPP_ABI_VERSION == 1 # if !(defined(_LIBCPP_OBJECT_FORMAT_COFF) || defined(_LIBCPP_OBJECT_FORMAT_XCOFF)) // Enable compiling copies of now inline methods into the dylib to support @@ -138,7 +93,7 @@ # endif // Feature macros for disabling pre ABI v1 features. All of these options // are deprecated. -# if defined(__FreeBSD__) && __FreeBSD__ < 14 +# if defined(__FreeBSD__) # define _LIBCPP_DEPRECATED_ABI_DISABLE_PAIR_TRIVIAL_COPY_CTOR # endif #endif @@ -153,35 +108,6 @@ // The macro below is used for all classes whose ABI have changed as part of fixing these bugs. #define _LIBCPP_ABI_LLVM18_NO_UNIQUE_ADDRESS __attribute__((__abi_tag__("llvm18_nua"))) -// Changes the iterator type of select containers (see below) to a bounded iterator that keeps track of whether it's -// within the bounds of the original container and asserts it on every dereference. -// -// ABI impact: changes the iterator type of the relevant containers. -// -// Supported containers: -// - `span`; -// - `string_view`. -// #define _LIBCPP_ABI_BOUNDED_ITERATORS - -// Changes the iterator type of `basic_string` to a bounded iterator that keeps track of whether it's within the bounds -// of the original container and asserts it on every dereference and when performing iterator arithmetics. -// -// ABI impact: changes the iterator type of `basic_string` and its specializations, such as `string` and `wstring`. -// #define _LIBCPP_ABI_BOUNDED_ITERATORS_IN_STRING - -// Changes the iterator type of `vector` to a bounded iterator that keeps track of whether it's within the bounds of the -// original container and asserts it on every dereference and when performing iterator arithmetics. Note: this doesn't -// yet affect `vector`. -// -// ABI impact: changes the iterator type of `vector` (except `vector`). -// #define _LIBCPP_ABI_BOUNDED_ITERATORS_IN_VECTOR - -// Changes the iterator type of `array` to a bounded iterator that keeps track of whether it's within the bounds of the -// container and asserts it on every dereference and when performing iterator arithmetic. -// -// ABI impact: changes the iterator type of `array`, its size and its layout. -// #define _LIBCPP_ABI_BOUNDED_ITERATORS_IN_STD_ARRAY - // [[msvc::no_unique_address]] seems to mostly affect empty classes, so the padding scheme for Itanium doesn't work. #if defined(_LIBCPP_ABI_MICROSOFT) && !defined(_LIBCPP_ABI_NO_COMPRESSED_PAIR_PADDING) # define _LIBCPP_ABI_NO_COMPRESSED_PAIR_PADDING diff --git a/lib/libcxx/include/__configuration/availability.h b/lib/libcxx/include/__configuration/availability.h index f9e52a690c..ae58e36b50 100644 --- a/lib/libcxx/include/__configuration/availability.h +++ b/lib/libcxx/include/__configuration/availability.h @@ -69,7 +69,13 @@ // Availability markup is disabled when building the library, or when a non-Clang // compiler is used because only Clang supports the necessary attributes. -#if defined(_LIBCPP_BUILDING_LIBRARY) || defined(_LIBCXXABI_BUILDING_LIBRARY) || !defined(_LIBCPP_COMPILER_CLANG_BASED) +// +// We also allow users to force-disable availability markup via the `_LIBCPP_DISABLE_AVAILABILITY` +// macro because that is the only way to work around a Clang bug related to availability +// attributes: https://github.com/llvm/llvm-project/issues/134151. +// Once that bug has been fixed, we should remove the macro. +#if defined(_LIBCPP_BUILDING_LIBRARY) || defined(_LIBCXXABI_BUILDING_LIBRARY) || \ + !defined(_LIBCPP_COMPILER_CLANG_BASED) || defined(_LIBCPP_DISABLE_AVAILABILITY) # undef _LIBCPP_HAS_VENDOR_AVAILABILITY_ANNOTATIONS # define _LIBCPP_HAS_VENDOR_AVAILABILITY_ANNOTATIONS 0 #endif @@ -78,6 +84,9 @@ // in all versions of the library are available. #if !_LIBCPP_HAS_VENDOR_AVAILABILITY_ANNOTATIONS +# define _LIBCPP_INTRODUCED_IN_LLVM_21 1 +# define _LIBCPP_INTRODUCED_IN_LLVM_21_ATTRIBUTE /* nothing */ + # define _LIBCPP_INTRODUCED_IN_LLVM_20 1 # define _LIBCPP_INTRODUCED_IN_LLVM_20_ATTRIBUTE /* nothing */ @@ -107,13 +116,15 @@ # define _LIBCPP_INTRODUCED_IN_LLVM_9_ATTRIBUTE_PUSH /* nothing */ # define _LIBCPP_INTRODUCED_IN_LLVM_9_ATTRIBUTE_POP /* nothing */ -# define _LIBCPP_INTRODUCED_IN_LLVM_4 1 -# define _LIBCPP_INTRODUCED_IN_LLVM_4_ATTRIBUTE /* nothing */ - #elif defined(__APPLE__) // clang-format off +// LLVM 21 +// TODO: Fill this in +# define _LIBCPP_INTRODUCED_IN_LLVM_21 0 +# define _LIBCPP_INTRODUCED_IN_LLVM_21_ATTRIBUTE __attribute__((unavailable)) + // LLVM 20 // TODO: Fill this in # define _LIBCPP_INTRODUCED_IN_LLVM_20 0 @@ -244,14 +255,6 @@ _Pragma("clang attribute pop") \ _Pragma("clang attribute pop") -// LLVM 4 -# if defined(__ENVIRONMENT_WATCH_OS_VERSION_MIN_REQUIRED__) && __ENVIRONMENT_WATCH_OS_VERSION_MIN_REQUIRED__ < 50000 -# define _LIBCPP_INTRODUCED_IN_LLVM_4 0 -# else -# define _LIBCPP_INTRODUCED_IN_LLVM_4 1 -# endif -# define _LIBCPP_INTRODUCED_IN_LLVM_4_ATTRIBUTE __attribute__((availability(watchos, strict, introduced = 5.0))) - // clang-format on #else @@ -263,23 +266,6 @@ #endif -// These macros control the availability of std::bad_optional_access and -// other exception types. These were put in the shared library to prevent -// code bloat from every user program defining the vtable for these exception -// types. -// -// Note that when exceptions are disabled, the methods that normally throw -// these exceptions can be used even on older deployment targets, but those -// methods will abort instead of throwing. -#define _LIBCPP_AVAILABILITY_HAS_BAD_OPTIONAL_ACCESS _LIBCPP_INTRODUCED_IN_LLVM_4 -#define _LIBCPP_AVAILABILITY_BAD_OPTIONAL_ACCESS _LIBCPP_INTRODUCED_IN_LLVM_4_ATTRIBUTE - -#define _LIBCPP_AVAILABILITY_HAS_BAD_VARIANT_ACCESS _LIBCPP_INTRODUCED_IN_LLVM_4 -#define _LIBCPP_AVAILABILITY_BAD_VARIANT_ACCESS _LIBCPP_INTRODUCED_IN_LLVM_4_ATTRIBUTE - -#define _LIBCPP_AVAILABILITY_HAS_BAD_ANY_CAST _LIBCPP_INTRODUCED_IN_LLVM_4 -#define _LIBCPP_AVAILABILITY_BAD_ANY_CAST _LIBCPP_INTRODUCED_IN_LLVM_4_ATTRIBUTE - // These macros control the availability of all parts of that // depend on something in the dylib. #define _LIBCPP_AVAILABILITY_HAS_FILESYSTEM_LIBRARY _LIBCPP_INTRODUCED_IN_LLVM_9 @@ -359,18 +345,15 @@ #define _LIBCPP_AVAILABILITY_HAS_FROM_CHARS_FLOATING_POINT _LIBCPP_INTRODUCED_IN_LLVM_20 #define _LIBCPP_AVAILABILITY_FROM_CHARS_FLOATING_POINT _LIBCPP_INTRODUCED_IN_LLVM_20_ATTRIBUTE -// Define availability attributes that depend on _LIBCPP_HAS_EXCEPTIONS. -// Those are defined in terms of the availability attributes above, and -// should not be vendor-specific. -#if !_LIBCPP_HAS_EXCEPTIONS -# define _LIBCPP_AVAILABILITY_THROW_BAD_ANY_CAST -# define _LIBCPP_AVAILABILITY_THROW_BAD_OPTIONAL_ACCESS -# define _LIBCPP_AVAILABILITY_THROW_BAD_VARIANT_ACCESS -#else -# define _LIBCPP_AVAILABILITY_THROW_BAD_ANY_CAST _LIBCPP_AVAILABILITY_BAD_ANY_CAST -# define _LIBCPP_AVAILABILITY_THROW_BAD_OPTIONAL_ACCESS _LIBCPP_AVAILABILITY_BAD_OPTIONAL_ACCESS -# define _LIBCPP_AVAILABILITY_THROW_BAD_VARIANT_ACCESS _LIBCPP_AVAILABILITY_BAD_VARIANT_ACCESS -#endif +// This controls whether `std::__hash_memory` is available in the dylib, which +// is used for some `std::hash` specializations. +#define _LIBCPP_AVAILABILITY_HAS_HASH_MEMORY _LIBCPP_INTRODUCED_IN_LLVM_21 +// No attribute, since we've had hash in the headers before + +// This controls whether we provide a message for `bad_function_call::what()` that specific to `std::bad_function_call`. +// See https://wg21.link/LWG2233. This requires `std::bad_function_call::what()` to be available in the dylib. +#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 // Define availability attributes that depend on both // _LIBCPP_HAS_EXCEPTIONS and _LIBCPP_HAS_RTTI. diff --git a/lib/libcxx/include/__configuration/compiler.h b/lib/libcxx/include/__configuration/compiler.h index caedfa9fd8..54025c5b22 100644 --- a/lib/libcxx/include/__configuration/compiler.h +++ b/lib/libcxx/include/__configuration/compiler.h @@ -33,8 +33,8 @@ // Warn if a compiler version is used that is not supported anymore // LLVM RELEASE Update the minimum compiler versions # if defined(_LIBCPP_CLANG_VER) -# if _LIBCPP_CLANG_VER < 1800 -# warning "Libc++ only supports Clang 18 and later" +# if _LIBCPP_CLANG_VER < 1900 +# warning "Libc++ only supports Clang 19 and later" # endif # elif defined(_LIBCPP_APPLE_CLANG_VER) # if _LIBCPP_APPLE_CLANG_VER < 1500 diff --git a/lib/libcxx/include/__configuration/platform.h b/lib/libcxx/include/__configuration/platform.h index b03d7c0f39..1a83b0dc27 100644 --- a/lib/libcxx/include/__configuration/platform.h +++ b/lib/libcxx/include/__configuration/platform.h @@ -42,6 +42,13 @@ # endif #endif +// This is required in order for _NEWLIB_VERSION to be defined in places where we use it. +// TODO: We shouldn't be including arbitrarily-named headers from libc++ since this can break valid +// user code. Move code paths that need _NEWLIB_VERSION to another customization mechanism. +#if __has_include() +# include +#endif + #ifndef __BYTE_ORDER__ # error \ "Your compiler doesn't seem to define __BYTE_ORDER__, which is required by libc++ to know the endianness of your target platform" diff --git a/lib/libcxx/include/__coroutine/coroutine_handle.h b/lib/libcxx/include/__coroutine/coroutine_handle.h index e2cde20498..b7add25851 100644 --- a/lib/libcxx/include/__coroutine/coroutine_handle.h +++ b/lib/libcxx/include/__coroutine/coroutine_handle.h @@ -28,10 +28,10 @@ _LIBCPP_BEGIN_NAMESPACE_STD // [coroutine.handle] template -struct _LIBCPP_TEMPLATE_VIS coroutine_handle; +struct coroutine_handle; template <> -struct _LIBCPP_TEMPLATE_VIS coroutine_handle { +struct coroutine_handle { public: // [coroutine.handle.con], construct/reset constexpr coroutine_handle() noexcept = default; @@ -93,7 +93,7 @@ operator<=>(coroutine_handle<> __x, coroutine_handle<> __y) noexcept { } template -struct _LIBCPP_TEMPLATE_VIS coroutine_handle { +struct coroutine_handle { public: // [coroutine.handle.con], construct/reset constexpr coroutine_handle() noexcept = default; @@ -172,6 +172,6 @@ struct hash> { _LIBCPP_END_NAMESPACE_STD -#endif // __LIBCPP_STD_VER >= 20 +#endif // _LIBCPP_STD_VER >= 20 #endif // _LIBCPP___COROUTINE_COROUTINE_HANDLE_H diff --git a/lib/libcxx/include/__coroutine/coroutine_traits.h b/lib/libcxx/include/__coroutine/coroutine_traits.h index 78f05341f7..60f7ca2311 100644 --- a/lib/libcxx/include/__coroutine/coroutine_traits.h +++ b/lib/libcxx/include/__coroutine/coroutine_traits.h @@ -43,6 +43,6 @@ struct coroutine_traits : public __coroutine_traits_sfinae<_Ret> {}; _LIBCPP_END_NAMESPACE_STD -#endif // __LIBCPP_STD_VER >= 20 +#endif // _LIBCPP_STD_VER >= 20 #endif // _LIBCPP___COROUTINE_COROUTINE_TRAITS_H diff --git a/lib/libcxx/include/__coroutine/noop_coroutine_handle.h b/lib/libcxx/include/__coroutine/noop_coroutine_handle.h index da13d57960..2b2838b6bf 100644 --- a/lib/libcxx/include/__coroutine/noop_coroutine_handle.h +++ b/lib/libcxx/include/__coroutine/noop_coroutine_handle.h @@ -28,7 +28,7 @@ struct noop_coroutine_promise {}; // [coroutine.handle.noop] template <> -struct _LIBCPP_TEMPLATE_VIS coroutine_handle { +struct coroutine_handle { public: // [coroutine.handle.noop.conv], conversion _LIBCPP_HIDE_FROM_ABI constexpr operator coroutine_handle<>() const noexcept { @@ -94,6 +94,6 @@ inline _LIBCPP_HIDE_FROM_ABI noop_coroutine_handle noop_coroutine() noexcept { r _LIBCPP_END_NAMESPACE_STD -#endif // __LIBCPP_STD_VER >= 20 +#endif // _LIBCPP_STD_VER >= 20 #endif // _LIBCPP___COROUTINE_NOOP_COROUTINE_HANDLE_H diff --git a/lib/libcxx/include/__coroutine/trivial_awaitables.h b/lib/libcxx/include/__coroutine/trivial_awaitables.h index b604bd3c2d..7cb7f4dfeb 100644 --- a/lib/libcxx/include/__coroutine/trivial_awaitables.h +++ b/lib/libcxx/include/__coroutine/trivial_awaitables.h @@ -35,6 +35,6 @@ struct suspend_always { _LIBCPP_END_NAMESPACE_STD -#endif // __LIBCPP_STD_VER >= 20 +#endif // _LIBCPP_STD_VER >= 20 #endif // __LIBCPP___COROUTINE_TRIVIAL_AWAITABLES_H diff --git a/lib/libcxx/include/__cstddef/byte.h b/lib/libcxx/include/__cstddef/byte.h index 09e1d75e0b..3d97db1bea 100644 --- a/lib/libcxx/include/__cstddef/byte.h +++ b/lib/libcxx/include/__cstddef/byte.h @@ -19,7 +19,7 @@ #endif #if _LIBCPP_STD_VER >= 17 -namespace std { // purposefully not versioned +_LIBCPP_BEGIN_UNVERSIONED_NAMESPACE_STD enum class byte : unsigned char {}; @@ -79,7 +79,7 @@ template ::value, int> = 0> return static_cast<_Integer>(__b); } -} // namespace std +_LIBCPP_END_UNVERSIONED_NAMESPACE_STD #endif // _LIBCPP_STD_VER >= 17 #endif // _LIBCPP___CSTDDEF_BYTE_H diff --git a/lib/libcxx/include/__debug_utils/sanitizers.h b/lib/libcxx/include/__debug_utils/sanitizers.h index 73d192711e..058feab026 100644 --- a/lib/libcxx/include/__debug_utils/sanitizers.h +++ b/lib/libcxx/include/__debug_utils/sanitizers.h @@ -17,7 +17,7 @@ # pragma GCC system_header #endif -#if _LIBCPP_HAS_ASAN +#if __has_feature(address_sanitizer) extern "C" { _LIBCPP_EXPORTED_FROM_ABI void @@ -28,12 +28,12 @@ _LIBCPP_EXPORTED_FROM_ABI int __sanitizer_verify_double_ended_contiguous_container(const void*, const void*, const void*, const void*); } -#endif // _LIBCPP_HAS_ASAN +#endif // __has_feature(address_sanitizer) _LIBCPP_BEGIN_NAMESPACE_STD // ASan choices -#if _LIBCPP_HAS_ASAN +#if __has_feature(address_sanitizer) # define _LIBCPP_HAS_ASAN_CONTAINER_ANNOTATIONS_FOR_ALL_ALLOCATORS 1 #endif @@ -57,7 +57,7 @@ _LIBCPP_HIDE_FROM_ABI void __annotate_double_ended_contiguous_container( const void* __last_old_contained, const void* __first_new_contained, const void* __last_new_contained) { -#if !_LIBCPP_HAS_ASAN +#if !__has_feature(address_sanitizer) (void)__first_storage; (void)__last_storage; (void)__first_old_contained; @@ -86,7 +86,7 @@ _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 void __annotate_contiguous_c const void* __last_storage, const void* __old_last_contained, const void* __new_last_contained) { -#if !_LIBCPP_HAS_ASAN +#if !__has_feature(address_sanitizer) (void)__first_storage; (void)__last_storage; (void)__old_last_contained; diff --git a/lib/libcxx/include/__exception/exception.h b/lib/libcxx/include/__exception/exception.h index e724e1b99b..f7dab6e83a 100644 --- a/lib/libcxx/include/__exception/exception.h +++ b/lib/libcxx/include/__exception/exception.h @@ -21,7 +21,7 @@ # pragma GCC system_header #endif -namespace std { // purposefully not using versioning namespace +_LIBCPP_BEGIN_UNVERSIONED_NAMESPACE_STD #if defined(_LIBCPP_ABI_VCRUNTIME) && (!defined(_HAS_EXCEPTIONS) || _HAS_EXCEPTIONS != 0) // The std::exception class was already included above, but we're explicit about this condition here for clarity. @@ -89,6 +89,6 @@ public: }; #endif // !_LIBCPP_ABI_VCRUNTIME -} // namespace std +_LIBCPP_END_UNVERSIONED_NAMESPACE_STD #endif // _LIBCPP___EXCEPTION_EXCEPTION_H diff --git a/lib/libcxx/include/__exception/exception_ptr.h b/lib/libcxx/include/__exception/exception_ptr.h index 6257e6f729..796fa924be 100644 --- a/lib/libcxx/include/__exception/exception_ptr.h +++ b/lib/libcxx/include/__exception/exception_ptr.h @@ -15,6 +15,7 @@ #include <__memory/addressof.h> #include <__memory/construct_at.h> #include <__type_traits/decay.h> +#include <__type_traits/is_pointer.h> #include #include @@ -52,7 +53,7 @@ _LIBCPP_OVERRIDABLE_FUNC_VIS __cxa_exception* __cxa_init_primary_exception( #endif -namespace std { // purposefully not using versioning namespace +_LIBCPP_BEGIN_UNVERSIONED_NAMESPACE_STD #ifndef _LIBCPP_ABI_MICROSOFT @@ -62,11 +63,13 @@ class _LIBCPP_EXPORTED_FROM_ABI exception_ptr { static exception_ptr __from_native_exception_pointer(void*) _NOEXCEPT; template - friend _LIBCPP_HIDE_FROM_ABI exception_ptr make_exception_ptr(_Ep) _NOEXCEPT; + friend _LIBCPP_HIDE_FROM_ABI exception_ptr __make_exception_ptr_explicit(_Ep&) _NOEXCEPT; public: - // exception_ptr is basically a COW string. + // exception_ptr is basically a COW string so it is trivially relocatable. + // It is also replaceable because assignment has normal value semantics. using __trivially_relocatable _LIBCPP_NODEBUG = exception_ptr; + using __replaceable _LIBCPP_NODEBUG = exception_ptr; _LIBCPP_HIDE_FROM_ABI exception_ptr() _NOEXCEPT : __ptr_() {} _LIBCPP_HIDE_FROM_ABI exception_ptr(nullptr_t) _NOEXCEPT : __ptr_() {} @@ -89,25 +92,21 @@ public: friend _LIBCPP_EXPORTED_FROM_ABI void rethrow_exception(exception_ptr); }; -template -_LIBCPP_HIDE_FROM_ABI exception_ptr make_exception_ptr(_Ep __e) _NOEXCEPT { # if _LIBCPP_HAS_EXCEPTIONS -# if _LIBCPP_AVAILABILITY_HAS_INIT_PRIMARY_EXCEPTION && __cplusplus >= 201103L +# if _LIBCPP_AVAILABILITY_HAS_INIT_PRIMARY_EXCEPTION +template +_LIBCPP_HIDE_FROM_ABI exception_ptr __make_exception_ptr_explicit(_Ep& __e) _NOEXCEPT { using _Ep2 = __decay_t<_Ep>; - void* __ex = __cxxabiv1::__cxa_allocate_exception(sizeof(_Ep)); # ifdef __wasm__ - // In Wasm, a destructor returns its argument - (void)__cxxabiv1::__cxa_init_primary_exception( - __ex, const_cast(&typeid(_Ep)), [](void* __p) -> void* { + auto __cleanup = [](void* __p) -> void* { + std::__destroy_at(static_cast<_Ep2*>(__p)); + return __p; + }; # else - (void)__cxxabiv1::__cxa_init_primary_exception(__ex, const_cast(&typeid(_Ep)), [](void* __p) { + auto __cleanup = [](void* __p) { std::__destroy_at(static_cast<_Ep2*>(__p)); }; # endif - std::__destroy_at(static_cast<_Ep2*>(__p)); -# ifdef __wasm__ - return __p; -# endif - }); + (void)__cxxabiv1::__cxa_init_primary_exception(__ex, const_cast(&typeid(_Ep)), __cleanup); try { ::new (__ex) _Ep2(__e); @@ -116,19 +115,48 @@ _LIBCPP_HIDE_FROM_ABI exception_ptr make_exception_ptr(_Ep __e) _NOEXCEPT { __cxxabiv1::__cxa_free_exception(__ex); return current_exception(); } -# else +} +# endif + +template +_LIBCPP_HIDE_FROM_ABI exception_ptr __make_exception_ptr_via_throw(_Ep& __e) _NOEXCEPT { try { throw __e; } catch (...) { return current_exception(); } -# endif -# else - ((void)__e); - std::abort(); -# endif } +template +_LIBCPP_HIDE_FROM_ABI exception_ptr make_exception_ptr(_Ep __e) _NOEXCEPT { + // Objective-C exceptions are thrown via pointer. When throwing an Objective-C exception, + // Clang generates a call to `objc_exception_throw` instead of the usual `__cxa_throw`. + // That function creates an exception with a special Objective-C typeinfo instead of + // the usual C++ typeinfo, since that is needed to implement the behavior documented + // at [1]). + // + // Because of this special behavior, we can't create an exception via `__cxa_init_primary_exception` + // for Objective-C exceptions, otherwise we'd bypass `objc_exception_throw`. See https://llvm.org/PR135089. + // + // [1]: + // https://developer.apple.com/library/archive/documentation/Cocoa/Conceptual/Exceptions/Articles/Exceptions64Bit.html + if _LIBCPP_CONSTEXPR (is_pointer<_Ep>::value) { + return std::__make_exception_ptr_via_throw(__e); + } + +# if _LIBCPP_AVAILABILITY_HAS_INIT_PRIMARY_EXCEPTION && !defined(_LIBCPP_CXX03_LANG) + return std::__make_exception_ptr_explicit(__e); +# else + return std::__make_exception_ptr_via_throw(__e); +# endif +} +# else // !_LIBCPP_HAS_EXCEPTIONS +template +_LIBCPP_HIDE_FROM_ABI exception_ptr make_exception_ptr(_Ep) _NOEXCEPT { + std::abort(); +} +# endif // _LIBCPP_HAS_EXCEPTIONS + #else // _LIBCPP_ABI_MICROSOFT class _LIBCPP_EXPORTED_FROM_ABI exception_ptr { @@ -171,6 +199,6 @@ _LIBCPP_HIDE_FROM_ABI exception_ptr make_exception_ptr(_Ep __e) _NOEXCEPT { } #endif // _LIBCPP_ABI_MICROSOFT -} // namespace std +_LIBCPP_END_UNVERSIONED_NAMESPACE_STD #endif // _LIBCPP___EXCEPTION_EXCEPTION_PTR_H diff --git a/lib/libcxx/include/__exception/nested_exception.h b/lib/libcxx/include/__exception/nested_exception.h index d560b6bbc3..90b14158d5 100644 --- a/lib/libcxx/include/__exception/nested_exception.h +++ b/lib/libcxx/include/__exception/nested_exception.h @@ -27,7 +27,7 @@ # pragma GCC system_header #endif -namespace std { // purposefully not using versioning namespace +_LIBCPP_BEGIN_UNVERSIONED_NAMESPACE_STD class _LIBCPP_EXPORTED_FROM_ABI nested_exception { exception_ptr __ptr_; @@ -95,6 +95,6 @@ inline _LIBCPP_HIDE_FROM_ABI void rethrow_if_nested(const _Ep& __e) { template ::value, int> = 0> inline _LIBCPP_HIDE_FROM_ABI void rethrow_if_nested(const _Ep&) {} -} // namespace std +_LIBCPP_END_UNVERSIONED_NAMESPACE_STD #endif // _LIBCPP___EXCEPTION_NESTED_EXCEPTION_H diff --git a/lib/libcxx/include/__exception/operations.h b/lib/libcxx/include/__exception/operations.h index 15520c558a..29d5c698a9 100644 --- a/lib/libcxx/include/__exception/operations.h +++ b/lib/libcxx/include/__exception/operations.h @@ -15,7 +15,7 @@ # pragma GCC system_header #endif -namespace std { // purposefully not using versioning namespace +_LIBCPP_BEGIN_UNVERSIONED_NAMESPACE_STD #if _LIBCPP_STD_VER <= 14 || defined(_LIBCPP_ENABLE_CXX17_REMOVED_UNEXPECTED_FUNCTIONS) || \ defined(_LIBCPP_BUILDING_LIBRARY) using unexpected_handler = void (*)(); @@ -37,6 +37,6 @@ class _LIBCPP_EXPORTED_FROM_ABI exception_ptr; _LIBCPP_EXPORTED_FROM_ABI exception_ptr current_exception() _NOEXCEPT; [[__noreturn__]] _LIBCPP_EXPORTED_FROM_ABI void rethrow_exception(exception_ptr); -} // namespace std +_LIBCPP_END_UNVERSIONED_NAMESPACE_STD #endif // _LIBCPP___EXCEPTION_OPERATIONS_H diff --git a/lib/libcxx/include/__exception/terminate.h b/lib/libcxx/include/__exception/terminate.h index 0bfc3506d3..955a49c2b0 100644 --- a/lib/libcxx/include/__exception/terminate.h +++ b/lib/libcxx/include/__exception/terminate.h @@ -15,8 +15,8 @@ # pragma GCC system_header #endif -namespace std { // purposefully not using versioning namespace +_LIBCPP_BEGIN_UNVERSIONED_NAMESPACE_STD [[__noreturn__]] _LIBCPP_EXPORTED_FROM_ABI void terminate() _NOEXCEPT; -} // namespace std +_LIBCPP_END_UNVERSIONED_NAMESPACE_STD #endif // _LIBCPP___EXCEPTION_TERMINATE_H diff --git a/lib/libcxx/include/__expected/expected.h b/lib/libcxx/include/__expected/expected.h index 03bbd1623e..0f446b8707 100644 --- a/lib/libcxx/include/__expected/expected.h +++ b/lib/libcxx/include/__expected/expected.h @@ -25,10 +25,12 @@ #include <__type_traits/is_assignable.h> #include <__type_traits/is_constructible.h> #include <__type_traits/is_convertible.h> +#include <__type_traits/is_core_convertible.h> #include <__type_traits/is_function.h> #include <__type_traits/is_nothrow_assignable.h> #include <__type_traits/is_nothrow_constructible.h> #include <__type_traits/is_reference.h> +#include <__type_traits/is_replaceable.h> #include <__type_traits/is_same.h> #include <__type_traits/is_swappable.h> #include <__type_traits/is_trivially_constructible.h> @@ -470,6 +472,8 @@ public: __conditional_t<__libcpp_is_trivially_relocatable<_Tp>::value && __libcpp_is_trivially_relocatable<_Err>::value, expected, void>; + using __replaceable _LIBCPP_NODEBUG = + __conditional_t<__is_replaceable_v<_Tp> && __is_replaceable_v<_Err>, expected, void>; template using rebind = expected<_Up, error_type>; @@ -1139,8 +1143,15 @@ public: // [expected.object.eq], equality operators template + _LIBCPP_HIDE_FROM_ABI friend constexpr bool operator==(const expected& __x, const expected<_T2, _E2>& __y) requires(!is_void_v<_T2>) - _LIBCPP_HIDE_FROM_ABI friend constexpr bool operator==(const expected& __x, const expected<_T2, _E2>& __y) { +# if _LIBCPP_STD_VER >= 26 + && requires { + { *__x == *__y } -> __core_convertible_to; + { __x.error() == __y.error() } -> __core_convertible_to; + } +# endif + { if (__x.__has_val() != __y.__has_val()) { return false; } else { @@ -1153,12 +1164,24 @@ public: } template - _LIBCPP_HIDE_FROM_ABI friend constexpr bool operator==(const expected& __x, const _T2& __v) { + _LIBCPP_HIDE_FROM_ABI friend constexpr bool operator==(const expected& __x, const _T2& __v) +# if _LIBCPP_STD_VER >= 26 + requires(!__is_std_expected<_T2>::value) && requires { + { *__x == __v } -> __core_convertible_to; + } +# endif + { return __x.__has_val() && static_cast(__x.__val() == __v); } template - _LIBCPP_HIDE_FROM_ABI friend constexpr bool operator==(const expected& __x, const unexpected<_E2>& __e) { + _LIBCPP_HIDE_FROM_ABI friend constexpr bool operator==(const expected& __x, const unexpected<_E2>& __e) +# if _LIBCPP_STD_VER >= 26 + requires requires { + { __x.error() == __e.error() } -> __core_convertible_to; + } +# endif + { return !__x.__has_val() && static_cast(__x.__unex() == __e.error()); } }; @@ -1851,7 +1874,13 @@ public: // [expected.void.eq], equality operators template requires is_void_v<_T2> - _LIBCPP_HIDE_FROM_ABI friend constexpr bool operator==(const expected& __x, const expected<_T2, _E2>& __y) { + _LIBCPP_HIDE_FROM_ABI friend constexpr bool operator==(const expected& __x, const expected<_T2, _E2>& __y) +# if _LIBCPP_STD_VER >= 26 + requires requires { + { __x.error() == __y.error() } -> __core_convertible_to; + } +# endif + { if (__x.__has_val() != __y.__has_val()) { return false; } else { @@ -1860,7 +1889,13 @@ public: } template - _LIBCPP_HIDE_FROM_ABI friend constexpr bool operator==(const expected& __x, const unexpected<_E2>& __y) { + _LIBCPP_HIDE_FROM_ABI friend constexpr bool operator==(const expected& __x, const unexpected<_E2>& __y) +# if _LIBCPP_STD_VER >= 26 + requires requires { + { __x.error() == __y.error() } -> __core_convertible_to; + } +# endif + { return !__x.__has_val() && static_cast(__x.__unex() == __y.error()); } }; diff --git a/lib/libcxx/include/__filesystem/directory_entry.h b/lib/libcxx/include/__filesystem/directory_entry.h index 11e07acdbe..5f236cf264 100644 --- a/lib/libcxx/include/__filesystem/directory_entry.h +++ b/lib/libcxx/include/__filesystem/directory_entry.h @@ -286,7 +286,7 @@ private: return; } if (__ec && (!__allow_dne || !__is_dne_error(__ec))) - __throw_filesystem_error(__msg, __p_, __ec); + filesystem::__throw_filesystem_error(__msg, __p_, __ec); } _LIBCPP_HIDE_FROM_ABI void __refresh(error_code* __ec = nullptr) { diff --git a/lib/libcxx/include/__filesystem/operations.h b/lib/libcxx/include/__filesystem/operations.h index 904023d2fb..29b6c2f798 100644 --- a/lib/libcxx/include/__filesystem/operations.h +++ b/lib/libcxx/include/__filesystem/operations.h @@ -66,6 +66,9 @@ _LIBCPP_EXPORTED_FROM_ABI bool __remove(const path&, error_code* __ec = nullptr) _LIBCPP_EXPORTED_FROM_ABI void __rename(const path& __from, const path& __to, error_code* __ec = nullptr); _LIBCPP_EXPORTED_FROM_ABI void __resize_file(const path&, uintmax_t __size, error_code* = nullptr); _LIBCPP_EXPORTED_FROM_ABI path __temp_directory_path(error_code* __ec = nullptr); +_LIBCPP_EXPORTED_FROM_ABI bool __fs_is_empty(const path& __p, error_code* __ec = nullptr); +_LIBCPP_EXPORTED_FROM_ABI void __permissions(const path&, perms, perm_options, error_code* = nullptr); +_LIBCPP_EXPORTED_FROM_ABI space_info __space(const path&, error_code* __ec = nullptr); inline _LIBCPP_HIDE_FROM_ABI path absolute(const path& __p) { return __absolute(__p); } inline _LIBCPP_HIDE_FROM_ABI path absolute(const path& __p, error_code& __ec) { return __absolute(__p, &__ec); } @@ -182,7 +185,6 @@ inline _LIBCPP_HIDE_FROM_ABI bool is_directory(const path& __p) { return is_dire inline _LIBCPP_HIDE_FROM_ABI bool is_directory(const path& __p, error_code& __ec) noexcept { return is_directory(__status(__p, &__ec)); } -_LIBCPP_EXPORTED_FROM_ABI bool __fs_is_empty(const path& __p, error_code* __ec = nullptr); inline _LIBCPP_HIDE_FROM_ABI bool is_empty(const path& __p) { return __fs_is_empty(__p); } inline _LIBCPP_HIDE_FROM_ABI bool is_empty(const path& __p, error_code& __ec) { return __fs_is_empty(__p, &__ec); } inline _LIBCPP_HIDE_FROM_ABI bool is_fifo(file_status __s) noexcept { return __s.type() == file_type::fifo; } @@ -220,7 +222,6 @@ inline _LIBCPP_HIDE_FROM_ABI void last_write_time(const path& __p, file_time_typ inline _LIBCPP_HIDE_FROM_ABI void last_write_time(const path& __p, file_time_type __t, error_code& __ec) noexcept { __last_write_time(__p, __t, &__ec); } -_LIBCPP_EXPORTED_FROM_ABI void __permissions(const path&, perms, perm_options, error_code* = nullptr); inline _LIBCPP_HIDE_FROM_ABI void permissions(const path& __p, perms __prms, perm_options __opts = perm_options::replace) { __permissions(__p, __prms, __opts); @@ -281,7 +282,6 @@ inline _LIBCPP_HIDE_FROM_ABI void resize_file(const path& __p, uintmax_t __ns) { inline _LIBCPP_HIDE_FROM_ABI void resize_file(const path& __p, uintmax_t __ns, error_code& __ec) noexcept { return __resize_file(__p, __ns, &__ec); } -_LIBCPP_EXPORTED_FROM_ABI space_info __space(const path&, error_code* __ec = nullptr); inline _LIBCPP_HIDE_FROM_ABI space_info space(const path& __p) { return __space(__p); } inline _LIBCPP_HIDE_FROM_ABI space_info space(const path& __p, error_code& __ec) noexcept { return __space(__p, &__ec); diff --git a/lib/libcxx/include/__filesystem/path.h b/lib/libcxx/include/__filesystem/path.h index 0a751ba329..381e5678a5 100644 --- a/lib/libcxx/include/__filesystem/path.h +++ b/lib/libcxx/include/__filesystem/path.h @@ -17,7 +17,9 @@ #include <__fwd/functional.h> #include <__iterator/back_insert_iterator.h> #include <__iterator/iterator_traits.h> +#include <__memory/addressof.h> #include <__type_traits/decay.h> +#include <__type_traits/enable_if.h> #include <__type_traits/is_pointer.h> #include <__type_traits/remove_const.h> #include <__type_traits/remove_pointer.h> @@ -27,7 +29,6 @@ #if _LIBCPP_HAS_LOCALIZATION # include // for quoted -# include #endif #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) @@ -583,7 +584,7 @@ public: template ::value, int> = 0> _LIBCPP_HIDE_FROM_ABI path& operator+=(_ECharT __x) { - _PathCVT<_ECharT>::__append_source(__pn_, basic_string_view<_ECharT>(&__x, 1)); + _PathCVT<_ECharT>::__append_source(__pn_, basic_string_view<_ECharT>(std::addressof(__x), 1)); return *this; } diff --git a/lib/libcxx/include/__filesystem/u8path.h b/lib/libcxx/include/__filesystem/u8path.h index e13980298d..a701425e42 100644 --- a/lib/libcxx/include/__filesystem/u8path.h +++ b/lib/libcxx/include/__filesystem/u8path.h @@ -13,14 +13,9 @@ #include <__algorithm/unwrap_iter.h> #include <__config> #include <__filesystem/path.h> +#include <__locale> #include -// Only required on Windows for __widen_from_utf8, and included conservatively -// because it requires support for localization. -#if defined(_LIBCPP_WIN32API) -# include -#endif - #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # pragma GCC system_header #endif diff --git a/lib/libcxx/include/__flat_map/flat_map.h b/lib/libcxx/include/__flat_map/flat_map.h index 9cc39c0a1e..bf193f6d3c 100644 --- a/lib/libcxx/include/__flat_map/flat_map.h +++ b/lib/libcxx/include/__flat_map/flat_map.h @@ -11,16 +11,15 @@ #define _LIBCPP___FLAT_MAP_FLAT_MAP_H #include <__algorithm/lexicographical_compare_three_way.h> +#include <__algorithm/lower_bound.h> #include <__algorithm/min.h> #include <__algorithm/ranges_adjacent_find.h> #include <__algorithm/ranges_equal.h> #include <__algorithm/ranges_inplace_merge.h> -#include <__algorithm/ranges_lower_bound.h> -#include <__algorithm/ranges_partition_point.h> #include <__algorithm/ranges_sort.h> #include <__algorithm/ranges_unique.h> -#include <__algorithm/ranges_upper_bound.h> #include <__algorithm/remove_if.h> +#include <__algorithm/upper_bound.h> #include <__assert> #include <__compare/synth_three_way.h> #include <__concepts/swappable.h> @@ -33,6 +32,7 @@ #include <__functional/invoke.h> #include <__functional/is_transparent.h> #include <__functional/operations.h> +#include <__fwd/memory.h> #include <__fwd/vector.h> #include <__iterator/concepts.h> #include <__iterator/distance.h> @@ -114,11 +114,12 @@ public: class value_compare { private: _LIBCPP_NO_UNIQUE_ADDRESS key_compare __comp_; - _LIBCPP_HIDE_FROM_ABI value_compare(key_compare __c) : __comp_(__c) {} + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 value_compare(key_compare __c) : __comp_(__c) {} friend flat_map; public: - _LIBCPP_HIDE_FROM_ABI bool operator()(const_reference __x, const_reference __y) const { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 bool + operator()(const_reference __x, const_reference __y) const { return __comp_(__x.first, __y.first); } }; @@ -137,14 +138,14 @@ private: public: // [flat.map.cons], construct/copy/destroy - _LIBCPP_HIDE_FROM_ABI flat_map() noexcept( + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 flat_map() noexcept( is_nothrow_default_constructible_v<_KeyContainer> && is_nothrow_default_constructible_v<_MappedContainer> && is_nothrow_default_constructible_v<_Compare>) : __containers_(), __compare_() {} _LIBCPP_HIDE_FROM_ABI flat_map(const flat_map&) = default; - _LIBCPP_HIDE_FROM_ABI flat_map(flat_map&& __other) noexcept( + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 flat_map(flat_map&& __other) noexcept( is_nothrow_move_constructible_v<_KeyContainer> && is_nothrow_move_constructible_v<_MappedContainer> && is_nothrow_move_constructible_v<_Compare>) # if _LIBCPP_HAS_EXCEPTIONS @@ -165,7 +166,7 @@ public: template requires __allocator_ctor_constraint<_Allocator> - _LIBCPP_HIDE_FROM_ABI flat_map(const flat_map& __other, const _Allocator& __alloc) + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 flat_map(const flat_map& __other, const _Allocator& __alloc) : flat_map(__ctor_uses_allocator_tag{}, __alloc, __other.__containers_.keys, @@ -174,7 +175,7 @@ public: template requires __allocator_ctor_constraint<_Allocator> - _LIBCPP_HIDE_FROM_ABI flat_map(flat_map&& __other, const _Allocator& __alloc) + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 flat_map(flat_map&& __other, const _Allocator& __alloc) # if _LIBCPP_HAS_EXCEPTIONS try # endif // _LIBCPP_HAS_EXCEPTIONS @@ -191,7 +192,7 @@ public: # endif // _LIBCPP_HAS_EXCEPTIONS } - _LIBCPP_HIDE_FROM_ABI flat_map( + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 flat_map( key_container_type __key_cont, mapped_container_type __mapped_cont, const key_compare& __comp = key_compare()) : __containers_{.keys = std::move(__key_cont), .values = std::move(__mapped_cont)}, __compare_(__comp) { _LIBCPP_ASSERT_VALID_INPUT_RANGE(__containers_.keys.size() == __containers_.values.size(), @@ -201,7 +202,7 @@ public: template requires __allocator_ctor_constraint<_Allocator> - _LIBCPP_HIDE_FROM_ABI + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 flat_map(const key_container_type& __key_cont, const mapped_container_type& __mapped_cont, const _Allocator& __alloc) : flat_map(__ctor_uses_allocator_tag{}, __alloc, __key_cont, __mapped_cont) { _LIBCPP_ASSERT_VALID_INPUT_RANGE(__containers_.keys.size() == __containers_.values.size(), @@ -211,7 +212,7 @@ public: template requires __allocator_ctor_constraint<_Allocator> - _LIBCPP_HIDE_FROM_ABI + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 flat_map(const key_container_type& __key_cont, const mapped_container_type& __mapped_cont, const key_compare& __comp, @@ -222,7 +223,7 @@ public: __sort_and_unique(); } - _LIBCPP_HIDE_FROM_ABI + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 flat_map(sorted_unique_t, key_container_type __key_cont, mapped_container_type __mapped_cont, @@ -236,7 +237,7 @@ public: template requires __allocator_ctor_constraint<_Allocator> - _LIBCPP_HIDE_FROM_ABI + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 flat_map(sorted_unique_t, const key_container_type& __key_cont, const mapped_container_type& __mapped_cont, @@ -250,12 +251,12 @@ public: template requires __allocator_ctor_constraint<_Allocator> - _LIBCPP_HIDE_FROM_ABI - flat_map(sorted_unique_t, - const key_container_type& __key_cont, - const mapped_container_type& __mapped_cont, - const key_compare& __comp, - const _Allocator& __alloc) + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 flat_map( + sorted_unique_t, + const key_container_type& __key_cont, + const mapped_container_type& __mapped_cont, + const key_compare& __comp, + const _Allocator& __alloc) : flat_map(__ctor_uses_allocator_tag{}, __alloc, __key_cont, __mapped_cont, __comp) { _LIBCPP_ASSERT_VALID_INPUT_RANGE(__containers_.keys.size() == __containers_.values.size(), "flat_map keys and mapped containers have different size"); @@ -263,21 +264,22 @@ public: __is_sorted_and_unique(__containers_.keys), "Either the key container is not sorted or it contains duplicates"); } - _LIBCPP_HIDE_FROM_ABI explicit flat_map(const key_compare& __comp) : __containers_(), __compare_(__comp) {} + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 explicit flat_map(const key_compare& __comp) + : __containers_(), __compare_(__comp) {} template requires __allocator_ctor_constraint<_Allocator> - _LIBCPP_HIDE_FROM_ABI flat_map(const key_compare& __comp, const _Allocator& __alloc) + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 flat_map(const key_compare& __comp, const _Allocator& __alloc) : flat_map(__ctor_uses_allocator_empty_tag{}, __alloc, __comp) {} template requires __allocator_ctor_constraint<_Allocator> - _LIBCPP_HIDE_FROM_ABI explicit flat_map(const _Allocator& __alloc) + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 explicit flat_map(const _Allocator& __alloc) : flat_map(__ctor_uses_allocator_empty_tag{}, __alloc) {} template requires __has_input_iterator_category<_InputIterator>::value - _LIBCPP_HIDE_FROM_ABI + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 flat_map(_InputIterator __first, _InputIterator __last, const key_compare& __comp = key_compare()) : __containers_(), __compare_(__comp) { insert(__first, __last); @@ -285,7 +287,7 @@ public: template requires(__has_input_iterator_category<_InputIterator>::value && __allocator_ctor_constraint<_Allocator>) - _LIBCPP_HIDE_FROM_ABI + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 flat_map(_InputIterator __first, _InputIterator __last, const key_compare& __comp, const _Allocator& __alloc) : flat_map(__ctor_uses_allocator_empty_tag{}, __alloc, __comp) { insert(__first, __last); @@ -293,99 +295,105 @@ public: template requires(__has_input_iterator_category<_InputIterator>::value && __allocator_ctor_constraint<_Allocator>) - _LIBCPP_HIDE_FROM_ABI flat_map(_InputIterator __first, _InputIterator __last, const _Allocator& __alloc) + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 + flat_map(_InputIterator __first, _InputIterator __last, const _Allocator& __alloc) : flat_map(__ctor_uses_allocator_empty_tag{}, __alloc) { insert(__first, __last); } template <_ContainerCompatibleRange _Range> - _LIBCPP_HIDE_FROM_ABI flat_map(from_range_t __fr, _Range&& __rg) + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 flat_map(from_range_t __fr, _Range&& __rg) : flat_map(__fr, std::forward<_Range>(__rg), key_compare()) {} template <_ContainerCompatibleRange _Range, class _Allocator> requires __allocator_ctor_constraint<_Allocator> - _LIBCPP_HIDE_FROM_ABI flat_map(from_range_t, _Range&& __rg, const _Allocator& __alloc) + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 flat_map(from_range_t, _Range&& __rg, const _Allocator& __alloc) : flat_map(__ctor_uses_allocator_empty_tag{}, __alloc) { insert_range(std::forward<_Range>(__rg)); } template <_ContainerCompatibleRange _Range> - _LIBCPP_HIDE_FROM_ABI flat_map(from_range_t, _Range&& __rg, const key_compare& __comp) : flat_map(__comp) { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 flat_map(from_range_t, _Range&& __rg, const key_compare& __comp) + : flat_map(__comp) { insert_range(std::forward<_Range>(__rg)); } template <_ContainerCompatibleRange _Range, class _Allocator> requires __allocator_ctor_constraint<_Allocator> - _LIBCPP_HIDE_FROM_ABI flat_map(from_range_t, _Range&& __rg, const key_compare& __comp, const _Allocator& __alloc) + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 + flat_map(from_range_t, _Range&& __rg, const key_compare& __comp, const _Allocator& __alloc) : flat_map(__ctor_uses_allocator_empty_tag{}, __alloc, __comp) { insert_range(std::forward<_Range>(__rg)); } template requires __has_input_iterator_category<_InputIterator>::value - _LIBCPP_HIDE_FROM_ABI + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 flat_map(sorted_unique_t, _InputIterator __first, _InputIterator __last, const key_compare& __comp = key_compare()) : __containers_(), __compare_(__comp) { insert(sorted_unique, __first, __last); } template requires(__has_input_iterator_category<_InputIterator>::value && __allocator_ctor_constraint<_Allocator>) - _LIBCPP_HIDE_FROM_ABI - flat_map(sorted_unique_t, - _InputIterator __first, - _InputIterator __last, - const key_compare& __comp, - const _Allocator& __alloc) + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 flat_map( + sorted_unique_t, + _InputIterator __first, + _InputIterator __last, + const key_compare& __comp, + const _Allocator& __alloc) : flat_map(__ctor_uses_allocator_empty_tag{}, __alloc, __comp) { insert(sorted_unique, __first, __last); } template requires(__has_input_iterator_category<_InputIterator>::value && __allocator_ctor_constraint<_Allocator>) - _LIBCPP_HIDE_FROM_ABI + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 flat_map(sorted_unique_t, _InputIterator __first, _InputIterator __last, const _Allocator& __alloc) : flat_map(__ctor_uses_allocator_empty_tag{}, __alloc) { insert(sorted_unique, __first, __last); } - _LIBCPP_HIDE_FROM_ABI flat_map(initializer_list __il, const key_compare& __comp = key_compare()) + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 + flat_map(initializer_list __il, const key_compare& __comp = key_compare()) : flat_map(__il.begin(), __il.end(), __comp) {} template requires __allocator_ctor_constraint<_Allocator> - _LIBCPP_HIDE_FROM_ABI + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 flat_map(initializer_list __il, const key_compare& __comp, const _Allocator& __alloc) : flat_map(__il.begin(), __il.end(), __comp, __alloc) {} template requires __allocator_ctor_constraint<_Allocator> - _LIBCPP_HIDE_FROM_ABI flat_map(initializer_list __il, const _Allocator& __alloc) + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 + flat_map(initializer_list __il, const _Allocator& __alloc) : flat_map(__il.begin(), __il.end(), __alloc) {} - _LIBCPP_HIDE_FROM_ABI + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 flat_map(sorted_unique_t, initializer_list __il, const key_compare& __comp = key_compare()) : flat_map(sorted_unique, __il.begin(), __il.end(), __comp) {} template requires __allocator_ctor_constraint<_Allocator> - _LIBCPP_HIDE_FROM_ABI + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 flat_map(sorted_unique_t, initializer_list __il, const key_compare& __comp, const _Allocator& __alloc) : flat_map(sorted_unique, __il.begin(), __il.end(), __comp, __alloc) {} template requires __allocator_ctor_constraint<_Allocator> - _LIBCPP_HIDE_FROM_ABI flat_map(sorted_unique_t, initializer_list __il, const _Allocator& __alloc) + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 + flat_map(sorted_unique_t, initializer_list __il, const _Allocator& __alloc) : flat_map(sorted_unique, __il.begin(), __il.end(), __alloc) {} - _LIBCPP_HIDE_FROM_ABI flat_map& operator=(initializer_list __il) { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 flat_map& operator=(initializer_list __il) { clear(); insert(__il); return *this; } - _LIBCPP_HIDE_FROM_ABI flat_map& operator=(const flat_map&) = default; + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 flat_map& operator=(const flat_map&) = default; - _LIBCPP_HIDE_FROM_ABI flat_map& operator=(flat_map&& __other) noexcept( + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 flat_map& operator=(flat_map&& __other) noexcept( is_nothrow_move_assignable_v<_KeyContainer> && is_nothrow_move_assignable_v<_MappedContainer> && is_nothrow_move_assignable_v<_Compare>) { // No matter what happens, we always want to clear the other container before returning @@ -402,49 +410,65 @@ public: } // iterators - _LIBCPP_HIDE_FROM_ABI iterator begin() noexcept { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 iterator begin() noexcept { return iterator(__containers_.keys.begin(), __containers_.values.begin()); } - _LIBCPP_HIDE_FROM_ABI const_iterator begin() const noexcept { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 const_iterator begin() const noexcept { return const_iterator(__containers_.keys.begin(), __containers_.values.begin()); } - _LIBCPP_HIDE_FROM_ABI iterator end() noexcept { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 iterator end() noexcept { return iterator(__containers_.keys.end(), __containers_.values.end()); } - _LIBCPP_HIDE_FROM_ABI const_iterator end() const noexcept { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 const_iterator end() const noexcept { return const_iterator(__containers_.keys.end(), __containers_.values.end()); } - _LIBCPP_HIDE_FROM_ABI reverse_iterator rbegin() noexcept { return reverse_iterator(end()); } - _LIBCPP_HIDE_FROM_ABI const_reverse_iterator rbegin() const noexcept { return const_reverse_iterator(end()); } - _LIBCPP_HIDE_FROM_ABI reverse_iterator rend() noexcept { return reverse_iterator(begin()); } - _LIBCPP_HIDE_FROM_ABI const_reverse_iterator rend() const noexcept { return const_reverse_iterator(begin()); } + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 reverse_iterator rbegin() noexcept { + return reverse_iterator(end()); + } + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 const_reverse_iterator rbegin() const noexcept { + return const_reverse_iterator(end()); + } + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 reverse_iterator rend() noexcept { + return reverse_iterator(begin()); + } + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 const_reverse_iterator rend() const noexcept { + return const_reverse_iterator(begin()); + } - _LIBCPP_HIDE_FROM_ABI const_iterator cbegin() const noexcept { return begin(); } - _LIBCPP_HIDE_FROM_ABI const_iterator cend() const noexcept { return end(); } - _LIBCPP_HIDE_FROM_ABI const_reverse_iterator crbegin() const noexcept { return const_reverse_iterator(end()); } - _LIBCPP_HIDE_FROM_ABI const_reverse_iterator crend() const noexcept { return const_reverse_iterator(begin()); } + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 const_iterator cbegin() const noexcept { return begin(); } + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 const_iterator cend() const noexcept { return end(); } + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 const_reverse_iterator crbegin() const noexcept { + return const_reverse_iterator(end()); + } + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 const_reverse_iterator crend() const noexcept { + return const_reverse_iterator(begin()); + } // [flat.map.capacity], capacity - [[nodiscard]] _LIBCPP_HIDE_FROM_ABI bool empty() const noexcept { return __containers_.keys.empty(); } + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 bool empty() const noexcept { + return __containers_.keys.empty(); + } - _LIBCPP_HIDE_FROM_ABI size_type size() const noexcept { return __containers_.keys.size(); } + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 size_type size() const noexcept { + return __containers_.keys.size(); + } - _LIBCPP_HIDE_FROM_ABI size_type max_size() const noexcept { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 size_type max_size() const noexcept { return std::min(__containers_.keys.max_size(), __containers_.values.max_size()); } // [flat.map.access], element access - _LIBCPP_HIDE_FROM_ABI mapped_type& operator[](const key_type& __x) + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 mapped_type& operator[](const key_type& __x) requires is_constructible_v { return try_emplace(__x).first->second; } - _LIBCPP_HIDE_FROM_ABI mapped_type& operator[](key_type&& __x) + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 mapped_type& operator[](key_type&& __x) requires is_constructible_v { return try_emplace(std::move(__x)).first->second; @@ -453,11 +477,11 @@ public: template requires(__is_compare_transparent && is_constructible_v && is_constructible_v && !is_convertible_v<_Kp &&, const_iterator> && !is_convertible_v<_Kp &&, iterator>) - _LIBCPP_HIDE_FROM_ABI mapped_type& operator[](_Kp&& __x) { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 mapped_type& operator[](_Kp&& __x) { return try_emplace(std::forward<_Kp>(__x)).first->second; } - _LIBCPP_HIDE_FROM_ABI mapped_type& at(const key_type& __x) { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 mapped_type& at(const key_type& __x) { auto __it = find(__x); if (__it == end()) { std::__throw_out_of_range("flat_map::at(const key_type&): Key does not exist"); @@ -465,7 +489,7 @@ public: return __it->second; } - _LIBCPP_HIDE_FROM_ABI const mapped_type& at(const key_type& __x) const { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 const mapped_type& at(const key_type& __x) const { auto __it = find(__x); if (__it == end()) { std::__throw_out_of_range("flat_map::at(const key_type&) const: Key does not exist"); @@ -475,7 +499,7 @@ public: template requires __is_compare_transparent - _LIBCPP_HIDE_FROM_ABI mapped_type& at(const _Kp& __x) { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 mapped_type& at(const _Kp& __x) { auto __it = find(__x); if (__it == end()) { std::__throw_out_of_range("flat_map::at(const K&): Key does not exist"); @@ -485,7 +509,7 @@ public: template requires __is_compare_transparent - _LIBCPP_HIDE_FROM_ABI const mapped_type& at(const _Kp& __x) const { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 const mapped_type& at(const _Kp& __x) const { auto __it = find(__x); if (__it == end()) { std::__throw_out_of_range("flat_map::at(const K&) const: Key does not exist"); @@ -496,45 +520,49 @@ public: // [flat.map.modifiers], modifiers template requires is_constructible_v, _Args...> - _LIBCPP_HIDE_FROM_ABI pair emplace(_Args&&... __args) { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 pair emplace(_Args&&... __args) { std::pair __pair(std::forward<_Args>(__args)...); return __try_emplace(std::move(__pair.first), std::move(__pair.second)); } template requires is_constructible_v, _Args...> - _LIBCPP_HIDE_FROM_ABI iterator emplace_hint(const_iterator __hint, _Args&&... __args) { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 iterator emplace_hint(const_iterator __hint, _Args&&... __args) { std::pair __pair(std::forward<_Args>(__args)...); return __try_emplace_hint(__hint, std::move(__pair.first), std::move(__pair.second)).first; } - _LIBCPP_HIDE_FROM_ABI pair insert(const value_type& __x) { return emplace(__x); } + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 pair insert(const value_type& __x) { + return emplace(__x); + } - _LIBCPP_HIDE_FROM_ABI pair insert(value_type&& __x) { return emplace(std::move(__x)); } + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 pair insert(value_type&& __x) { + return emplace(std::move(__x)); + } - _LIBCPP_HIDE_FROM_ABI iterator insert(const_iterator __hint, const value_type& __x) { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 iterator insert(const_iterator __hint, const value_type& __x) { return emplace_hint(__hint, __x); } - _LIBCPP_HIDE_FROM_ABI iterator insert(const_iterator __hint, value_type&& __x) { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 iterator insert(const_iterator __hint, value_type&& __x) { return emplace_hint(__hint, std::move(__x)); } template requires is_constructible_v, _PairLike> - _LIBCPP_HIDE_FROM_ABI pair insert(_PairLike&& __x) { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 pair insert(_PairLike&& __x) { return emplace(std::forward<_PairLike>(__x)); } template requires is_constructible_v, _PairLike> - _LIBCPP_HIDE_FROM_ABI iterator insert(const_iterator __hint, _PairLike&& __x) { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 iterator insert(const_iterator __hint, _PairLike&& __x) { return emplace_hint(__hint, std::forward<_PairLike>(__x)); } template requires __has_input_iterator_category<_InputIterator>::value - _LIBCPP_HIDE_FROM_ABI void insert(_InputIterator __first, _InputIterator __last) { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 void insert(_InputIterator __first, _InputIterator __last) { if constexpr (sized_sentinel_for<_InputIterator, _InputIterator>) { __reserve(__last - __first); } @@ -543,7 +571,8 @@ public: template requires __has_input_iterator_category<_InputIterator>::value - _LIBCPP_HIDE_FROM_ABI void insert(sorted_unique_t, _InputIterator __first, _InputIterator __last) { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 void + insert(sorted_unique_t, _InputIterator __first, _InputIterator __last) { if constexpr (sized_sentinel_for<_InputIterator, _InputIterator>) { __reserve(__last - __first); } @@ -552,7 +581,7 @@ public: } template <_ContainerCompatibleRange _Range> - _LIBCPP_HIDE_FROM_ABI void insert_range(_Range&& __range) { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 void insert_range(_Range&& __range) { if constexpr (ranges::sized_range<_Range>) { __reserve(ranges::size(__range)); } @@ -560,19 +589,22 @@ public: __append_sort_merge_unique(ranges::begin(__range), ranges::end(__range)); } - _LIBCPP_HIDE_FROM_ABI void insert(initializer_list __il) { insert(__il.begin(), __il.end()); } + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 void insert(initializer_list __il) { + insert(__il.begin(), __il.end()); + } - _LIBCPP_HIDE_FROM_ABI void insert(sorted_unique_t, initializer_list __il) { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 void insert(sorted_unique_t, initializer_list __il) { insert(sorted_unique, __il.begin(), __il.end()); } - _LIBCPP_HIDE_FROM_ABI containers extract() && { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 containers extract() && { auto __guard = std::__make_scope_guard([&]() noexcept { clear() /* noexcept */; }); auto __ret = std::move(__containers_); return __ret; } - _LIBCPP_HIDE_FROM_ABI void replace(key_container_type&& __key_cont, mapped_container_type&& __mapped_cont) { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 void + replace(key_container_type&& __key_cont, mapped_container_type&& __mapped_cont) { _LIBCPP_ASSERT_VALID_INPUT_RANGE( __key_cont.size() == __mapped_cont.size(), "flat_map keys and mapped containers have different size"); @@ -586,13 +618,15 @@ public: template requires is_constructible_v - _LIBCPP_HIDE_FROM_ABI pair try_emplace(const key_type& __key, _Args&&... __args) { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 pair + try_emplace(const key_type& __key, _Args&&... __args) { return __try_emplace(__key, std::forward<_Args>(__args)...); } template requires is_constructible_v - _LIBCPP_HIDE_FROM_ABI pair try_emplace(key_type&& __key, _Args&&... __args) { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 pair + try_emplace(key_type&& __key, _Args&&... __args) { return __try_emplace(std::move(__key), std::forward<_Args>(__args)...); } @@ -600,75 +634,84 @@ public: requires(__is_compare_transparent && is_constructible_v && is_constructible_v && !is_convertible_v<_Kp &&, const_iterator> && !is_convertible_v<_Kp &&, iterator>) - _LIBCPP_HIDE_FROM_ABI pair try_emplace(_Kp&& __key, _Args&&... __args) { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 pair try_emplace(_Kp&& __key, _Args&&... __args) { return __try_emplace(std::forward<_Kp>(__key), std::forward<_Args>(__args)...); } template requires is_constructible_v - _LIBCPP_HIDE_FROM_ABI iterator try_emplace(const_iterator __hint, const key_type& __key, _Args&&... __args) { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 iterator + try_emplace(const_iterator __hint, const key_type& __key, _Args&&... __args) { return __try_emplace_hint(__hint, __key, std::forward<_Args>(__args)...).first; } template requires is_constructible_v - _LIBCPP_HIDE_FROM_ABI iterator try_emplace(const_iterator __hint, key_type&& __key, _Args&&... __args) { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 iterator + try_emplace(const_iterator __hint, key_type&& __key, _Args&&... __args) { return __try_emplace_hint(__hint, std::move(__key), std::forward<_Args>(__args)...).first; } template requires __is_compare_transparent && is_constructible_v && is_constructible_v - _LIBCPP_HIDE_FROM_ABI iterator try_emplace(const_iterator __hint, _Kp&& __key, _Args&&... __args) { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 iterator + try_emplace(const_iterator __hint, _Kp&& __key, _Args&&... __args) { return __try_emplace_hint(__hint, std::forward<_Kp>(__key), std::forward<_Args>(__args)...).first; } template requires is_assignable_v && is_constructible_v - _LIBCPP_HIDE_FROM_ABI pair insert_or_assign(const key_type& __key, _Mapped&& __obj) { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 pair + insert_or_assign(const key_type& __key, _Mapped&& __obj) { return __insert_or_assign(__key, std::forward<_Mapped>(__obj)); } template requires is_assignable_v && is_constructible_v - _LIBCPP_HIDE_FROM_ABI pair insert_or_assign(key_type&& __key, _Mapped&& __obj) { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 pair + insert_or_assign(key_type&& __key, _Mapped&& __obj) { return __insert_or_assign(std::move(__key), std::forward<_Mapped>(__obj)); } template requires __is_compare_transparent && is_constructible_v && is_assignable_v && is_constructible_v - _LIBCPP_HIDE_FROM_ABI pair insert_or_assign(_Kp&& __key, _Mapped&& __obj) { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 pair + insert_or_assign(_Kp&& __key, _Mapped&& __obj) { return __insert_or_assign(std::forward<_Kp>(__key), std::forward<_Mapped>(__obj)); } template requires is_assignable_v && is_constructible_v - _LIBCPP_HIDE_FROM_ABI iterator insert_or_assign(const_iterator __hint, const key_type& __key, _Mapped&& __obj) { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 iterator + insert_or_assign(const_iterator __hint, const key_type& __key, _Mapped&& __obj) { return __insert_or_assign(__hint, __key, std::forward<_Mapped>(__obj)); } template requires is_assignable_v && is_constructible_v - _LIBCPP_HIDE_FROM_ABI iterator insert_or_assign(const_iterator __hint, key_type&& __key, _Mapped&& __obj) { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 iterator + insert_or_assign(const_iterator __hint, key_type&& __key, _Mapped&& __obj) { return __insert_or_assign(__hint, std::move(__key), std::forward<_Mapped>(__obj)); } template requires __is_compare_transparent && is_constructible_v && is_assignable_v && is_constructible_v - _LIBCPP_HIDE_FROM_ABI iterator insert_or_assign(const_iterator __hint, _Kp&& __key, _Mapped&& __obj) { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 iterator + insert_or_assign(const_iterator __hint, _Kp&& __key, _Mapped&& __obj) { return __insert_or_assign(__hint, std::forward<_Kp>(__key), std::forward<_Mapped>(__obj)); } - _LIBCPP_HIDE_FROM_ABI iterator erase(iterator __position) { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 iterator erase(iterator __position) { return __erase(__position.__key_iter_, __position.__mapped_iter_); } - _LIBCPP_HIDE_FROM_ABI iterator erase(const_iterator __position) { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 iterator erase(const_iterator __position) { return __erase(__position.__key_iter_, __position.__mapped_iter_); } - _LIBCPP_HIDE_FROM_ABI size_type erase(const key_type& __x) { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 size_type erase(const key_type& __x) { auto __iter = find(__x); if (__iter != end()) { erase(__iter); @@ -680,14 +723,14 @@ public: template requires(__is_compare_transparent && !is_convertible_v<_Kp &&, iterator> && !is_convertible_v<_Kp &&, const_iterator>) - _LIBCPP_HIDE_FROM_ABI size_type erase(_Kp&& __x) { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 size_type erase(_Kp&& __x) { auto [__first, __last] = equal_range(__x); auto __res = __last - __first; erase(__first, __last); return __res; } - _LIBCPP_HIDE_FROM_ABI iterator erase(const_iterator __first, const_iterator __last) { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 iterator erase(const_iterator __first, const_iterator __last) { auto __on_failure = std::__make_exception_guard([&]() noexcept { clear() /* noexcept */; }); auto __key_it = __containers_.keys.erase(__first.__key_iter_, __last.__key_iter_); auto __mapped_it = __containers_.values.erase(__first.__mapped_iter_, __last.__mapped_iter_); @@ -695,7 +738,7 @@ public: return iterator(std::move(__key_it), std::move(__mapped_it)); } - _LIBCPP_HIDE_FROM_ABI void swap(flat_map& __y) noexcept { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 void swap(flat_map& __y) noexcept { // warning: The spec has unconditional noexcept, which means that // if any of the following functions throw an exception, // std::terminate will be called. @@ -705,133 +748,156 @@ public: ranges::swap(__containers_.values, __y.__containers_.values); } - _LIBCPP_HIDE_FROM_ABI void clear() noexcept { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 void clear() noexcept { __containers_.keys.clear(); __containers_.values.clear(); } // observers - _LIBCPP_HIDE_FROM_ABI key_compare key_comp() const { return __compare_; } - _LIBCPP_HIDE_FROM_ABI value_compare value_comp() const { return value_compare(__compare_); } + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 key_compare key_comp() const { return __compare_; } + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 value_compare value_comp() const { + return value_compare(__compare_); + } - _LIBCPP_HIDE_FROM_ABI const key_container_type& keys() const noexcept { return __containers_.keys; } - _LIBCPP_HIDE_FROM_ABI const mapped_container_type& values() const noexcept { return __containers_.values; } + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 const key_container_type& keys() const noexcept { + return __containers_.keys; + } + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 const mapped_container_type& values() const noexcept { + return __containers_.values; + } // map operations - _LIBCPP_HIDE_FROM_ABI iterator find(const key_type& __x) { return __find_impl(*this, __x); } + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 iterator find(const key_type& __x) { + return __find_impl(*this, __x); + } - _LIBCPP_HIDE_FROM_ABI const_iterator find(const key_type& __x) const { return __find_impl(*this, __x); } - - template - requires __is_compare_transparent - _LIBCPP_HIDE_FROM_ABI iterator find(const _Kp& __x) { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 const_iterator find(const key_type& __x) const { return __find_impl(*this, __x); } template requires __is_compare_transparent - _LIBCPP_HIDE_FROM_ABI const_iterator find(const _Kp& __x) const { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 iterator find(const _Kp& __x) { return __find_impl(*this, __x); } - _LIBCPP_HIDE_FROM_ABI size_type count(const key_type& __x) const { return contains(__x) ? 1 : 0; } - template requires __is_compare_transparent - _LIBCPP_HIDE_FROM_ABI size_type count(const _Kp& __x) const { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 const_iterator find(const _Kp& __x) const { + return __find_impl(*this, __x); + } + + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 size_type count(const key_type& __x) const { return contains(__x) ? 1 : 0; } - _LIBCPP_HIDE_FROM_ABI bool contains(const key_type& __x) const { return find(__x) != end(); } - template requires __is_compare_transparent - _LIBCPP_HIDE_FROM_ABI bool contains(const _Kp& __x) const { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 size_type count(const _Kp& __x) const { + return contains(__x) ? 1 : 0; + } + + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 bool contains(const key_type& __x) const { return find(__x) != end(); } - _LIBCPP_HIDE_FROM_ABI iterator lower_bound(const key_type& __x) { return __lower_bound(*this, __x); } + template + requires __is_compare_transparent + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 bool contains(const _Kp& __x) const { + return find(__x) != end(); + } - _LIBCPP_HIDE_FROM_ABI const_iterator lower_bound(const key_type& __x) const { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 iterator lower_bound(const key_type& __x) { + return __lower_bound(*this, __x); + } + + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 const_iterator lower_bound(const key_type& __x) const { return __lower_bound(*this, __x); } template requires __is_compare_transparent - _LIBCPP_HIDE_FROM_ABI iterator lower_bound(const _Kp& __x) { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 iterator lower_bound(const _Kp& __x) { return __lower_bound(*this, __x); } template requires __is_compare_transparent - _LIBCPP_HIDE_FROM_ABI const_iterator lower_bound(const _Kp& __x) const { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 const_iterator lower_bound(const _Kp& __x) const { return __lower_bound(*this, __x); } - _LIBCPP_HIDE_FROM_ABI iterator upper_bound(const key_type& __x) { return __upper_bound(*this, __x); } + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 iterator upper_bound(const key_type& __x) { + return __upper_bound(*this, __x); + } - _LIBCPP_HIDE_FROM_ABI const_iterator upper_bound(const key_type& __x) const { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 const_iterator upper_bound(const key_type& __x) const { return __upper_bound(*this, __x); } template requires __is_compare_transparent - _LIBCPP_HIDE_FROM_ABI iterator upper_bound(const _Kp& __x) { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 iterator upper_bound(const _Kp& __x) { return __upper_bound(*this, __x); } template requires __is_compare_transparent - _LIBCPP_HIDE_FROM_ABI const_iterator upper_bound(const _Kp& __x) const { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 const_iterator upper_bound(const _Kp& __x) const { return __upper_bound(*this, __x); } - _LIBCPP_HIDE_FROM_ABI pair equal_range(const key_type& __x) { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 pair equal_range(const key_type& __x) { return __equal_range_impl(*this, __x); } - _LIBCPP_HIDE_FROM_ABI pair equal_range(const key_type& __x) const { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 pair + equal_range(const key_type& __x) const { return __equal_range_impl(*this, __x); } template requires __is_compare_transparent - _LIBCPP_HIDE_FROM_ABI pair equal_range(const _Kp& __x) { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 pair equal_range(const _Kp& __x) { return __equal_range_impl(*this, __x); } template requires __is_compare_transparent - _LIBCPP_HIDE_FROM_ABI pair equal_range(const _Kp& __x) const { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 pair + equal_range(const _Kp& __x) const { return __equal_range_impl(*this, __x); } - friend _LIBCPP_HIDE_FROM_ABI bool operator==(const flat_map& __x, const flat_map& __y) { + friend _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 bool operator==(const flat_map& __x, const flat_map& __y) { return ranges::equal(__x, __y); } - friend _LIBCPP_HIDE_FROM_ABI auto operator<=>(const flat_map& __x, const flat_map& __y) { + friend _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 auto + operator<=>(const flat_map& __x, const flat_map& __y) { return std::lexicographical_compare_three_way( __x.begin(), __x.end(), __y.begin(), __y.end(), std::__synth_three_way); } - friend _LIBCPP_HIDE_FROM_ABI void swap(flat_map& __x, flat_map& __y) noexcept { __x.swap(__y); } + friend _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 void swap(flat_map& __x, flat_map& __y) noexcept { + __x.swap(__y); + } private: struct __ctor_uses_allocator_tag { - explicit _LIBCPP_HIDE_FROM_ABI __ctor_uses_allocator_tag() = default; + explicit _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 __ctor_uses_allocator_tag() = default; }; struct __ctor_uses_allocator_empty_tag { - explicit _LIBCPP_HIDE_FROM_ABI __ctor_uses_allocator_empty_tag() = default; + explicit _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 __ctor_uses_allocator_empty_tag() = default; }; template requires __allocator_ctor_constraint<_Allocator> - _LIBCPP_HIDE_FROM_ABI - flat_map(__ctor_uses_allocator_tag, - const _Allocator& __alloc, - _KeyCont&& __key_cont, - _MappedCont&& __mapped_cont, - _CompArg&&... __comp) + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 flat_map( + __ctor_uses_allocator_tag, + const _Allocator& __alloc, + _KeyCont&& __key_cont, + _MappedCont&& __mapped_cont, + _CompArg&&... __comp) : __containers_{.keys = std::make_obj_using_allocator( __alloc, std::forward<_KeyCont>(__key_cont)), .values = std::make_obj_using_allocator( @@ -840,12 +906,13 @@ private: template requires __allocator_ctor_constraint<_Allocator> - _LIBCPP_HIDE_FROM_ABI flat_map(__ctor_uses_allocator_empty_tag, const _Allocator& __alloc, _CompArg&&... __comp) + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 + flat_map(__ctor_uses_allocator_empty_tag, const _Allocator& __alloc, _CompArg&&... __comp) : __containers_{.keys = std::make_obj_using_allocator(__alloc), .values = std::make_obj_using_allocator(__alloc)}, __compare_(std::forward<_CompArg>(__comp)...) {} - _LIBCPP_HIDE_FROM_ABI bool __is_sorted_and_unique(auto&& __key_container) const { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 bool __is_sorted_and_unique(auto&& __key_container) const { auto __greater_or_equal_to = [this](const auto& __x, const auto& __y) { return !__compare_(__x, __y); }; return ranges::adjacent_find(__key_container, __greater_or_equal_to) == ranges::end(__key_container); } @@ -853,7 +920,7 @@ private: // This function is only used in constructors. So there is not exception handling in this function. // If the function exits via an exception, there will be no flat_map object constructed, thus, there // is no invariant state to preserve - _LIBCPP_HIDE_FROM_ABI void __sort_and_unique() { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 void __sort_and_unique() { auto __zv = ranges::views::zip(__containers_.keys, __containers_.values); ranges::sort(__zv, __compare_, [](const auto& __p) -> decltype(auto) { return std::get<0>(__p); }); auto __dup_start = ranges::unique(__zv, __key_equiv(__compare_)).begin(); @@ -862,8 +929,17 @@ private: __containers_.values.erase(__containers_.values.begin() + __dist, __containers_.values.end()); } + template + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 static auto + __corresponding_mapped_it(_Self&& __self, _KeyIter&& __key_iter) { + return __self.__containers_.values.begin() + + static_cast>( + ranges::distance(__self.__containers_.keys.begin(), __key_iter)); + } + template - _LIBCPP_HIDE_FROM_ABI void __append_sort_merge_unique(_InputIterator __first, _Sentinel __last) { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 void + __append_sort_merge_unique(_InputIterator __first, _Sentinel __last) { auto __on_failure = std::__make_exception_guard([&]() noexcept { clear() /* noexcept */; }); size_t __num_of_appended = __flat_map_utils::__append(*this, std::move(__first), std::move(__last)); if (__num_of_appended != 0) { @@ -891,7 +967,7 @@ private: } template - _LIBCPP_HIDE_FROM_ABI static auto __find_impl(_Self&& __self, const _Kp& __key) { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 static auto __find_impl(_Self&& __self, const _Kp& __key) { auto __it = __self.lower_bound(__key); auto __last = __self.end(); if (__it == __last || __self.__compare_(__key, __it->first)) { @@ -901,8 +977,9 @@ private: } template - _LIBCPP_HIDE_FROM_ABI static auto __key_equal_range(_Self&& __self, const _Kp& __key) { - auto __it = ranges::lower_bound(__self.__containers_.keys, __key, __self.__compare_); + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 static auto __key_equal_range(_Self&& __self, const _Kp& __key) { + auto __it = + std::lower_bound(__self.__containers_.keys.begin(), __self.__containers_.keys.end(), __key, __self.__compare_); auto __last = __self.__containers_.keys.end(); if (__it == __last || __self.__compare_(__key, *__it)) { return std::make_pair(__it, __it); @@ -911,44 +988,33 @@ private: } template - _LIBCPP_HIDE_FROM_ABI static auto __equal_range_impl(_Self&& __self, const _Kp& __key) { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 static auto __equal_range_impl(_Self&& __self, const _Kp& __key) { auto [__key_first, __key_last] = __key_equal_range(__self, __key); - - const auto __make_mapped_iter = [&](const auto& __key_iter) { - return __self.__containers_.values.begin() + - static_cast>( - ranges::distance(__self.__containers_.keys.begin(), __key_iter)); - }; - - using __iterator_type = ranges::iterator_t; - return std::make_pair(__iterator_type(__key_first, __make_mapped_iter(__key_first)), - __iterator_type(__key_last, __make_mapped_iter(__key_last))); + using __iterator_type = ranges::iterator_t; + return std::make_pair(__iterator_type(__key_first, __corresponding_mapped_it(__self, __key_first)), + __iterator_type(__key_last, __corresponding_mapped_it(__self, __key_last))); } template - _LIBCPP_HIDE_FROM_ABI static _Res __lower_bound(_Self&& __self, _Kp& __x) { - return __binary_search<_Res>(__self, ranges::lower_bound, __x); + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 static _Res __lower_bound(_Self&& __self, _Kp& __x) { + auto __key_iter = + std::lower_bound(__self.__containers_.keys.begin(), __self.__containers_.keys.end(), __x, __self.__compare_); + auto __mapped_iter = __corresponding_mapped_it(__self, __key_iter); + return _Res(std::move(__key_iter), std::move(__mapped_iter)); } template - _LIBCPP_HIDE_FROM_ABI static _Res __upper_bound(_Self&& __self, _Kp& __x) { - return __binary_search<_Res>(__self, ranges::upper_bound, __x); - } - - template - _LIBCPP_HIDE_FROM_ABI static _Res __binary_search(_Self&& __self, _Fn __search_fn, _Kp& __x) { - auto __key_iter = __search_fn(__self.__containers_.keys, __x, __self.__compare_); - auto __mapped_iter = - __self.__containers_.values.begin() + - static_cast>( - ranges::distance(__self.__containers_.keys.begin(), __key_iter)); - + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 static _Res __upper_bound(_Self&& __self, _Kp& __x) { + auto __key_iter = + std::upper_bound(__self.__containers_.keys.begin(), __self.__containers_.keys.end(), __x, __self.__compare_); + auto __mapped_iter = __corresponding_mapped_it(__self, __key_iter); return _Res(std::move(__key_iter), std::move(__mapped_iter)); } template - _LIBCPP_HIDE_FROM_ABI pair __try_emplace(_KeyArg&& __key, _MArgs&&... __mapped_args) { - auto __key_it = ranges::lower_bound(__containers_.keys, __key, __compare_); + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 pair + __try_emplace(_KeyArg&& __key, _MArgs&&... __mapped_args) { + auto __key_it = std::lower_bound(__containers_.keys.begin(), __containers_.keys.end(), __key, __compare_); auto __mapped_it = __containers_.values.begin() + ranges::distance(__containers_.keys.begin(), __key_it); if (__key_it == __containers_.keys.end() || __compare_(__key, *__key_it)) { @@ -966,7 +1032,7 @@ private: } template - _LIBCPP_HIDE_FROM_ABI bool __is_hint_correct(const_iterator __hint, _Kp&& __key) { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 bool __is_hint_correct(const_iterator __hint, _Kp&& __key) { if (__hint != cbegin() && !__compare_((__hint - 1)->first, __key)) { return false; } @@ -977,7 +1043,8 @@ private: } template - _LIBCPP_HIDE_FROM_ABI pair __try_emplace_hint(const_iterator __hint, _Kp&& __key, _Args&&... __args) { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 pair + __try_emplace_hint(const_iterator __hint, _Kp&& __key, _Args&&... __args) { if (__is_hint_correct(__hint, __key)) { if (__hint == cend() || __compare_(__key, __hint->first)) { return {__flat_map_utils::__emplace_exact_pos( @@ -998,7 +1065,8 @@ private: } template - _LIBCPP_HIDE_FROM_ABI pair __insert_or_assign(_Kp&& __key, _Mapped&& __mapped) { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 pair + __insert_or_assign(_Kp&& __key, _Mapped&& __mapped) { auto __r = try_emplace(std::forward<_Kp>(__key), std::forward<_Mapped>(__mapped)); if (!__r.second) { __r.first->second = std::forward<_Mapped>(__mapped); @@ -1007,7 +1075,8 @@ private: } template - _LIBCPP_HIDE_FROM_ABI iterator __insert_or_assign(const_iterator __hint, _Kp&& __key, _Mapped&& __mapped) { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 iterator + __insert_or_assign(const_iterator __hint, _Kp&& __key, _Mapped&& __mapped) { auto __r = __try_emplace_hint(__hint, std::forward<_Kp>(__key), std::forward<_Mapped>(__mapped)); if (!__r.second) { __r.first->second = std::forward<_Mapped>(__mapped); @@ -1015,18 +1084,19 @@ private: return __r.first; } - _LIBCPP_HIDE_FROM_ABI void __reserve(size_t __size) { - if constexpr (requires { __containers_.keys.reserve(__size); }) { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 void __reserve(size_t __size) { + if constexpr (__container_traits<_KeyContainer>::__reservable) { __containers_.keys.reserve(__size); } - if constexpr (requires { __containers_.values.reserve(__size); }) { + if constexpr (__container_traits<_MappedContainer>::__reservable) { __containers_.values.reserve(__size); } } template - _LIBCPP_HIDE_FROM_ABI iterator __erase(_KIter __key_iter_to_remove, _MIter __mapped_iter_to_remove) { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 iterator + __erase(_KIter __key_iter_to_remove, _MIter __mapped_iter_to_remove) { auto __on_failure = std::__make_exception_guard([&]() noexcept { clear() /* noexcept */; }); auto __key_iter = __containers_.keys.erase(__key_iter_to_remove); auto __mapped_iter = __containers_.values.erase(__mapped_iter_to_remove); @@ -1036,7 +1106,8 @@ private: template friend typename flat_map<_Key2, _Tp2, _Compare2, _KeyContainer2, _MappedContainer2>::size_type - erase_if(flat_map<_Key2, _Tp2, _Compare2, _KeyContainer2, _MappedContainer2>&, _Predicate); + _LIBCPP_CONSTEXPR_SINCE_CXX26 + erase_if(flat_map<_Key2, _Tp2, _Compare2, _KeyContainer2, _MappedContainer2>&, _Predicate); friend __flat_map_utils; @@ -1044,8 +1115,9 @@ private: _LIBCPP_NO_UNIQUE_ADDRESS key_compare __compare_; struct __key_equiv { - _LIBCPP_HIDE_FROM_ABI __key_equiv(key_compare __c) : __comp_(__c) {} - _LIBCPP_HIDE_FROM_ABI bool operator()(const_reference __x, const_reference __y) const { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 __key_equiv(key_compare __c) : __comp_(__c) {} + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 bool + operator()(const_reference __x, const_reference __y) const { return !__comp_(std::get<0>(__x), std::get<0>(__y)) && !__comp_(std::get<0>(__y), std::get<0>(__x)); } key_compare __comp_; @@ -1168,8 +1240,9 @@ struct uses_allocator && uses_allocator_v<_MappedContainer, _Allocator>> {}; template -_LIBCPP_HIDE_FROM_ABI typename flat_map<_Key, _Tp, _Compare, _KeyContainer, _MappedContainer>::size_type -erase_if(flat_map<_Key, _Tp, _Compare, _KeyContainer, _MappedContainer>& __flat_map, _Predicate __pred) { +_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 + typename flat_map<_Key, _Tp, _Compare, _KeyContainer, _MappedContainer>::size_type + erase_if(flat_map<_Key, _Tp, _Compare, _KeyContainer, _MappedContainer>& __flat_map, _Predicate __pred) { auto __zv = ranges::views::zip(__flat_map.__containers_.keys, __flat_map.__containers_.values); auto __first = __zv.begin(); auto __last = __zv.end(); diff --git a/lib/libcxx/include/__flat_map/flat_multimap.h b/lib/libcxx/include/__flat_map/flat_multimap.h index 15fcd7995a..0af6aac00c 100644 --- a/lib/libcxx/include/__flat_map/flat_multimap.h +++ b/lib/libcxx/include/__flat_map/flat_multimap.h @@ -10,18 +10,16 @@ #ifndef _LIBCPP___FLAT_MAP_FLAT_MULTIMAP_H #define _LIBCPP___FLAT_MAP_FLAT_MULTIMAP_H +#include <__algorithm/equal_range.h> #include <__algorithm/lexicographical_compare_three_way.h> +#include <__algorithm/lower_bound.h> #include <__algorithm/min.h> #include <__algorithm/ranges_equal.h> -#include <__algorithm/ranges_equal_range.h> #include <__algorithm/ranges_inplace_merge.h> #include <__algorithm/ranges_is_sorted.h> -#include <__algorithm/ranges_lower_bound.h> -#include <__algorithm/ranges_partition_point.h> #include <__algorithm/ranges_sort.h> -#include <__algorithm/ranges_unique.h> -#include <__algorithm/ranges_upper_bound.h> #include <__algorithm/remove_if.h> +#include <__algorithm/upper_bound.h> #include <__assert> #include <__compare/synth_three_way.h> #include <__concepts/convertible_to.h> @@ -443,7 +441,7 @@ public: is_move_constructible_v _LIBCPP_HIDE_FROM_ABI iterator emplace(_Args&&... __args) { std::pair __pair(std::forward<_Args>(__args)...); - auto __key_it = ranges::upper_bound(__containers_.keys, __pair.first, __compare_); + auto __key_it = std::upper_bound(__containers_.keys.begin(), __containers_.keys.end(), __pair.first, __compare_); auto __mapped_it = __corresponding_mapped_it(*this, __key_it); return __flat_map_utils::__emplace_exact_pos( @@ -473,7 +471,7 @@ public: // | // hint // We want to insert "2" after the last existing "2" - __key_iter = ranges::upper_bound(__containers_.keys.begin(), __key_iter, __pair.first, __compare_); + __key_iter = std::upper_bound(__containers_.keys.begin(), __key_iter, __pair.first, __compare_); __mapped_iter = __corresponding_mapped_it(*this, __key_iter); } else { _LIBCPP_ASSERT_INTERNAL(!__prev_larger && __next_smaller, "this means that the multimap is not sorted"); @@ -485,7 +483,7 @@ public: // | // hint // We want to insert "2" before the first existing "2" - __key_iter = ranges::lower_bound(__key_iter, __containers_.keys.end(), __pair.first, __compare_); + __key_iter = std::lower_bound(__key_iter, __containers_.keys.end(), __pair.first, __compare_); __mapped_iter = __corresponding_mapped_it(*this, __key_iter); } return __flat_map_utils::__emplace_exact_pos( @@ -804,7 +802,8 @@ private: template _LIBCPP_HIDE_FROM_ABI static auto __equal_range_impl(_Self&& __self, const _Kp& __key) { - auto [__key_first, __key_last] = ranges::equal_range(__self.__containers_.keys, __key, __self.__compare_); + auto [__key_first, __key_last] = + std::equal_range(__self.__containers_.keys.begin(), __self.__containers_.keys.end(), __key, __self.__compare_); using __iterator_type = ranges::iterator_t; return std::make_pair(__iterator_type(__key_first, __corresponding_mapped_it(__self, __key_first)), @@ -813,24 +812,26 @@ private: template _LIBCPP_HIDE_FROM_ABI static _Res __lower_bound(_Self&& __self, _Kp& __x) { - auto __key_iter = ranges::lower_bound(__self.__containers_.keys, __x, __self.__compare_); + auto __key_iter = + std::lower_bound(__self.__containers_.keys.begin(), __self.__containers_.keys.end(), __x, __self.__compare_); auto __mapped_iter = __corresponding_mapped_it(__self, __key_iter); return _Res(std::move(__key_iter), std::move(__mapped_iter)); } template _LIBCPP_HIDE_FROM_ABI static _Res __upper_bound(_Self&& __self, _Kp& __x) { - auto __key_iter = ranges::upper_bound(__self.__containers_.keys, __x, __self.__compare_); + auto __key_iter = + std::upper_bound(__self.__containers_.keys.begin(), __self.__containers_.keys.end(), __x, __self.__compare_); auto __mapped_iter = __corresponding_mapped_it(__self, __key_iter); return _Res(std::move(__key_iter), std::move(__mapped_iter)); } _LIBCPP_HIDE_FROM_ABI void __reserve(size_t __size) { - if constexpr (requires { __containers_.keys.reserve(__size); }) { + if constexpr (__container_traits<_KeyContainer>::__reservable) { __containers_.keys.reserve(__size); } - if constexpr (requires { __containers_.values.reserve(__size); }) { + if constexpr (__container_traits<_MappedContainer>::__reservable) { __containers_.values.reserve(__size); } } diff --git a/lib/libcxx/include/__flat_map/key_value_iterator.h b/lib/libcxx/include/__flat_map/key_value_iterator.h index 3ebb653deb..d04a23d1f8 100644 --- a/lib/libcxx/include/__flat_map/key_value_iterator.h +++ b/lib/libcxx/include/__flat_map/key_value_iterator.h @@ -13,9 +13,12 @@ #include <__compare/three_way_comparable.h> #include <__concepts/convertible_to.h> #include <__config> +#include <__cstddef/size_t.h> #include <__iterator/iterator_traits.h> +#include <__iterator/product_iterator.h> #include <__memory/addressof.h> #include <__type_traits/conditional.h> +#include <__utility/forward.h> #include <__utility/move.h> #include <__utility/pair.h> @@ -46,7 +49,7 @@ private: struct __arrow_proxy { __reference __ref_; - _LIBCPP_HIDE_FROM_ABI __reference* operator->() { return std::addressof(__ref_); } + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 __reference* operator->() { return std::addressof(__ref_); } }; __key_iterator __key_iter_; @@ -57,6 +60,8 @@ private: template friend struct __key_value_iterator; + friend struct __product_iterator_traits<__key_value_iterator>; + public: using iterator_concept = random_access_iterator_tag; // `__key_value_iterator` only satisfy "Cpp17InputIterator" named requirements, because @@ -69,104 +74,141 @@ public: _LIBCPP_HIDE_FROM_ABI __key_value_iterator() = default; - _LIBCPP_HIDE_FROM_ABI __key_value_iterator(__key_value_iterator<_Owner, _KeyContainer, _MappedContainer, !_Const> __i) + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 + __key_value_iterator(__key_value_iterator<_Owner, _KeyContainer, _MappedContainer, !_Const> __i) requires _Const && convertible_to && convertible_to : __key_iter_(std::move(__i.__key_iter_)), __mapped_iter_(std::move(__i.__mapped_iter_)) {} - _LIBCPP_HIDE_FROM_ABI __key_value_iterator(__key_iterator __key_iter, __mapped_iterator __mapped_iter) + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 + __key_value_iterator(__key_iterator __key_iter, __mapped_iterator __mapped_iter) : __key_iter_(std::move(__key_iter)), __mapped_iter_(std::move(__mapped_iter)) {} - _LIBCPP_HIDE_FROM_ABI __reference operator*() const { return __reference(*__key_iter_, *__mapped_iter_); } - _LIBCPP_HIDE_FROM_ABI __arrow_proxy operator->() const { return __arrow_proxy{**this}; } + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 __reference operator*() const { + return __reference(*__key_iter_, *__mapped_iter_); + } + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 __arrow_proxy operator->() const { return __arrow_proxy{**this}; } - _LIBCPP_HIDE_FROM_ABI __key_value_iterator& operator++() { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 __key_value_iterator& operator++() { ++__key_iter_; ++__mapped_iter_; return *this; } - _LIBCPP_HIDE_FROM_ABI __key_value_iterator operator++(int) { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 __key_value_iterator operator++(int) { __key_value_iterator __tmp(*this); ++*this; return __tmp; } - _LIBCPP_HIDE_FROM_ABI __key_value_iterator& operator--() { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 __key_value_iterator& operator--() { --__key_iter_; --__mapped_iter_; return *this; } - _LIBCPP_HIDE_FROM_ABI __key_value_iterator operator--(int) { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 __key_value_iterator operator--(int) { __key_value_iterator __tmp(*this); --*this; return __tmp; } - _LIBCPP_HIDE_FROM_ABI __key_value_iterator& operator+=(difference_type __x) { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 __key_value_iterator& operator+=(difference_type __x) { __key_iter_ += __x; __mapped_iter_ += __x; return *this; } - _LIBCPP_HIDE_FROM_ABI __key_value_iterator& operator-=(difference_type __x) { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 __key_value_iterator& operator-=(difference_type __x) { __key_iter_ -= __x; __mapped_iter_ -= __x; return *this; } - _LIBCPP_HIDE_FROM_ABI __reference operator[](difference_type __n) const { return *(*this + __n); } + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 __reference operator[](difference_type __n) const { + return *(*this + __n); + } - _LIBCPP_HIDE_FROM_ABI friend constexpr bool + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 friend bool operator==(const __key_value_iterator& __x, const __key_value_iterator& __y) { return __x.__key_iter_ == __y.__key_iter_; } - _LIBCPP_HIDE_FROM_ABI friend bool operator<(const __key_value_iterator& __x, const __key_value_iterator& __y) { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 friend bool + operator<(const __key_value_iterator& __x, const __key_value_iterator& __y) { return __x.__key_iter_ < __y.__key_iter_; } - _LIBCPP_HIDE_FROM_ABI friend bool operator>(const __key_value_iterator& __x, const __key_value_iterator& __y) { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 friend bool + operator>(const __key_value_iterator& __x, const __key_value_iterator& __y) { return __y < __x; } - _LIBCPP_HIDE_FROM_ABI friend bool operator<=(const __key_value_iterator& __x, const __key_value_iterator& __y) { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 friend bool + operator<=(const __key_value_iterator& __x, const __key_value_iterator& __y) { return !(__y < __x); } - _LIBCPP_HIDE_FROM_ABI friend bool operator>=(const __key_value_iterator& __x, const __key_value_iterator& __y) { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 friend bool + operator>=(const __key_value_iterator& __x, const __key_value_iterator& __y) { return !(__x < __y); } - _LIBCPP_HIDE_FROM_ABI friend auto operator<=>(const __key_value_iterator& __x, const __key_value_iterator& __y) + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 friend auto + operator<=>(const __key_value_iterator& __x, const __key_value_iterator& __y) requires three_way_comparable<__key_iterator> { return __x.__key_iter_ <=> __y.__key_iter_; } - _LIBCPP_HIDE_FROM_ABI friend __key_value_iterator operator+(const __key_value_iterator& __i, difference_type __n) { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 friend __key_value_iterator + operator+(const __key_value_iterator& __i, difference_type __n) { auto __tmp = __i; __tmp += __n; return __tmp; } - _LIBCPP_HIDE_FROM_ABI friend __key_value_iterator operator+(difference_type __n, const __key_value_iterator& __i) { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 friend __key_value_iterator + operator+(difference_type __n, const __key_value_iterator& __i) { return __i + __n; } - _LIBCPP_HIDE_FROM_ABI friend __key_value_iterator operator-(const __key_value_iterator& __i, difference_type __n) { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 friend __key_value_iterator + operator-(const __key_value_iterator& __i, difference_type __n) { auto __tmp = __i; __tmp -= __n; return __tmp; } - _LIBCPP_HIDE_FROM_ABI friend difference_type + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 friend difference_type operator-(const __key_value_iterator& __x, const __key_value_iterator& __y) { return difference_type(__x.__key_iter_ - __y.__key_iter_); } }; +template +struct __product_iterator_traits<__key_value_iterator<_Owner, _KeyContainer, _MappedContainer, _Const>> { + static constexpr size_t __size = 2; + + template + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 static decltype(auto) __get_iterator_element(_Iter&& __it) + requires(_Nth <= 1) + { + if constexpr (_Nth == 0) { + return std::forward<_Iter>(__it).__key_iter_; + } else { + return std::forward<_Iter>(__it).__mapped_iter_; + } + } + + template + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 static auto + __make_product_iterator(_KeyIter&& __key_iter, _MappedIter&& __mapped_iter) { + return __key_value_iterator<_Owner, _KeyContainer, _MappedContainer, _Const>( + std::forward<_KeyIter>(__key_iter), std::forward<_MappedIter>(__mapped_iter)); + } +}; + _LIBCPP_END_NAMESPACE_STD #endif // _LIBCPP_STD_VER >= 23 diff --git a/lib/libcxx/include/__flat_map/utils.h b/lib/libcxx/include/__flat_map/utils.h index acb7dca7ff..3a05c71566 100644 --- a/lib/libcxx/include/__flat_map/utils.h +++ b/lib/libcxx/include/__flat_map/utils.h @@ -11,6 +11,7 @@ #define _LIBCPP___FLAT_MAP_UTILS_H #include <__config> +#include <__iterator/product_iterator.h> #include <__type_traits/container_traits.h> #include <__utility/exception_guard.h> #include <__utility/forward.h> @@ -35,7 +36,7 @@ struct __flat_map_utils { // roll back the changes it made to the map. If it cannot roll back the changes, it will // clear the map. template - _LIBCPP_HIDE_FROM_ABI static typename _Map::iterator __emplace_exact_pos( + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 static typename _Map::iterator __emplace_exact_pos( _Map& __map, _IterK&& __it_key, _IterM&& __it_mapped, _KeyArg&& __key, _MArgs&&... __mapped_args) { auto __on_key_failed = std::__make_exception_guard([&]() noexcept { using _KeyContainer = typename _Map::key_container_type; @@ -79,10 +80,8 @@ struct __flat_map_utils { return typename _Map::iterator(std::move(__key_it), std::move(__mapped_it)); } - // TODO: We could optimize this, see - // https://github.com/llvm/llvm-project/issues/108624 template - _LIBCPP_HIDE_FROM_ABI static typename _Map::size_type + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 static typename _Map::size_type __append(_Map& __map, _InputIterator __first, _Sentinel __last) { typename _Map::size_type __num_appended = 0; for (; __first != __last; ++__first) { @@ -93,6 +92,25 @@ struct __flat_map_utils { } return __num_appended; } + + template + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 static typename _Map::size_type + __append(_Map& __map, _InputIterator __first, _InputIterator __last) + requires __is_product_iterator_of_size<_InputIterator, 2>::value + { + auto __s1 = __map.__containers_.keys.size(); + __map.__containers_.keys.insert( + __map.__containers_.keys.end(), + __product_iterator_traits<_InputIterator>::template __get_iterator_element<0>(__first), + __product_iterator_traits<_InputIterator>::template __get_iterator_element<0>(__last)); + + __map.__containers_.values.insert( + __map.__containers_.values.end(), + __product_iterator_traits<_InputIterator>::template __get_iterator_element<1>(__first), + __product_iterator_traits<_InputIterator>::template __get_iterator_element<1>(__last)); + + return __map.__containers_.keys.size() - __s1; + } }; _LIBCPP_END_NAMESPACE_STD diff --git a/lib/libcxx/include/__flat_set/flat_multiset.h b/lib/libcxx/include/__flat_set/flat_multiset.h new file mode 100644 index 0000000000..44d8af05a5 --- /dev/null +++ b/lib/libcxx/include/__flat_set/flat_multiset.h @@ -0,0 +1,792 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___FLAT_MAP_FLAT_MULTISET_H +#define _LIBCPP___FLAT_MAP_FLAT_MULTISET_H + +#include <__algorithm/equal_range.h> +#include <__algorithm/lexicographical_compare_three_way.h> +#include <__algorithm/lower_bound.h> +#include <__algorithm/min.h> +#include <__algorithm/ranges_equal.h> +#include <__algorithm/ranges_inplace_merge.h> +#include <__algorithm/ranges_is_sorted.h> +#include <__algorithm/ranges_sort.h> +#include <__algorithm/ranges_unique.h> +#include <__algorithm/remove_if.h> +#include <__algorithm/upper_bound.h> +#include <__assert> +#include <__compare/synth_three_way.h> +#include <__concepts/convertible_to.h> +#include <__concepts/swappable.h> +#include <__config> +#include <__cstddef/byte.h> +#include <__cstddef/ptrdiff_t.h> +#include <__flat_map/key_value_iterator.h> +#include <__flat_map/sorted_equivalent.h> +#include <__flat_set/ra_iterator.h> +#include <__flat_set/utils.h> +#include <__functional/invoke.h> +#include <__functional/is_transparent.h> +#include <__functional/operations.h> +#include <__fwd/vector.h> +#include <__iterator/concepts.h> +#include <__iterator/distance.h> +#include <__iterator/iterator_traits.h> +#include <__iterator/prev.h> +#include <__iterator/ranges_iterator_traits.h> +#include <__iterator/reverse_iterator.h> +#include <__memory/allocator_traits.h> +#include <__memory/uses_allocator.h> +#include <__memory/uses_allocator_construction.h> +#include <__ranges/access.h> +#include <__ranges/concepts.h> +#include <__ranges/container_compatible_range.h> +#include <__ranges/drop_view.h> +#include <__ranges/from_range.h> +#include <__ranges/ref_view.h> +#include <__ranges/size.h> +#include <__ranges/subrange.h> +#include <__ranges/zip_view.h> +#include <__type_traits/conjunction.h> +#include <__type_traits/container_traits.h> +#include <__type_traits/invoke.h> +#include <__type_traits/is_allocator.h> +#include <__type_traits/is_nothrow_constructible.h> +#include <__type_traits/is_same.h> +#include <__type_traits/maybe_const.h> +#include <__utility/as_const.h> +#include <__utility/exception_guard.h> +#include <__utility/move.h> +#include <__utility/pair.h> +#include <__utility/scope_guard.h> +#include <__vector/vector.h> +#include + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_PUSH_MACROS +#include <__undef_macros> + +#if _LIBCPP_STD_VER >= 23 + +_LIBCPP_BEGIN_NAMESPACE_STD + +template , class _KeyContainer = vector<_Key>> +class flat_multiset { + template + friend class flat_multiset; + + friend __flat_set_utils; + + static_assert(is_same_v<_Key, typename _KeyContainer::value_type>); + static_assert(!is_same_v<_KeyContainer, std::vector>, "vector is not a sequence container"); + +public: + // types + using key_type = _Key; + using value_type = _Key; + using key_compare = __type_identity_t<_Compare>; + using value_compare = _Compare; + using reference = value_type&; + using const_reference = const value_type&; + using size_type = typename _KeyContainer::size_type; + using difference_type = typename _KeyContainer::difference_type; + using iterator = __ra_iterator; + using const_iterator = iterator; + using reverse_iterator = std::reverse_iterator; + using const_reverse_iterator = std::reverse_iterator; + using container_type = _KeyContainer; + +public: + // [flat.multiset.cons], constructors + _LIBCPP_HIDE_FROM_ABI flat_multiset() noexcept(is_nothrow_default_constructible_v<_KeyContainer> && + is_nothrow_default_constructible_v<_Compare>) + : __keys_(), __compare_() {} + + _LIBCPP_HIDE_FROM_ABI flat_multiset(const flat_multiset&) = default; + + // The copy/move constructors are not specified in the spec, which means they should be defaulted. + // However, the move constructor can potentially leave a moved-from object in an inconsistent + // state if an exception is thrown. + _LIBCPP_HIDE_FROM_ABI flat_multiset(flat_multiset&& __other) noexcept( + is_nothrow_move_constructible_v<_KeyContainer> && is_nothrow_move_constructible_v<_Compare>) +# if _LIBCPP_HAS_EXCEPTIONS + try +# endif // _LIBCPP_HAS_EXCEPTIONS + : __keys_(std::move(__other.__keys_)), __compare_(std::move(__other.__compare_)) { + __other.clear(); +# if _LIBCPP_HAS_EXCEPTIONS + } catch (...) { + __other.clear(); + // gcc does not like the `throw` keyword in a conditionally noexcept function + if constexpr (!(is_nothrow_move_constructible_v<_KeyContainer> && is_nothrow_move_constructible_v<_Compare>)) { + throw; + } +# endif // _LIBCPP_HAS_EXCEPTIONS + } + + _LIBCPP_HIDE_FROM_ABI explicit flat_multiset(const key_compare& __comp) : __keys_(), __compare_(__comp) {} + + _LIBCPP_HIDE_FROM_ABI explicit flat_multiset(container_type __keys, const key_compare& __comp = key_compare()) + : __keys_(std::move(__keys)), __compare_(__comp) { + ranges::sort(__keys_, __compare_); + } + + _LIBCPP_HIDE_FROM_ABI + flat_multiset(sorted_equivalent_t, container_type __keys, const key_compare& __comp = key_compare()) + : __keys_(std::move(__keys)), __compare_(__comp) { + _LIBCPP_ASSERT_SEMANTIC_REQUIREMENT(ranges::is_sorted(__keys_, __compare_), "Key container is not sorted"); + } + + template + requires __has_input_iterator_category<_InputIterator>::value + _LIBCPP_HIDE_FROM_ABI + flat_multiset(_InputIterator __first, _InputIterator __last, const key_compare& __comp = key_compare()) + : __keys_(), __compare_(__comp) { + insert(__first, __last); + } + + template + requires __has_input_iterator_category<_InputIterator>::value + _LIBCPP_HIDE_FROM_ABI flat_multiset( + sorted_equivalent_t, _InputIterator __first, _InputIterator __last, const key_compare& __comp = key_compare()) + : __keys_(__first, __last), __compare_(__comp) { + _LIBCPP_ASSERT_SEMANTIC_REQUIREMENT(ranges::is_sorted(__keys_, __compare_), "Key container is not sorted"); + } + + template <_ContainerCompatibleRange _Range> + _LIBCPP_HIDE_FROM_ABI flat_multiset(from_range_t __fr, _Range&& __rg) + : flat_multiset(__fr, std::forward<_Range>(__rg), key_compare()) {} + + template <_ContainerCompatibleRange _Range> + _LIBCPP_HIDE_FROM_ABI flat_multiset(from_range_t, _Range&& __rg, const key_compare& __comp) : flat_multiset(__comp) { + insert_range(std::forward<_Range>(__rg)); + } + + _LIBCPP_HIDE_FROM_ABI flat_multiset(initializer_list __il, const key_compare& __comp = key_compare()) + : flat_multiset(__il.begin(), __il.end(), __comp) {} + + _LIBCPP_HIDE_FROM_ABI + flat_multiset(sorted_equivalent_t, initializer_list __il, const key_compare& __comp = key_compare()) + : flat_multiset(sorted_equivalent, __il.begin(), __il.end(), __comp) {} + + template + requires uses_allocator::value + _LIBCPP_HIDE_FROM_ABI explicit flat_multiset(const _Allocator& __alloc) + : __keys_(std::make_obj_using_allocator(__alloc)), __compare_() {} + + template + requires uses_allocator::value + _LIBCPP_HIDE_FROM_ABI flat_multiset(const key_compare& __comp, const _Allocator& __alloc) + : __keys_(std::make_obj_using_allocator(__alloc)), __compare_(__comp) {} + + template + requires uses_allocator::value + _LIBCPP_HIDE_FROM_ABI flat_multiset(const container_type& __keys, const _Allocator& __alloc) + : __keys_(std::make_obj_using_allocator(__alloc, __keys)), __compare_() { + ranges::sort(__keys_, __compare_); + } + + template + requires uses_allocator::value + _LIBCPP_HIDE_FROM_ABI + flat_multiset(const container_type& __keys, const key_compare& __comp, const _Allocator& __alloc) + : __keys_(std::make_obj_using_allocator(__alloc, __keys)), __compare_(__comp) { + ranges::sort(__keys_, __compare_); + } + + template + requires uses_allocator::value + _LIBCPP_HIDE_FROM_ABI flat_multiset(sorted_equivalent_t, const container_type& __keys, const _Allocator& __alloc) + : __keys_(std::make_obj_using_allocator(__alloc, __keys)), __compare_() { + _LIBCPP_ASSERT_SEMANTIC_REQUIREMENT(ranges::is_sorted(__keys_, __compare_), "Key container is not sorted"); + } + + template + requires uses_allocator::value + _LIBCPP_HIDE_FROM_ABI + flat_multiset(sorted_equivalent_t, const container_type& __keys, const key_compare& __comp, const _Allocator& __alloc) + : __keys_(std::make_obj_using_allocator(__alloc, __keys)), __compare_(__comp) { + _LIBCPP_ASSERT_SEMANTIC_REQUIREMENT(ranges::is_sorted(__keys_, __compare_), "Key container is not sorted"); + } + + template + requires uses_allocator::value + _LIBCPP_HIDE_FROM_ABI flat_multiset(const flat_multiset& __other, const _Allocator& __alloc) + : __keys_(std::make_obj_using_allocator(__alloc, __other.__keys_)), + __compare_(__other.__compare_) {} + + template + requires uses_allocator::value + _LIBCPP_HIDE_FROM_ABI flat_multiset(flat_multiset&& __other, const _Allocator& __alloc) +# if _LIBCPP_HAS_EXCEPTIONS + try +# endif // _LIBCPP_HAS_EXCEPTIONS + : __keys_(std::make_obj_using_allocator(__alloc, std::move(__other.__keys_))), + __compare_(std::move(__other.__compare_)) { + __other.clear(); +# if _LIBCPP_HAS_EXCEPTIONS + } catch (...) { + __other.clear(); + throw; +# endif // _LIBCPP_HAS_EXCEPTIONS + } + + template + requires(__has_input_iterator_category<_InputIterator>::value && uses_allocator::value) + _LIBCPP_HIDE_FROM_ABI flat_multiset(_InputIterator __first, _InputIterator __last, const _Allocator& __alloc) + : __keys_(std::make_obj_using_allocator(__alloc)), __compare_() { + insert(__first, __last); + } + + template + requires(__has_input_iterator_category<_InputIterator>::value && uses_allocator::value) + _LIBCPP_HIDE_FROM_ABI + flat_multiset(_InputIterator __first, _InputIterator __last, const key_compare& __comp, const _Allocator& __alloc) + : __keys_(std::make_obj_using_allocator(__alloc)), __compare_(__comp) { + insert(__first, __last); + } + + template + requires(__has_input_iterator_category<_InputIterator>::value && uses_allocator::value) + _LIBCPP_HIDE_FROM_ABI + flat_multiset(sorted_equivalent_t, _InputIterator __first, _InputIterator __last, const _Allocator& __alloc) + : __keys_(std::make_obj_using_allocator(__alloc, __first, __last)), __compare_() { + _LIBCPP_ASSERT_SEMANTIC_REQUIREMENT(ranges::is_sorted(__keys_, __compare_), "Key container is not sorted"); + } + + template + requires(__has_input_iterator_category<_InputIterator>::value && uses_allocator::value) + _LIBCPP_HIDE_FROM_ABI + flat_multiset(sorted_equivalent_t, + _InputIterator __first, + _InputIterator __last, + const key_compare& __comp, + const _Allocator& __alloc) + : __keys_(std::make_obj_using_allocator(__alloc, __first, __last)), __compare_(__comp) { + _LIBCPP_ASSERT_SEMANTIC_REQUIREMENT(ranges::is_sorted(__keys_, __compare_), "Key container is not sorted"); + } + + template <_ContainerCompatibleRange _Range, class _Allocator> + requires uses_allocator::value + _LIBCPP_HIDE_FROM_ABI flat_multiset(from_range_t, _Range&& __rg, const _Allocator& __alloc) + : __keys_(std::make_obj_using_allocator(__alloc)), __compare_() { + insert_range(std::forward<_Range>(__rg)); + } + + template <_ContainerCompatibleRange _Range, class _Allocator> + requires uses_allocator::value + _LIBCPP_HIDE_FROM_ABI flat_multiset(from_range_t, _Range&& __rg, const key_compare& __comp, const _Allocator& __alloc) + : __keys_(std::make_obj_using_allocator(__alloc)), __compare_(__comp) { + insert_range(std::forward<_Range>(__rg)); + } + + template + requires uses_allocator::value + _LIBCPP_HIDE_FROM_ABI flat_multiset(initializer_list __il, const _Allocator& __alloc) + : flat_multiset(__il.begin(), __il.end(), __alloc) {} + + template + requires uses_allocator::value + _LIBCPP_HIDE_FROM_ABI + flat_multiset(initializer_list __il, const key_compare& __comp, const _Allocator& __alloc) + : flat_multiset(__il.begin(), __il.end(), __comp, __alloc) {} + + template + requires uses_allocator::value + _LIBCPP_HIDE_FROM_ABI flat_multiset(sorted_equivalent_t, initializer_list __il, const _Allocator& __alloc) + : flat_multiset(sorted_equivalent, __il.begin(), __il.end(), __alloc) {} + + template + requires uses_allocator::value + _LIBCPP_HIDE_FROM_ABI flat_multiset( + sorted_equivalent_t, initializer_list __il, const key_compare& __comp, const _Allocator& __alloc) + : flat_multiset(sorted_equivalent, __il.begin(), __il.end(), __comp, __alloc) {} + + _LIBCPP_HIDE_FROM_ABI flat_multiset& operator=(initializer_list __il) { + clear(); + insert(__il); + return *this; + } + + // copy/move assignment are not specified in the spec (defaulted) + // but move assignment can potentially leave moved from object in an inconsistent + // state if an exception is thrown + _LIBCPP_HIDE_FROM_ABI flat_multiset& operator=(const flat_multiset&) = default; + + _LIBCPP_HIDE_FROM_ABI flat_multiset& operator=(flat_multiset&& __other) noexcept( + is_nothrow_move_assignable_v<_KeyContainer> && is_nothrow_move_assignable_v<_Compare>) { + auto __clear_other_guard = std::__make_scope_guard([&]() noexcept { __other.clear() /* noexcept */; }); + auto __clear_self_guard = std::__make_exception_guard([&]() noexcept { clear() /* noexcept */; }); + __keys_ = std::move(__other.__keys_); + __compare_ = std::move(__other.__compare_); + __clear_self_guard.__complete(); + return *this; + } + + // iterators + _LIBCPP_HIDE_FROM_ABI iterator begin() noexcept { return iterator(std::as_const(__keys_).begin()); } + _LIBCPP_HIDE_FROM_ABI const_iterator begin() const noexcept { return const_iterator(__keys_.begin()); } + _LIBCPP_HIDE_FROM_ABI iterator end() noexcept { return iterator(std::as_const(__keys_).end()); } + _LIBCPP_HIDE_FROM_ABI const_iterator end() const noexcept { return const_iterator(__keys_.end()); } + + _LIBCPP_HIDE_FROM_ABI reverse_iterator rbegin() noexcept { return reverse_iterator(end()); } + _LIBCPP_HIDE_FROM_ABI const_reverse_iterator rbegin() const noexcept { return const_reverse_iterator(end()); } + _LIBCPP_HIDE_FROM_ABI reverse_iterator rend() noexcept { return reverse_iterator(begin()); } + _LIBCPP_HIDE_FROM_ABI const_reverse_iterator rend() const noexcept { return const_reverse_iterator(begin()); } + + _LIBCPP_HIDE_FROM_ABI const_iterator cbegin() const noexcept { return begin(); } + _LIBCPP_HIDE_FROM_ABI const_iterator cend() const noexcept { return end(); } + _LIBCPP_HIDE_FROM_ABI const_reverse_iterator crbegin() const noexcept { return const_reverse_iterator(end()); } + _LIBCPP_HIDE_FROM_ABI const_reverse_iterator crend() const noexcept { return const_reverse_iterator(begin()); } + + // capacity + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI bool empty() const noexcept { return __keys_.empty(); } + _LIBCPP_HIDE_FROM_ABI size_type size() const noexcept { return __keys_.size(); } + _LIBCPP_HIDE_FROM_ABI size_type max_size() const noexcept { return __keys_.max_size(); } + + // [flat.multiset.modifiers], modifiers + template + requires is_constructible_v + _LIBCPP_HIDE_FROM_ABI iterator emplace(_Args&&... __args) { + if constexpr (sizeof...(__args) == 1 && (is_same_v, _Key> && ...)) { + return __emplace(std::forward<_Args>(__args)...); + } else { + return __emplace(_Key(std::forward<_Args>(__args)...)); + } + } + + template + requires is_constructible_v + _LIBCPP_HIDE_FROM_ABI iterator emplace_hint(const_iterator __hint, _Args&&... __args) { + if constexpr (sizeof...(__args) == 1 && (is_same_v, _Key> && ...)) { + return __emplace_hint(std::move(__hint), std::forward<_Args>(__args)...); + } else { + return __emplace_hint(std::move(__hint), _Key(std::forward<_Args>(__args)...)); + } + } + + _LIBCPP_HIDE_FROM_ABI iterator insert(const value_type& __x) { return emplace(__x); } + + _LIBCPP_HIDE_FROM_ABI iterator insert(value_type&& __x) { return emplace(std::move(__x)); } + + _LIBCPP_HIDE_FROM_ABI iterator insert(const_iterator __hint, const value_type& __x) { + return emplace_hint(__hint, __x); + } + + _LIBCPP_HIDE_FROM_ABI iterator insert(const_iterator __hint, value_type&& __x) { + return emplace_hint(__hint, std::move(__x)); + } + + template + requires __has_input_iterator_category<_InputIterator>::value + _LIBCPP_HIDE_FROM_ABI void insert(_InputIterator __first, _InputIterator __last) { + if constexpr (sized_sentinel_for<_InputIterator, _InputIterator>) { + __reserve(__last - __first); + } + __append_sort_merge(std::move(__first), std::move(__last)); + } + + template + requires __has_input_iterator_category<_InputIterator>::value + _LIBCPP_HIDE_FROM_ABI void insert(sorted_equivalent_t, _InputIterator __first, _InputIterator __last) { + if constexpr (sized_sentinel_for<_InputIterator, _InputIterator>) { + __reserve(__last - __first); + } + + __append_sort_merge(std::move(__first), std::move(__last)); + } + + template <_ContainerCompatibleRange _Range> + _LIBCPP_HIDE_FROM_ABI void insert_range(_Range&& __range) { + if constexpr (ranges::sized_range<_Range>) { + __reserve(ranges::size(__range)); + } + + __append_sort_merge(std::forward<_Range>(__range)); + } + + _LIBCPP_HIDE_FROM_ABI void insert(initializer_list __il) { insert(__il.begin(), __il.end()); } + + _LIBCPP_HIDE_FROM_ABI void insert(sorted_equivalent_t, initializer_list __il) { + insert(sorted_equivalent, __il.begin(), __il.end()); + } + + _LIBCPP_HIDE_FROM_ABI container_type extract() && { + auto __guard = std::__make_scope_guard([&]() noexcept { clear() /* noexcept */; }); + auto __ret = std::move(__keys_); + return __ret; + } + + _LIBCPP_HIDE_FROM_ABI void replace(container_type&& __keys) { + _LIBCPP_ASSERT_SEMANTIC_REQUIREMENT(ranges::is_sorted(__keys, __compare_), "Key container is not sorted"); + auto __guard = std::__make_exception_guard([&]() noexcept { clear() /* noexcept */; }); + __keys_ = std::move(__keys); + __guard.__complete(); + } + + _LIBCPP_HIDE_FROM_ABI iterator erase(iterator __position) { + auto __on_failure = std::__make_exception_guard([&]() noexcept { clear() /* noexcept */; }); + auto __key_iter = __keys_.erase(__position.__base()); + __on_failure.__complete(); + return iterator(__key_iter); + } + + // The following overload is the same as the iterator overload + // iterator erase(const_iterator __position); + + _LIBCPP_HIDE_FROM_ABI size_type erase(const key_type& __x) { + auto [__first, __last] = equal_range(__x); + auto __res = __last - __first; + erase(__first, __last); + return __res; + } + + template + requires(__is_transparent_v<_Compare> && !is_convertible_v<_Kp &&, iterator> && + !is_convertible_v<_Kp &&, const_iterator>) + _LIBCPP_HIDE_FROM_ABI size_type erase(_Kp&& __x) { + auto [__first, __last] = equal_range(__x); + auto __res = __last - __first; + erase(__first, __last); + return __res; + } + + _LIBCPP_HIDE_FROM_ABI iterator erase(const_iterator __first, const_iterator __last) { + auto __on_failure = std::__make_exception_guard([&]() noexcept { clear() /* noexcept */; }); + auto __key_it = __keys_.erase(__first.__base(), __last.__base()); + __on_failure.__complete(); + return iterator(std::move(__key_it)); + } + + _LIBCPP_HIDE_FROM_ABI void swap(flat_multiset& __y) noexcept { + // warning: The spec has unconditional noexcept, which means that + // if any of the following functions throw an exception, + // std::terminate will be called + // This is discussed in P3567, which hasn't been voted on yet. + ranges::swap(__compare_, __y.__compare_); + ranges::swap(__keys_, __y.__keys_); + } + + _LIBCPP_HIDE_FROM_ABI void clear() noexcept { __keys_.clear(); } + + // observers + _LIBCPP_HIDE_FROM_ABI key_compare key_comp() const { return __compare_; } + _LIBCPP_HIDE_FROM_ABI value_compare value_comp() const { return __compare_; } + + // map operations + _LIBCPP_HIDE_FROM_ABI iterator find(const key_type& __x) { return __find_impl(*this, __x); } + + _LIBCPP_HIDE_FROM_ABI const_iterator find(const key_type& __x) const { return __find_impl(*this, __x); } + + template + requires __is_transparent_v<_Compare> + _LIBCPP_HIDE_FROM_ABI iterator find(const _Kp& __x) { + return __find_impl(*this, __x); + } + + template + requires __is_transparent_v<_Compare> + _LIBCPP_HIDE_FROM_ABI const_iterator find(const _Kp& __x) const { + return __find_impl(*this, __x); + } + + _LIBCPP_HIDE_FROM_ABI size_type count(const key_type& __x) const { + auto [__first, __last] = equal_range(__x); + return __last - __first; + } + + template + requires __is_transparent_v<_Compare> + _LIBCPP_HIDE_FROM_ABI size_type count(const _Kp& __x) const { + auto [__first, __last] = equal_range(__x); + return __last - __first; + } + + _LIBCPP_HIDE_FROM_ABI bool contains(const key_type& __x) const { return find(__x) != end(); } + + template + requires __is_transparent_v<_Compare> + _LIBCPP_HIDE_FROM_ABI bool contains(const _Kp& __x) const { + return find(__x) != end(); + } + + _LIBCPP_HIDE_FROM_ABI iterator lower_bound(const key_type& __x) { + const auto& __keys = __keys_; + return iterator(std::lower_bound(__keys.begin(), __keys.end(), __x, __compare_)); + } + + _LIBCPP_HIDE_FROM_ABI const_iterator lower_bound(const key_type& __x) const { + return const_iterator(std::lower_bound(__keys_.begin(), __keys_.end(), __x, __compare_)); + } + + template + requires __is_transparent_v<_Compare> + _LIBCPP_HIDE_FROM_ABI iterator lower_bound(const _Kp& __x) { + const auto& __keys = __keys_; + return iterator(std::lower_bound(__keys.begin(), __keys.end(), __x, __compare_)); + } + + template + requires __is_transparent_v<_Compare> + _LIBCPP_HIDE_FROM_ABI const_iterator lower_bound(const _Kp& __x) const { + return const_iterator(std::lower_bound(__keys_.begin(), __keys_.end(), __x, __compare_)); + } + + _LIBCPP_HIDE_FROM_ABI iterator upper_bound(const key_type& __x) { + const auto& __keys = __keys_; + return iterator(std::upper_bound(__keys.begin(), __keys.end(), __x, __compare_)); + } + + _LIBCPP_HIDE_FROM_ABI const_iterator upper_bound(const key_type& __x) const { + return const_iterator(std::upper_bound(__keys_.begin(), __keys_.end(), __x, __compare_)); + } + + template + requires __is_transparent_v<_Compare> + _LIBCPP_HIDE_FROM_ABI iterator upper_bound(const _Kp& __x) { + const auto& __keys = __keys_; + return iterator(std::upper_bound(__keys.begin(), __keys.end(), __x, __compare_)); + } + + template + requires __is_transparent_v<_Compare> + _LIBCPP_HIDE_FROM_ABI const_iterator upper_bound(const _Kp& __x) const { + return const_iterator(std::upper_bound(__keys_.begin(), __keys_.end(), __x, __compare_)); + } + + _LIBCPP_HIDE_FROM_ABI pair equal_range(const key_type& __x) { + return __equal_range_impl(*this, __x); + } + + _LIBCPP_HIDE_FROM_ABI pair equal_range(const key_type& __x) const { + return __equal_range_impl(*this, __x); + } + + template + requires __is_transparent_v<_Compare> + _LIBCPP_HIDE_FROM_ABI pair equal_range(const _Kp& __x) { + return __equal_range_impl(*this, __x); + } + template + requires __is_transparent_v<_Compare> + _LIBCPP_HIDE_FROM_ABI pair equal_range(const _Kp& __x) const { + return __equal_range_impl(*this, __x); + } + + friend _LIBCPP_HIDE_FROM_ABI bool operator==(const flat_multiset& __x, const flat_multiset& __y) { + return ranges::equal(__x, __y); + } + + friend _LIBCPP_HIDE_FROM_ABI auto operator<=>(const flat_multiset& __x, const flat_multiset& __y) { + return std::lexicographical_compare_three_way( + __x.begin(), __x.end(), __y.begin(), __y.end(), std::__synth_three_way); + } + + friend _LIBCPP_HIDE_FROM_ABI void swap(flat_multiset& __x, flat_multiset& __y) noexcept { __x.swap(__y); } + +private: + template + _LIBCPP_HIDE_FROM_ABI void __append_sort_merge(_Args&&... __args) { + auto __on_failure = std::__make_exception_guard([&]() noexcept { clear() /* noexcept */; }); + size_type __old_size = size(); + __flat_set_utils::__append(*this, std::forward<_Args>(__args)...); + if constexpr (!_WasSorted) { + ranges::sort(__keys_.begin() + __old_size, __keys_.end(), __compare_); + } else { + _LIBCPP_ASSERT_SEMANTIC_REQUIREMENT( + ranges::is_sorted(__keys_ | ranges::views::drop(__old_size)), "Key container is not sorted"); + } + ranges::inplace_merge(__keys_.begin(), __keys_.begin() + __old_size, __keys_.end(), __compare_); + __on_failure.__complete(); + } + + template + _LIBCPP_HIDE_FROM_ABI iterator __emplace(_Kp&& __key) { + auto __it = upper_bound(__key); + return __flat_set_utils::__emplace_exact_pos(*this, __it, std::forward<_Kp>(__key)); + } + + template + _LIBCPP_HIDE_FROM_ABI iterator __emplace_hint(const_iterator __hint, _Kp&& __key) { + auto __prev_larger = __hint != cbegin() && __compare_(__key, *std::prev(__hint)); + auto __next_smaller = __hint != cend() && __compare_(*__hint, __key); + + if (!__prev_larger && !__next_smaller) [[likely]] { + // hint correct, just use exact hint iterator + } else if (__prev_larger && !__next_smaller) { + // the hint position is more to the right than the key should have been. + // we want to emplace the element to a position as right as possible + // e.g. Insert new element "2" in the following range + // 1, 1, 2, 2, 2, 3, 4, 6 + // ^ + // | + // hint + // We want to insert "2" after the last existing "2" + __hint = std::upper_bound(begin(), __hint, __key, __compare_); + } else { + _LIBCPP_ASSERT_INTERNAL(!__prev_larger && __next_smaller, "this means that the multiset is not sorted"); + + // the hint position is more to the left than the key should have been. + // we want to emplace the element to a position as left as possible + // 1, 1, 2, 2, 2, 3, 4, 6 + // ^ + // | + // hint + // We want to insert "2" before the first existing "2" + __hint = std::lower_bound(__hint, end(), __key, __compare_); + } + return __flat_set_utils::__emplace_exact_pos(*this, __hint, std::forward<_Kp>(__key)); + } + + template + _LIBCPP_HIDE_FROM_ABI static auto __find_impl(_Self&& __self, const _Kp& __key) { + auto __it = __self.lower_bound(__key); + auto __last = __self.end(); + if (__it == __last || __self.__compare_(__key, *__it)) { + return __last; + } + return __it; + } + + template + _LIBCPP_HIDE_FROM_ABI static auto __equal_range_impl(_Self&& __self, const _Kp& __key) { + using __iter = _If>, const_iterator, iterator>; + auto [__key_first, __key_last] = + std::equal_range(__self.__keys_.begin(), __self.__keys_.end(), __key, __self.__compare_); + return std::make_pair(__iter(__key_first), __iter(__key_last)); + } + + _LIBCPP_HIDE_FROM_ABI void __reserve(size_t __size) { + if constexpr (__container_traits<_KeyContainer>::__reservable) { + __keys_.reserve(__size); + } + } + + template + friend typename flat_multiset<_Key2, _Compare2, _KeyContainer2>::size_type + erase_if(flat_multiset<_Key2, _Compare2, _KeyContainer2>&, _Predicate); + + _KeyContainer __keys_; + _LIBCPP_NO_UNIQUE_ADDRESS key_compare __compare_; + + struct __key_equiv { + _LIBCPP_HIDE_FROM_ABI __key_equiv(key_compare __c) : __comp_(__c) {} + _LIBCPP_HIDE_FROM_ABI bool operator()(const_reference __x, const_reference __y) const { + return !__comp_(std::get<0>(__x), std::get<0>(__y)) && !__comp_(std::get<0>(__y), std::get<0>(__x)); + } + key_compare __comp_; + }; +}; + +template > + requires(!__is_allocator<_Compare>::value && !__is_allocator<_KeyContainer>::value && + is_invocable_v) +flat_multiset(_KeyContainer, _Compare = _Compare()) + -> flat_multiset; + +template + requires(uses_allocator_v<_KeyContainer, _Allocator> && !__is_allocator<_KeyContainer>::value) +flat_multiset(_KeyContainer, _Allocator) + -> flat_multiset, _KeyContainer>; + +template + requires(!__is_allocator<_Compare>::value && !__is_allocator<_KeyContainer>::value && + uses_allocator_v<_KeyContainer, _Allocator> && + is_invocable_v) +flat_multiset(_KeyContainer, _Compare, _Allocator) + -> flat_multiset; + +template > + requires(!__is_allocator<_Compare>::value && !__is_allocator<_KeyContainer>::value && + is_invocable_v) +flat_multiset(sorted_equivalent_t, _KeyContainer, _Compare = _Compare()) + -> flat_multiset; + +template + requires(uses_allocator_v<_KeyContainer, _Allocator> && !__is_allocator<_KeyContainer>::value) +flat_multiset(sorted_equivalent_t, _KeyContainer, _Allocator) + -> flat_multiset, _KeyContainer>; + +template + requires(!__is_allocator<_Compare>::value && !__is_allocator<_KeyContainer>::value && + uses_allocator_v<_KeyContainer, _Allocator> && + is_invocable_v) +flat_multiset(sorted_equivalent_t, _KeyContainer, _Compare, _Allocator) + -> flat_multiset; + +template >> + requires(__has_input_iterator_category<_InputIterator>::value && !__is_allocator<_Compare>::value) +flat_multiset(_InputIterator, _InputIterator, _Compare = _Compare()) + -> flat_multiset<__iter_value_type<_InputIterator>, _Compare>; + +template >> + requires(__has_input_iterator_category<_InputIterator>::value && !__is_allocator<_Compare>::value) +flat_multiset(sorted_equivalent_t, _InputIterator, _InputIterator, _Compare = _Compare()) + -> flat_multiset<__iter_value_type<_InputIterator>, _Compare>; + +template >, + class _Allocator = allocator>, + class = __enable_if_t::value && __is_allocator<_Allocator>::value>> +flat_multiset(from_range_t, _Range&&, _Compare = _Compare(), _Allocator = _Allocator()) -> flat_multiset< + ranges::range_value_t<_Range>, + _Compare, + vector, __allocator_traits_rebind_t<_Allocator, ranges::range_value_t<_Range>>>>; + +template ::value>> +flat_multiset(from_range_t, _Range&&, _Allocator) -> flat_multiset< + ranges::range_value_t<_Range>, + less>, + vector, __allocator_traits_rebind_t<_Allocator, ranges::range_value_t<_Range>>>>; + +template > + requires(!__is_allocator<_Compare>::value) +flat_multiset(initializer_list<_Key>, _Compare = _Compare()) -> flat_multiset<_Key, _Compare>; + +template > + requires(!__is_allocator<_Compare>::value) +flat_multiset(sorted_equivalent_t, initializer_list<_Key>, _Compare = _Compare()) -> flat_multiset<_Key, _Compare>; + +template +struct uses_allocator, _Allocator> + : bool_constant > {}; + +template +_LIBCPP_HIDE_FROM_ABI typename flat_multiset<_Key, _Compare, _KeyContainer>::size_type +erase_if(flat_multiset<_Key, _Compare, _KeyContainer>& __flat_multiset, _Predicate __pred) { + auto __guard = std::__make_exception_guard([&] { __flat_multiset.clear(); }); + auto __it = + std::remove_if(__flat_multiset.__keys_.begin(), __flat_multiset.__keys_.end(), [&](const auto& __e) -> bool { + return static_cast(__pred(__e)); + }); + auto __res = __flat_multiset.__keys_.end() - __it; + __flat_multiset.__keys_.erase(__it, __flat_multiset.__keys_.end()); + __guard.__complete(); + return __res; +} + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP_STD_VER >= 23 + +_LIBCPP_POP_MACROS + +#endif // _LIBCPP___FLAT_MAP_FLAT_MULTISET_H diff --git a/lib/libcxx/include/__flat_set/flat_set.h b/lib/libcxx/include/__flat_set/flat_set.h new file mode 100644 index 0000000000..95cb998459 --- /dev/null +++ b/lib/libcxx/include/__flat_set/flat_set.h @@ -0,0 +1,874 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___FLAT_SET_FLAT_SET_H +#define _LIBCPP___FLAT_SET_FLAT_SET_H + +#include <__algorithm/lexicographical_compare_three_way.h> +#include <__algorithm/lower_bound.h> +#include <__algorithm/min.h> +#include <__algorithm/ranges_adjacent_find.h> +#include <__algorithm/ranges_equal.h> +#include <__algorithm/ranges_inplace_merge.h> +#include <__algorithm/ranges_sort.h> +#include <__algorithm/ranges_unique.h> +#include <__algorithm/remove_if.h> +#include <__algorithm/upper_bound.h> +#include <__assert> +#include <__compare/synth_three_way.h> +#include <__concepts/swappable.h> +#include <__config> +#include <__cstddef/ptrdiff_t.h> +#include <__flat_map/sorted_unique.h> +#include <__flat_set/ra_iterator.h> +#include <__flat_set/utils.h> +#include <__functional/invoke.h> +#include <__functional/is_transparent.h> +#include <__functional/operations.h> +#include <__fwd/vector.h> +#include <__iterator/concepts.h> +#include <__iterator/distance.h> +#include <__iterator/iterator_traits.h> +#include <__iterator/next.h> +#include <__iterator/prev.h> +#include <__iterator/ranges_iterator_traits.h> +#include <__iterator/reverse_iterator.h> +#include <__memory/allocator_traits.h> +#include <__memory/uses_allocator.h> +#include <__memory/uses_allocator_construction.h> +#include <__ranges/access.h> +#include <__ranges/concepts.h> +#include <__ranges/container_compatible_range.h> +#include <__ranges/drop_view.h> +#include <__ranges/from_range.h> +#include <__ranges/ref_view.h> +#include <__ranges/size.h> +#include <__ranges/subrange.h> +#include <__type_traits/conjunction.h> +#include <__type_traits/container_traits.h> +#include <__type_traits/invoke.h> +#include <__type_traits/is_allocator.h> +#include <__type_traits/is_const.h> +#include <__type_traits/is_nothrow_constructible.h> +#include <__type_traits/is_same.h> +#include <__type_traits/remove_reference.h> +#include <__utility/as_const.h> +#include <__utility/exception_guard.h> +#include <__utility/move.h> +#include <__utility/pair.h> +#include <__utility/scope_guard.h> +#include <__vector/vector.h> +#include + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_PUSH_MACROS +#include <__undef_macros> + +#if _LIBCPP_STD_VER >= 23 + +_LIBCPP_BEGIN_NAMESPACE_STD + +template , class _KeyContainer = vector<_Key>> +class flat_set { + template + friend class flat_set; + + friend __flat_set_utils; + + static_assert(is_same_v<_Key, typename _KeyContainer::value_type>); + static_assert(!is_same_v<_KeyContainer, std::vector>, "vector is not a sequence container"); + + using __key_iterator _LIBCPP_NODEBUG = typename _KeyContainer::const_iterator; + +public: + // types + using key_type = _Key; + using value_type = _Key; + using key_compare = __type_identity_t<_Compare>; + using value_compare = _Compare; + using reference = value_type&; + using const_reference = const value_type&; + using size_type = typename _KeyContainer::size_type; + using difference_type = typename _KeyContainer::difference_type; + using iterator = __ra_iterator; + using const_iterator = iterator; + using reverse_iterator = std::reverse_iterator; + using const_reverse_iterator = std::reverse_iterator; + using container_type = _KeyContainer; + +public: + // [flat.set.cons], construct/copy/destroy + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 + flat_set() noexcept(is_nothrow_default_constructible_v<_KeyContainer> && is_nothrow_default_constructible_v<_Compare>) + : __keys_(), __compare_() {} + + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 flat_set(const flat_set&) = default; + + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 flat_set(flat_set&& __other) noexcept( + is_nothrow_move_constructible_v<_KeyContainer> && is_nothrow_move_constructible_v<_Compare>) +# if _LIBCPP_HAS_EXCEPTIONS + try +# endif // _LIBCPP_HAS_EXCEPTIONS + : __keys_(std::move(__other.__keys_)), __compare_(std::move(__other.__compare_)) { + __other.clear(); +# if _LIBCPP_HAS_EXCEPTIONS + } catch (...) { + __other.clear(); + // gcc does not like the `throw` keyword in a conditionally noexcept function + if constexpr (!(is_nothrow_move_constructible_v<_KeyContainer> && is_nothrow_move_constructible_v<_Compare>)) { + throw; + } +# endif // _LIBCPP_HAS_EXCEPTIONS + } + + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 explicit flat_set(const key_compare& __comp) + : __keys_(), __compare_(__comp) {} + + _LIBCPP_HIDE_FROM_ABI + _LIBCPP_CONSTEXPR_SINCE_CXX26 explicit flat_set(container_type __keys, const key_compare& __comp = key_compare()) + : __keys_(std::move(__keys)), __compare_(__comp) { + __sort_and_unique(); + } + + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 + flat_set(sorted_unique_t, container_type __keys, const key_compare& __comp = key_compare()) + : __keys_(std::move(__keys)), __compare_(__comp) { + _LIBCPP_ASSERT_SEMANTIC_REQUIREMENT( + __is_sorted_and_unique(__keys_), "Either the key container is not sorted or it contains duplicates"); + } + + template + requires __has_input_iterator_category<_InputIterator>::value + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 + flat_set(_InputIterator __first, _InputIterator __last, const key_compare& __comp = key_compare()) + : __keys_(), __compare_(__comp) { + insert(__first, __last); + } + + template + requires __has_input_iterator_category<_InputIterator>::value + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 + flat_set(sorted_unique_t, _InputIterator __first, _InputIterator __last, const key_compare& __comp = key_compare()) + : __keys_(__first, __last), __compare_(__comp) { + _LIBCPP_ASSERT_SEMANTIC_REQUIREMENT( + __is_sorted_and_unique(__keys_), "Either the key container is not sorted or it contains duplicates"); + } + + template <_ContainerCompatibleRange _Range> + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 flat_set(from_range_t, _Range&& __rg) + : flat_set(from_range, std::forward<_Range>(__rg), key_compare()) {} + + template <_ContainerCompatibleRange _Range> + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 flat_set(from_range_t, _Range&& __rg, const key_compare& __comp) + : flat_set(__comp) { + insert_range(std::forward<_Range>(__rg)); + } + + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 + flat_set(initializer_list __il, const key_compare& __comp = key_compare()) + : flat_set(__il.begin(), __il.end(), __comp) {} + + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 + flat_set(sorted_unique_t, initializer_list __il, const key_compare& __comp = key_compare()) + : flat_set(sorted_unique, __il.begin(), __il.end(), __comp) {} + + template + requires uses_allocator::value + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 explicit flat_set(const _Allocator& __alloc) + : __keys_(std::make_obj_using_allocator(__alloc)), __compare_() {} + + template + requires uses_allocator::value + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 flat_set(const key_compare& __comp, const _Allocator& __alloc) + : __keys_(std::make_obj_using_allocator(__alloc)), __compare_(__comp) {} + + template + requires uses_allocator::value + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 flat_set(const container_type& __keys, const _Allocator& __alloc) + : __keys_(std::make_obj_using_allocator(__alloc, __keys)), __compare_() { + __sort_and_unique(); + } + + template + requires uses_allocator::value + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 + flat_set(const container_type& __keys, const key_compare& __comp, const _Allocator& __alloc) + : __keys_(std::make_obj_using_allocator(__alloc, __keys)), __compare_(__comp) { + __sort_and_unique(); + } + + template + requires uses_allocator::value + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 + flat_set(sorted_unique_t, const container_type& __keys, const _Allocator& __alloc) + : __keys_(std::make_obj_using_allocator(__alloc, __keys)), __compare_() { + _LIBCPP_ASSERT_SEMANTIC_REQUIREMENT( + __is_sorted_and_unique(__keys_), "Either the key container is not sorted or it contains duplicates"); + } + + template + requires uses_allocator::value + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 + flat_set(sorted_unique_t, const container_type& __keys, const key_compare& __comp, const _Allocator& __alloc) + : __keys_(std::make_obj_using_allocator(__alloc, __keys)), __compare_(__comp) { + _LIBCPP_ASSERT_SEMANTIC_REQUIREMENT( + __is_sorted_and_unique(__keys_), "Either the key container is not sorted or it contains duplicates"); + } + + template + requires uses_allocator::value + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 flat_set(const flat_set& __other, const _Allocator& __alloc) + : __keys_(std::make_obj_using_allocator(__alloc, __other.__keys_)), + __compare_(__other.__compare_) {} + + template + requires uses_allocator::value + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 flat_set(flat_set&& __other, const _Allocator& __alloc) +# if _LIBCPP_HAS_EXCEPTIONS + try +# endif // _LIBCPP_HAS_EXCEPTIONS + : __keys_(std::make_obj_using_allocator(__alloc, std::move(__other.__keys_))), + __compare_(std::move(__other.__compare_)) { + __other.clear(); +# if _LIBCPP_HAS_EXCEPTIONS + } catch (...) { + __other.clear(); + throw; +# endif // _LIBCPP_HAS_EXCEPTIONS + } + + template + requires(__has_input_iterator_category<_InputIterator>::value && uses_allocator::value) + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 + flat_set(_InputIterator __first, _InputIterator __last, const _Allocator& __alloc) + : __keys_(std::make_obj_using_allocator(__alloc)), __compare_() { + insert(__first, __last); + } + + template + requires(__has_input_iterator_category<_InputIterator>::value && uses_allocator::value) + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 + flat_set(_InputIterator __first, _InputIterator __last, const key_compare& __comp, const _Allocator& __alloc) + : __keys_(std::make_obj_using_allocator(__alloc)), __compare_(__comp) { + insert(__first, __last); + } + + template + requires(__has_input_iterator_category<_InputIterator>::value && uses_allocator::value) + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 + flat_set(sorted_unique_t, _InputIterator __first, _InputIterator __last, const _Allocator& __alloc) + : __keys_(std::make_obj_using_allocator(__alloc, __first, __last)), __compare_() { + _LIBCPP_ASSERT_SEMANTIC_REQUIREMENT( + __is_sorted_and_unique(__keys_), "Either the key container is not sorted or it contains duplicates"); + } + + template + requires(__has_input_iterator_category<_InputIterator>::value && uses_allocator::value) + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 flat_set( + sorted_unique_t, + _InputIterator __first, + _InputIterator __last, + const key_compare& __comp, + const _Allocator& __alloc) + : __keys_(std::make_obj_using_allocator(__alloc, __first, __last)), __compare_(__comp) { + _LIBCPP_ASSERT_SEMANTIC_REQUIREMENT( + __is_sorted_and_unique(__keys_), "Either the key container is not sorted or it contains duplicates"); + } + + template <_ContainerCompatibleRange _Range, class _Allocator> + requires uses_allocator::value + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 flat_set(from_range_t, _Range&& __rg, const _Allocator& __alloc) + : __keys_(std::make_obj_using_allocator(__alloc)), __compare_() { + insert_range(std::forward<_Range>(__rg)); + } + + template <_ContainerCompatibleRange _Range, class _Allocator> + requires uses_allocator::value + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 + flat_set(from_range_t, _Range&& __rg, const key_compare& __comp, const _Allocator& __alloc) + : __keys_(std::make_obj_using_allocator(__alloc)), __compare_(__comp) { + insert_range(std::forward<_Range>(__rg)); + } + + template + requires uses_allocator::value + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 + flat_set(initializer_list __il, const _Allocator& __alloc) + : flat_set(__il.begin(), __il.end(), __alloc) {} + + template + requires uses_allocator::value + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 + flat_set(initializer_list __il, const key_compare& __comp, const _Allocator& __alloc) + : flat_set(__il.begin(), __il.end(), __comp, __alloc) {} + + template + requires uses_allocator::value + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 + flat_set(sorted_unique_t, initializer_list __il, const _Allocator& __alloc) + : flat_set(sorted_unique, __il.begin(), __il.end(), __alloc) {} + + template + requires uses_allocator::value + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 + flat_set(sorted_unique_t, initializer_list __il, const key_compare& __comp, const _Allocator& __alloc) + : flat_set(sorted_unique, __il.begin(), __il.end(), __comp, __alloc) {} + + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 flat_set& operator=(initializer_list __il) { + clear(); + insert(__il); + return *this; + } + + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 flat_set& operator=(const flat_set&) = default; + + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 flat_set& operator=(flat_set&& __other) noexcept( + is_nothrow_move_assignable_v<_KeyContainer> && is_nothrow_move_assignable_v<_Compare>) { + // No matter what happens, we always want to clear the other container before returning + // since we moved from it + auto __clear_other_guard = std::__make_scope_guard([&]() noexcept { __other.clear() /* noexcept */; }); + { + // If an exception is thrown, we have no choice but to clear *this to preserve invariants + auto __on_exception = std::__make_exception_guard([&]() noexcept { clear() /* noexcept */; }); + __keys_ = std::move(__other.__keys_); + __compare_ = std::move(__other.__compare_); + __on_exception.__complete(); + } + return *this; + } + + // iterators + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 iterator begin() noexcept { + return iterator(std::as_const(__keys_).begin()); + } + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 const_iterator begin() const noexcept { + return const_iterator(__keys_.begin()); + } + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 iterator end() noexcept { + return iterator(std::as_const(__keys_).end()); + } + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 const_iterator end() const noexcept { + return const_iterator(__keys_.end()); + } + + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 reverse_iterator rbegin() noexcept { + return reverse_iterator(end()); + } + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 const_reverse_iterator rbegin() const noexcept { + return const_reverse_iterator(end()); + } + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 reverse_iterator rend() noexcept { + return reverse_iterator(begin()); + } + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 const_reverse_iterator rend() const noexcept { + return const_reverse_iterator(begin()); + } + + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 const_iterator cbegin() const noexcept { return begin(); } + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 const_iterator cend() const noexcept { return end(); } + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 const_reverse_iterator crbegin() const noexcept { + return const_reverse_iterator(end()); + } + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 const_reverse_iterator crend() const noexcept { + return const_reverse_iterator(begin()); + } + + // [flat.set.capacity], capacity + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 bool empty() const noexcept { + return __keys_.empty(); + } + + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 size_type size() const noexcept { return __keys_.size(); } + + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 size_type max_size() const noexcept { return __keys_.max_size(); } + + // [flat.set.modifiers], modifiers + template + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 pair emplace(_Args&&... __args) { + if constexpr (sizeof...(__args) == 1 && (is_same_v, _Key> && ...)) { + return __emplace(std::forward<_Args>(__args)...); + } else { + return __emplace(_Key(std::forward<_Args>(__args)...)); + } + } + + template + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 iterator emplace_hint(const_iterator __hint, _Args&&... __args) { + if constexpr (sizeof...(__args) == 1 && (is_same_v, _Key> && ...)) { + return __emplace_hint(std::move(__hint), std::forward<_Args>(__args)...); + } else { + return __emplace_hint(std::move(__hint), _Key(std::forward<_Args>(__args)...)); + } + } + + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 pair insert(const value_type& __x) { + return emplace(__x); + } + + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 pair insert(value_type&& __x) { + return emplace(std::move(__x)); + } + + template + requires(__is_transparent_v<_Compare> && is_constructible_v) + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 pair insert(_Kp&& __x) { + return __emplace(std::forward<_Kp>(__x)); + } + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 iterator insert(const_iterator __hint, const value_type& __x) { + return emplace_hint(__hint, __x); + } + + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 iterator insert(const_iterator __hint, value_type&& __x) { + return emplace_hint(__hint, std::move(__x)); + } + + template + requires(__is_transparent_v<_Compare> && is_constructible_v) + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 iterator insert(const_iterator __hint, _Kp&& __x) { + return __emplace_hint(__hint, std::forward<_Kp>(__x)); + } + + template + requires __has_input_iterator_category<_InputIterator>::value + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 void insert(_InputIterator __first, _InputIterator __last) { + if constexpr (sized_sentinel_for<_InputIterator, _InputIterator>) { + __reserve(__last - __first); + } + __append_sort_merge_unique(std::move(__first), std::move(__last)); + } + + template + requires __has_input_iterator_category<_InputIterator>::value + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 void + insert(sorted_unique_t, _InputIterator __first, _InputIterator __last) { + if constexpr (sized_sentinel_for<_InputIterator, _InputIterator>) { + __reserve(__last - __first); + } + + __append_sort_merge_unique(std::move(__first), std::move(__last)); + } + + template <_ContainerCompatibleRange _Range> + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 void insert_range(_Range&& __range) { + if constexpr (ranges::sized_range<_Range>) { + __reserve(ranges::size(__range)); + } + + __append_sort_merge_unique(std::forward<_Range>(__range)); + } + + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 void insert(initializer_list __il) { + insert(__il.begin(), __il.end()); + } + + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 void insert(sorted_unique_t, initializer_list __il) { + insert(sorted_unique, __il.begin(), __il.end()); + } + + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 container_type extract() && { + auto __guard = std::__make_scope_guard([&]() noexcept { clear() /* noexcept */; }); + auto __ret = std::move(__keys_); + return __ret; + } + + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 void replace(container_type&& __keys) { + _LIBCPP_ASSERT_SEMANTIC_REQUIREMENT( + __is_sorted_and_unique(__keys), "Either the key container is not sorted or it contains duplicates"); + auto __guard = std::__make_exception_guard([&]() noexcept { clear() /* noexcept */; }); + __keys_ = std::move(__keys); + __guard.__complete(); + } + + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 iterator erase(iterator __position) { + auto __on_failure = std::__make_exception_guard([&]() noexcept { clear() /* noexcept */; }); + auto __key_iter = __keys_.erase(__position.__base()); + __on_failure.__complete(); + return iterator(__key_iter); + } + + // The following overload is the same as the iterator overload + // iterator erase(const_iterator __position); + + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 size_type erase(const key_type& __x) { + auto __iter = find(__x); + if (__iter != end()) { + erase(__iter); + return 1; + } + return 0; + } + + template + requires(__is_transparent_v<_Compare> && !is_convertible_v<_Kp &&, iterator> && + !is_convertible_v<_Kp &&, const_iterator>) + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 size_type erase(_Kp&& __x) { + auto [__first, __last] = equal_range(__x); + auto __res = __last - __first; + erase(__first, __last); + return __res; + } + + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 iterator erase(const_iterator __first, const_iterator __last) { + auto __on_failure = std::__make_exception_guard([&]() noexcept { clear() /* noexcept */; }); + auto __key_it = __keys_.erase(__first.__base(), __last.__base()); + __on_failure.__complete(); + return iterator(std::move(__key_it)); + } + + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 void swap(flat_set& __y) noexcept { + // warning: The spec has unconditional noexcept, which means that + // if any of the following functions throw an exception, + // std::terminate will be called. + // This is discussed in P2767, which hasn't been voted on yet. + ranges::swap(__compare_, __y.__compare_); + ranges::swap(__keys_, __y.__keys_); + } + + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 void clear() noexcept { __keys_.clear(); } + + // observers + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 key_compare key_comp() const { return __compare_; } + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 value_compare value_comp() const { return __compare_; } + + // set operations + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 iterator find(const key_type& __x) { + return __find_impl(*this, __x); + } + + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 const_iterator find(const key_type& __x) const { + return __find_impl(*this, __x); + } + + template + requires __is_transparent_v<_Compare> + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 iterator find(const _Kp& __x) { + return __find_impl(*this, __x); + } + + template + requires __is_transparent_v<_Compare> + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 const_iterator find(const _Kp& __x) const { + return __find_impl(*this, __x); + } + + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 size_type count(const key_type& __x) const { + return contains(__x) ? 1 : 0; + } + + template + requires __is_transparent_v<_Compare> + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 size_type count(const _Kp& __x) const { + return contains(__x) ? 1 : 0; + } + + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 bool contains(const key_type& __x) const { + return find(__x) != end(); + } + + template + requires __is_transparent_v<_Compare> + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 bool contains(const _Kp& __x) const { + return find(__x) != end(); + } + + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 iterator lower_bound(const key_type& __x) { + const auto& __keys = __keys_; + return iterator(std::lower_bound(__keys.begin(), __keys.end(), __x, __compare_)); + } + + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 const_iterator lower_bound(const key_type& __x) const { + return const_iterator(std::lower_bound(__keys_.begin(), __keys_.end(), __x, __compare_)); + } + + template + requires __is_transparent_v<_Compare> + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 iterator lower_bound(const _Kp& __x) { + const auto& __keys = __keys_; + return iterator(std::lower_bound(__keys.begin(), __keys.end(), __x, __compare_)); + } + + template + requires __is_transparent_v<_Compare> + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 const_iterator lower_bound(const _Kp& __x) const { + return const_iterator(std::lower_bound(__keys_.begin(), __keys_.end(), __x, __compare_)); + } + + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 iterator upper_bound(const key_type& __x) { + const auto& __keys = __keys_; + return iterator(std::upper_bound(__keys.begin(), __keys.end(), __x, __compare_)); + } + + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 const_iterator upper_bound(const key_type& __x) const { + return const_iterator(std::upper_bound(__keys_.begin(), __keys_.end(), __x, __compare_)); + } + + template + requires __is_transparent_v<_Compare> + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 iterator upper_bound(const _Kp& __x) { + const auto& __keys = __keys_; + return iterator(std::upper_bound(__keys.begin(), __keys.end(), __x, __compare_)); + } + + template + requires __is_transparent_v<_Compare> + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 const_iterator upper_bound(const _Kp& __x) const { + return const_iterator(std::upper_bound(__keys_.begin(), __keys_.end(), __x, __compare_)); + } + + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 pair equal_range(const key_type& __x) { + return __equal_range_impl(*this, __x); + } + + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 pair + equal_range(const key_type& __x) const { + return __equal_range_impl(*this, __x); + } + + template + requires __is_transparent_v<_Compare> + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 pair equal_range(const _Kp& __x) { + return __equal_range_impl(*this, __x); + } + template + requires __is_transparent_v<_Compare> + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 pair + equal_range(const _Kp& __x) const { + return __equal_range_impl(*this, __x); + } + + friend _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 bool operator==(const flat_set& __x, const flat_set& __y) { + return ranges::equal(__x, __y); + } + + friend _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 auto + operator<=>(const flat_set& __x, const flat_set& __y) { + return std::lexicographical_compare_three_way( + __x.begin(), __x.end(), __y.begin(), __y.end(), std::__synth_three_way); + } + + friend _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 void swap(flat_set& __x, flat_set& __y) noexcept { + __x.swap(__y); + } + +private: + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 bool __is_sorted_and_unique(auto&& __key_container) const { + auto __greater_or_equal_to = [this](const auto& __x, const auto& __y) { return !__compare_(__x, __y); }; + return ranges::adjacent_find(__key_container, __greater_or_equal_to) == ranges::end(__key_container); + } + + // This function is only used in constructors. So there is not exception handling in this function. + // If the function exits via an exception, there will be no flat_set object constructed, thus, there + // is no invariant state to preserve + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 void __sort_and_unique() { + ranges::sort(__keys_, __compare_); + auto __dup_start = ranges::unique(__keys_, __key_equiv(__compare_)).begin(); + __keys_.erase(__dup_start, __keys_.end()); + } + + template + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 void __append_sort_merge_unique(_Args&&... __args) { + auto __on_failure = std::__make_exception_guard([&]() noexcept { clear() /* noexcept */; }); + size_type __old_size = size(); + __flat_set_utils::__append(*this, std::forward<_Args>(__args)...); + if (size() != __old_size) { + if constexpr (!_WasSorted) { + ranges::sort(__keys_.begin() + __old_size, __keys_.end(), __compare_); + } else { + _LIBCPP_ASSERT_SEMANTIC_REQUIREMENT(__is_sorted_and_unique(__keys_ | ranges::views::drop(__old_size)), + "Either the key container is not sorted or it contains duplicates"); + } + ranges::inplace_merge(__keys_.begin(), __keys_.begin() + __old_size, __keys_.end(), __compare_); + + auto __dup_start = ranges::unique(__keys_, __key_equiv(__compare_)).begin(); + __keys_.erase(__dup_start, __keys_.end()); + } + __on_failure.__complete(); + } + + template + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 static auto __find_impl(_Self&& __self, const _Kp& __key) { + auto __it = __self.lower_bound(__key); + auto __last = __self.end(); + if (__it == __last || __self.__compare_(__key, *__it)) { + return __last; + } + return __it; + } + + template + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 static auto __equal_range_impl(_Self&& __self, const _Kp& __key) { + using __iter = _If>, const_iterator, iterator>; + auto __it = std::lower_bound(__self.__keys_.begin(), __self.__keys_.end(), __key, __self.__compare_); + auto __last = __self.__keys_.end(); + if (__it == __last || __self.__compare_(__key, *__it)) { + return std::make_pair(__iter(__it), __iter(__it)); + } + return std::make_pair(__iter(__it), __iter(std::next(__it))); + } + + template + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 pair __emplace(_Kp&& __key) { + auto __it = lower_bound(__key); + if (__it == end() || __compare_(__key, *__it)) { + return pair(__flat_set_utils::__emplace_exact_pos(*this, __it, std::forward<_Kp>(__key)), true); + } else { + return pair(std::move(__it), false); + } + } + + template + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 bool __is_hint_correct(const_iterator __hint, _Kp&& __key) { + if (__hint != cbegin() && !__compare_(*std::prev(__hint), __key)) { + return false; + } + if (__hint != cend() && __compare_(*__hint, __key)) { + return false; + } + return true; + } + + template + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 iterator __emplace_hint(const_iterator __hint, _Kp&& __key) { + if (__is_hint_correct(__hint, __key)) { + if (__hint == cend() || __compare_(__key, *__hint)) { + return __flat_set_utils::__emplace_exact_pos(*this, __hint, std::forward<_Kp>(__key)); + } else { + // we already have an equal key + return __hint; + } + } else { + return __emplace(std::forward<_Kp>(__key)).first; + } + } + + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 void __reserve(size_t __size) { + if constexpr (__container_traits<_KeyContainer>::__reservable) { + __keys_.reserve(__size); + } + } + + template + friend typename flat_set<_Key2, _Compare2, _KeyContainer2>::size_type _LIBCPP_CONSTEXPR_SINCE_CXX26 + erase_if(flat_set<_Key2, _Compare2, _KeyContainer2>&, _Predicate); + + _KeyContainer __keys_; + _LIBCPP_NO_UNIQUE_ADDRESS key_compare __compare_; + + struct __key_equiv { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 __key_equiv(key_compare __c) : __comp_(__c) {} + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 bool + operator()(const_reference __x, const_reference __y) const { + return !__comp_(__x, __y) && !__comp_(__y, __x); + } + key_compare __comp_; + }; +}; + +template > + requires(!__is_allocator<_Compare>::value && !__is_allocator<_KeyContainer>::value && + is_invocable_v) +flat_set(_KeyContainer, _Compare = _Compare()) -> flat_set; + +template + requires(uses_allocator_v<_KeyContainer, _Allocator> && !__is_allocator<_KeyContainer>::value) +flat_set(_KeyContainer, _Allocator) + -> flat_set, _KeyContainer>; + +template + requires(!__is_allocator<_Compare>::value && !__is_allocator<_KeyContainer>::value && + uses_allocator_v<_KeyContainer, _Allocator> && + is_invocable_v) +flat_set(_KeyContainer, _Compare, _Allocator) -> flat_set; + +template > + requires(!__is_allocator<_Compare>::value && !__is_allocator<_KeyContainer>::value && + is_invocable_v) +flat_set(sorted_unique_t, _KeyContainer, _Compare = _Compare()) + -> flat_set; + +template + requires(uses_allocator_v<_KeyContainer, _Allocator> && !__is_allocator<_KeyContainer>::value) +flat_set(sorted_unique_t, _KeyContainer, _Allocator) + -> flat_set, _KeyContainer>; + +template + requires(!__is_allocator<_Compare>::value && !__is_allocator<_KeyContainer>::value && + uses_allocator_v<_KeyContainer, _Allocator> && + is_invocable_v) +flat_set(sorted_unique_t, _KeyContainer, _Compare, _Allocator) + -> flat_set; + +template >> + requires(__has_input_iterator_category<_InputIterator>::value && !__is_allocator<_Compare>::value) +flat_set(_InputIterator, _InputIterator, _Compare = _Compare()) + -> flat_set<__iter_value_type<_InputIterator>, _Compare>; + +template >> + requires(__has_input_iterator_category<_InputIterator>::value && !__is_allocator<_Compare>::value) +flat_set(sorted_unique_t, _InputIterator, _InputIterator, _Compare = _Compare()) + -> flat_set<__iter_value_type<_InputIterator>, _Compare>; + +template >, + class _Allocator = allocator>, + class = __enable_if_t::value && __is_allocator<_Allocator>::value>> +flat_set(from_range_t, _Range&&, _Compare = _Compare(), _Allocator = _Allocator()) -> flat_set< + ranges::range_value_t<_Range>, + _Compare, + vector, __allocator_traits_rebind_t<_Allocator, ranges::range_value_t<_Range>>>>; + +template ::value>> +flat_set(from_range_t, _Range&&, _Allocator) -> flat_set< + ranges::range_value_t<_Range>, + less>, + vector, __allocator_traits_rebind_t<_Allocator, ranges::range_value_t<_Range>>>>; + +template > + requires(!__is_allocator<_Compare>::value) +flat_set(initializer_list<_Key>, _Compare = _Compare()) -> flat_set<_Key, _Compare>; + +template > + requires(!__is_allocator<_Compare>::value) +flat_set(sorted_unique_t, initializer_list<_Key>, _Compare = _Compare()) -> flat_set<_Key, _Compare>; + +template +struct uses_allocator, _Allocator> + : bool_constant> {}; + +template +_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 typename flat_set<_Key, _Compare, _KeyContainer>::size_type +erase_if(flat_set<_Key, _Compare, _KeyContainer>& __flat_set, _Predicate __pred) { + auto __guard = std::__make_exception_guard([&] { __flat_set.clear(); }); + auto __it = std::remove_if(__flat_set.__keys_.begin(), __flat_set.__keys_.end(), [&](const auto& __e) -> bool { + return static_cast(__pred(__e)); + }); + auto __res = __flat_set.__keys_.end() - __it; + __flat_set.__keys_.erase(__it, __flat_set.__keys_.end()); + __guard.__complete(); + return __res; +} + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP_STD_VER >= 23 + +_LIBCPP_POP_MACROS + +#endif // _LIBCPP___FLAT_SET_FLAT_SET_H diff --git a/lib/libcxx/include/__flat_set/ra_iterator.h b/lib/libcxx/include/__flat_set/ra_iterator.h new file mode 100644 index 0000000000..6fac62895a --- /dev/null +++ b/lib/libcxx/include/__flat_set/ra_iterator.h @@ -0,0 +1,157 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___FLAT_SET_RA_ITERATOR_H +#define _LIBCPP___FLAT_SET_RA_ITERATOR_H + +#include "__type_traits/is_same.h" +#include <__compare/three_way_comparable.h> +#include <__config> +#include <__iterator/incrementable_traits.h> +#include <__iterator/iterator_traits.h> +#include <__type_traits/is_constructible.h> +#include <__utility/move.h> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_PUSH_MACROS +#include <__undef_macros> + +#if _LIBCPP_STD_VER >= 23 + +_LIBCPP_BEGIN_NAMESPACE_STD + +/** + * __ra_iterator is a random access iterator that wraps an underlying iterator. + * It also stores the underlying container type in its type so that algorithms + * can optimize based on the underlying container type, and to avoid inadvertently + * mixing iterators coming from different containers.. + */ +template +struct __ra_iterator { +private: + _Iterator __iter_; + + friend _Container; + + // note: checking the concept random_access_iterator does not work for incomplete types + static_assert(_IsSame::iterator_category, random_access_iterator_tag>::value, + "Underlying iterator must be a random access iterator"); + +public: + using iterator_concept = random_access_iterator_tag; // deliberately lower contiguous_iterator + using iterator_category = random_access_iterator_tag; + using value_type = iter_value_t<_Iterator>; + using difference_type = iter_difference_t<_Iterator>; + + _LIBCPP_HIDE_FROM_ABI __ra_iterator() + requires is_default_constructible_v<_Iterator> + = default; + + _LIBCPP_HIDE_FROM_ABI explicit constexpr __ra_iterator(_Iterator __iter) : __iter_(std::move(__iter)) {} + + _LIBCPP_HIDE_FROM_ABI constexpr _Iterator __base() const noexcept(noexcept(_Iterator(__iter_))) { return __iter_; } + + _LIBCPP_HIDE_FROM_ABI constexpr decltype(auto) operator*() const { return *__iter_; } + _LIBCPP_HIDE_FROM_ABI constexpr decltype(auto) operator->() const + requires requires { __iter_.operator->(); } + { + return __iter_.operator->(); + } + + _LIBCPP_HIDE_FROM_ABI constexpr __ra_iterator& operator++() { + ++__iter_; + return *this; + } + + _LIBCPP_HIDE_FROM_ABI constexpr __ra_iterator operator++(int) { + __ra_iterator __tmp(*this); + ++*this; + return __tmp; + } + + _LIBCPP_HIDE_FROM_ABI constexpr __ra_iterator& operator--() { + --__iter_; + return *this; + } + + _LIBCPP_HIDE_FROM_ABI constexpr __ra_iterator operator--(int) { + __ra_iterator __tmp(*this); + --*this; + return __tmp; + } + + _LIBCPP_HIDE_FROM_ABI constexpr __ra_iterator& operator+=(difference_type __x) { + __iter_ += __x; + return *this; + } + + _LIBCPP_HIDE_FROM_ABI constexpr __ra_iterator& operator-=(difference_type __x) { + __iter_ -= __x; + return *this; + } + + _LIBCPP_HIDE_FROM_ABI constexpr decltype(auto) operator[](difference_type __n) const { return *(*this + __n); } + + _LIBCPP_HIDE_FROM_ABI friend constexpr bool operator==(const __ra_iterator& __x, const __ra_iterator& __y) { + return __x.__iter_ == __y.__iter_; + } + + _LIBCPP_HIDE_FROM_ABI friend constexpr bool operator<(const __ra_iterator& __x, const __ra_iterator& __y) { + return __x.__iter_ < __y.__iter_; + } + + _LIBCPP_HIDE_FROM_ABI friend constexpr bool operator>(const __ra_iterator& __x, const __ra_iterator& __y) { + return __y < __x; + } + + _LIBCPP_HIDE_FROM_ABI friend constexpr bool operator<=(const __ra_iterator& __x, const __ra_iterator& __y) { + return !(__y < __x); + } + + _LIBCPP_HIDE_FROM_ABI friend constexpr bool operator>=(const __ra_iterator& __x, const __ra_iterator& __y) { + return !(__x < __y); + } + + _LIBCPP_HIDE_FROM_ABI friend constexpr auto operator<=>(const __ra_iterator& __x, const __ra_iterator& __y) + requires three_way_comparable<_Iterator> + { + return __x.__iter_ <=> __y.__iter_; + } + + _LIBCPP_HIDE_FROM_ABI friend constexpr __ra_iterator operator+(const __ra_iterator& __i, difference_type __n) { + auto __tmp = __i; + __tmp += __n; + return __tmp; + } + + _LIBCPP_HIDE_FROM_ABI friend constexpr __ra_iterator operator+(difference_type __n, const __ra_iterator& __i) { + return __i + __n; + } + + _LIBCPP_HIDE_FROM_ABI friend constexpr __ra_iterator operator-(const __ra_iterator& __i, difference_type __n) { + auto __tmp = __i; + __tmp -= __n; + return __tmp; + } + + _LIBCPP_HIDE_FROM_ABI friend constexpr difference_type operator-(const __ra_iterator& __x, const __ra_iterator& __y) { + return __x.__iter_ - __y.__iter_; + } +}; + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP_STD_VER >= 23 + +_LIBCPP_POP_MACROS + +#endif // _LIBCPP___FLAT_SET_RA_ITERATOR_H diff --git a/lib/libcxx/include/__flat_set/utils.h b/lib/libcxx/include/__flat_set/utils.h new file mode 100644 index 0000000000..8a7f93a004 --- /dev/null +++ b/lib/libcxx/include/__flat_set/utils.h @@ -0,0 +1,82 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___FLAT_SET_UTILS_H +#define _LIBCPP___FLAT_SET_UTILS_H + +#include <__config> +#include <__iterator/iterator_traits.h> +#include <__ranges/access.h> +#include <__ranges/concepts.h> +#include <__type_traits/container_traits.h> +#include <__type_traits/decay.h> +#include <__utility/exception_guard.h> +#include <__utility/forward.h> +#include <__utility/move.h> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_PUSH_MACROS +#include <__undef_macros> + +#if _LIBCPP_STD_VER >= 23 + +_LIBCPP_BEGIN_NAMESPACE_STD + +// These utilities are defined in a class instead of a namespace so that this class can be befriended more easily. +struct __flat_set_utils { + // Emplace a key into a flat_{multi}set, at the exact position that + // __it point to, assuming that the key is not already present in the set. + // When an exception is thrown during the emplacement, the function will clear the set if the container does not + // have strong exception safety guarantee on emplacement. + template + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 static auto + __emplace_exact_pos(_Set& __set, _Iter&& __iter, _KeyArg&& __key) { + using _KeyContainer = typename decay_t<_Set>::container_type; + auto __on_failure = std::__make_exception_guard([&]() noexcept { + if constexpr (!__container_traits<_KeyContainer>::__emplacement_has_strong_exception_safety_guarantee) { + __set.clear() /* noexcept */; + } + }); + auto __key_it = __set.__keys_.emplace(__iter.__base(), std::forward<_KeyArg>(__key)); + __on_failure.__complete(); + return typename decay_t<_Set>::iterator(std::move(__key_it)); + } + + template + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 static void + __append(_Set& __set, _InputIterator __first, _InputIterator __last) { + __set.__keys_.insert(__set.__keys_.end(), std::move(__first), std::move(__last)); + } + + template + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 static void __append(_Set& __set, _Range&& __rng) { + if constexpr (requires { __set.__keys_.insert_range(__set.__keys_.end(), std::forward<_Range>(__rng)); }) { + // C++23 Sequence Container should have insert_range member function + // Note that not all Sequence Containers provide append_range. + __set.__keys_.insert_range(__set.__keys_.end(), std::forward<_Range>(__rng)); + } else if constexpr (ranges::common_range<_Range> && + __has_input_iterator_category>::value) { + __set.__keys_.insert(__set.__keys_.end(), ranges::begin(__rng), ranges::end(__rng)); + } else { + for (auto&& __x : __rng) { + __set.__keys_.insert(__set.__keys_.end(), std::forward(__x)); + } + } + } +}; +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP_STD_VER >= 23 + +_LIBCPP_POP_MACROS + +#endif // #define _LIBCPP___FLAT_SET_UTILS_H diff --git a/lib/libcxx/include/__format/buffer.h b/lib/libcxx/include/__format/buffer.h index 0c054bbc3a..e7454f08f4 100644 --- a/lib/libcxx/include/__format/buffer.h +++ b/lib/libcxx/include/__format/buffer.h @@ -15,7 +15,6 @@ #include <__algorithm/max.h> #include <__algorithm/min.h> #include <__algorithm/ranges_copy.h> -#include <__algorithm/ranges_copy_n.h> #include <__algorithm/transform.h> #include <__algorithm/unwrap_iter.h> #include <__concepts/same_as.h> @@ -33,7 +32,7 @@ #include <__memory/allocator.h> #include <__memory/allocator_traits.h> #include <__memory/construct_at.h> -#include <__memory/ranges_construct_at.h> +#include <__memory/destroy.h> #include <__memory/uninitialized_algorithms.h> #include <__type_traits/add_pointer.h> #include <__type_traits/conditional.h> @@ -180,7 +179,7 @@ private: /// The latter option allows formatted_size to use the output buffer without /// ever writing anything to the buffer. template <__fmt_char_type _CharT> -class _LIBCPP_TEMPLATE_VIS __output_buffer { +class __output_buffer { public: using value_type _LIBCPP_NODEBUG = _CharT; using __prepare_write_type _LIBCPP_NODEBUG = void (*)(__output_buffer<_CharT>&, size_t); @@ -340,18 +339,18 @@ concept __insertable = /// Extract the container type of a \ref back_insert_iterator. template -struct _LIBCPP_TEMPLATE_VIS __back_insert_iterator_container { +struct __back_insert_iterator_container { using type _LIBCPP_NODEBUG = void; }; template <__insertable _Container> -struct _LIBCPP_TEMPLATE_VIS __back_insert_iterator_container> { +struct __back_insert_iterator_container> { using type _LIBCPP_NODEBUG = _Container; }; // A dynamically growing buffer. template <__fmt_char_type _CharT> -class _LIBCPP_TEMPLATE_VIS __allocating_buffer : public __output_buffer<_CharT> { +class __allocating_buffer : public __output_buffer<_CharT> { public: __allocating_buffer(const __allocating_buffer&) = delete; __allocating_buffer& operator=(const __allocating_buffer&) = delete; @@ -408,7 +407,7 @@ private: // A buffer that directly writes to the underlying buffer. template -class _LIBCPP_TEMPLATE_VIS __direct_iterator_buffer : public __output_buffer<_CharT> { +class __direct_iterator_buffer : public __output_buffer<_CharT> { public: [[nodiscard]] _LIBCPP_HIDE_FROM_ABI explicit __direct_iterator_buffer(_OutIt __out_it) : __direct_iterator_buffer{__out_it, nullptr} {} @@ -437,7 +436,7 @@ private: // A buffer that writes its output to the end of a container. template -class _LIBCPP_TEMPLATE_VIS __container_inserter_buffer : public __output_buffer<_CharT> { +class __container_inserter_buffer : public __output_buffer<_CharT> { public: [[nodiscard]] _LIBCPP_HIDE_FROM_ABI explicit __container_inserter_buffer(_OutIt __out_it) : __container_inserter_buffer{__out_it, nullptr} {} @@ -478,7 +477,7 @@ private: // Unlike the __container_inserter_buffer this class' performance does benefit // from allocating and then inserting. template -class _LIBCPP_TEMPLATE_VIS __iterator_buffer : public __allocating_buffer<_CharT> { +class __iterator_buffer : public __allocating_buffer<_CharT> { public: [[nodiscard]] _LIBCPP_HIDE_FROM_ABI explicit __iterator_buffer(_OutIt __out_it) : __allocating_buffer<_CharT>{}, __out_it_{std::move(__out_it)} {} @@ -496,7 +495,7 @@ private: // Selects the type of the buffer used for the output iterator. template -class _LIBCPP_TEMPLATE_VIS __buffer_selector { +class __buffer_selector { using _Container _LIBCPP_NODEBUG = __back_insert_iterator_container<_OutIt>::type; public: @@ -510,7 +509,7 @@ public: // A buffer that counts and limits the number of insertions. template -class _LIBCPP_TEMPLATE_VIS __format_to_n_buffer : private __buffer_selector<_OutIt, _CharT>::type { +class __format_to_n_buffer : private __buffer_selector<_OutIt, _CharT>::type { public: using _Base _LIBCPP_NODEBUG = __buffer_selector<_OutIt, _CharT>::type; @@ -534,7 +533,7 @@ private: // Since formatted_size only needs to know the size, the output itself is // discarded. template <__fmt_char_type _CharT> -class _LIBCPP_TEMPLATE_VIS __formatted_size_buffer : private __output_buffer<_CharT> { +class __formatted_size_buffer : private __output_buffer<_CharT> { public: using _Base _LIBCPP_NODEBUG = __output_buffer<_CharT>; @@ -577,7 +576,7 @@ private: // This class uses its own buffer management, since using vector // would lead to a circular include with formatter for vector. template <__fmt_char_type _CharT> -class _LIBCPP_TEMPLATE_VIS __retarget_buffer { +class __retarget_buffer { using _Alloc _LIBCPP_NODEBUG = allocator<_CharT>; public: @@ -621,7 +620,7 @@ public: } _LIBCPP_HIDE_FROM_ABI ~__retarget_buffer() { - ranges::destroy_n(__ptr_, __size_); + std::destroy_n(__ptr_, __size_); allocator_traits<_Alloc>::deallocate(__alloc_, __ptr_, __capacity_); } @@ -686,7 +685,7 @@ private: // guard is optimized away so there is no runtime overhead. std::uninitialized_move_n(__ptr_, __size_, __result.ptr); __guard.__complete(); - ranges::destroy_n(__ptr_, __size_); + std::destroy_n(__ptr_, __size_); allocator_traits<_Alloc>::deallocate(__alloc_, __ptr_, __capacity_); __ptr_ = __result.ptr; diff --git a/lib/libcxx/include/__format/container_adaptor.h b/lib/libcxx/include/__format/container_adaptor.h index 48d42ee7d9..6a99a02861 100644 --- a/lib/libcxx/include/__format/container_adaptor.h +++ b/lib/libcxx/include/__format/container_adaptor.h @@ -35,7 +35,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD // adaptor headers. To use the format functions users already include . template -struct _LIBCPP_TEMPLATE_VIS __formatter_container_adaptor { +struct __formatter_container_adaptor { private: using __maybe_const_container _LIBCPP_NODEBUG = __fmt_maybe_const; using __maybe_const_adaptor _LIBCPP_NODEBUG = __maybe_const, _Adaptor>; @@ -55,15 +55,15 @@ public: }; template _Container> -struct _LIBCPP_TEMPLATE_VIS formatter, _CharT> +struct formatter, _CharT> : public __formatter_container_adaptor, _CharT> {}; template -struct _LIBCPP_TEMPLATE_VIS formatter, _CharT> +struct formatter, _CharT> : public __formatter_container_adaptor, _CharT> {}; template _Container> -struct _LIBCPP_TEMPLATE_VIS formatter, _CharT> +struct formatter, _CharT> : public __formatter_container_adaptor, _CharT> {}; #endif // _LIBCPP_STD_VER >= 23 diff --git a/lib/libcxx/include/__format/escaped_output_table.h b/lib/libcxx/include/__format/escaped_output_table.h index 7a0b352398..1401b4637d 100644 --- a/lib/libcxx/include/__format/escaped_output_table.h +++ b/lib/libcxx/include/__format/escaped_output_table.h @@ -109,7 +109,7 @@ namespace __escaped_output_table { /// - bits [14, 31] The lower bound code point of the range. The upper bound of /// the range is lower bound + size. Note the code expects code units the fit /// into 18 bits, instead of the 21 bits needed for the full Unicode range. -_LIBCPP_HIDE_FROM_ABI inline constexpr uint32_t __entries[711] = { +_LIBCPP_HIDE_FROM_ABI inline constexpr uint32_t __entries[735] = { 0x00000020 /* 00000000 - 00000020 [ 33] */, 0x001fc021 /* 0000007f - 000000a0 [ 34] */, 0x002b4000 /* 000000ad - 000000ad [ 1] */, @@ -136,7 +136,7 @@ _LIBCPP_HIDE_FROM_ABI inline constexpr uint32_t __entries[711] = { 0x02170001 /* 0000085c - 0000085d [ 2] */, 0x0217c000 /* 0000085f - 0000085f [ 1] */, 0x021ac004 /* 0000086b - 0000086f [ 5] */, - 0x0223c008 /* 0000088f - 00000897 [ 9] */, + 0x0223c007 /* 0000088f - 00000896 [ 8] */, 0x02388000 /* 000008e2 - 000008e2 [ 1] */, 0x02610000 /* 00000984 - 00000984 [ 1] */, 0x02634001 /* 0000098d - 0000098e [ 2] */, @@ -331,12 +331,11 @@ _LIBCPP_HIDE_FROM_ABI inline constexpr uint32_t __entries[711] = { 0x06a68005 /* 00001a9a - 00001a9f [ 6] */, 0x06ab8001 /* 00001aae - 00001aaf [ 2] */, 0x06b3c030 /* 00001acf - 00001aff [ 49] */, - 0x06d34002 /* 00001b4d - 00001b4f [ 3] */, - 0x06dfc000 /* 00001b7f - 00001b7f [ 1] */, + 0x06d34000 /* 00001b4d - 00001b4d [ 1] */, 0x06fd0007 /* 00001bf4 - 00001bfb [ 8] */, 0x070e0002 /* 00001c38 - 00001c3a [ 3] */, 0x07128002 /* 00001c4a - 00001c4c [ 3] */, - 0x07224006 /* 00001c89 - 00001c8f [ 7] */, + 0x0722c004 /* 00001c8b - 00001c8f [ 5] */, 0x072ec001 /* 00001cbb - 00001cbc [ 2] */, 0x07320007 /* 00001cc8 - 00001ccf [ 8] */, 0x073ec004 /* 00001cfb - 00001cff [ 5] */, @@ -364,7 +363,7 @@ _LIBCPP_HIDE_FROM_ABI inline constexpr uint32_t __entries[711] = { 0x0830400e /* 000020c1 - 000020cf [ 15] */, 0x083c400e /* 000020f1 - 000020ff [ 15] */, 0x08630003 /* 0000218c - 0000218f [ 4] */, - 0x0909c018 /* 00002427 - 0000243f [ 25] */, + 0x090a8015 /* 0000242a - 0000243f [ 22] */, 0x0912c014 /* 0000244b - 0000245f [ 21] */, 0x0add0001 /* 00002b74 - 00002b75 [ 2] */, 0x0ae58000 /* 00002b96 - 00002b96 [ 1] */, @@ -393,16 +392,16 @@ _LIBCPP_HIDE_FROM_ABI inline constexpr uint32_t __entries[711] = { 0x0c400004 /* 00003100 - 00003104 [ 5] */, 0x0c4c0000 /* 00003130 - 00003130 [ 1] */, 0x0c63c000 /* 0000318f - 0000318f [ 1] */, - 0x0c79000a /* 000031e4 - 000031ee [ 11] */, + 0x0c798008 /* 000031e6 - 000031ee [ 9] */, 0x0c87c000 /* 0000321f - 0000321f [ 1] */, 0x29234002 /* 0000a48d - 0000a48f [ 3] */, 0x2931c008 /* 0000a4c7 - 0000a4cf [ 9] */, 0x298b0013 /* 0000a62c - 0000a63f [ 20] */, 0x29be0007 /* 0000a6f8 - 0000a6ff [ 8] */, - 0x29f2c004 /* 0000a7cb - 0000a7cf [ 5] */, + 0x29f38001 /* 0000a7ce - 0000a7cf [ 2] */, 0x29f48000 /* 0000a7d2 - 0000a7d2 [ 1] */, 0x29f50000 /* 0000a7d4 - 0000a7d4 [ 1] */, - 0x29f68017 /* 0000a7da - 0000a7f1 [ 24] */, + 0x29f74014 /* 0000a7dd - 0000a7f1 [ 21] */, 0x2a0b4002 /* 0000a82d - 0000a82f [ 3] */, 0x2a0e8005 /* 0000a83a - 0000a83f [ 6] */, 0x2a1e0007 /* 0000a878 - 0000a87f [ 8] */, @@ -491,7 +490,8 @@ _LIBCPP_HIDE_FROM_ABI inline constexpr uint32_t __entries[711] = { 0x41688000 /* 000105a2 - 000105a2 [ 1] */, 0x416c8000 /* 000105b2 - 000105b2 [ 1] */, 0x416e8000 /* 000105ba - 000105ba [ 1] */, - 0x416f4042 /* 000105bd - 000105ff [ 67] */, + 0x416f4002 /* 000105bd - 000105bf [ 3] */, + 0x417d000b /* 000105f4 - 000105ff [ 12] */, 0x41cdc008 /* 00010737 - 0001073f [ 9] */, 0x41d58009 /* 00010756 - 0001075f [ 10] */, 0x41da0017 /* 00010768 - 0001077f [ 24] */, @@ -534,11 +534,15 @@ _LIBCPP_HIDE_FROM_ABI inline constexpr uint32_t __entries[711] = { 0x432cc00c /* 00010cb3 - 00010cbf [ 13] */, 0x433cc006 /* 00010cf3 - 00010cf9 [ 7] */, 0x434a0007 /* 00010d28 - 00010d2f [ 8] */, - 0x434e8125 /* 00010d3a - 00010e5f [ 294] */, + 0x434e8005 /* 00010d3a - 00010d3f [ 6] */, + 0x43598002 /* 00010d66 - 00010d68 [ 3] */, + 0x43618007 /* 00010d86 - 00010d8d [ 8] */, + 0x436400cf /* 00010d90 - 00010e5f [ 208] */, 0x439fc000 /* 00010e7f - 00010e7f [ 1] */, 0x43aa8000 /* 00010eaa - 00010eaa [ 1] */, 0x43ab8001 /* 00010eae - 00010eaf [ 2] */, - 0x43ac804a /* 00010eb2 - 00010efc [ 75] */, + 0x43ac800f /* 00010eb2 - 00010ec1 [ 16] */, + 0x43b14036 /* 00010ec5 - 00010efb [ 55] */, 0x43ca0007 /* 00010f28 - 00010f2f [ 8] */, 0x43d68015 /* 00010f5a - 00010f6f [ 22] */, 0x43e28025 /* 00010f8a - 00010faf [ 38] */, @@ -578,7 +582,18 @@ _LIBCPP_HIDE_FROM_ABI inline constexpr uint32_t __entries[711] = { 0x44d60004 /* 00011358 - 0001135c [ 5] */, 0x44d90001 /* 00011364 - 00011365 [ 2] */, 0x44db4002 /* 0001136d - 0001136f [ 3] */, - 0x44dd408a /* 00011375 - 000113ff [ 139] */, + 0x44dd400a /* 00011375 - 0001137f [ 11] */, + 0x44e28000 /* 0001138a - 0001138a [ 1] */, + 0x44e30001 /* 0001138c - 0001138d [ 2] */, + 0x44e3c000 /* 0001138f - 0001138f [ 1] */, + 0x44ed8000 /* 000113b6 - 000113b6 [ 1] */, + 0x44f04000 /* 000113c1 - 000113c1 [ 1] */, + 0x44f0c001 /* 000113c3 - 000113c4 [ 2] */, + 0x44f18000 /* 000113c6 - 000113c6 [ 1] */, + 0x44f2c000 /* 000113cb - 000113cb [ 1] */, + 0x44f58000 /* 000113d6 - 000113d6 [ 1] */, + 0x44f64007 /* 000113d9 - 000113e0 [ 8] */, + 0x44f8c01c /* 000113e3 - 000113ff [ 29] */, 0x45170000 /* 0001145c - 0001145c [ 1] */, 0x4518801d /* 00011462 - 0001147f [ 30] */, 0x45320007 /* 000114c8 - 000114cf [ 8] */, @@ -589,7 +604,8 @@ _LIBCPP_HIDE_FROM_ABI inline constexpr uint32_t __entries[711] = { 0x45968005 /* 0001165a - 0001165f [ 6] */, 0x459b4012 /* 0001166d - 0001167f [ 19] */, 0x45ae8005 /* 000116ba - 000116bf [ 6] */, - 0x45b28035 /* 000116ca - 000116ff [ 54] */, + 0x45b28005 /* 000116ca - 000116cf [ 6] */, + 0x45b9001b /* 000116e4 - 000116ff [ 28] */, 0x45c6c001 /* 0001171b - 0001171c [ 2] */, 0x45cb0003 /* 0001172c - 0001172f [ 4] */, 0x45d1c0b8 /* 00011747 - 000117ff [ 185] */, @@ -609,7 +625,9 @@ _LIBCPP_HIDE_FROM_ABI inline constexpr uint32_t __entries[711] = { 0x46920007 /* 00011a48 - 00011a4f [ 8] */, 0x46a8c00c /* 00011aa3 - 00011aaf [ 13] */, 0x46be4006 /* 00011af9 - 00011aff [ 7] */, - 0x46c280f5 /* 00011b0a - 00011bff [ 246] */, + 0x46c280b5 /* 00011b0a - 00011bbf [ 182] */, + 0x46f8800d /* 00011be2 - 00011bef [ 14] */, + 0x46fe8005 /* 00011bfa - 00011bff [ 6] */, 0x47024000 /* 00011c09 - 00011c09 [ 1] */, 0x470dc000 /* 00011c37 - 00011c37 [ 1] */, 0x47118009 /* 00011c46 - 00011c4f [ 10] */, @@ -633,7 +651,7 @@ _LIBCPP_HIDE_FROM_ABI inline constexpr uint32_t __entries[711] = { 0x47be4006 /* 00011ef9 - 00011eff [ 7] */, 0x47c44000 /* 00011f11 - 00011f11 [ 1] */, 0x47cec002 /* 00011f3b - 00011f3d [ 3] */, - 0x47d68055 /* 00011f5a - 00011faf [ 86] */, + 0x47d6c054 /* 00011f5b - 00011faf [ 85] */, 0x47ec400e /* 00011fb1 - 00011fbf [ 15] */, 0x47fc800c /* 00011ff2 - 00011ffe [ 13] */, 0x48e68065 /* 0001239a - 000123ff [ 102] */, @@ -642,8 +660,10 @@ _LIBCPP_HIDE_FROM_ABI inline constexpr uint32_t __entries[711] = { 0x49510a4b /* 00012544 - 00012f8f [ 2636] */, 0x4bfcc00c /* 00012ff3 - 00012fff [ 13] */, 0x4d0c000f /* 00013430 - 0001343f [ 16] */, - 0x4d158fa9 /* 00013456 - 000143ff [ 4010] */, - 0x5191e1b8 /* 00014647 - 000167ff [ 8633] */, + 0x4d158009 /* 00013456 - 0001345f [ 10] */, + 0x50fec004 /* 000143fb - 000143ff [ 5] */, + 0x5191dab8 /* 00014647 - 000160ff [ 6841] */, + 0x584e86c5 /* 0001613a - 000167ff [ 1734] */, 0x5a8e4006 /* 00016a39 - 00016a3f [ 7] */, 0x5a97c000 /* 00016a5f - 00016a5f [ 1] */, 0x5a9a8003 /* 00016a6a - 00016a6d [ 4] */, @@ -655,7 +675,8 @@ _LIBCPP_HIDE_FROM_ABI inline constexpr uint32_t __entries[711] = { 0x5ad68000 /* 00016b5a - 00016b5a [ 1] */, 0x5ad88000 /* 00016b62 - 00016b62 [ 1] */, 0x5ade0004 /* 00016b78 - 00016b7c [ 5] */, - 0x5ae402af /* 00016b90 - 00016e3f [ 688] */, + 0x5ae401af /* 00016b90 - 00016d3f [ 432] */, + 0x5b5e80c5 /* 00016d7a - 00016e3f [ 198] */, 0x5ba6c064 /* 00016e9b - 00016eff [ 101] */, 0x5bd2c003 /* 00016f4b - 00016f4e [ 4] */, 0x5be20006 /* 00016f88 - 00016f8e [ 7] */, @@ -663,7 +684,7 @@ _LIBCPP_HIDE_FROM_ABI inline constexpr uint32_t __entries[711] = { 0x5bf9400a /* 00016fe5 - 00016fef [ 11] */, 0x5bfc800d /* 00016ff2 - 00016fff [ 14] */, 0x61fe0007 /* 000187f8 - 000187ff [ 8] */, - 0x63358029 /* 00018cd6 - 00018cff [ 42] */, + 0x63358028 /* 00018cd6 - 00018cfe [ 41] */, 0x634262e6 /* 00018d09 - 0001afef [ 8935] */, 0x6bfd0000 /* 0001aff4 - 0001aff4 [ 1] */, 0x6bff0000 /* 0001affc - 0001affc [ 1] */, @@ -678,7 +699,9 @@ _LIBCPP_HIDE_FROM_ABI inline constexpr uint32_t __entries[711] = { 0x6f1f4002 /* 0001bc7d - 0001bc7f [ 3] */, 0x6f224006 /* 0001bc89 - 0001bc8f [ 7] */, 0x6f268001 /* 0001bc9a - 0001bc9b [ 2] */, - 0x6f28125f /* 0001bca0 - 0001ceff [ 4704] */, + 0x6f280f5f /* 0001bca0 - 0001cbff [ 3936] */, + 0x733e8005 /* 0001ccfa - 0001ccff [ 6] */, + 0x73ad004b /* 0001ceb4 - 0001ceff [ 76] */, 0x73cb8001 /* 0001cf2e - 0001cf2f [ 2] */, 0x73d1c008 /* 0001cf47 - 0001cf4f [ 9] */, 0x73f1003b /* 0001cfc4 - 0001cfff [ 60] */, @@ -730,7 +753,9 @@ _LIBCPP_HIDE_FROM_ABI inline constexpr uint32_t __entries[711] = { 0x78abc010 /* 0001e2af - 0001e2bf [ 17] */, 0x78be8004 /* 0001e2fa - 0001e2fe [ 5] */, 0x78c001cf /* 0001e300 - 0001e4cf [ 464] */, - 0x793e82e5 /* 0001e4fa - 0001e7df [ 742] */, + 0x793e80d5 /* 0001e4fa - 0001e5cf [ 214] */, + 0x797ec003 /* 0001e5fb - 0001e5fe [ 4] */, + 0x798001df /* 0001e600 - 0001e7df [ 480] */, 0x79f9c000 /* 0001e7e7 - 0001e7e7 [ 1] */, 0x79fb0000 /* 0001e7ec - 0001e7ec [ 1] */, 0x79fbc000 /* 0001e7ef - 0001e7ef [ 1] */, @@ -800,18 +825,17 @@ _LIBCPP_HIDE_FROM_ABI inline constexpr uint32_t __entries[711] = { 0x7e168005 /* 0001f85a - 0001f85f [ 6] */, 0x7e220007 /* 0001f888 - 0001f88f [ 8] */, 0x7e2b8001 /* 0001f8ae - 0001f8af [ 2] */, - 0x7e2c804d /* 0001f8b2 - 0001f8ff [ 78] */, + 0x7e2f0003 /* 0001f8bc - 0001f8bf [ 4] */, + 0x7e30803d /* 0001f8c2 - 0001f8ff [ 62] */, 0x7e95000b /* 0001fa54 - 0001fa5f [ 12] */, 0x7e9b8001 /* 0001fa6e - 0001fa6f [ 2] */, 0x7e9f4002 /* 0001fa7d - 0001fa7f [ 3] */, - 0x7ea24006 /* 0001fa89 - 0001fa8f [ 7] */, - 0x7eaf8000 /* 0001fabe - 0001fabe [ 1] */, - 0x7eb18007 /* 0001fac6 - 0001facd [ 8] */, - 0x7eb70003 /* 0001fadc - 0001fadf [ 4] */, - 0x7eba4006 /* 0001fae9 - 0001faef [ 7] */, + 0x7ea28004 /* 0001fa8a - 0001fa8e [ 5] */, + 0x7eb1c006 /* 0001fac7 - 0001facd [ 7] */, + 0x7eb74001 /* 0001fadd - 0001fade [ 2] */, + 0x7eba8005 /* 0001faea - 0001faef [ 6] */, 0x7ebe4006 /* 0001faf9 - 0001faff [ 7] */, 0x7ee4c000 /* 0001fb93 - 0001fb93 [ 1] */, - 0x7ef2c024 /* 0001fbcb - 0001fbef [ 37] */, 0x7efe8405 /* 0001fbfa - 0001ffff [ 1030] */, 0xa9b8001f /* 0002a6e0 - 0002a6ff [ 32] */, 0xadce8005 /* 0002b73a - 0002b73f [ 6] */, diff --git a/lib/libcxx/include/__format/extended_grapheme_cluster_table.h b/lib/libcxx/include/__format/extended_grapheme_cluster_table.h index 7653a9e03b..f76e018df7 100644 --- a/lib/libcxx/include/__format/extended_grapheme_cluster_table.h +++ b/lib/libcxx/include/__format/extended_grapheme_cluster_table.h @@ -125,7 +125,7 @@ enum class __property : uint8_t { /// following benchmark. /// libcxx/benchmarks/std_format_spec_string_unicode.bench.cpp // clang-format off -_LIBCPP_HIDE_FROM_ABI inline constexpr uint32_t __entries[1496] = { +_LIBCPP_HIDE_FROM_ABI inline constexpr uint32_t __entries[1501] = { 0x00000091, 0x00005005, 0x00005811, @@ -164,7 +164,7 @@ _LIBCPP_HIDE_FROM_ABI inline constexpr uint32_t __entries[1496] = { 0x00414842, 0x0042c822, 0x00448018, - 0x0044c072, + 0x0044b882, 0x00465172, 0x00471008, 0x004719f2, @@ -246,14 +246,12 @@ _LIBCPP_HIDE_FROM_ABI inline constexpr uint32_t __entries[1496] = { 0x0064101a, 0x0065e002, 0x0065f00a, - 0x0065f802, - 0x0066001a, + 0x0065f812, + 0x0066080a, 0x00661002, 0x0066181a, - 0x00663002, - 0x0066381a, - 0x0066501a, - 0x00666012, + 0x00663022, + 0x00665032, 0x0066a812, 0x00671012, 0x0067980a, @@ -318,10 +316,8 @@ _LIBCPP_HIDE_FROM_ABI inline constexpr uint32_t __entries[1496] = { 0x008b047c, 0x008d457b, 0x009ae822, - 0x00b89022, - 0x00b8a80a, - 0x00b99012, - 0x00b9a00a, + 0x00b89032, + 0x00b99022, 0x00ba9012, 0x00bb9012, 0x00bda012, @@ -361,29 +357,23 @@ _LIBCPP_HIDE_FROM_ABI inline constexpr uint32_t __entries[1496] = { 0x00d581e2, 0x00d80032, 0x00d8200a, - 0x00d9a062, - 0x00d9d80a, - 0x00d9e002, - 0x00d9e84a, - 0x00da1002, - 0x00da181a, + 0x00d9a092, + 0x00d9f03a, + 0x00da1022, 0x00db5882, 0x00dc0012, 0x00dc100a, 0x00dd080a, 0x00dd1032, 0x00dd301a, - 0x00dd4012, - 0x00dd500a, - 0x00dd5822, + 0x00dd4052, 0x00df3002, 0x00df380a, 0x00df4012, 0x00df502a, 0x00df6802, 0x00df700a, - 0x00df7822, - 0x00df901a, + 0x00df7842, 0x00e1207a, 0x00e16072, 0x00e1a01a, @@ -475,7 +465,8 @@ _LIBCPP_HIDE_FROM_ABI inline constexpr uint32_t __entries[1496] = { 0x0547f802, 0x05493072, 0x054a38a2, - 0x054a901a, + 0x054a900a, + 0x054a9802, 0x054b01c4, 0x054c0022, 0x054c180a, @@ -484,7 +475,8 @@ _LIBCPP_HIDE_FROM_ABI inline constexpr uint32_t __entries[1496] = { 0x054db032, 0x054dd01a, 0x054de012, - 0x054df02a, + 0x054df01a, + 0x054e0002, 0x054f2802, 0x05514852, 0x0551781a, @@ -1328,8 +1320,9 @@ _LIBCPP_HIDE_FROM_ABI inline constexpr uint32_t __entries[1496] = { 0x0851f802, 0x08572812, 0x08692032, + 0x086b4842, 0x08755812, - 0x0877e822, + 0x0877e032, 0x087a30a2, 0x087c1032, 0x0880000a, @@ -1357,7 +1350,8 @@ _LIBCPP_HIDE_FROM_ABI inline constexpr uint32_t __entries[1496] = { 0x088c100a, 0x088d982a, 0x088db082, - 0x088df81a, + 0x088df80a, + 0x088e0002, 0x088e1018, 0x088e4832, 0x088e700a, @@ -1365,9 +1359,7 @@ _LIBCPP_HIDE_FROM_ABI inline constexpr uint32_t __entries[1496] = { 0x0891602a, 0x08917822, 0x0891901a, - 0x0891a002, - 0x0891a80a, - 0x0891b012, + 0x0891a032, 0x0891f002, 0x08920802, 0x0896f802, @@ -1381,11 +1373,24 @@ _LIBCPP_HIDE_FROM_ABI inline constexpr uint32_t __entries[1496] = { 0x089a0002, 0x089a083a, 0x089a381a, - 0x089a582a, + 0x089a581a, + 0x089a6802, 0x089ab802, 0x089b101a, 0x089b3062, 0x089b8042, + 0x089dc002, + 0x089dc81a, + 0x089dd852, + 0x089e1002, + 0x089e2802, + 0x089e3822, + 0x089e500a, + 0x089e601a, + 0x089e7022, + 0x089e8808, + 0x089e9002, + 0x089f0812, 0x08a1a82a, 0x08a1c072, 0x08a2001a, @@ -1422,10 +1427,10 @@ _LIBCPP_HIDE_FROM_ABI inline constexpr uint32_t __entries[1496] = { 0x08b5600a, 0x08b56802, 0x08b5701a, - 0x08b58052, - 0x08b5b00a, - 0x08b5b802, - 0x08b8e822, + 0x08b58072, + 0x08b8e802, + 0x08b8f00a, + 0x08b8f802, 0x08b91032, 0x08b9300a, 0x08b93842, @@ -1436,9 +1441,7 @@ _LIBCPP_HIDE_FROM_ABI inline constexpr uint32_t __entries[1496] = { 0x08c98002, 0x08c9884a, 0x08c9b81a, - 0x08c9d812, - 0x08c9e80a, - 0x08c9f002, + 0x08c9d832, 0x08c9f808, 0x08ca000a, 0x08ca0808, @@ -1495,28 +1498,29 @@ _LIBCPP_HIDE_FROM_ABI inline constexpr uint32_t __entries[1496] = { 0x08f9a01a, 0x08f9b042, 0x08f9f01a, - 0x08fa0002, - 0x08fa080a, - 0x08fa1002, + 0x08fa0022, + 0x08fad002, 0x09a180f1, 0x09a20002, 0x09a238e2, + 0x0b08f0b2, + 0x0b09502a, + 0x0b096822, 0x0b578042, 0x0b598062, + 0x0b6b180c, + 0x0b6b383c, 0x0b7a7802, 0x0b7a8b6a, 0x0b7c7832, 0x0b7f2002, - 0x0b7f801a, + 0x0b7f8012, 0x0de4e812, 0x0de50031, 0x0e7802d2, 0x0e798162, - 0x0e8b2802, - 0x0e8b300a, - 0x0e8b3822, - 0x0e8b680a, - 0x0e8b7042, + 0x0e8b2842, + 0x0e8b6852, 0x0e8b9871, 0x0e8bd872, 0x0e8c2862, @@ -1538,6 +1542,7 @@ _LIBCPP_HIDE_FROM_ABI inline constexpr uint32_t __entries[1496] = { 0x0f157002, 0x0f176032, 0x0f276032, + 0x0f2f7012, 0x0f468062, 0x0f4a2062, 0x0f8007f3, diff --git a/lib/libcxx/include/__format/format_arg.h b/lib/libcxx/include/__format/format_arg.h index 10f0ba9928..ed5e76275e 100644 --- a/lib/libcxx/include/__format/format_arg.h +++ b/lib/libcxx/include/__format/format_arg.h @@ -277,9 +277,9 @@ public: }; template -class _LIBCPP_TEMPLATE_VIS _LIBCPP_NO_SPECIALIZATIONS basic_format_arg { +class _LIBCPP_NO_SPECIALIZATIONS basic_format_arg { public: - class _LIBCPP_TEMPLATE_VIS handle; + class handle; _LIBCPP_HIDE_FROM_ABI basic_format_arg() noexcept : __type_{__format::__arg_t::__none} {} @@ -355,7 +355,7 @@ public: }; template -class _LIBCPP_TEMPLATE_VIS basic_format_arg<_Context>::handle { +class basic_format_arg<_Context>::handle { public: _LIBCPP_HIDE_FROM_ABI void format(basic_format_parse_context& __parse_ctx, _Context& __ctx) const { __handle_.__format_(__parse_ctx, __ctx, __handle_.__ptr_); diff --git a/lib/libcxx/include/__format/format_arg_store.h b/lib/libcxx/include/__format/format_arg_store.h index 4c5ee9e9e4..fbb4cad21b 100644 --- a/lib/libcxx/include/__format/format_arg_store.h +++ b/lib/libcxx/include/__format/format_arg_store.h @@ -14,13 +14,14 @@ # pragma GCC system_header #endif -#include <__concepts/arithmetic.h> #include <__concepts/same_as.h> #include <__config> +#include <__cstddef/size_t.h> #include <__format/concepts.h> #include <__format/format_arg.h> #include <__type_traits/conditional.h> #include <__type_traits/extent.h> +#include <__type_traits/integer_traits.h> #include <__type_traits/remove_const.h> #include #include @@ -32,6 +33,12 @@ _LIBCPP_BEGIN_NAMESPACE_STD namespace __format { +template +inline constexpr bool __is_bounded_array_of = false; + +template +inline constexpr bool __is_bounded_array_of<_Elem[_Len], _Elem> = true; + /// \returns The @c __arg_t based on the type of the formatting argument. /// /// \pre \c __formattable<_Tp, typename _Context::char_type> @@ -58,7 +65,7 @@ consteval __arg_t __determine_arg_t() { # endif // Signed integers -template +template consteval __arg_t __determine_arg_t() { if constexpr (sizeof(_Tp) <= sizeof(int)) return __arg_t::__int; @@ -73,7 +80,7 @@ consteval __arg_t __determine_arg_t() { } // Unsigned integers -template +template consteval __arg_t __determine_arg_t() { if constexpr (sizeof(_Tp) <= sizeof(unsigned)) return __arg_t::__unsigned; @@ -110,7 +117,7 @@ consteval __arg_t __determine_arg_t() { // Char array template - requires(is_array_v<_Tp> && same_as<_Tp, typename _Context::char_type[extent_v<_Tp>]>) + requires __is_bounded_array_of<_Tp, typename _Context::char_type> consteval __arg_t __determine_arg_t() { return __arg_t::__string_view; } @@ -164,17 +171,18 @@ consteval __arg_t __determine_arg_t() { template _LIBCPP_HIDE_FROM_ABI basic_format_arg<_Context> __create_format_arg(_Tp& __value) noexcept { using _Dp = remove_const_t<_Tp>; - constexpr __arg_t __arg = __determine_arg_t<_Context, _Dp>(); + constexpr __arg_t __arg = __format::__determine_arg_t<_Context, _Dp>(); static_assert(__arg != __arg_t::__none, "the supplied type is not formattable"); static_assert(__formattable_with<_Tp, _Context>); + using __context_char_type = _Context::char_type; // Not all types can be used to directly initialize the // __basic_format_arg_value. First handle all types needing adjustment, the // final else requires no adjustment. if constexpr (__arg == __arg_t::__char_type) # if _LIBCPP_HAS_WIDE_CHARACTERS - if constexpr (same_as && same_as<_Dp, char>) + if constexpr (same_as<__context_char_type, wchar_t> && same_as<_Dp, char>) return basic_format_arg<_Context>{__arg, static_cast(static_cast(__value))}; else # endif @@ -189,14 +197,16 @@ _LIBCPP_HIDE_FROM_ABI basic_format_arg<_Context> __create_format_arg(_Tp& __valu return basic_format_arg<_Context>{__arg, static_cast(__value)}; else if constexpr (__arg == __arg_t::__string_view) // Using std::size on a character array will add the NUL-terminator to the size. - if constexpr (is_array_v<_Dp>) + if constexpr (__is_bounded_array_of<_Dp, __context_char_type>) { + const __context_char_type* const __pbegin = std::begin(__value); + const __context_char_type* const __pzero = + char_traits<__context_char_type>::find(__pbegin, extent_v<_Dp>, __context_char_type{}); + _LIBCPP_ASSERT_VALID_INPUT_RANGE(__pzero != nullptr, "formatting a non-null-terminated array"); return basic_format_arg<_Context>{ - __arg, basic_string_view{__value, extent_v<_Dp> - 1}}; - else - // When the _Traits or _Allocator are different an implicit conversion will - // fail. - return basic_format_arg<_Context>{ - __arg, basic_string_view{__value.data(), __value.size()}}; + __arg, basic_string_view<__context_char_type>{__pbegin, static_cast(__pzero - __pbegin)}}; + } else + // When the _Traits or _Allocator are different an implicit conversion will fail. + return basic_format_arg<_Context>{__arg, basic_string_view<__context_char_type>{__value.data(), __value.size()}}; else if constexpr (__arg == __arg_t::__ptr) return basic_format_arg<_Context>{__arg, static_cast(__value)}; else if constexpr (__arg == __arg_t::__handle) @@ -247,7 +257,7 @@ struct __unpacked_format_arg_store { } // namespace __format template -struct _LIBCPP_TEMPLATE_VIS __format_arg_store { +struct __format_arg_store { _LIBCPP_HIDE_FROM_ABI __format_arg_store(_Args&... __args) noexcept { if constexpr (sizeof...(_Args) != 0) { if constexpr (__format::__use_packed_format_arg_store(sizeof...(_Args))) diff --git a/lib/libcxx/include/__format/format_args.h b/lib/libcxx/include/__format/format_args.h index b98663c06e..9dd7a5ed9c 100644 --- a/lib/libcxx/include/__format/format_args.h +++ b/lib/libcxx/include/__format/format_args.h @@ -26,7 +26,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD #if _LIBCPP_STD_VER >= 20 template -class _LIBCPP_TEMPLATE_VIS basic_format_args { +class basic_format_args { public: template _LIBCPP_HIDE_FROM_ABI basic_format_args(const __format_arg_store<_Context, _Args...>& __store) noexcept diff --git a/lib/libcxx/include/__format/format_context.h b/lib/libcxx/include/__format/format_context.h index 4dbfdbc02a..e672ee7ad0 100644 --- a/lib/libcxx/include/__format/format_context.h +++ b/lib/libcxx/include/__format/format_context.h @@ -42,7 +42,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD template requires output_iterator<_OutIt, const _CharT&> -class _LIBCPP_TEMPLATE_VIS basic_format_context; +class basic_format_context; # if _LIBCPP_HAS_LOCALIZATION /** @@ -72,13 +72,8 @@ using wformat_context = basic_format_context< back_insert_iterator<__format::__o template requires output_iterator<_OutIt, const _CharT&> -class - // clang-format off - _LIBCPP_TEMPLATE_VIS - _LIBCPP_PREFERRED_NAME(format_context) - _LIBCPP_IF_WIDE_CHARACTERS(_LIBCPP_PREFERRED_NAME(wformat_context)) - // clang-format on - basic_format_context { +class _LIBCPP_PREFERRED_NAME(format_context) + _LIBCPP_IF_WIDE_CHARACTERS(_LIBCPP_PREFERRED_NAME(wformat_context)) basic_format_context { public: using iterator = _OutIt; using char_type = _CharT; @@ -153,7 +148,7 @@ public: // Here the width of an element in input is determined dynamically. // Note when the top-level element has no width the retargeting is not needed. template -class _LIBCPP_TEMPLATE_VIS basic_format_context::__iterator, _CharT> { +class basic_format_context::__iterator, _CharT> { public: using iterator = typename __format::__retarget_buffer<_CharT>::__iterator; using char_type = _CharT; diff --git a/lib/libcxx/include/__format/format_functions.h b/lib/libcxx/include/__format/format_functions.h index 5feaf7e5a0..873265bc17 100644 --- a/lib/libcxx/include/__format/format_functions.h +++ b/lib/libcxx/include/__format/format_functions.h @@ -11,6 +11,8 @@ #define _LIBCPP___FORMAT_FORMAT_FUNCTIONS #include <__algorithm/clamp.h> +#include <__algorithm/ranges_find_first_of.h> +#include <__chrono/statically_widen.h> #include <__concepts/convertible_to.h> #include <__concepts/same_as.h> #include <__config> @@ -36,6 +38,7 @@ #include <__iterator/iterator_traits.h> // iter_value_t #include <__variant/monostate.h> #include +#include #include #include @@ -83,7 +86,7 @@ namespace __format { /// When parsing a handle which is not enabled the code is ill-formed. /// This helper uses the parser of the appropriate formatter for the stored type. template -class _LIBCPP_TEMPLATE_VIS __compile_time_handle { +class __compile_time_handle { public: template _LIBCPP_HIDE_FROM_ABI constexpr void __parse(_ParseContext& __ctx) const { @@ -110,7 +113,7 @@ private: // Dummy format_context only providing the parts used during constant // validation of the basic_format_string. template -struct _LIBCPP_TEMPLATE_VIS __compile_time_basic_format_context { +struct __compile_time_basic_format_context { public: using char_type = _CharT; @@ -339,12 +342,12 @@ _LIBCPP_HIDE_FROM_ABI constexpr typename _Ctx::iterator __vformat_to(_ParseCtx&& # if _LIBCPP_STD_VER >= 26 template -struct _LIBCPP_TEMPLATE_VIS __runtime_format_string { +struct __runtime_format_string { private: basic_string_view<_CharT> __str_; template - friend struct _LIBCPP_TEMPLATE_VIS basic_format_string; + friend struct basic_format_string; public: _LIBCPP_HIDE_FROM_ABI __runtime_format_string(basic_string_view<_CharT> __s) noexcept : __str_(__s) {} @@ -362,7 +365,7 @@ _LIBCPP_HIDE_FROM_ABI inline __runtime_format_string runtime_format(wst # endif // _LIBCPP_STD_VER >= 26 template -struct _LIBCPP_TEMPLATE_VIS basic_format_string { +struct basic_format_string { template requires convertible_to> consteval basic_format_string(const _Tp& __str) : __str_{__str} { @@ -447,10 +450,47 @@ format_to(_OutIt __out_it, wformat_string<_Args...> __fmt, _Args&&... __args) { } # endif +// Try constant folding the format string instead of going through the whole formatting machinery. If there is no +// constant folding no extra code should be emitted (with optimizations enabled) and the function returns nullopt. When +// constant folding is successful, the formatting is performed and the resulting string is returned. +namespace __format { +template +[[nodiscard]] _LIBCPP_HIDE_FROM_ABI optional> __try_constant_folding( + basic_string_view<_CharT> __fmt, + basic_format_args>, _CharT>> __args) { + // Fold strings not containing '{' or '}' to just return the string + if (bool __is_identity = [&] [[__gnu__::__pure__]] // Make sure the compiler knows this call can be eliminated + { return std::ranges::find_first_of(__fmt, array{'{', '}'}) == __fmt.end(); }(); + __builtin_constant_p(__is_identity) && __is_identity) + return basic_string<_CharT>{__fmt}; + + // Fold '{}' to the appropriate conversion function + if (auto __only_first_arg = __fmt == _LIBCPP_STATICALLY_WIDEN(_CharT, "{}"); + __builtin_constant_p(__only_first_arg) && __only_first_arg) { + if (auto __arg = __args.get(0); __builtin_constant_p(__arg.__type_)) { + return std::__visit_format_arg( + [](_Tp&& __argument) -> optional> { + if constexpr (is_same_v, basic_string_view<_CharT>>) { + return basic_string<_CharT>{__argument}; + } else { + return nullopt; + } + }, + __arg); + } + } + + return nullopt; +} +} // namespace __format + // TODO FMT This needs to be a template or std::to_chars(floating-point) availability markup // fires too eagerly, see http://llvm.org/PR61563. template [[nodiscard]] _LIBCPP_ALWAYS_INLINE inline _LIBCPP_HIDE_FROM_ABI string vformat(string_view __fmt, format_args __args) { + auto __result = __format::__try_constant_folding(__fmt, __args); + if (__result.has_value()) + return *std::move(__result); __format::__allocating_buffer __buffer; std::vformat_to(__buffer.__make_output_iterator(), __fmt, __args); return string{__buffer.__view()}; @@ -462,6 +502,9 @@ template template [[nodiscard]] _LIBCPP_ALWAYS_INLINE inline _LIBCPP_HIDE_FROM_ABI wstring vformat(wstring_view __fmt, wformat_args __args) { + auto __result = __format::__try_constant_folding(__fmt, __args); + if (__result.has_value()) + return *std::move(__result); __format::__allocating_buffer __buffer; std::vformat_to(__buffer.__make_output_iterator(), __fmt, __args); return wstring{__buffer.__view()}; diff --git a/lib/libcxx/include/__format/format_parse_context.h b/lib/libcxx/include/__format/format_parse_context.h index 459db751c9..67b90c7b7e 100644 --- a/lib/libcxx/include/__format/format_parse_context.h +++ b/lib/libcxx/include/__format/format_parse_context.h @@ -24,7 +24,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD #if _LIBCPP_STD_VER >= 20 template -class _LIBCPP_TEMPLATE_VIS basic_format_parse_context { +class basic_format_parse_context { public: using char_type = _CharT; using const_iterator = typename basic_string_view<_CharT>::const_iterator; diff --git a/lib/libcxx/include/__format/format_string.h b/lib/libcxx/include/__format/format_string.h index 5db5973dd5..b60ed4db38 100644 --- a/lib/libcxx/include/__format/format_string.h +++ b/lib/libcxx/include/__format/format_string.h @@ -29,7 +29,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD namespace __format { template -struct _LIBCPP_TEMPLATE_VIS __parse_number_result { +struct __parse_number_result { _Iterator __last; uint32_t __value; }; diff --git a/lib/libcxx/include/__format/format_to_n_result.h b/lib/libcxx/include/__format/format_to_n_result.h index 344299e32f..0c807be732 100644 --- a/lib/libcxx/include/__format/format_to_n_result.h +++ b/lib/libcxx/include/__format/format_to_n_result.h @@ -22,7 +22,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD #if _LIBCPP_STD_VER >= 20 template -struct _LIBCPP_TEMPLATE_VIS format_to_n_result { +struct format_to_n_result { _OutIt out; iter_difference_t<_OutIt> size; }; diff --git a/lib/libcxx/include/__format/formatter.h b/lib/libcxx/include/__format/formatter.h index 39c2670dd8..cbbd9d4f7c 100644 --- a/lib/libcxx/include/__format/formatter.h +++ b/lib/libcxx/include/__format/formatter.h @@ -21,6 +21,12 @@ _LIBCPP_BEGIN_NAMESPACE_STD #if _LIBCPP_STD_VER >= 20 +struct __disabled_formatter { + __disabled_formatter() = delete; + __disabled_formatter(const __disabled_formatter&) = delete; + __disabled_formatter& operator=(const __disabled_formatter&) = delete; +}; + /// The default formatter template. /// /// [format.formatter.spec]/5 @@ -28,14 +34,10 @@ _LIBCPP_BEGIN_NAMESPACE_STD /// - is_default_constructible_v, /// - is_copy_constructible_v, /// - is_move_constructible_v, -/// - is_copy_assignable, and -/// - is_move_assignable. +/// - is_copy_assignable_v, and +/// - is_move_assignable_v. template -struct _LIBCPP_TEMPLATE_VIS formatter { - formatter() = delete; - formatter(const formatter&) = delete; - formatter& operator=(const formatter&) = delete; -}; +struct formatter : __disabled_formatter {}; # if _LIBCPP_STD_VER >= 23 diff --git a/lib/libcxx/include/__format/formatter_bool.h b/lib/libcxx/include/__format/formatter_bool.h index d08acd4744..33a148a546 100644 --- a/lib/libcxx/include/__format/formatter_bool.h +++ b/lib/libcxx/include/__format/formatter_bool.h @@ -33,7 +33,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD #if _LIBCPP_STD_VER >= 20 template <__fmt_char_type _CharT> -struct _LIBCPP_TEMPLATE_VIS formatter { +struct formatter { public: template _LIBCPP_HIDE_FROM_ABI constexpr typename _ParseContext::iterator parse(_ParseContext& __ctx) { diff --git a/lib/libcxx/include/__format/formatter_char.h b/lib/libcxx/include/__format/formatter_char.h index 8b8fd2d42c..40eb5a02a7 100644 --- a/lib/libcxx/include/__format/formatter_char.h +++ b/lib/libcxx/include/__format/formatter_char.h @@ -31,7 +31,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD #if _LIBCPP_STD_VER >= 20 template <__fmt_char_type _CharT> -struct _LIBCPP_TEMPLATE_VIS __formatter_char { +struct __formatter_char { public: template _LIBCPP_HIDE_FROM_ABI constexpr typename _ParseContext::iterator parse(_ParseContext& __ctx) { @@ -75,14 +75,14 @@ public: }; template <> -struct _LIBCPP_TEMPLATE_VIS formatter : public __formatter_char {}; +struct formatter : public __formatter_char {}; # if _LIBCPP_HAS_WIDE_CHARACTERS template <> -struct _LIBCPP_TEMPLATE_VIS formatter : public __formatter_char {}; +struct formatter : public __formatter_char {}; template <> -struct _LIBCPP_TEMPLATE_VIS formatter : public __formatter_char {}; +struct formatter : public __formatter_char {}; # endif // _LIBCPP_HAS_WIDE_CHARACTERS # if _LIBCPP_STD_VER >= 23 diff --git a/lib/libcxx/include/__format/formatter_floating_point.h b/lib/libcxx/include/__format/formatter_floating_point.h index ac4be9b619..b200bc58ba 100644 --- a/lib/libcxx/include/__format/formatter_floating_point.h +++ b/lib/libcxx/include/__format/formatter_floating_point.h @@ -19,6 +19,7 @@ #include <__assert> #include <__charconv/chars_format.h> #include <__charconv/to_chars_floating_point.h> +#include <__charconv/to_chars_integral.h> #include <__charconv/to_chars_result.h> #include <__concepts/arithmetic.h> #include <__concepts/same_as.h> @@ -140,7 +141,7 @@ struct __traits { /// Depending on the maximum size required for a value, the buffer is allocated /// on the stack or the heap. template -class _LIBCPP_TEMPLATE_VIS __float_buffer { +class __float_buffer { using _Traits _LIBCPP_NODEBUG = __traits<_Fp>; public: @@ -750,7 +751,7 @@ __format_floating_point(_Tp __value, _FormatContext& __ctx, __format_spec::__par } // namespace __formatter template <__fmt_char_type _CharT> -struct _LIBCPP_TEMPLATE_VIS __formatter_floating_point { +struct __formatter_floating_point { public: template _LIBCPP_HIDE_FROM_ABI constexpr typename _ParseContext::iterator parse(_ParseContext& __ctx) { @@ -768,11 +769,11 @@ public: }; template <__fmt_char_type _CharT> -struct _LIBCPP_TEMPLATE_VIS formatter : public __formatter_floating_point<_CharT> {}; +struct formatter : public __formatter_floating_point<_CharT> {}; template <__fmt_char_type _CharT> -struct _LIBCPP_TEMPLATE_VIS formatter : public __formatter_floating_point<_CharT> {}; +struct formatter : public __formatter_floating_point<_CharT> {}; template <__fmt_char_type _CharT> -struct _LIBCPP_TEMPLATE_VIS formatter : public __formatter_floating_point<_CharT> {}; +struct formatter : public __formatter_floating_point<_CharT> {}; # if _LIBCPP_STD_VER >= 23 template <> diff --git a/lib/libcxx/include/__format/formatter_integer.h b/lib/libcxx/include/__format/formatter_integer.h index 3f51b10d75..cf186c64e3 100644 --- a/lib/libcxx/include/__format/formatter_integer.h +++ b/lib/libcxx/include/__format/formatter_integer.h @@ -30,7 +30,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD #if _LIBCPP_STD_VER >= 20 template <__fmt_char_type _CharT> -struct _LIBCPP_TEMPLATE_VIS __formatter_integer { +struct __formatter_integer { public: template _LIBCPP_HIDE_FROM_ABI constexpr typename _ParseContext::iterator parse(_ParseContext& __ctx) { @@ -58,34 +58,34 @@ public: // Signed integral types. template <__fmt_char_type _CharT> -struct _LIBCPP_TEMPLATE_VIS formatter : public __formatter_integer<_CharT> {}; +struct formatter : public __formatter_integer<_CharT> {}; template <__fmt_char_type _CharT> -struct _LIBCPP_TEMPLATE_VIS formatter : public __formatter_integer<_CharT> {}; +struct formatter : public __formatter_integer<_CharT> {}; template <__fmt_char_type _CharT> -struct _LIBCPP_TEMPLATE_VIS formatter : public __formatter_integer<_CharT> {}; +struct formatter : public __formatter_integer<_CharT> {}; template <__fmt_char_type _CharT> -struct _LIBCPP_TEMPLATE_VIS formatter : public __formatter_integer<_CharT> {}; +struct formatter : public __formatter_integer<_CharT> {}; template <__fmt_char_type _CharT> -struct _LIBCPP_TEMPLATE_VIS formatter : public __formatter_integer<_CharT> {}; +struct formatter : public __formatter_integer<_CharT> {}; # if _LIBCPP_HAS_INT128 template <__fmt_char_type _CharT> -struct _LIBCPP_TEMPLATE_VIS formatter<__int128_t, _CharT> : public __formatter_integer<_CharT> {}; +struct formatter<__int128_t, _CharT> : public __formatter_integer<_CharT> {}; # endif // Unsigned integral types. template <__fmt_char_type _CharT> -struct _LIBCPP_TEMPLATE_VIS formatter : public __formatter_integer<_CharT> {}; +struct formatter : public __formatter_integer<_CharT> {}; template <__fmt_char_type _CharT> -struct _LIBCPP_TEMPLATE_VIS formatter : public __formatter_integer<_CharT> {}; +struct formatter : public __formatter_integer<_CharT> {}; template <__fmt_char_type _CharT> -struct _LIBCPP_TEMPLATE_VIS formatter : public __formatter_integer<_CharT> {}; +struct formatter : public __formatter_integer<_CharT> {}; template <__fmt_char_type _CharT> -struct _LIBCPP_TEMPLATE_VIS formatter : public __formatter_integer<_CharT> {}; +struct formatter : public __formatter_integer<_CharT> {}; template <__fmt_char_type _CharT> -struct _LIBCPP_TEMPLATE_VIS formatter : public __formatter_integer<_CharT> {}; +struct formatter : public __formatter_integer<_CharT> {}; # if _LIBCPP_HAS_INT128 template <__fmt_char_type _CharT> -struct _LIBCPP_TEMPLATE_VIS formatter<__uint128_t, _CharT> : public __formatter_integer<_CharT> {}; +struct formatter<__uint128_t, _CharT> : public __formatter_integer<_CharT> {}; # endif # if _LIBCPP_STD_VER >= 23 diff --git a/lib/libcxx/include/__format/formatter_integral.h b/lib/libcxx/include/__format/formatter_integral.h index 996b7620b3..85f509fad4 100644 --- a/lib/libcxx/include/__format/formatter_integral.h +++ b/lib/libcxx/include/__format/formatter_integral.h @@ -338,7 +338,7 @@ _LIBCPP_HIDE_FROM_ABI typename _FormatContext::iterator __format_integer( if (__specs.__std_.__type_ != __format_spec::__type::__hexadecimal_upper_case) [[likely]] return __formatter::__write(__first, __last, __ctx.out(), __specs); - return __formatter::__write_transformed(__first, __last, __ctx.out(), __specs, __formatter::__hex_to_upper); + return __formatter::__write_transformed(__first, __last, __ctx.out(), __specs, std::__hex_to_upper); } template @@ -404,17 +404,17 @@ __format_integer(_Tp __value, _FormatContext& __ctx, __format_spec::__parsed_spe // template -struct _LIBCPP_TEMPLATE_VIS __bool_strings; +struct __bool_strings; template <> -struct _LIBCPP_TEMPLATE_VIS __bool_strings { +struct __bool_strings { static constexpr string_view __true{"true"}; static constexpr string_view __false{"false"}; }; # if _LIBCPP_HAS_WIDE_CHARACTERS template <> -struct _LIBCPP_TEMPLATE_VIS __bool_strings { +struct __bool_strings { static constexpr wstring_view __true{L"true"}; static constexpr wstring_view __false{L"false"}; }; diff --git a/lib/libcxx/include/__format/formatter_output.h b/lib/libcxx/include/__format/formatter_output.h index e1f1309cd2..cc74e3858a 100644 --- a/lib/libcxx/include/__format/formatter_output.h +++ b/lib/libcxx/include/__format/formatter_output.h @@ -45,24 +45,6 @@ _LIBCPP_BEGIN_NAMESPACE_STD namespace __formatter { -_LIBCPP_HIDE_FROM_ABI constexpr char __hex_to_upper(char __c) { - switch (__c) { - case 'a': - return 'A'; - case 'b': - return 'B'; - case 'c': - return 'C'; - case 'd': - return 'D'; - case 'e': - return 'E'; - case 'f': - return 'F'; - } - return __c; -} - struct _LIBCPP_EXPORTED_FROM_ABI __padding_size_result { size_t __before_; size_t __after_; diff --git a/lib/libcxx/include/__format/formatter_pointer.h b/lib/libcxx/include/__format/formatter_pointer.h index 4ef48c168d..4c5896d589 100644 --- a/lib/libcxx/include/__format/formatter_pointer.h +++ b/lib/libcxx/include/__format/formatter_pointer.h @@ -29,7 +29,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD #if _LIBCPP_STD_VER >= 20 template <__fmt_char_type _CharT> -struct _LIBCPP_TEMPLATE_VIS __formatter_pointer { +struct __formatter_pointer { public: template _LIBCPP_HIDE_FROM_ABI constexpr typename _ParseContext::iterator parse(_ParseContext& __ctx) { @@ -59,11 +59,11 @@ public: // - template<> struct formatter; // - template<> struct formatter; template <__fmt_char_type _CharT> -struct _LIBCPP_TEMPLATE_VIS formatter : public __formatter_pointer<_CharT> {}; +struct formatter : public __formatter_pointer<_CharT> {}; template <__fmt_char_type _CharT> -struct _LIBCPP_TEMPLATE_VIS formatter : public __formatter_pointer<_CharT> {}; +struct formatter : public __formatter_pointer<_CharT> {}; template <__fmt_char_type _CharT> -struct _LIBCPP_TEMPLATE_VIS formatter : public __formatter_pointer<_CharT> {}; +struct formatter : public __formatter_pointer<_CharT> {}; # if _LIBCPP_STD_VER >= 23 template <> diff --git a/lib/libcxx/include/__format/formatter_string.h b/lib/libcxx/include/__format/formatter_string.h index 30084e5822..bad6a4d2bb 100644 --- a/lib/libcxx/include/__format/formatter_string.h +++ b/lib/libcxx/include/__format/formatter_string.h @@ -10,6 +10,7 @@ #ifndef _LIBCPP___FORMAT_FORMATTER_STRING_H #define _LIBCPP___FORMAT_FORMATTER_STRING_H +#include <__assert> #include <__config> #include <__format/concepts.h> #include <__format/format_parse_context.h> @@ -17,6 +18,7 @@ #include <__format/formatter_output.h> #include <__format/parser_std_format_spec.h> #include <__format/write_escaped.h> +#include #include #include @@ -29,7 +31,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD #if _LIBCPP_STD_VER >= 20 template <__fmt_char_type _CharT> -struct _LIBCPP_TEMPLATE_VIS __formatter_string { +struct __formatter_string { public: template _LIBCPP_HIDE_FROM_ABI constexpr typename _ParseContext::iterator parse(_ParseContext& __ctx) { @@ -58,7 +60,7 @@ public: // Formatter const char*. template <__fmt_char_type _CharT> -struct _LIBCPP_TEMPLATE_VIS formatter : public __formatter_string<_CharT> { +struct formatter : public __formatter_string<_CharT> { using _Base _LIBCPP_NODEBUG = __formatter_string<_CharT>; template @@ -77,7 +79,7 @@ struct _LIBCPP_TEMPLATE_VIS formatter : public __formatte // Formatter char*. template <__fmt_char_type _CharT> -struct _LIBCPP_TEMPLATE_VIS formatter<_CharT*, _CharT> : public formatter { +struct formatter<_CharT*, _CharT> : public formatter { using _Base _LIBCPP_NODEBUG = formatter; template @@ -88,20 +90,21 @@ struct _LIBCPP_TEMPLATE_VIS formatter<_CharT*, _CharT> : public formatter -struct _LIBCPP_TEMPLATE_VIS formatter<_CharT[_Size], _CharT> : public __formatter_string<_CharT> { +struct formatter<_CharT[_Size], _CharT> : public __formatter_string<_CharT> { using _Base _LIBCPP_NODEBUG = __formatter_string<_CharT>; template _LIBCPP_HIDE_FROM_ABI typename _FormatContext::iterator format(const _CharT (&__str)[_Size], _FormatContext& __ctx) const { - return _Base::format(basic_string_view<_CharT>(__str, _Size), __ctx); + const _CharT* const __pzero = char_traits<_CharT>::find(__str, _Size, _CharT{}); + _LIBCPP_ASSERT_VALID_INPUT_RANGE(__pzero != nullptr, "formatting a non-null-terminated array"); + return _Base::format(basic_string_view<_CharT>(__str, static_cast(__pzero - __str)), __ctx); } }; // Formatter std::string. template <__fmt_char_type _CharT, class _Traits, class _Allocator> -struct _LIBCPP_TEMPLATE_VIS formatter, _CharT> - : public __formatter_string<_CharT> { +struct formatter, _CharT> : public __formatter_string<_CharT> { using _Base _LIBCPP_NODEBUG = __formatter_string<_CharT>; template @@ -114,7 +117,7 @@ struct _LIBCPP_TEMPLATE_VIS formatter, // Formatter std::string_view. template <__fmt_char_type _CharT, class _Traits> -struct _LIBCPP_TEMPLATE_VIS formatter, _CharT> : public __formatter_string<_CharT> { +struct formatter, _CharT> : public __formatter_string<_CharT> { using _Base _LIBCPP_NODEBUG = __formatter_string<_CharT>; template @@ -125,6 +128,19 @@ struct _LIBCPP_TEMPLATE_VIS formatter, _CharT } }; +# if _LIBCPP_HAS_WIDE_CHARACTERS +template <> +struct formatter : __disabled_formatter {}; +template <> +struct formatter : __disabled_formatter {}; +template +struct formatter : __disabled_formatter {}; +template +struct formatter, wchar_t> : __disabled_formatter {}; +template +struct formatter, wchar_t> : __disabled_formatter {}; +# endif // _LIBCPP_HAS_WIDE_CHARACTERS + # if _LIBCPP_STD_VER >= 23 template <> inline constexpr bool enable_nonlocking_formatter_optimization = true; diff --git a/lib/libcxx/include/__format/formatter_tuple.h b/lib/libcxx/include/__format/formatter_tuple.h index bb841ef114..0b095e6f71 100644 --- a/lib/libcxx/include/__format/formatter_tuple.h +++ b/lib/libcxx/include/__format/formatter_tuple.h @@ -36,7 +36,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD #if _LIBCPP_STD_VER >= 23 template <__fmt_char_type _CharT, class _Tuple, formattable<_CharT>... _Args> -struct _LIBCPP_TEMPLATE_VIS __formatter_tuple { +struct __formatter_tuple { _LIBCPP_HIDE_FROM_ABI constexpr void set_separator(basic_string_view<_CharT> __separator) noexcept { __separator_ = __separator; } @@ -136,12 +136,10 @@ private: }; template <__fmt_char_type _CharT, formattable<_CharT>... _Args> -struct _LIBCPP_TEMPLATE_VIS formatter, _CharT> - : public __formatter_tuple<_CharT, pair<_Args...>, _Args...> {}; +struct formatter, _CharT> : public __formatter_tuple<_CharT, pair<_Args...>, _Args...> {}; template <__fmt_char_type _CharT, formattable<_CharT>... _Args> -struct _LIBCPP_TEMPLATE_VIS formatter, _CharT> - : public __formatter_tuple<_CharT, tuple<_Args...>, _Args...> {}; +struct formatter, _CharT> : public __formatter_tuple<_CharT, tuple<_Args...>, _Args...> {}; #endif // _LIBCPP_STD_VER >= 23 diff --git a/lib/libcxx/include/__format/indic_conjunct_break_table.h b/lib/libcxx/include/__format/indic_conjunct_break_table.h index df6cfe6a02..f48ea62590 100644 --- a/lib/libcxx/include/__format/indic_conjunct_break_table.h +++ b/lib/libcxx/include/__format/indic_conjunct_break_table.h @@ -107,10 +107,9 @@ enum class __property : uint8_t { /// following benchmark. /// libcxx/benchmarks/std_format_spec_string_unicode.bench.cpp // clang-format off -_LIBCPP_HIDE_FROM_ABI inline constexpr uint32_t __entries[201] = { - 0x00180139, - 0x001a807d, - 0x00241811, +_LIBCPP_HIDE_FROM_ABI inline constexpr uint32_t __entries[403] = { + 0x001801bd, + 0x00241819, 0x002c88b1, 0x002df801, 0x002e0805, @@ -125,6 +124,7 @@ _LIBCPP_HIDE_FROM_ABI inline constexpr uint32_t __entries[201] = { 0x0037500d, 0x00388801, 0x00398069, + 0x003d3029, 0x003f5821, 0x003fe801, 0x0040b00d, @@ -132,87 +132,174 @@ _LIBCPP_HIDE_FROM_ABI inline constexpr uint32_t __entries[201] = { 0x00412809, 0x00414811, 0x0042c809, - 0x0044c01d, + 0x0044b821, 0x0046505d, - 0x00471871, + 0x0047187d, 0x0048a890, + 0x0049d001, 0x0049e001, + 0x004a081d, 0x004a6802, - 0x004a880d, + 0x004a8819, 0x004ac01c, + 0x004b1005, 0x004bc01c, + 0x004c0801, 0x004ca84c, 0x004d5018, 0x004d9000, 0x004db00c, 0x004de001, + 0x004df001, + 0x004e080d, 0x004e6802, + 0x004eb801, 0x004ee004, 0x004ef800, + 0x004f1005, 0x004f8004, 0x004ff001, + 0x00500805, 0x0051e001, + 0x00520805, + 0x00523805, + 0x00525809, + 0x00528801, + 0x00538005, + 0x0053a801, + 0x00540805, 0x0054a84c, 0x00555018, 0x00559004, 0x0055a810, 0x0055e001, + 0x00560811, + 0x00563805, 0x00566802, + 0x00571005, 0x0057c800, + 0x0057d015, + 0x00580801, 0x0058a84c, 0x00595018, 0x00599004, 0x0059a810, 0x0059e001, + 0x0059f005, + 0x005a080d, 0x005a6802, + 0x005aa809, 0x005ae004, 0x005af800, + 0x005b1005, 0x005b8800, + 0x005c1001, + 0x005df001, + 0x005e0001, + 0x005e6801, + 0x005eb801, + 0x00600001, + 0x00602001, 0x0060a84c, 0x0061503c, 0x0061e001, + 0x0061f009, + 0x00623009, + 0x00625009, 0x00626802, 0x0062a805, 0x0062c008, + 0x00631005, + 0x00640801, 0x0065e001, + 0x0065f805, + 0x00661001, + 0x00663009, + 0x0066500d, + 0x0066a805, + 0x00671005, + 0x00680005, 0x0068a894, 0x0069d805, + 0x0069f001, + 0x006a080d, 0x006a6802, - 0x0071c009, - 0x0072400d, - 0x0075c009, - 0x0076400d, + 0x006ab801, + 0x006b1005, + 0x006c0801, + 0x006e5001, + 0x006e7801, + 0x006e9009, + 0x006eb001, + 0x006ef801, + 0x00718801, + 0x0071a019, + 0x0072381d, + 0x00758801, + 0x0075a021, + 0x00764019, 0x0078c005, 0x0079a801, 0x0079b801, 0x0079c801, - 0x007b8805, - 0x007ba001, - 0x007bd00d, - 0x007c0001, - 0x007c1009, + 0x007b8835, + 0x007c0011, 0x007c3005, + 0x007c6829, + 0x007cc88d, 0x007e3001, - 0x0081b801, + 0x0081680d, + 0x00819015, 0x0081c805, + 0x0081e805, + 0x0082c005, + 0x0082f009, + 0x0083880d, + 0x00841001, + 0x00842805, 0x00846801, + 0x0084e801, 0x009ae809, - 0x00b8a001, - 0x00be9001, + 0x00b8900d, + 0x00b99009, + 0x00ba9005, + 0x00bb9005, + 0x00bda005, + 0x00bdb819, + 0x00be3001, + 0x00be4829, 0x00bee801, + 0x00c05809, + 0x00c07801, + 0x00c42805, 0x00c54801, + 0x00c90009, + 0x00c93805, + 0x00c99001, 0x00c9c809, 0x00d0b805, + 0x00d0d801, + 0x00d2b001, + 0x00d2c019, 0x00d30001, - 0x00d3a81d, + 0x00d31001, + 0x00d3281d, + 0x00d39825, 0x00d3f801, - 0x00d58035, - 0x00d5f83d, - 0x00d9a001, + 0x00d58079, + 0x00d8000d, + 0x00d9a025, + 0x00da1009, 0x00db5821, - 0x00dd5801, + 0x00dc0005, + 0x00dd100d, + 0x00dd4015, 0x00df3001, - 0x00e1b801, + 0x00df4005, + 0x00df6801, + 0x00df7811, + 0x00e1601d, + 0x00e1b005, 0x00e68009, 0x00e6a031, 0x00e71019, @@ -221,82 +308,193 @@ _LIBCPP_HIDE_FROM_ABI inline constexpr uint32_t __entries[201] = { 0x00e7c005, 0x00ee00fd, 0x01006801, - 0x01068031, - 0x01070801, - 0x0107282d, + 0x01068081, 0x01677809, 0x016bf801, 0x016f007d, 0x01815015, 0x0184c805, - 0x05337801, + 0x0533780d, 0x0533a025, 0x0534f005, 0x05378005, + 0x05401001, + 0x05403001, + 0x05405801, + 0x05412805, 0x05416001, + 0x05462005, 0x05470045, - 0x05495809, + 0x0547f801, + 0x0549301d, + 0x054a3829, + 0x054a9801, + 0x054c0009, 0x054d9801, + 0x054db00d, + 0x054de005, + 0x054e0001, + 0x054f2801, + 0x05514815, + 0x05518805, + 0x0551a805, + 0x05521801, + 0x05526001, + 0x0553e001, 0x05558001, 0x05559009, 0x0555b805, 0x0555f005, 0x05560801, + 0x05576005, 0x0557b001, + 0x055f2801, + 0x055f4001, 0x055f6801, 0x07d8f001, + 0x07f0003d, 0x07f1003d, + 0x07fcf005, 0x080fe801, 0x08170001, 0x081bb011, - 0x08506801, - 0x08507801, + 0x08500809, + 0x08502805, + 0x0850600d, 0x0851c009, 0x0851f801, 0x08572805, 0x0869200d, + 0x086b4811, 0x08755805, - 0x0877e809, + 0x0877e00d, 0x087a3029, 0x087c100d, + 0x08800801, + 0x0881c039, 0x08838001, - 0x0883f801, - 0x0885d001, + 0x08839805, + 0x0883f809, + 0x0885980d, + 0x0885c805, + 0x08861001, 0x08880009, - 0x08899805, + 0x08893811, + 0x0889681d, 0x088b9801, - 0x088e5001, - 0x0891b001, - 0x08974805, + 0x088c0005, + 0x088db021, + 0x088e0001, + 0x088e480d, + 0x088e7801, + 0x08917809, + 0x0891a00d, + 0x0891f001, + 0x08920801, + 0x0896f801, + 0x0897181d, + 0x08980005, 0x0899d805, + 0x0899f001, + 0x089a0001, + 0x089a6801, + 0x089ab801, 0x089b3019, 0x089b8011, + 0x089dc001, + 0x089dd815, + 0x089e1001, + 0x089e2801, + 0x089e3809, + 0x089e7009, + 0x089e9001, + 0x089f0805, + 0x08a1c01d, + 0x08a21009, 0x08a23001, 0x08a2f001, - 0x08a61801, - 0x08ae0001, - 0x08b5b801, - 0x08b95801, - 0x08c1d001, - 0x08c9f001, + 0x08a58001, + 0x08a59815, + 0x08a5d001, + 0x08a5e801, + 0x08a5f805, + 0x08a61005, + 0x08ad7801, + 0x08ad900d, + 0x08ade005, + 0x08adf805, + 0x08aee005, + 0x08b1981d, + 0x08b1e801, + 0x08b1f805, + 0x08b55801, + 0x08b56801, + 0x08b5801d, + 0x08b8e801, + 0x08b8f801, + 0x08b9100d, + 0x08b93811, + 0x08c17821, + 0x08c1c805, + 0x08c98001, + 0x08c9d80d, 0x08ca1801, - 0x08d1a001, + 0x08cea00d, + 0x08ced005, + 0x08cf0001, + 0x08d00825, + 0x08d19815, + 0x08d1d80d, 0x08d23801, - 0x08d4c801, - 0x08ea1001, - 0x08ea2005, + 0x08d28815, + 0x08d2c809, + 0x08d45031, + 0x08d4c005, + 0x08e18019, + 0x08e1c015, + 0x08e1f801, + 0x08e49055, + 0x08e55019, + 0x08e59005, + 0x08e5a805, + 0x08e98815, + 0x08e9d001, + 0x08e9e005, + 0x08e9f819, + 0x08ea3801, + 0x08ec8005, + 0x08eca801, 0x08ecb801, - 0x08fa1001, + 0x08f79805, + 0x08f80005, + 0x08f9b011, + 0x08fa0009, + 0x08fad001, + 0x09a20001, + 0x09a23839, + 0x0b08f02d, + 0x0b096809, 0x0b578011, 0x0b598019, - 0x0de4f001, - 0x0e8b2801, - 0x0e8b3809, - 0x0e8b7011, + 0x0b7a7801, + 0x0b7c780d, + 0x0b7f2001, + 0x0b7f8005, + 0x0de4e805, + 0x0e7800b5, + 0x0e798059, + 0x0e8b2811, + 0x0e8b6815, 0x0e8bd81d, 0x0e8c2819, 0x0e8d500d, 0x0e921009, + 0x0ed000d9, + 0x0ed1d8c5, + 0x0ed3a801, + 0x0ed42001, + 0x0ed4d811, + 0x0ed50839, 0x0f000019, 0x0f004041, 0x0f00d819, @@ -307,8 +505,12 @@ _LIBCPP_HIDE_FROM_ABI inline constexpr uint32_t __entries[201] = { 0x0f157001, 0x0f17600d, 0x0f27600d, + 0x0f2f7005, 0x0f468019, - 0x0f4a2019}; + 0x0f4a2019, + 0x0f9fd811, + 0x7001017d, + 0x700803bd}; // clang-format on /// Returns the indic conjuct break property of a code point. diff --git a/lib/libcxx/include/__format/parser_std_format_spec.h b/lib/libcxx/include/__format/parser_std_format_spec.h index 415261acf0..99ab3dc23c 100644 --- a/lib/libcxx/include/__format/parser_std_format_spec.h +++ b/lib/libcxx/include/__format/parser_std_format_spec.h @@ -335,7 +335,7 @@ static_assert(is_trivially_copyable_v<__parsed_specifications>); /// set to zero. That way they can be repurposed if a future revision of the /// Standards adds new fields to std-format-spec. template -class _LIBCPP_TEMPLATE_VIS __parser { +class __parser { public: // Parses the format specification. // diff --git a/lib/libcxx/include/__format/range_default_formatter.h b/lib/libcxx/include/__format/range_default_formatter.h index bb4c520f5e..7149debb2f 100644 --- a/lib/libcxx/include/__format/range_default_formatter.h +++ b/lib/libcxx/include/__format/range_default_formatter.h @@ -52,7 +52,7 @@ _LIBCPP_DIAGNOSTIC_POP // There is no definition of this struct, it's purely intended to be used to // generate diagnostics. template -struct _LIBCPP_TEMPLATE_VIS __instantiated_the_primary_template_of_format_kind; +struct __instantiated_the_primary_template_of_format_kind; template constexpr range_format format_kind = [] { @@ -88,12 +88,12 @@ inline constexpr range_format format_kind<_Rp> = [] { }(); template -struct _LIBCPP_TEMPLATE_VIS __range_default_formatter; +struct __range_default_formatter; // Required specializations template -struct _LIBCPP_TEMPLATE_VIS __range_default_formatter { +struct __range_default_formatter { private: using __maybe_const_r _LIBCPP_NODEBUG = __fmt_maybe_const<_Rp, _CharT>; range_formatter>, _CharT> __underlying_; @@ -120,7 +120,7 @@ public: }; template -struct _LIBCPP_TEMPLATE_VIS __range_default_formatter { +struct __range_default_formatter { private: using __maybe_const_map _LIBCPP_NODEBUG = __fmt_maybe_const<_Rp, _CharT>; using __element_type _LIBCPP_NODEBUG = remove_cvref_t>; @@ -148,7 +148,7 @@ public: }; template -struct _LIBCPP_TEMPLATE_VIS __range_default_formatter { +struct __range_default_formatter { private: using __maybe_const_set _LIBCPP_NODEBUG = __fmt_maybe_const<_Rp, _CharT>; using __element_type _LIBCPP_NODEBUG = remove_cvref_t>; @@ -173,7 +173,7 @@ public: template requires(_Kp == range_format::string || _Kp == range_format::debug_string) -struct _LIBCPP_TEMPLATE_VIS __range_default_formatter<_Kp, _Rp, _CharT> { +struct __range_default_formatter<_Kp, _Rp, _CharT> { private: // This deviates from the Standard, there the exposition only type is // formatter, charT> underlying_; @@ -205,7 +205,7 @@ public: template requires(format_kind<_Rp> != range_format::disabled && formattable, _CharT>) -struct _LIBCPP_TEMPLATE_VIS formatter<_Rp, _CharT> : __range_default_formatter, _Rp, _CharT> {}; +struct formatter<_Rp, _CharT> : __range_default_formatter, _Rp, _CharT> {}; #endif // _LIBCPP_STD_VER >= 23 diff --git a/lib/libcxx/include/__format/range_formatter.h b/lib/libcxx/include/__format/range_formatter.h index def55c86ce..0d7fe9970c 100644 --- a/lib/libcxx/include/__format/range_formatter.h +++ b/lib/libcxx/include/__format/range_formatter.h @@ -39,7 +39,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD template requires same_as, _Tp> && formattable<_Tp, _CharT> -struct _LIBCPP_TEMPLATE_VIS range_formatter { +struct range_formatter { _LIBCPP_HIDE_FROM_ABI constexpr void set_separator(basic_string_view<_CharT> __separator) noexcept { __separator_ = __separator; } diff --git a/lib/libcxx/include/__format/width_estimation_table.h b/lib/libcxx/include/__format/width_estimation_table.h index 5b4b3950c6..0ea0b4f413 100644 --- a/lib/libcxx/include/__format/width_estimation_table.h +++ b/lib/libcxx/include/__format/width_estimation_table.h @@ -119,7 +119,7 @@ namespace __width_estimation_table { /// - bits [0, 13] The size of the range, allowing 16384 elements. /// - bits [14, 31] The lower bound code point of the range. The upper bound of /// the range is lower bound + size. -_LIBCPP_HIDE_FROM_ABI inline constexpr uint32_t __entries[107] = { +_LIBCPP_HIDE_FROM_ABI inline constexpr uint32_t __entries[110] = { 0x0440005f /* 00001100 - 0000115f [ 96] */, // 0x08c68001 /* 0000231a - 0000231b [ 2] */, // 0x08ca4001 /* 00002329 - 0000232a [ 2] */, // @@ -128,8 +128,10 @@ _LIBCPP_HIDE_FROM_ABI inline constexpr uint32_t __entries[107] = { 0x08fcc000 /* 000023f3 - 000023f3 [ 1] */, // 0x097f4001 /* 000025fd - 000025fe [ 2] */, // 0x09850001 /* 00002614 - 00002615 [ 2] */, // + 0x098c0007 /* 00002630 - 00002637 [ 8] */, // 0x0992000b /* 00002648 - 00002653 [ 12] */, // 0x099fc000 /* 0000267f - 0000267f [ 1] */, // + 0x09a28005 /* 0000268a - 0000268f [ 6] */, // 0x09a4c000 /* 00002693 - 00002693 [ 1] */, // 0x09a84000 /* 000026a1 - 000026a1 [ 1] */, // 0x09aa8001 /* 000026aa - 000026ab [ 2] */, // @@ -163,7 +165,7 @@ _LIBCPP_HIDE_FROM_ABI inline constexpr uint32_t __entries[107] = { 0x0c264066 /* 00003099 - 000030ff [ 103] */, // 0x0c41402a /* 00003105 - 0000312f [ 43] */, // 0x0c4c405d /* 00003131 - 0000318e [ 94] */, // - 0x0c640053 /* 00003190 - 000031e3 [ 84] */, // + 0x0c640055 /* 00003190 - 000031e5 [ 86] */, // 0x0c7bc02f /* 000031ef - 0000321e [ 48] */, // 0x0c880027 /* 00003220 - 00003247 [ 40] */, // 0x0c943fff /* 00003250 - 0000724f [16384] */, // @@ -182,7 +184,7 @@ _LIBCPP_HIDE_FROM_ABI inline constexpr uint32_t __entries[107] = { 0x5bfc0001 /* 00016ff0 - 00016ff1 [ 2] */, // 0x5c0017f7 /* 00017000 - 000187f7 [ 6136] */, // 0x620004d5 /* 00018800 - 00018cd5 [ 1238] */, // - 0x63400008 /* 00018d00 - 00018d08 [ 9] */, // + 0x633fc009 /* 00018cff - 00018d08 [ 10] */, // 0x6bfc0003 /* 0001aff0 - 0001aff3 [ 4] */, // 0x6bfd4006 /* 0001aff5 - 0001affb [ 7] */, // 0x6bff4001 /* 0001affd - 0001affe [ 2] */, // @@ -192,6 +194,8 @@ _LIBCPP_HIDE_FROM_ABI inline constexpr uint32_t __entries[107] = { 0x6c554000 /* 0001b155 - 0001b155 [ 1] */, // 0x6c590003 /* 0001b164 - 0001b167 [ 4] */, // 0x6c5c018b /* 0001b170 - 0001b2fb [ 396] */, // + 0x74c00056 /* 0001d300 - 0001d356 [ 87] */, // + 0x74d80016 /* 0001d360 - 0001d376 [ 23] */, // 0x7c010000 /* 0001f004 - 0001f004 [ 1] */, // 0x7c33c000 /* 0001f0cf - 0001f0cf [ 1] */, // 0x7c638000 /* 0001f18e - 0001f18e [ 1] */, // @@ -213,11 +217,10 @@ _LIBCPP_HIDE_FROM_ABI inline constexpr uint32_t __entries[107] = { 0x7dfc0000 /* 0001f7f0 - 0001f7f0 [ 1] */, // 0x7e4000ff /* 0001f900 - 0001f9ff [ 256] */, // 0x7e9c000c /* 0001fa70 - 0001fa7c [ 13] */, // - 0x7ea00008 /* 0001fa80 - 0001fa88 [ 9] */, // - 0x7ea4002d /* 0001fa90 - 0001fabd [ 46] */, // - 0x7eafc006 /* 0001fabf - 0001fac5 [ 7] */, // - 0x7eb3800d /* 0001face - 0001fadb [ 14] */, // - 0x7eb80008 /* 0001fae0 - 0001fae8 [ 9] */, // + 0x7ea00009 /* 0001fa80 - 0001fa89 [ 10] */, // + 0x7ea3c037 /* 0001fa8f - 0001fac6 [ 56] */, // + 0x7eb3800e /* 0001face - 0001fadc [ 15] */, // + 0x7eb7c00a /* 0001fadf - 0001fae9 [ 11] */, // 0x7ebc0008 /* 0001faf0 - 0001faf8 [ 9] */, // 0x80003fff /* 00020000 - 00023fff [16384] */, // 0x90003fff /* 00024000 - 00027fff [16384] */, // diff --git a/lib/libcxx/include/__functional/binary_function.h b/lib/libcxx/include/__functional/binary_function.h index bde8b03ef8..531274b7d4 100644 --- a/lib/libcxx/include/__functional/binary_function.h +++ b/lib/libcxx/include/__functional/binary_function.h @@ -21,7 +21,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD #if _LIBCPP_STD_VER <= 14 || defined(_LIBCPP_ENABLE_CXX17_REMOVED_UNARY_BINARY_FUNCTION) template -struct _LIBCPP_TEMPLATE_VIS _LIBCPP_DEPRECATED_IN_CXX11 binary_function { +struct _LIBCPP_DEPRECATED_IN_CXX11 binary_function { typedef _Arg1 first_argument_type; typedef _Arg2 second_argument_type; typedef _Result result_type; @@ -39,11 +39,10 @@ struct __binary_function_keep_layout_base { }; #if _LIBCPP_STD_VER <= 14 || defined(_LIBCPP_ENABLE_CXX17_REMOVED_UNARY_BINARY_FUNCTION) -_LIBCPP_DIAGNOSTIC_PUSH -_LIBCPP_CLANG_DIAGNOSTIC_IGNORED("-Wdeprecated-declarations") +_LIBCPP_SUPPRESS_DEPRECATED_PUSH template using __binary_function _LIBCPP_NODEBUG = binary_function<_Arg1, _Arg2, _Result>; -_LIBCPP_DIAGNOSTIC_POP +_LIBCPP_SUPPRESS_DEPRECATED_POP #else template using __binary_function _LIBCPP_NODEBUG = __binary_function_keep_layout_base<_Arg1, _Arg2, _Result>; diff --git a/lib/libcxx/include/__functional/binary_negate.h b/lib/libcxx/include/__functional/binary_negate.h index ce52b5ae9f..73acfb37a7 100644 --- a/lib/libcxx/include/__functional/binary_negate.h +++ b/lib/libcxx/include/__functional/binary_negate.h @@ -22,7 +22,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD #if _LIBCPP_STD_VER <= 17 || defined(_LIBCPP_ENABLE_CXX20_REMOVED_NEGATORS) template -class _LIBCPP_TEMPLATE_VIS _LIBCPP_DEPRECATED_IN_CXX17 binary_negate +class _LIBCPP_DEPRECATED_IN_CXX17 binary_negate : public __binary_function { diff --git a/lib/libcxx/include/__functional/bind.h b/lib/libcxx/include/__functional/bind.h index a3c327ab40..596cce03cd 100644 --- a/lib/libcxx/include/__functional/bind.h +++ b/lib/libcxx/include/__functional/bind.h @@ -130,7 +130,7 @@ struct __mu_return_invokable // false template struct __mu_return_invokable { - using type = __invoke_result_t<_Ti&, _Uj...>; + using type _LIBCPP_NODEBUG = __invoke_result_t<_Ti&, _Uj...>; }; template @@ -181,12 +181,12 @@ struct __bind_return; template struct __bind_return<_Fp, tuple<_BoundArgs...>, _TupleUj, true> { - using type = __invoke_result_t< _Fp&, typename __mu_return< _BoundArgs, _TupleUj >::type... >; + using type _LIBCPP_NODEBUG = __invoke_result_t<_Fp&, typename __mu_return<_BoundArgs, _TupleUj>::type...>; }; template struct __bind_return<_Fp, const tuple<_BoundArgs...>, _TupleUj, true> { - using type = __invoke_result_t< _Fp&, typename __mu_return< const _BoundArgs, _TupleUj >::type... >; + using type _LIBCPP_NODEBUG = __invoke_result_t<_Fp&, typename __mu_return::type...>; }; template diff --git a/lib/libcxx/include/__functional/binder1st.h b/lib/libcxx/include/__functional/binder1st.h index 04b51fefab..77a0322450 100644 --- a/lib/libcxx/include/__functional/binder1st.h +++ b/lib/libcxx/include/__functional/binder1st.h @@ -22,7 +22,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD #if _LIBCPP_STD_VER <= 14 || defined(_LIBCPP_ENABLE_CXX17_REMOVED_BINDERS) template -class _LIBCPP_TEMPLATE_VIS _LIBCPP_DEPRECATED_IN_CXX11 binder1st +class _LIBCPP_DEPRECATED_IN_CXX11 binder1st : public __unary_function { protected: _Operation op; diff --git a/lib/libcxx/include/__functional/binder2nd.h b/lib/libcxx/include/__functional/binder2nd.h index 9d22e4430b..8cc644151a 100644 --- a/lib/libcxx/include/__functional/binder2nd.h +++ b/lib/libcxx/include/__functional/binder2nd.h @@ -22,7 +22,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD #if _LIBCPP_STD_VER <= 14 || defined(_LIBCPP_ENABLE_CXX17_REMOVED_BINDERS) template -class _LIBCPP_TEMPLATE_VIS _LIBCPP_DEPRECATED_IN_CXX11 binder2nd +class _LIBCPP_DEPRECATED_IN_CXX11 binder2nd : public __unary_function { protected: _Operation op; diff --git a/lib/libcxx/include/__functional/boyer_moore_searcher.h b/lib/libcxx/include/__functional/boyer_moore_searcher.h index 1e49cc5464..6c51c32d2f 100644 --- a/lib/libcxx/include/__functional/boyer_moore_searcher.h +++ b/lib/libcxx/include/__functional/boyer_moore_searcher.h @@ -17,12 +17,10 @@ #include <__config> #include <__functional/hash.h> #include <__functional/operations.h> -#include <__iterator/distance.h> #include <__iterator/iterator_traits.h> #include <__memory/shared_ptr.h> #include <__type_traits/make_unsigned.h> #include <__utility/pair.h> -#include <__vector/vector.h> #include #include #include @@ -88,7 +86,7 @@ public: template ::value_type>, class _BinaryPredicate = equal_to<>> -class _LIBCPP_TEMPLATE_VIS boyer_moore_searcher { +class boyer_moore_searcher { private: using difference_type = typename std::iterator_traits<_RandomAccessIterator1>::difference_type; using value_type = typename std::iterator_traits<_RandomAccessIterator1>::value_type; @@ -125,8 +123,8 @@ public: template _LIBCPP_HIDE_FROM_ABI pair<_RandomAccessIterator2, _RandomAccessIterator2> operator()(_RandomAccessIterator2 __first, _RandomAccessIterator2 __last) const { - static_assert(__is_same_uncvref::value_type, - typename iterator_traits<_RandomAccessIterator2>::value_type>::value, + static_assert(is_same_v<__remove_cvref_t::value_type>, + __remove_cvref_t::value_type>>, "Corpus and Pattern iterators must point to the same type"); if (__first == __last) return std::make_pair(__last, __last); @@ -196,7 +194,7 @@ private: if (__count == 0) return; - vector __scratch(__count); + auto __scratch = std::make_unique(__count); __compute_bm_prefix(__first, __last, __pred, __scratch); for (size_t __i = 0; __i <= __count; ++__i) @@ -219,7 +217,7 @@ _LIBCPP_CTAD_SUPPORTED_FOR_TYPE(boyer_moore_searcher); template ::value_type>, class _BinaryPredicate = equal_to<>> -class _LIBCPP_TEMPLATE_VIS boyer_moore_horspool_searcher { +class boyer_moore_horspool_searcher { private: using difference_type = typename iterator_traits<_RandomAccessIterator1>::difference_type; using value_type = typename iterator_traits<_RandomAccessIterator1>::value_type; @@ -256,8 +254,8 @@ public: template _LIBCPP_HIDE_FROM_ABI pair<_RandomAccessIterator2, _RandomAccessIterator2> operator()(_RandomAccessIterator2 __first, _RandomAccessIterator2 __last) const { - static_assert(__is_same_uncvref::value_type, - typename std::iterator_traits<_RandomAccessIterator2>::value_type>::value, + static_assert(is_same_v<__remove_cvref_t::value_type>, + __remove_cvref_t::value_type>>, "Corpus and Pattern iterators must point to the same type"); if (__first == __last) return std::make_pair(__last, __last); diff --git a/lib/libcxx/include/__functional/default_searcher.h b/lib/libcxx/include/__functional/default_searcher.h index db89d10757..afbf07e238 100644 --- a/lib/libcxx/include/__functional/default_searcher.h +++ b/lib/libcxx/include/__functional/default_searcher.h @@ -27,7 +27,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD // default searcher template > -class _LIBCPP_TEMPLATE_VIS default_searcher { +class default_searcher { public: _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 default_searcher(_ForwardIterator __f, _ForwardIterator __l, _BinaryPredicate __p = _BinaryPredicate()) diff --git a/lib/libcxx/include/__functional/function.h b/lib/libcxx/include/__functional/function.h index 2a1293cfcc..dc112ebfd0 100644 --- a/lib/libcxx/include/__functional/function.h +++ b/lib/libcxx/include/__functional/function.h @@ -17,13 +17,7 @@ #include <__functional/binary_function.h> #include <__functional/invoke.h> #include <__functional/unary_function.h> -#include <__iterator/iterator_traits.h> #include <__memory/addressof.h> -#include <__memory/allocator.h> -#include <__memory/allocator_destructor.h> -#include <__memory/allocator_traits.h> -#include <__memory/compressed_pair.h> -#include <__memory/unique_ptr.h> #include <__type_traits/aligned_storage.h> #include <__type_traits/decay.h> #include <__type_traits/is_core_convertible.h> @@ -34,9 +28,7 @@ #include <__type_traits/strip_signature.h> #include <__utility/forward.h> #include <__utility/move.h> -#include <__utility/piecewise_construct.h> #include <__utility/swap.h> -#include <__verbose_abort> #include #include @@ -71,7 +63,7 @@ public: _LIBCPP_HIDE_FROM_ABI_VIRTUAL ~bad_function_call() _NOEXCEPT override {} # endif -# ifdef _LIBCPP_ABI_BAD_FUNCTION_CALL_GOOD_WHAT_MESSAGE +# if _LIBCPP_AVAILABILITY_HAS_BAD_FUNCTION_CALL_GOOD_WHAT_MESSAGE const char* what() const _NOEXCEPT override; # endif }; @@ -86,7 +78,7 @@ _LIBCPP_DIAGNOSTIC_POP } template -class _LIBCPP_TEMPLATE_VIS function; // undefined +class function; // undefined namespace __function { @@ -122,7 +114,7 @@ _LIBCPP_HIDE_FROM_ABI bool __not_null(function<_Fp> const& __f) { return !!__f; } -# if _LIBCPP_HAS_EXTENSION_BLOCKS +# if __has_extension(blocks) template _LIBCPP_HIDE_FROM_ABI bool __not_null(_Rp (^__p)(_Args...)) { return __p; @@ -133,108 +125,10 @@ _LIBCPP_HIDE_FROM_ABI bool __not_null(_Rp (^__p)(_Args...)) { namespace __function { -// __alloc_func holds a functor and an allocator. - -template -class __alloc_func; -template -class __default_alloc_func; - -template -class __alloc_func<_Fp, _Ap, _Rp(_ArgTypes...)> { - _LIBCPP_COMPRESSED_PAIR(_Fp, __func_, _Ap, __alloc_); - -public: - using _Target _LIBCPP_NODEBUG = _Fp; - using _Alloc _LIBCPP_NODEBUG = _Ap; - - _LIBCPP_HIDE_FROM_ABI const _Target& __target() const { return __func_; } - - // WIN32 APIs may define __allocator, so use __get_allocator instead. - _LIBCPP_HIDE_FROM_ABI const _Alloc& __get_allocator() const { return __alloc_; } - - _LIBCPP_HIDE_FROM_ABI explicit __alloc_func(_Target&& __f) : __func_(std::move(__f)), __alloc_() {} - - _LIBCPP_HIDE_FROM_ABI explicit __alloc_func(const _Target& __f, const _Alloc& __a) : __func_(__f), __alloc_(__a) {} - - _LIBCPP_HIDE_FROM_ABI explicit __alloc_func(const _Target& __f, _Alloc&& __a) - : __func_(__f), __alloc_(std::move(__a)) {} - - _LIBCPP_HIDE_FROM_ABI explicit __alloc_func(_Target&& __f, _Alloc&& __a) - : __func_(std::move(__f)), __alloc_(std::move(__a)) {} - - _LIBCPP_HIDE_FROM_ABI _Rp operator()(_ArgTypes&&... __arg) { - return std::__invoke_r<_Rp>(__func_, std::forward<_ArgTypes>(__arg)...); - } - - _LIBCPP_HIDE_FROM_ABI __alloc_func* __clone() const { - typedef allocator_traits<_Alloc> __alloc_traits; - typedef __rebind_alloc<__alloc_traits, __alloc_func> _AA; - _AA __a(__alloc_); - typedef __allocator_destructor<_AA> _Dp; - unique_ptr<__alloc_func, _Dp> __hold(__a.allocate(1), _Dp(__a, 1)); - ::new ((void*)__hold.get()) __alloc_func(__func_, _Alloc(__a)); - return __hold.release(); - } - - _LIBCPP_HIDE_FROM_ABI void destroy() _NOEXCEPT { - __func_.~_Fp(); - __alloc_.~_Alloc(); - } - - _LIBCPP_HIDE_FROM_ABI static void __destroy_and_delete(__alloc_func* __f) { - typedef allocator_traits<_Alloc> __alloc_traits; - typedef __rebind_alloc<__alloc_traits, __alloc_func> _FunAlloc; - _FunAlloc __a(__f->__get_allocator()); - __f->destroy(); - __a.deallocate(__f, 1); - } -}; - -template -struct __deallocating_deleter { - _LIBCPP_HIDE_FROM_ABI void operator()(void* __p) const { - std::__libcpp_deallocate<_Tp>(static_cast<_Tp*>(__p), __element_count(1)); - } -}; - -template -class __default_alloc_func<_Fp, _Rp(_ArgTypes...)> { - _Fp __f_; - -public: - using _Target _LIBCPP_NODEBUG = _Fp; - - _LIBCPP_HIDE_FROM_ABI const _Target& __target() const { return __f_; } - - _LIBCPP_HIDE_FROM_ABI explicit __default_alloc_func(_Target&& __f) : __f_(std::move(__f)) {} - - _LIBCPP_HIDE_FROM_ABI explicit __default_alloc_func(const _Target& __f) : __f_(__f) {} - - _LIBCPP_HIDE_FROM_ABI _Rp operator()(_ArgTypes&&... __arg) { - return std::__invoke_r<_Rp>(__f_, std::forward<_ArgTypes>(__arg)...); - } - - _LIBCPP_HIDE_FROM_ABI __default_alloc_func* __clone() const { - using _Self = __default_alloc_func; - unique_ptr<_Self, __deallocating_deleter<_Self>> __hold(std::__libcpp_allocate<_Self>(__element_count(1))); - _Self* __res = ::new ((void*)__hold.get()) _Self(__f_); - (void)__hold.release(); - return __res; - } - - _LIBCPP_HIDE_FROM_ABI void destroy() _NOEXCEPT { __f_.~_Target(); } - - _LIBCPP_HIDE_FROM_ABI static void __destroy_and_delete(__default_alloc_func* __f) { - __f->destroy(); - std::__libcpp_deallocate<__default_alloc_func>(__f, __element_count(1)); - } -}; - // __base provides an abstract interface for copyable functors. template -class _LIBCPP_TEMPLATE_VIS __base; +class __base; template class __base<_Rp(_ArgTypes...)> { @@ -257,84 +151,38 @@ public: // __func implements __base for a given functor type. -template +template class __func; -template -class __func<_Fp, _Alloc, _Rp(_ArgTypes...)> : public __base<_Rp(_ArgTypes...)> { - __alloc_func<_Fp, _Alloc, _Rp(_ArgTypes...)> __f_; +template +class __func<_Fp, _Rp(_ArgTypes...)> : public __base<_Rp(_ArgTypes...)> { + _Fp __func_; public: - _LIBCPP_HIDE_FROM_ABI explicit __func(_Fp&& __f) : __f_(std::move(__f)) {} + _LIBCPP_HIDE_FROM_ABI explicit __func(_Fp&& __f) : __func_(std::move(__f)) {} + _LIBCPP_HIDE_FROM_ABI explicit __func(const _Fp& __f) : __func_(__f) {} - _LIBCPP_HIDE_FROM_ABI explicit __func(const _Fp& __f, const _Alloc& __a) : __f_(__f, __a) {} + _LIBCPP_HIDE_FROM_ABI_VIRTUAL __base<_Rp(_ArgTypes...)>* __clone() const override { return new __func(__func_); } - _LIBCPP_HIDE_FROM_ABI explicit __func(const _Fp& __f, _Alloc&& __a) : __f_(__f, std::move(__a)) {} + _LIBCPP_HIDE_FROM_ABI_VIRTUAL void __clone(__base<_Rp(_ArgTypes...)>* __p) const override { + ::new ((void*)__p) __func(__func_); + } - _LIBCPP_HIDE_FROM_ABI explicit __func(_Fp&& __f, _Alloc&& __a) : __f_(std::move(__f), std::move(__a)) {} - - _LIBCPP_HIDE_FROM_ABI_VIRTUAL virtual __base<_Rp(_ArgTypes...)>* __clone() const; - _LIBCPP_HIDE_FROM_ABI_VIRTUAL virtual void __clone(__base<_Rp(_ArgTypes...)>*) const; - _LIBCPP_HIDE_FROM_ABI_VIRTUAL virtual void destroy() _NOEXCEPT; - _LIBCPP_HIDE_FROM_ABI_VIRTUAL virtual void destroy_deallocate() _NOEXCEPT; - _LIBCPP_HIDE_FROM_ABI_VIRTUAL virtual _Rp operator()(_ArgTypes&&... __arg); + _LIBCPP_HIDE_FROM_ABI_VIRTUAL void destroy() _NOEXCEPT override { __func_.~_Fp(); } + _LIBCPP_HIDE_FROM_ABI_VIRTUAL void destroy_deallocate() _NOEXCEPT override { delete this; } + _LIBCPP_HIDE_FROM_ABI_VIRTUAL _Rp operator()(_ArgTypes&&... __arg) override { + return std::__invoke_r<_Rp>(__func_, std::forward<_ArgTypes>(__arg)...); + } # if _LIBCPP_HAS_RTTI - _LIBCPP_HIDE_FROM_ABI_VIRTUAL virtual const void* target(const type_info&) const _NOEXCEPT; - _LIBCPP_HIDE_FROM_ABI_VIRTUAL virtual const std::type_info& target_type() const _NOEXCEPT; + _LIBCPP_HIDE_FROM_ABI_VIRTUAL const void* target(const type_info& __ti) const _NOEXCEPT override { + if (__ti == typeid(_Fp)) + return std::addressof(__func_); + return nullptr; + } + _LIBCPP_HIDE_FROM_ABI_VIRTUAL const std::type_info& target_type() const _NOEXCEPT override { return typeid(_Fp); } # endif // _LIBCPP_HAS_RTTI }; -template -__base<_Rp(_ArgTypes...)>* __func<_Fp, _Alloc, _Rp(_ArgTypes...)>::__clone() const { - typedef allocator_traits<_Alloc> __alloc_traits; - typedef __rebind_alloc<__alloc_traits, __func> _Ap; - _Ap __a(__f_.__get_allocator()); - typedef __allocator_destructor<_Ap> _Dp; - unique_ptr<__func, _Dp> __hold(__a.allocate(1), _Dp(__a, 1)); - ::new ((void*)__hold.get()) __func(__f_.__target(), _Alloc(__a)); - return __hold.release(); -} - -template -void __func<_Fp, _Alloc, _Rp(_ArgTypes...)>::__clone(__base<_Rp(_ArgTypes...)>* __p) const { - ::new ((void*)__p) __func(__f_.__target(), __f_.__get_allocator()); -} - -template -void __func<_Fp, _Alloc, _Rp(_ArgTypes...)>::destroy() _NOEXCEPT { - __f_.destroy(); -} - -template -void __func<_Fp, _Alloc, _Rp(_ArgTypes...)>::destroy_deallocate() _NOEXCEPT { - typedef allocator_traits<_Alloc> __alloc_traits; - typedef __rebind_alloc<__alloc_traits, __func> _Ap; - _Ap __a(__f_.__get_allocator()); - __f_.destroy(); - __a.deallocate(this, 1); -} - -template -_Rp __func<_Fp, _Alloc, _Rp(_ArgTypes...)>::operator()(_ArgTypes&&... __arg) { - return __f_(std::forward<_ArgTypes>(__arg)...); -} - -# if _LIBCPP_HAS_RTTI - -template -const void* __func<_Fp, _Alloc, _Rp(_ArgTypes...)>::target(const type_info& __ti) const _NOEXCEPT { - if (__ti == typeid(_Fp)) - return std::addressof(__f_.__target()); - return nullptr; -} - -template -const std::type_info& __func<_Fp, _Alloc, _Rp(_ArgTypes...)>::target_type() const _NOEXCEPT { - return typeid(_Fp); -} - -# endif // _LIBCPP_HAS_RTTI - // __value_func creates a value-type from a __func. template @@ -354,29 +202,19 @@ class __value_func<_Rp(_ArgTypes...)> { public: _LIBCPP_HIDE_FROM_ABI __value_func() _NOEXCEPT : __f_(nullptr) {} - template - _LIBCPP_HIDE_FROM_ABI __value_func(_Fp&& __f, const _Alloc& __a) : __f_(nullptr) { - typedef allocator_traits<_Alloc> __alloc_traits; - typedef __function::__func<_Fp, _Alloc, _Rp(_ArgTypes...)> _Fun; - typedef __rebind_alloc<__alloc_traits, _Fun> _FunAlloc; + template , __value_func>::value, int> = 0> + _LIBCPP_HIDE_FROM_ABI explicit __value_func(_Fp&& __f) : __f_(nullptr) { + typedef __function::__func<_Fp, _Rp(_ArgTypes...)> _Fun; if (__function::__not_null(__f)) { - _FunAlloc __af(__a); - if (sizeof(_Fun) <= sizeof(__buf_) && is_nothrow_copy_constructible<_Fp>::value && - is_nothrow_copy_constructible<_FunAlloc>::value) { - __f_ = ::new ((void*)&__buf_) _Fun(std::move(__f), _Alloc(__af)); + if (sizeof(_Fun) <= sizeof(__buf_) && is_nothrow_copy_constructible<_Fp>::value) { + __f_ = ::new (std::addressof(__buf_)) _Fun(std::move(__f)); } else { - typedef __allocator_destructor<_FunAlloc> _Dp; - unique_ptr<__func, _Dp> __hold(__af.allocate(1), _Dp(__af, 1)); - ::new ((void*)__hold.get()) _Fun(std::move(__f), _Alloc(__a)); - __f_ = __hold.release(); + __f_ = new _Fun(std::move(__f)); } } } - template , __value_func>::value, int> = 0> - _LIBCPP_HIDE_FROM_ABI explicit __value_func(_Fp&& __f) : __value_func(std::forward<_Fp>(__f), allocator<_Fp>()) {} - _LIBCPP_HIDE_FROM_ABI __value_func(const __value_func& __f) { if (__f.__f_ == nullptr) __f_ = nullptr; @@ -432,12 +270,12 @@ public: _LIBCPP_HIDE_FROM_ABI _Rp operator()(_ArgTypes&&... __args) const { if (__f_ == nullptr) - __throw_bad_function_call(); + std::__throw_bad_function_call(); return (*__f_)(std::forward<_ArgTypes>(__args)...); } _LIBCPP_HIDE_FROM_ABI void swap(__value_func& __f) _NOEXCEPT { - if (&__f == this) + if (std::addressof(__f) == this) return; if ((void*)__f_ == &__buf_ && (void*)__f.__f_ == &__f.__buf_) { _LIBCPP_SUPPRESS_DEPRECATED_PUSH @@ -539,22 +377,22 @@ private: template _LIBCPP_HIDE_FROM_ABI static void* __large_clone(const void* __s) { const _Fun* __f = static_cast(__s); - return __f->__clone(); + return new _Fun(*__f); } template _LIBCPP_HIDE_FROM_ABI static void __large_destroy(void* __s) { - _Fun::__destroy_and_delete(static_cast<_Fun*>(__s)); + delete static_cast<_Fun*>(__s); } template _LIBCPP_HIDE_FROM_ABI static const __policy* __choose_policy(/* is_small = */ false_type) { static constexpr __policy __policy = { - &__large_clone<_Fun>, - &__large_destroy<_Fun>, + std::addressof(__large_clone<_Fun>), + std::addressof(__large_destroy<_Fun>), false, # if _LIBCPP_HAS_RTTI - &typeid(typename _Fun::_Target) + &typeid(_Fun) # else nullptr # endif @@ -569,7 +407,7 @@ private: nullptr, false, # if _LIBCPP_HAS_RTTI - &typeid(typename _Fun::_Target) + &typeid(_Fun) # else nullptr # endif @@ -583,42 +421,7 @@ private: template using __fast_forward _LIBCPP_NODEBUG = __conditional_t::value, _Tp, _Tp&&>; -// __policy_invoker calls an instance of __alloc_func held in __policy_storage. - -template -struct __policy_invoker; - -template -struct __policy_invoker<_Rp(_ArgTypes...)> { - typedef _Rp (*__Call)(const __policy_storage*, __fast_forward<_ArgTypes>...); - - __Call __call_; - - // Creates an invoker that throws bad_function_call. - _LIBCPP_HIDE_FROM_ABI __policy_invoker() : __call_(&__call_empty) {} - - // Creates an invoker that calls the given instance of __func. - template - _LIBCPP_HIDE_FROM_ABI static __policy_invoker __create() { - return __policy_invoker(&__call_impl<_Fun>); - } - -private: - _LIBCPP_HIDE_FROM_ABI explicit __policy_invoker(__Call __c) : __call_(__c) {} - - _LIBCPP_HIDE_FROM_ABI static _Rp __call_empty(const __policy_storage*, __fast_forward<_ArgTypes>...) { - __throw_bad_function_call(); - } - - template - _LIBCPP_HIDE_FROM_ABI static _Rp __call_impl(const __policy_storage* __buf, __fast_forward<_ArgTypes>... __args) { - _Fun* __f = reinterpret_cast<_Fun*>(__use_small_storage<_Fun>::value ? &__buf->__small : __buf->__large); - return (*__f)(std::forward<_ArgTypes>(__args)...); - } -}; - -// __policy_func uses a __policy and __policy_invoker to create a type-erased, -// copyable functor. +// __policy_func uses a __policy to create a type-erased, copyable functor. template class __policy_func; @@ -628,69 +431,52 @@ class __policy_func<_Rp(_ArgTypes...)> { // Inline storage for small objects. __policy_storage __buf_; - // Calls the value stored in __buf_. This could technically be part of - // policy, but storing it here eliminates a level of indirection inside - // operator(). - typedef __function::__policy_invoker<_Rp(_ArgTypes...)> __invoker; - __invoker __invoker_; + using _ErasedFunc _LIBCPP_NODEBUG = _Rp(const __policy_storage*, __fast_forward<_ArgTypes>...); + + _ErasedFunc* __func_; // The policy that describes how to move / copy / destroy __buf_. Never // null, even if the function is empty. const __policy* __policy_; -public: - _LIBCPP_HIDE_FROM_ABI __policy_func() : __policy_(__policy::__create_empty()) {} - - template - _LIBCPP_HIDE_FROM_ABI __policy_func(_Fp&& __f, const _Alloc& __a) : __policy_(__policy::__create_empty()) { - typedef __alloc_func<_Fp, _Alloc, _Rp(_ArgTypes...)> _Fun; - typedef allocator_traits<_Alloc> __alloc_traits; - typedef __rebind_alloc<__alloc_traits, _Fun> _FunAlloc; - - if (__function::__not_null(__f)) { - __invoker_ = __invoker::template __create<_Fun>(); - __policy_ = __policy::__create<_Fun>(); - - _FunAlloc __af(__a); - if (__use_small_storage<_Fun>()) { - ::new ((void*)&__buf_.__small) _Fun(std::move(__f), _Alloc(__af)); - } else { - typedef __allocator_destructor<_FunAlloc> _Dp; - unique_ptr<_Fun, _Dp> __hold(__af.allocate(1), _Dp(__af, 1)); - ::new ((void*)__hold.get()) _Fun(std::move(__f), _Alloc(__af)); - __buf_.__large = __hold.release(); - } - } + _LIBCPP_HIDE_FROM_ABI static _Rp __empty_func(const __policy_storage*, __fast_forward<_ArgTypes>...) { + std::__throw_bad_function_call(); } + template + _LIBCPP_HIDE_FROM_ABI static _Rp __call_func(const __policy_storage* __buf, __fast_forward<_ArgTypes>... __args) { + _Fun* __func = reinterpret_cast<_Fun*>(__use_small_storage<_Fun>::value ? &__buf->__small : __buf->__large); + + return std::__invoke_r<_Rp>(*__func, std::forward<_ArgTypes>(__args)...); + } + +public: + _LIBCPP_HIDE_FROM_ABI __policy_func() : __func_(__empty_func), __policy_(__policy::__create_empty()) {} + template , __policy_func>::value, int> = 0> _LIBCPP_HIDE_FROM_ABI explicit __policy_func(_Fp&& __f) : __policy_(__policy::__create_empty()) { - typedef __default_alloc_func<_Fp, _Rp(_ArgTypes...)> _Fun; - if (__function::__not_null(__f)) { - __invoker_ = __invoker::template __create<_Fun>(); - __policy_ = __policy::__create<_Fun>(); - if (__use_small_storage<_Fun>()) { - ::new ((void*)&__buf_.__small) _Fun(std::move(__f)); + __func_ = __call_func<_Fp>; + __policy_ = __policy::__create<_Fp>(); + if (__use_small_storage<_Fp>()) { + ::new ((void*)&__buf_.__small) _Fp(std::move(__f)); } else { - unique_ptr<_Fun, __deallocating_deleter<_Fun>> __hold(std::__libcpp_allocate<_Fun>(__element_count(1))); - __buf_.__large = ::new ((void*)__hold.get()) _Fun(std::move(__f)); - (void)__hold.release(); + __buf_.__large = ::new _Fp(std::move(__f)); } } } _LIBCPP_HIDE_FROM_ABI __policy_func(const __policy_func& __f) - : __buf_(__f.__buf_), __invoker_(__f.__invoker_), __policy_(__f.__policy_) { + : __buf_(__f.__buf_), __func_(__f.__func_), __policy_(__f.__policy_) { if (__policy_->__clone) __buf_.__large = __policy_->__clone(__f.__buf_.__large); } _LIBCPP_HIDE_FROM_ABI __policy_func(__policy_func&& __f) - : __buf_(__f.__buf_), __invoker_(__f.__invoker_), __policy_(__f.__policy_) { + : __buf_(__f.__buf_), __func_(__f.__func_), __policy_(__f.__policy_) { if (__policy_->__destroy) { - __f.__policy_ = __policy::__create_empty(); - __f.__invoker_ = __invoker(); + __f.__policy_ = __policy::__create_empty(); + __f.__func_ = {}; } } @@ -700,30 +486,30 @@ public: } _LIBCPP_HIDE_FROM_ABI __policy_func& operator=(__policy_func&& __f) { - *this = nullptr; - __buf_ = __f.__buf_; - __invoker_ = __f.__invoker_; - __policy_ = __f.__policy_; - __f.__policy_ = __policy::__create_empty(); - __f.__invoker_ = __invoker(); + *this = nullptr; + __buf_ = __f.__buf_; + __func_ = __f.__func_; + __policy_ = __f.__policy_; + __f.__policy_ = __policy::__create_empty(); + __f.__func_ = {}; return *this; } _LIBCPP_HIDE_FROM_ABI __policy_func& operator=(nullptr_t) { const __policy* __p = __policy_; __policy_ = __policy::__create_empty(); - __invoker_ = __invoker(); + __func_ = {}; if (__p->__destroy) __p->__destroy(__buf_.__large); return *this; } _LIBCPP_HIDE_FROM_ABI _Rp operator()(_ArgTypes&&... __args) const { - return __invoker_.__call_(std::addressof(__buf_), std::forward<_ArgTypes>(__args)...); + return __func_(std::addressof(__buf_), std::forward<_ArgTypes>(__args)...); } _LIBCPP_HIDE_FROM_ABI void swap(__policy_func& __f) { - std::swap(__invoker_, __f.__invoker_); + std::swap(__func_, __f.__func_); std::swap(__policy_, __f.__policy_); std::swap(__buf_, __f.__buf_); } @@ -750,14 +536,14 @@ public: extern "C" void* _Block_copy(const void*); extern "C" void _Block_release(const void*); -template -class __func<_Rp1 (^)(_ArgTypes1...), _Alloc, _Rp(_ArgTypes...)> : public __base<_Rp(_ArgTypes...)> { +template +class __func<_Rp1 (^)(_ArgTypes1...), _Rp(_ArgTypes...)> : public __base<_Rp(_ArgTypes...)> { typedef _Rp1 (^__block_type)(_ArgTypes1...); __block_type __f_; public: _LIBCPP_HIDE_FROM_ABI explicit __func(__block_type const& __f) -# if _LIBCPP_HAS_OBJC_ARC +# if __has_feature(objc_arc) : __f_(__f) # else : __f_(reinterpret_cast<__block_type>(__f ? _Block_copy(__f) : nullptr)) @@ -767,15 +553,6 @@ public: // [TODO] add && to save on a retain - _LIBCPP_HIDE_FROM_ABI explicit __func(__block_type __f, const _Alloc& /* unused */) -# if _LIBCPP_HAS_OBJC_ARC - : __f_(__f) -# else - : __f_(reinterpret_cast<__block_type>(__f ? _Block_copy(__f) : nullptr)) -# endif - { - } - _LIBCPP_HIDE_FROM_ABI_VIRTUAL virtual __base<_Rp(_ArgTypes...)>* __clone() const { _LIBCPP_ASSERT_INTERNAL( false, @@ -790,7 +567,7 @@ public: } _LIBCPP_HIDE_FROM_ABI_VIRTUAL virtual void destroy() _NOEXCEPT { -# if !_LIBCPP_HAS_OBJC_ARC +# if !__has_feature(objc_arc) if (__f_) _Block_release(__f_); # endif @@ -822,12 +599,12 @@ public: # endif // _LIBCPP_HAS_RTTI }; -# endif // _LIBCPP_HAS_EXTENSION_BLOCKS +# endif // _LIBCPP_HAS_BLOCKS_RUNTIME } // namespace __function template -class _LIBCPP_TEMPLATE_VIS function<_Rp(_ArgTypes...)> +class function<_Rp(_ArgTypes...)> : public __function::__maybe_derive_from_unary_function<_Rp(_ArgTypes...)>, public __function::__maybe_derive_from_binary_function<_Rp(_ArgTypes...)> { # ifndef _LIBCPP_ABI_OPTIMIZED_FUNCTION @@ -954,7 +731,7 @@ function<_Rp(_ArgTypes...)>::function(_Fp __f) : __f_(std::move(__f)) {} # if _LIBCPP_STD_VER <= 14 template template -function<_Rp(_ArgTypes...)>::function(allocator_arg_t, const _Alloc& __a, _Fp __f) : __f_(std::move(__f), __a) {} +function<_Rp(_ArgTypes...)>::function(allocator_arg_t, const _Alloc&, _Fp __f) : __f_(std::move(__f)) {} # endif template diff --git a/lib/libcxx/include/__functional/hash.h b/lib/libcxx/include/__functional/hash.h index 28b2635ab1..489a6f00b8 100644 --- a/lib/libcxx/include/__functional/hash.h +++ b/lib/libcxx/include/__functional/hash.h @@ -13,11 +13,14 @@ #include <__cstddef/nullptr_t.h> #include <__functional/unary_function.h> #include <__fwd/functional.h> +#include <__memory/addressof.h> #include <__type_traits/conjunction.h> #include <__type_traits/enable_if.h> #include <__type_traits/invoke.h> #include <__type_traits/is_constructible.h> #include <__type_traits/is_enum.h> +#include <__type_traits/is_floating_point.h> +#include <__type_traits/is_integral.h> #include <__type_traits/underlying_type.h> #include <__utility/pair.h> #include <__utility/swap.h> @@ -33,7 +36,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD template inline _LIBCPP_HIDE_FROM_ABI _Size __loadword(const void* __p) { _Size __r; - std::memcpy(&__r, __p, sizeof(__r)); + std::memcpy(std::addressof(__r), __p, sizeof(__r)); return __r; } @@ -63,10 +66,10 @@ struct __murmur2_or_cityhash<_Size, 32> { switch (__len) { case 3: __h ^= static_cast<_Size>(__data[2] << 16); - _LIBCPP_FALLTHROUGH(); + [[__fallthrough__]]; case 2: __h ^= static_cast<_Size>(__data[1] << 8); - _LIBCPP_FALLTHROUGH(); + [[__fallthrough__]]; case 1: __h ^= __data[0]; __h *= __m; @@ -237,6 +240,14 @@ private: } }; +#if _LIBCPP_AVAILABILITY_HAS_HASH_MEMORY +[[__gnu__::__pure__]] _LIBCPP_EXPORTED_FROM_ABI size_t __hash_memory(_LIBCPP_NOESCAPE const void*, size_t) _NOEXCEPT; +#else +_LIBCPP_HIDE_FROM_ABI inline size_t __hash_memory(const void* __ptr, size_t __size) _NOEXCEPT { + return __murmur2_or_cityhash()(__ptr, __size); +} +#endif + template struct __scalar_hash; @@ -276,7 +287,7 @@ struct __scalar_hash<_Tp, 2> : public __unary_function<_Tp, size_t> { } __s; } __u; __u.__t = __v; - return __murmur2_or_cityhash()(&__u, sizeof(__u)); + return std::__hash_memory(std::addressof(__u), sizeof(__u)); } }; @@ -292,7 +303,7 @@ struct __scalar_hash<_Tp, 3> : public __unary_function<_Tp, size_t> { } __s; } __u; __u.__t = __v; - return __murmur2_or_cityhash()(&__u, sizeof(__u)); + return std::__hash_memory(std::addressof(__u), sizeof(__u)); } }; @@ -309,7 +320,7 @@ struct __scalar_hash<_Tp, 4> : public __unary_function<_Tp, size_t> { } __s; } __u; __u.__t = __v; - return __murmur2_or_cityhash()(&__u, sizeof(__u)); + return std::__hash_memory(std::addressof(__u), sizeof(__u)); } }; @@ -325,133 +336,54 @@ _LIBCPP_HIDE_FROM_ABI inline size_t __hash_combine(size_t __lhs, size_t __rhs) _ } template -struct _LIBCPP_TEMPLATE_VIS hash<_Tp*> : public __unary_function<_Tp*, size_t> { +struct hash<_Tp*> : public __unary_function<_Tp*, size_t> { _LIBCPP_HIDE_FROM_ABI size_t operator()(_Tp* __v) const _NOEXCEPT { union { _Tp* __t; size_t __a; } __u; __u.__t = __v; - return __murmur2_or_cityhash()(&__u, sizeof(__u)); + return std::__hash_memory(std::addressof(__u), sizeof(__u)); } }; -template <> -struct _LIBCPP_TEMPLATE_VIS hash : public __unary_function { - _LIBCPP_HIDE_FROM_ABI size_t operator()(bool __v) const _NOEXCEPT { return static_cast(__v); } +template +struct __hash_impl { + __hash_impl() = delete; + __hash_impl(__hash_impl const&) = delete; + __hash_impl& operator=(__hash_impl const&) = delete; }; -template <> -struct _LIBCPP_TEMPLATE_VIS hash : public __unary_function { - _LIBCPP_HIDE_FROM_ABI size_t operator()(char __v) const _NOEXCEPT { return static_cast(__v); } -}; - -template <> -struct _LIBCPP_TEMPLATE_VIS hash : public __unary_function { - _LIBCPP_HIDE_FROM_ABI size_t operator()(signed char __v) const _NOEXCEPT { return static_cast(__v); } -}; - -template <> -struct _LIBCPP_TEMPLATE_VIS hash : public __unary_function { - _LIBCPP_HIDE_FROM_ABI size_t operator()(unsigned char __v) const _NOEXCEPT { return static_cast(__v); } -}; - -#if _LIBCPP_HAS_CHAR8_T -template <> -struct _LIBCPP_TEMPLATE_VIS hash : public __unary_function { - _LIBCPP_HIDE_FROM_ABI size_t operator()(char8_t __v) const _NOEXCEPT { return static_cast(__v); } -}; -#endif // _LIBCPP_HAS_CHAR8_T - -template <> -struct _LIBCPP_TEMPLATE_VIS hash : public __unary_function { - _LIBCPP_HIDE_FROM_ABI size_t operator()(char16_t __v) const _NOEXCEPT { return static_cast(__v); } -}; - -template <> -struct _LIBCPP_TEMPLATE_VIS hash : public __unary_function { - _LIBCPP_HIDE_FROM_ABI size_t operator()(char32_t __v) const _NOEXCEPT { return static_cast(__v); } -}; - -#if _LIBCPP_HAS_WIDE_CHARACTERS -template <> -struct _LIBCPP_TEMPLATE_VIS hash : public __unary_function { - _LIBCPP_HIDE_FROM_ABI size_t operator()(wchar_t __v) const _NOEXCEPT { return static_cast(__v); } -}; -#endif // _LIBCPP_HAS_WIDE_CHARACTERS - -template <> -struct _LIBCPP_TEMPLATE_VIS hash : public __unary_function { - _LIBCPP_HIDE_FROM_ABI size_t operator()(short __v) const _NOEXCEPT { return static_cast(__v); } -}; - -template <> -struct _LIBCPP_TEMPLATE_VIS hash : public __unary_function { - _LIBCPP_HIDE_FROM_ABI size_t operator()(unsigned short __v) const _NOEXCEPT { return static_cast(__v); } -}; - -template <> -struct _LIBCPP_TEMPLATE_VIS hash : public __unary_function { - _LIBCPP_HIDE_FROM_ABI size_t operator()(int __v) const _NOEXCEPT { return static_cast(__v); } -}; - -template <> -struct _LIBCPP_TEMPLATE_VIS hash : public __unary_function { - _LIBCPP_HIDE_FROM_ABI size_t operator()(unsigned int __v) const _NOEXCEPT { return static_cast(__v); } -}; - -template <> -struct _LIBCPP_TEMPLATE_VIS hash : public __unary_function { - _LIBCPP_HIDE_FROM_ABI size_t operator()(long __v) const _NOEXCEPT { return static_cast(__v); } -}; - -template <> -struct _LIBCPP_TEMPLATE_VIS hash : public __unary_function { - _LIBCPP_HIDE_FROM_ABI size_t operator()(unsigned long __v) const _NOEXCEPT { - static_assert(sizeof(size_t) >= sizeof(unsigned long), - "This would be a terrible hash function on a platform where size_t is smaller than unsigned long"); - return static_cast(__v); +template +struct __hash_impl<_Tp, __enable_if_t::value> > : __unary_function<_Tp, size_t> { + _LIBCPP_HIDE_FROM_ABI size_t operator()(_Tp __v) const _NOEXCEPT { + using type = __underlying_type_t<_Tp>; + return hash()(static_cast(__v)); } }; -template <> -struct _LIBCPP_TEMPLATE_VIS hash : public __scalar_hash {}; +template +struct __hash_impl<_Tp, __enable_if_t::value && (sizeof(_Tp) <= sizeof(size_t))> > + : __unary_function<_Tp, size_t> { + _LIBCPP_HIDE_FROM_ABI size_t operator()(_Tp __v) const _NOEXCEPT { return static_cast(__v); } +}; -template <> -struct _LIBCPP_TEMPLATE_VIS hash : public __scalar_hash {}; +template +struct __hash_impl<_Tp, __enable_if_t::value && (sizeof(_Tp) > sizeof(size_t))> > + : __scalar_hash<_Tp> {}; -#if _LIBCPP_HAS_INT128 - -template <> -struct _LIBCPP_TEMPLATE_VIS hash<__int128_t> : public __scalar_hash<__int128_t> {}; - -template <> -struct _LIBCPP_TEMPLATE_VIS hash<__uint128_t> : public __scalar_hash<__uint128_t> {}; - -#endif - -template <> -struct _LIBCPP_TEMPLATE_VIS hash : public __scalar_hash { - _LIBCPP_HIDE_FROM_ABI size_t operator()(float __v) const _NOEXCEPT { +template +struct __hash_impl<_Tp, __enable_if_t::value> > : __scalar_hash<_Tp> { + _LIBCPP_HIDE_FROM_ABI size_t operator()(_Tp __v) const _NOEXCEPT { // -0.0 and 0.0 should return same hash if (__v == 0.0f) return 0; - return __scalar_hash::operator()(__v); + return __scalar_hash<_Tp>::operator()(__v); } }; template <> -struct _LIBCPP_TEMPLATE_VIS hash : public __scalar_hash { - _LIBCPP_HIDE_FROM_ABI size_t operator()(double __v) const _NOEXCEPT { - // -0.0 and 0.0 should return same hash - if (__v == 0.0) - return 0; - return __scalar_hash::operator()(__v); - } -}; - -template <> -struct _LIBCPP_TEMPLATE_VIS hash : public __scalar_hash { +struct __hash_impl : __scalar_hash { _LIBCPP_HIDE_FROM_ABI size_t operator()(long double __v) const _NOEXCEPT { // -0.0 and 0.0 should return same hash if (__v == 0.0L) @@ -492,27 +424,13 @@ struct _LIBCPP_TEMPLATE_VIS hash : public __scalar_hash::value> -struct _LIBCPP_TEMPLATE_VIS __enum_hash : public __unary_function<_Tp, size_t> { - _LIBCPP_HIDE_FROM_ABI size_t operator()(_Tp __v) const _NOEXCEPT { - typedef typename underlying_type<_Tp>::type type; - return hash()(static_cast(__v)); - } -}; template -struct _LIBCPP_TEMPLATE_VIS __enum_hash<_Tp, false> { - __enum_hash() = delete; - __enum_hash(__enum_hash const&) = delete; - __enum_hash& operator=(__enum_hash const&) = delete; -}; - -template -struct _LIBCPP_TEMPLATE_VIS hash : public __enum_hash<_Tp> {}; +struct hash : public __hash_impl<_Tp> {}; #if _LIBCPP_STD_VER >= 17 template <> -struct _LIBCPP_TEMPLATE_VIS hash : public __unary_function { +struct hash : public __unary_function { _LIBCPP_HIDE_FROM_ABI size_t operator()(nullptr_t) const _NOEXCEPT { return 662607004ull; } }; #endif diff --git a/lib/libcxx/include/__functional/mem_fun_ref.h b/lib/libcxx/include/__functional/mem_fun_ref.h index c344420b02..68223772a1 100644 --- a/lib/libcxx/include/__functional/mem_fun_ref.h +++ b/lib/libcxx/include/__functional/mem_fun_ref.h @@ -23,7 +23,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD #if _LIBCPP_STD_VER <= 14 || defined(_LIBCPP_ENABLE_CXX17_REMOVED_BINDERS) template -class _LIBCPP_TEMPLATE_VIS _LIBCPP_DEPRECATED_IN_CXX11 mem_fun_t : public __unary_function<_Tp*, _Sp> { +class _LIBCPP_DEPRECATED_IN_CXX11 mem_fun_t : public __unary_function<_Tp*, _Sp> { _Sp (_Tp::*__p_)(); public: @@ -32,7 +32,7 @@ public: }; template -class _LIBCPP_TEMPLATE_VIS _LIBCPP_DEPRECATED_IN_CXX11 mem_fun1_t : public __binary_function<_Tp*, _Ap, _Sp> { +class _LIBCPP_DEPRECATED_IN_CXX11 mem_fun1_t : public __binary_function<_Tp*, _Ap, _Sp> { _Sp (_Tp::*__p_)(_Ap); public: @@ -51,7 +51,7 @@ _LIBCPP_DEPRECATED_IN_CXX11 inline _LIBCPP_HIDE_FROM_ABI mem_fun1_t<_Sp, _Tp, _A } template -class _LIBCPP_TEMPLATE_VIS _LIBCPP_DEPRECATED_IN_CXX11 mem_fun_ref_t : public __unary_function<_Tp, _Sp> { +class _LIBCPP_DEPRECATED_IN_CXX11 mem_fun_ref_t : public __unary_function<_Tp, _Sp> { _Sp (_Tp::*__p_)(); public: @@ -60,7 +60,7 @@ public: }; template -class _LIBCPP_TEMPLATE_VIS _LIBCPP_DEPRECATED_IN_CXX11 mem_fun1_ref_t : public __binary_function<_Tp, _Ap, _Sp> { +class _LIBCPP_DEPRECATED_IN_CXX11 mem_fun1_ref_t : public __binary_function<_Tp, _Ap, _Sp> { _Sp (_Tp::*__p_)(_Ap); public: @@ -80,7 +80,7 @@ mem_fun_ref(_Sp (_Tp::*__f)(_Ap)) { } template -class _LIBCPP_TEMPLATE_VIS _LIBCPP_DEPRECATED_IN_CXX11 const_mem_fun_t : public __unary_function { +class _LIBCPP_DEPRECATED_IN_CXX11 const_mem_fun_t : public __unary_function { _Sp (_Tp::*__p_)() const; public: @@ -89,8 +89,7 @@ public: }; template -class _LIBCPP_TEMPLATE_VIS -_LIBCPP_DEPRECATED_IN_CXX11 const_mem_fun1_t : public __binary_function { +class _LIBCPP_DEPRECATED_IN_CXX11 const_mem_fun1_t : public __binary_function { _Sp (_Tp::*__p_)(_Ap) const; public: @@ -110,7 +109,7 @@ mem_fun(_Sp (_Tp::*__f)(_Ap) const) { } template -class _LIBCPP_TEMPLATE_VIS _LIBCPP_DEPRECATED_IN_CXX11 const_mem_fun_ref_t : public __unary_function<_Tp, _Sp> { +class _LIBCPP_DEPRECATED_IN_CXX11 const_mem_fun_ref_t : public __unary_function<_Tp, _Sp> { _Sp (_Tp::*__p_)() const; public: @@ -119,7 +118,7 @@ public: }; template -class _LIBCPP_TEMPLATE_VIS _LIBCPP_DEPRECATED_IN_CXX11 const_mem_fun1_ref_t : public __binary_function<_Tp, _Ap, _Sp> { +class _LIBCPP_DEPRECATED_IN_CXX11 const_mem_fun1_ref_t : public __binary_function<_Tp, _Ap, _Sp> { _Sp (_Tp::*__p_)(_Ap) const; public: diff --git a/lib/libcxx/include/__functional/operations.h b/lib/libcxx/include/__functional/operations.h index 67d9da289a..7b0ea11db5 100644 --- a/lib/libcxx/include/__functional/operations.h +++ b/lib/libcxx/include/__functional/operations.h @@ -13,6 +13,7 @@ #include <__config> #include <__functional/binary_function.h> #include <__functional/unary_function.h> +#include <__fwd/functional.h> #include <__type_traits/desugars_to.h> #include <__type_traits/is_integral.h> #include <__utility/forward.h> @@ -30,7 +31,7 @@ template #else template #endif -struct _LIBCPP_TEMPLATE_VIS plus : __binary_function<_Tp, _Tp, _Tp> { +struct plus : __binary_function<_Tp, _Tp, _Tp> { typedef _Tp __result_type; // used by valarray _LIBCPP_CONSTEXPR_SINCE_CXX14 _LIBCPP_HIDE_FROM_ABI _Tp operator()(const _Tp& __x, const _Tp& __y) const { return __x + __y; @@ -48,7 +49,7 @@ inline const bool __desugars_to_v<__plus_tag, plus, _Tp, _Up> = true; #if _LIBCPP_STD_VER >= 14 template <> -struct _LIBCPP_TEMPLATE_VIS plus { +struct plus { template _LIBCPP_CONSTEXPR_SINCE_CXX14 _LIBCPP_HIDE_FROM_ABI auto operator()(_T1&& __t, _T2&& __u) const noexcept(noexcept(std::forward<_T1>(__t) + std::forward<_T2>(__u))) // @@ -64,7 +65,7 @@ template #else template #endif -struct _LIBCPP_TEMPLATE_VIS minus : __binary_function<_Tp, _Tp, _Tp> { +struct minus : __binary_function<_Tp, _Tp, _Tp> { typedef _Tp __result_type; // used by valarray _LIBCPP_CONSTEXPR_SINCE_CXX14 _LIBCPP_HIDE_FROM_ABI _Tp operator()(const _Tp& __x, const _Tp& __y) const { return __x - __y; @@ -74,7 +75,7 @@ _LIBCPP_CTAD_SUPPORTED_FOR_TYPE(minus); #if _LIBCPP_STD_VER >= 14 template <> -struct _LIBCPP_TEMPLATE_VIS minus { +struct minus { template _LIBCPP_CONSTEXPR_SINCE_CXX14 _LIBCPP_HIDE_FROM_ABI auto operator()(_T1&& __t, _T2&& __u) const noexcept(noexcept(std::forward<_T1>(__t) - std::forward<_T2>(__u))) // @@ -90,7 +91,7 @@ template #else template #endif -struct _LIBCPP_TEMPLATE_VIS multiplies : __binary_function<_Tp, _Tp, _Tp> { +struct multiplies : __binary_function<_Tp, _Tp, _Tp> { typedef _Tp __result_type; // used by valarray _LIBCPP_CONSTEXPR_SINCE_CXX14 _LIBCPP_HIDE_FROM_ABI _Tp operator()(const _Tp& __x, const _Tp& __y) const { return __x * __y; @@ -100,7 +101,7 @@ _LIBCPP_CTAD_SUPPORTED_FOR_TYPE(multiplies); #if _LIBCPP_STD_VER >= 14 template <> -struct _LIBCPP_TEMPLATE_VIS multiplies { +struct multiplies { template _LIBCPP_CONSTEXPR_SINCE_CXX14 _LIBCPP_HIDE_FROM_ABI auto operator()(_T1&& __t, _T2&& __u) const noexcept(noexcept(std::forward<_T1>(__t) * std::forward<_T2>(__u))) // @@ -116,7 +117,7 @@ template #else template #endif -struct _LIBCPP_TEMPLATE_VIS divides : __binary_function<_Tp, _Tp, _Tp> { +struct divides : __binary_function<_Tp, _Tp, _Tp> { typedef _Tp __result_type; // used by valarray _LIBCPP_CONSTEXPR_SINCE_CXX14 _LIBCPP_HIDE_FROM_ABI _Tp operator()(const _Tp& __x, const _Tp& __y) const { return __x / __y; @@ -126,7 +127,7 @@ _LIBCPP_CTAD_SUPPORTED_FOR_TYPE(divides); #if _LIBCPP_STD_VER >= 14 template <> -struct _LIBCPP_TEMPLATE_VIS divides { +struct divides { template _LIBCPP_CONSTEXPR_SINCE_CXX14 _LIBCPP_HIDE_FROM_ABI auto operator()(_T1&& __t, _T2&& __u) const noexcept(noexcept(std::forward<_T1>(__t) / std::forward<_T2>(__u))) // @@ -142,7 +143,7 @@ template #else template #endif -struct _LIBCPP_TEMPLATE_VIS modulus : __binary_function<_Tp, _Tp, _Tp> { +struct modulus : __binary_function<_Tp, _Tp, _Tp> { typedef _Tp __result_type; // used by valarray _LIBCPP_CONSTEXPR_SINCE_CXX14 _LIBCPP_HIDE_FROM_ABI _Tp operator()(const _Tp& __x, const _Tp& __y) const { return __x % __y; @@ -152,7 +153,7 @@ _LIBCPP_CTAD_SUPPORTED_FOR_TYPE(modulus); #if _LIBCPP_STD_VER >= 14 template <> -struct _LIBCPP_TEMPLATE_VIS modulus { +struct modulus { template _LIBCPP_CONSTEXPR_SINCE_CXX14 _LIBCPP_HIDE_FROM_ABI auto operator()(_T1&& __t, _T2&& __u) const noexcept(noexcept(std::forward<_T1>(__t) % std::forward<_T2>(__u))) // @@ -168,7 +169,7 @@ template #else template #endif -struct _LIBCPP_TEMPLATE_VIS negate : __unary_function<_Tp, _Tp> { +struct negate : __unary_function<_Tp, _Tp> { typedef _Tp __result_type; // used by valarray _LIBCPP_CONSTEXPR_SINCE_CXX14 _LIBCPP_HIDE_FROM_ABI _Tp operator()(const _Tp& __x) const { return -__x; } }; @@ -176,7 +177,7 @@ _LIBCPP_CTAD_SUPPORTED_FOR_TYPE(negate); #if _LIBCPP_STD_VER >= 14 template <> -struct _LIBCPP_TEMPLATE_VIS negate { +struct negate { template _LIBCPP_CONSTEXPR_SINCE_CXX14 _LIBCPP_HIDE_FROM_ABI auto operator()(_Tp&& __x) const noexcept(noexcept(-std::forward<_Tp>(__x))) // @@ -194,7 +195,7 @@ template #else template #endif -struct _LIBCPP_TEMPLATE_VIS bit_and : __binary_function<_Tp, _Tp, _Tp> { +struct bit_and : __binary_function<_Tp, _Tp, _Tp> { typedef _Tp __result_type; // used by valarray _LIBCPP_CONSTEXPR_SINCE_CXX14 _LIBCPP_HIDE_FROM_ABI _Tp operator()(const _Tp& __x, const _Tp& __y) const { return __x & __y; @@ -204,7 +205,7 @@ _LIBCPP_CTAD_SUPPORTED_FOR_TYPE(bit_and); #if _LIBCPP_STD_VER >= 14 template <> -struct _LIBCPP_TEMPLATE_VIS bit_and { +struct bit_and { template _LIBCPP_CONSTEXPR_SINCE_CXX14 _LIBCPP_HIDE_FROM_ABI auto operator()(_T1&& __t, _T2&& __u) const noexcept(noexcept(std::forward<_T1>(__t) & @@ -217,13 +218,13 @@ struct _LIBCPP_TEMPLATE_VIS bit_and { #if _LIBCPP_STD_VER >= 14 template -struct _LIBCPP_TEMPLATE_VIS bit_not : __unary_function<_Tp, _Tp> { +struct bit_not : __unary_function<_Tp, _Tp> { _LIBCPP_CONSTEXPR_SINCE_CXX14 _LIBCPP_HIDE_FROM_ABI _Tp operator()(const _Tp& __x) const { return ~__x; } }; _LIBCPP_CTAD_SUPPORTED_FOR_TYPE(bit_not); template <> -struct _LIBCPP_TEMPLATE_VIS bit_not { +struct bit_not { template _LIBCPP_CONSTEXPR_SINCE_CXX14 _LIBCPP_HIDE_FROM_ABI auto operator()(_Tp&& __x) const noexcept(noexcept(~std::forward<_Tp>(__x))) // @@ -239,7 +240,7 @@ template #else template #endif -struct _LIBCPP_TEMPLATE_VIS bit_or : __binary_function<_Tp, _Tp, _Tp> { +struct bit_or : __binary_function<_Tp, _Tp, _Tp> { typedef _Tp __result_type; // used by valarray _LIBCPP_CONSTEXPR_SINCE_CXX14 _LIBCPP_HIDE_FROM_ABI _Tp operator()(const _Tp& __x, const _Tp& __y) const { return __x | __y; @@ -249,7 +250,7 @@ _LIBCPP_CTAD_SUPPORTED_FOR_TYPE(bit_or); #if _LIBCPP_STD_VER >= 14 template <> -struct _LIBCPP_TEMPLATE_VIS bit_or { +struct bit_or { template _LIBCPP_CONSTEXPR_SINCE_CXX14 _LIBCPP_HIDE_FROM_ABI auto operator()(_T1&& __t, _T2&& __u) const noexcept(noexcept(std::forward<_T1>(__t) | std::forward<_T2>(__u))) // @@ -265,7 +266,7 @@ template #else template #endif -struct _LIBCPP_TEMPLATE_VIS bit_xor : __binary_function<_Tp, _Tp, _Tp> { +struct bit_xor : __binary_function<_Tp, _Tp, _Tp> { typedef _Tp __result_type; // used by valarray _LIBCPP_CONSTEXPR_SINCE_CXX14 _LIBCPP_HIDE_FROM_ABI _Tp operator()(const _Tp& __x, const _Tp& __y) const { return __x ^ __y; @@ -275,7 +276,7 @@ _LIBCPP_CTAD_SUPPORTED_FOR_TYPE(bit_xor); #if _LIBCPP_STD_VER >= 14 template <> -struct _LIBCPP_TEMPLATE_VIS bit_xor { +struct bit_xor { template _LIBCPP_CONSTEXPR_SINCE_CXX14 _LIBCPP_HIDE_FROM_ABI auto operator()(_T1&& __t, _T2&& __u) const noexcept(noexcept(std::forward<_T1>(__t) ^ std::forward<_T2>(__u))) // @@ -293,7 +294,7 @@ template #else template #endif -struct _LIBCPP_TEMPLATE_VIS equal_to : __binary_function<_Tp, _Tp, bool> { +struct equal_to : __binary_function<_Tp, _Tp, bool> { typedef bool __result_type; // used by valarray _LIBCPP_CONSTEXPR_SINCE_CXX14 _LIBCPP_HIDE_FROM_ABI bool operator()(const _Tp& __x, const _Tp& __y) const { return __x == __y; @@ -303,7 +304,7 @@ _LIBCPP_CTAD_SUPPORTED_FOR_TYPE(equal_to); #if _LIBCPP_STD_VER >= 14 template <> -struct _LIBCPP_TEMPLATE_VIS equal_to { +struct equal_to { template _LIBCPP_CONSTEXPR_SINCE_CXX14 _LIBCPP_HIDE_FROM_ABI auto operator()(_T1&& __t, _T2&& __u) const noexcept(noexcept(std::forward<_T1>(__t) == std::forward<_T2>(__u))) // @@ -328,7 +329,7 @@ template #else template #endif -struct _LIBCPP_TEMPLATE_VIS not_equal_to : __binary_function<_Tp, _Tp, bool> { +struct not_equal_to : __binary_function<_Tp, _Tp, bool> { typedef bool __result_type; // used by valarray _LIBCPP_CONSTEXPR_SINCE_CXX14 _LIBCPP_HIDE_FROM_ABI bool operator()(const _Tp& __x, const _Tp& __y) const { return __x != __y; @@ -338,7 +339,7 @@ _LIBCPP_CTAD_SUPPORTED_FOR_TYPE(not_equal_to); #if _LIBCPP_STD_VER >= 14 template <> -struct _LIBCPP_TEMPLATE_VIS not_equal_to { +struct not_equal_to { template _LIBCPP_CONSTEXPR_SINCE_CXX14 _LIBCPP_HIDE_FROM_ABI auto operator()(_T1&& __t, _T2&& __u) const noexcept(noexcept(std::forward<_T1>(__t) != std::forward<_T2>(__u))) // @@ -349,12 +350,8 @@ struct _LIBCPP_TEMPLATE_VIS not_equal_to { }; #endif -#if _LIBCPP_STD_VER >= 14 -template -#else template -#endif -struct _LIBCPP_TEMPLATE_VIS less : __binary_function<_Tp, _Tp, bool> { +struct less : __binary_function<_Tp, _Tp, bool> { typedef bool __result_type; // used by valarray _LIBCPP_CONSTEXPR_SINCE_CXX14 _LIBCPP_HIDE_FROM_ABI bool operator()(const _Tp& __x, const _Tp& __y) const { return __x < __y; @@ -370,7 +367,7 @@ inline const bool __desugars_to_v<__totally_ordered_less_tag, less<_Tp>, _Tp, _T #if _LIBCPP_STD_VER >= 14 template <> -struct _LIBCPP_TEMPLATE_VIS less { +struct less { template _LIBCPP_CONSTEXPR_SINCE_CXX14 _LIBCPP_HIDE_FROM_ABI auto operator()(_T1&& __t, _T2&& __u) const noexcept(noexcept(std::forward<_T1>(__t) < std::forward<_T2>(__u))) // @@ -392,7 +389,7 @@ template #else template #endif -struct _LIBCPP_TEMPLATE_VIS less_equal : __binary_function<_Tp, _Tp, bool> { +struct less_equal : __binary_function<_Tp, _Tp, bool> { typedef bool __result_type; // used by valarray _LIBCPP_CONSTEXPR_SINCE_CXX14 _LIBCPP_HIDE_FROM_ABI bool operator()(const _Tp& __x, const _Tp& __y) const { return __x <= __y; @@ -402,7 +399,7 @@ _LIBCPP_CTAD_SUPPORTED_FOR_TYPE(less_equal); #if _LIBCPP_STD_VER >= 14 template <> -struct _LIBCPP_TEMPLATE_VIS less_equal { +struct less_equal { template _LIBCPP_CONSTEXPR_SINCE_CXX14 _LIBCPP_HIDE_FROM_ABI auto operator()(_T1&& __t, _T2&& __u) const noexcept(noexcept(std::forward<_T1>(__t) <= std::forward<_T2>(__u))) // @@ -418,7 +415,7 @@ template #else template #endif -struct _LIBCPP_TEMPLATE_VIS greater_equal : __binary_function<_Tp, _Tp, bool> { +struct greater_equal : __binary_function<_Tp, _Tp, bool> { typedef bool __result_type; // used by valarray _LIBCPP_CONSTEXPR_SINCE_CXX14 _LIBCPP_HIDE_FROM_ABI bool operator()(const _Tp& __x, const _Tp& __y) const { return __x >= __y; @@ -428,7 +425,7 @@ _LIBCPP_CTAD_SUPPORTED_FOR_TYPE(greater_equal); #if _LIBCPP_STD_VER >= 14 template <> -struct _LIBCPP_TEMPLATE_VIS greater_equal { +struct greater_equal { template _LIBCPP_CONSTEXPR_SINCE_CXX14 _LIBCPP_HIDE_FROM_ABI auto operator()(_T1&& __t, _T2&& __u) const noexcept(noexcept(std::forward<_T1>(__t) >= @@ -444,7 +441,7 @@ template #else template #endif -struct _LIBCPP_TEMPLATE_VIS greater : __binary_function<_Tp, _Tp, bool> { +struct greater : __binary_function<_Tp, _Tp, bool> { typedef bool __result_type; // used by valarray _LIBCPP_CONSTEXPR_SINCE_CXX14 _LIBCPP_HIDE_FROM_ABI bool operator()(const _Tp& __x, const _Tp& __y) const { return __x > __y; @@ -457,7 +454,7 @@ inline const bool __desugars_to_v<__greater_tag, greater<_Tp>, _Tp, _Tp> = true; #if _LIBCPP_STD_VER >= 14 template <> -struct _LIBCPP_TEMPLATE_VIS greater { +struct greater { template _LIBCPP_CONSTEXPR_SINCE_CXX14 _LIBCPP_HIDE_FROM_ABI auto operator()(_T1&& __t, _T2&& __u) const noexcept(noexcept(std::forward<_T1>(__t) > std::forward<_T2>(__u))) // @@ -478,7 +475,7 @@ template #else template #endif -struct _LIBCPP_TEMPLATE_VIS logical_and : __binary_function<_Tp, _Tp, bool> { +struct logical_and : __binary_function<_Tp, _Tp, bool> { typedef bool __result_type; // used by valarray _LIBCPP_CONSTEXPR_SINCE_CXX14 _LIBCPP_HIDE_FROM_ABI bool operator()(const _Tp& __x, const _Tp& __y) const { return __x && __y; @@ -488,7 +485,7 @@ _LIBCPP_CTAD_SUPPORTED_FOR_TYPE(logical_and); #if _LIBCPP_STD_VER >= 14 template <> -struct _LIBCPP_TEMPLATE_VIS logical_and { +struct logical_and { template _LIBCPP_CONSTEXPR_SINCE_CXX14 _LIBCPP_HIDE_FROM_ABI auto operator()(_T1&& __t, _T2&& __u) const noexcept(noexcept(std::forward<_T1>(__t) && std::forward<_T2>(__u))) // @@ -504,7 +501,7 @@ template #else template #endif -struct _LIBCPP_TEMPLATE_VIS logical_not : __unary_function<_Tp, bool> { +struct logical_not : __unary_function<_Tp, bool> { typedef bool __result_type; // used by valarray _LIBCPP_CONSTEXPR_SINCE_CXX14 _LIBCPP_HIDE_FROM_ABI bool operator()(const _Tp& __x) const { return !__x; } }; @@ -512,7 +509,7 @@ _LIBCPP_CTAD_SUPPORTED_FOR_TYPE(logical_not); #if _LIBCPP_STD_VER >= 14 template <> -struct _LIBCPP_TEMPLATE_VIS logical_not { +struct logical_not { template _LIBCPP_CONSTEXPR_SINCE_CXX14 _LIBCPP_HIDE_FROM_ABI auto operator()(_Tp&& __x) const noexcept(noexcept(!std::forward<_Tp>(__x))) // @@ -528,7 +525,7 @@ template #else template #endif -struct _LIBCPP_TEMPLATE_VIS logical_or : __binary_function<_Tp, _Tp, bool> { +struct logical_or : __binary_function<_Tp, _Tp, bool> { typedef bool __result_type; // used by valarray _LIBCPP_CONSTEXPR_SINCE_CXX14 _LIBCPP_HIDE_FROM_ABI bool operator()(const _Tp& __x, const _Tp& __y) const { return __x || __y; @@ -538,7 +535,7 @@ _LIBCPP_CTAD_SUPPORTED_FOR_TYPE(logical_or); #if _LIBCPP_STD_VER >= 14 template <> -struct _LIBCPP_TEMPLATE_VIS logical_or { +struct logical_or { template _LIBCPP_CONSTEXPR_SINCE_CXX14 _LIBCPP_HIDE_FROM_ABI auto operator()(_T1&& __t, _T2&& __u) const noexcept(noexcept(std::forward<_T1>(__t) || std::forward<_T2>(__u))) // diff --git a/lib/libcxx/include/__functional/pointer_to_binary_function.h b/lib/libcxx/include/__functional/pointer_to_binary_function.h index e345250dcd..eb0e7674ee 100644 --- a/lib/libcxx/include/__functional/pointer_to_binary_function.h +++ b/lib/libcxx/include/__functional/pointer_to_binary_function.h @@ -22,8 +22,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD #if _LIBCPP_STD_VER <= 14 || defined(_LIBCPP_ENABLE_CXX17_REMOVED_BINDERS) template -class _LIBCPP_TEMPLATE_VIS -_LIBCPP_DEPRECATED_IN_CXX11 pointer_to_binary_function : public __binary_function<_Arg1, _Arg2, _Result> { +class _LIBCPP_DEPRECATED_IN_CXX11 pointer_to_binary_function : public __binary_function<_Arg1, _Arg2, _Result> { _Result (*__f_)(_Arg1, _Arg2); public: diff --git a/lib/libcxx/include/__functional/pointer_to_unary_function.h b/lib/libcxx/include/__functional/pointer_to_unary_function.h index 3a5d153d36..459d24abdd 100644 --- a/lib/libcxx/include/__functional/pointer_to_unary_function.h +++ b/lib/libcxx/include/__functional/pointer_to_unary_function.h @@ -22,8 +22,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD #if _LIBCPP_STD_VER <= 14 || defined(_LIBCPP_ENABLE_CXX17_REMOVED_BINDERS) template -class _LIBCPP_TEMPLATE_VIS -_LIBCPP_DEPRECATED_IN_CXX11 pointer_to_unary_function : public __unary_function<_Arg, _Result> { +class _LIBCPP_DEPRECATED_IN_CXX11 pointer_to_unary_function : public __unary_function<_Arg, _Result> { _Result (*__f_)(_Arg); public: diff --git a/lib/libcxx/include/__functional/reference_wrapper.h b/lib/libcxx/include/__functional/reference_wrapper.h index d6cd6428f2..148703b21d 100644 --- a/lib/libcxx/include/__functional/reference_wrapper.h +++ b/lib/libcxx/include/__functional/reference_wrapper.h @@ -11,13 +11,18 @@ #define _LIBCPP___FUNCTIONAL_REFERENCE_WRAPPER_H #include <__compare/synth_three_way.h> -#include <__concepts/boolean_testable.h> +#include <__concepts/convertible_to.h> #include <__config> #include <__functional/weak_result_type.h> #include <__memory/addressof.h> +#include <__type_traits/common_reference.h> +#include <__type_traits/desugars_to.h> #include <__type_traits/enable_if.h> #include <__type_traits/invoke.h> #include <__type_traits/is_const.h> +#include <__type_traits/is_core_convertible.h> +#include <__type_traits/is_same.h> +#include <__type_traits/is_specialization.h> #include <__type_traits/remove_cvref.h> #include <__type_traits/void_t.h> #include <__utility/declval.h> @@ -30,7 +35,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD template -class _LIBCPP_TEMPLATE_VIS reference_wrapper : public __weak_result_type<_Tp> { +class reference_wrapper : public __weak_result_type<_Tp> { public: // types typedef _Tp type; @@ -44,7 +49,7 @@ private: public: template ()))>, - __enable_if_t::value, int> = 0> + __enable_if_t, reference_wrapper>::value, int> = 0> _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 reference_wrapper(_Up&& __u) _NOEXCEPT_(noexcept(__fun(std::declval<_Up>()))) { type& __f = static_cast<_Up&&>(__u); @@ -74,7 +79,7 @@ public: _LIBCPP_HIDE_FROM_ABI friend constexpr bool operator==(reference_wrapper __x, reference_wrapper __y) requires requires { - { __x.get() == __y.get() } -> __boolean_testable; + { __x.get() == __y.get() } -> __core_convertible_to; } { return __x.get() == __y.get(); @@ -82,7 +87,7 @@ public: _LIBCPP_HIDE_FROM_ABI friend constexpr bool operator==(reference_wrapper __x, const _Tp& __y) requires requires { - { __x.get() == __y } -> __boolean_testable; + { __x.get() == __y } -> __core_convertible_to; } { return __x.get() == __y; @@ -90,7 +95,7 @@ public: _LIBCPP_HIDE_FROM_ABI friend constexpr bool operator==(reference_wrapper __x, reference_wrapper __y) requires(!is_const_v<_Tp>) && requires { - { __x.get() == __y.get() } -> __boolean_testable; + { __x.get() == __y.get() } -> __core_convertible_to; } { return __x.get() == __y.get(); @@ -149,6 +154,37 @@ void ref(const _Tp&&) = delete; template void cref(const _Tp&&) = delete; +// Let desugars-to pass through std::reference_wrapper +template +inline const bool __desugars_to_v<_CanonicalTag, reference_wrapper<_Operation>, _Args...> = + __desugars_to_v<_CanonicalTag, _Operation, _Args...>; + +#if _LIBCPP_STD_VER >= 20 + +template +inline constexpr bool __is_ref_wrapper = __is_specialization_v<_Tp, reference_wrapper>; + +template +concept __ref_wrap_common_reference_exists_with = __is_ref_wrapper<_Rp> && requires { + typename common_reference_t; +} && convertible_to<_RpQual, common_reference_t>; + +template class _RpQual, template class _TpQual> + requires(__ref_wrap_common_reference_exists_with<_Rp, _Tp, _RpQual<_Rp>, _TpQual<_Tp>> && + !__ref_wrap_common_reference_exists_with<_Tp, _Rp, _TpQual<_Tp>, _RpQual<_Rp>>) +struct basic_common_reference<_Rp, _Tp, _RpQual, _TpQual> { + using type _LIBCPP_NODEBUG = common_reference_t>; +}; + +template class _TpQual, template class _RpQual> + requires(__ref_wrap_common_reference_exists_with<_Rp, _Tp, _RpQual<_Rp>, _TpQual<_Tp>> && + !__ref_wrap_common_reference_exists_with<_Tp, _Rp, _TpQual<_Tp>, _RpQual<_Rp>>) +struct basic_common_reference<_Tp, _Rp, _TpQual, _RpQual> { + using type _LIBCPP_NODEBUG = common_reference_t>; +}; + +#endif // _LIBCPP_STD_VER >= 20 + _LIBCPP_END_NAMESPACE_STD #endif // _LIBCPP___FUNCTIONAL_REFERENCE_WRAPPER_H diff --git a/lib/libcxx/include/__functional/unary_function.h b/lib/libcxx/include/__functional/unary_function.h index 769ffc9893..d6d5fae45b 100644 --- a/lib/libcxx/include/__functional/unary_function.h +++ b/lib/libcxx/include/__functional/unary_function.h @@ -20,7 +20,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD #if _LIBCPP_STD_VER <= 14 || defined(_LIBCPP_ENABLE_CXX17_REMOVED_UNARY_BINARY_FUNCTION) template -struct _LIBCPP_TEMPLATE_VIS _LIBCPP_DEPRECATED_IN_CXX11 unary_function { +struct _LIBCPP_DEPRECATED_IN_CXX11 unary_function { typedef _Arg argument_type; typedef _Result result_type; }; @@ -36,11 +36,10 @@ struct __unary_function_keep_layout_base { }; #if _LIBCPP_STD_VER <= 14 || defined(_LIBCPP_ENABLE_CXX17_REMOVED_UNARY_BINARY_FUNCTION) -_LIBCPP_DIAGNOSTIC_PUSH -_LIBCPP_CLANG_DIAGNOSTIC_IGNORED("-Wdeprecated-declarations") +_LIBCPP_SUPPRESS_DEPRECATED_PUSH template using __unary_function _LIBCPP_NODEBUG = unary_function<_Arg, _Result>; -_LIBCPP_DIAGNOSTIC_POP +_LIBCPP_SUPPRESS_DEPRECATED_POP #else template using __unary_function _LIBCPP_NODEBUG = __unary_function_keep_layout_base<_Arg, _Result>; diff --git a/lib/libcxx/include/__functional/unary_negate.h b/lib/libcxx/include/__functional/unary_negate.h index 5bd487a97b..a93abc8e6b 100644 --- a/lib/libcxx/include/__functional/unary_negate.h +++ b/lib/libcxx/include/__functional/unary_negate.h @@ -22,8 +22,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD #if _LIBCPP_STD_VER <= 17 || defined(_LIBCPP_ENABLE_CXX20_REMOVED_NEGATORS) template -class _LIBCPP_TEMPLATE_VIS -_LIBCPP_DEPRECATED_IN_CXX17 unary_negate : public __unary_function { +class _LIBCPP_DEPRECATED_IN_CXX17 unary_negate : public __unary_function { _Predicate __pred_; public: diff --git a/lib/libcxx/include/__functional/weak_result_type.h b/lib/libcxx/include/__functional/weak_result_type.h index 233d86009a..aa462e4d5c 100644 --- a/lib/libcxx/include/__functional/weak_result_type.h +++ b/lib/libcxx/include/__functional/weak_result_type.h @@ -77,6 +77,7 @@ struct __maybe_derive_from_unary_function // bool is true template struct __maybe_derive_from_unary_function<_Tp, false> {}; +_LIBCPP_SUPPRESS_DEPRECATED_PUSH template ::value> struct __maybe_derive_from_binary_function // bool is true : public __derives_from_binary_function<_Tp>::type {}; @@ -99,6 +100,7 @@ struct __weak_result_type_imp<_Tp, false> template struct __weak_result_type : public __weak_result_type_imp<_Tp> {}; +_LIBCPP_SUPPRESS_DEPRECATED_POP // 0 argument case diff --git a/lib/libcxx/include/__fwd/array.h b/lib/libcxx/include/__fwd/array.h index 794779ae46..476de885c5 100644 --- a/lib/libcxx/include/__fwd/array.h +++ b/lib/libcxx/include/__fwd/array.h @@ -20,7 +20,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD template -struct _LIBCPP_TEMPLATE_VIS array; +struct array; template _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 _Tp& get(array<_Tp, _Size>&) _NOEXCEPT; diff --git a/lib/libcxx/include/__fwd/bit_reference.h b/lib/libcxx/include/__fwd/bit_reference.h index 30462b6ce4..36058d59cc 100644 --- a/lib/libcxx/include/__fwd/bit_reference.h +++ b/lib/libcxx/include/__fwd/bit_reference.h @@ -20,9 +20,25 @@ _LIBCPP_BEGIN_NAMESPACE_STD template class __bit_iterator; +template +struct __bit_array; + template struct __size_difference_type_traits; +template +_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 void +__fill_masked_range(_StoragePointer __word, unsigned __clz, unsigned __ctz, bool __fill_val); + +template +_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _StorageType __trailing_mask(unsigned __clz); + +template +_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _StorageType __leading_mask(unsigned __ctz); + +template +_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _StorageType __middle_mask(unsigned __clz, unsigned __ctz); + _LIBCPP_END_NAMESPACE_STD #endif // _LIBCPP___FWD_BIT_REFERENCE_H diff --git a/lib/libcxx/include/__fwd/byte.h b/lib/libcxx/include/__fwd/byte.h index 0301833d93..6f2d6ae254 100644 --- a/lib/libcxx/include/__fwd/byte.h +++ b/lib/libcxx/include/__fwd/byte.h @@ -16,11 +16,11 @@ #endif #if _LIBCPP_STD_VER >= 17 -namespace std { // purposefully not versioned +_LIBCPP_BEGIN_UNVERSIONED_NAMESPACE_STD enum class byte : unsigned char; -} // namespace std +_LIBCPP_END_UNVERSIONED_NAMESPACE_STD #endif // _LIBCPP_STD_VER >= 17 #endif // _LIBCPP___FWD_BYTE_H diff --git a/lib/libcxx/include/__fwd/complex.h b/lib/libcxx/include/__fwd/complex.h index 092d2e10b1..ff3c5c1e14 100644 --- a/lib/libcxx/include/__fwd/complex.h +++ b/lib/libcxx/include/__fwd/complex.h @@ -19,7 +19,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD template -class _LIBCPP_TEMPLATE_VIS complex; +class complex; #if _LIBCPP_STD_VER >= 26 diff --git a/lib/libcxx/include/__fwd/deque.h b/lib/libcxx/include/__fwd/deque.h index fd2fb5bb4b..35877a70e9 100644 --- a/lib/libcxx/include/__fwd/deque.h +++ b/lib/libcxx/include/__fwd/deque.h @@ -19,7 +19,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD template > -class _LIBCPP_TEMPLATE_VIS deque; +class deque; _LIBCPP_END_NAMESPACE_STD diff --git a/lib/libcxx/include/__fwd/format.h b/lib/libcxx/include/__fwd/format.h index 815e3e1922..b7f4cecb65 100644 --- a/lib/libcxx/include/__fwd/format.h +++ b/lib/libcxx/include/__fwd/format.h @@ -22,14 +22,14 @@ _LIBCPP_BEGIN_NAMESPACE_STD #if _LIBCPP_STD_VER >= 20 template -class _LIBCPP_TEMPLATE_VIS basic_format_arg; +class basic_format_arg; template requires output_iterator<_OutIt, const _CharT&> -class _LIBCPP_TEMPLATE_VIS basic_format_context; +class basic_format_context; template -struct _LIBCPP_TEMPLATE_VIS formatter; +struct formatter; #endif // _LIBCPP_STD_VER >= 20 diff --git a/lib/libcxx/include/__fwd/fstream.h b/lib/libcxx/include/__fwd/fstream.h index e6c430dbf7..34a14dfa84 100644 --- a/lib/libcxx/include/__fwd/fstream.h +++ b/lib/libcxx/include/__fwd/fstream.h @@ -19,13 +19,13 @@ _LIBCPP_BEGIN_NAMESPACE_STD template > -class _LIBCPP_TEMPLATE_VIS basic_filebuf; +class basic_filebuf; template > -class _LIBCPP_TEMPLATE_VIS basic_ifstream; +class basic_ifstream; template > -class _LIBCPP_TEMPLATE_VIS basic_ofstream; +class basic_ofstream; template > -class _LIBCPP_TEMPLATE_VIS basic_fstream; +class basic_fstream; using filebuf = basic_filebuf; using ifstream = basic_ifstream; diff --git a/lib/libcxx/include/__fwd/functional.h b/lib/libcxx/include/__fwd/functional.h index 32c9ef33e4..a8c602417b 100644 --- a/lib/libcxx/include/__fwd/functional.h +++ b/lib/libcxx/include/__fwd/functional.h @@ -17,11 +17,18 @@ _LIBCPP_BEGIN_NAMESPACE_STD -template -struct _LIBCPP_TEMPLATE_VIS hash; +#if _LIBCPP_STD_VER >= 14 +template +#else +template +#endif +struct less; template -class _LIBCPP_TEMPLATE_VIS reference_wrapper; +struct hash; + +template +class reference_wrapper; _LIBCPP_END_NAMESPACE_STD diff --git a/lib/libcxx/include/__fwd/ios.h b/lib/libcxx/include/__fwd/ios.h index bb0c6eb49b..831624f4b1 100644 --- a/lib/libcxx/include/__fwd/ios.h +++ b/lib/libcxx/include/__fwd/ios.h @@ -21,7 +21,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD class _LIBCPP_EXPORTED_FROM_ABI ios_base; template > -class _LIBCPP_TEMPLATE_VIS basic_ios; +class basic_ios; using ios = basic_ios; #if _LIBCPP_HAS_WIDE_CHARACTERS diff --git a/lib/libcxx/include/__fwd/istream.h b/lib/libcxx/include/__fwd/istream.h index 66a6708544..91c21c1dab 100644 --- a/lib/libcxx/include/__fwd/istream.h +++ b/lib/libcxx/include/__fwd/istream.h @@ -19,10 +19,10 @@ _LIBCPP_BEGIN_NAMESPACE_STD template > -class _LIBCPP_TEMPLATE_VIS basic_istream; +class basic_istream; template > -class _LIBCPP_TEMPLATE_VIS basic_iostream; +class basic_iostream; using istream = basic_istream; using iostream = basic_iostream; diff --git a/lib/libcxx/include/__fwd/map.h b/lib/libcxx/include/__fwd/map.h new file mode 100644 index 0000000000..940298dd3e --- /dev/null +++ b/lib/libcxx/include/__fwd/map.h @@ -0,0 +1,31 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___FWD_MAP_H +#define _LIBCPP___FWD_MAP_H + +#include <__config> +#include <__fwd/functional.h> +#include <__fwd/memory.h> +#include <__fwd/pair.h> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +template , class _Allocator = allocator > > +class map; + +template , class _Allocator = allocator > > +class multimap; + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___FWD_MAP_H diff --git a/lib/libcxx/include/__fwd/memory.h b/lib/libcxx/include/__fwd/memory.h index 564000997d..09ab5d861b 100644 --- a/lib/libcxx/include/__fwd/memory.h +++ b/lib/libcxx/include/__fwd/memory.h @@ -18,10 +18,10 @@ _LIBCPP_BEGIN_NAMESPACE_STD template -class _LIBCPP_TEMPLATE_VIS allocator; +class allocator; template -class _LIBCPP_TEMPLATE_VIS shared_ptr; +class shared_ptr; _LIBCPP_END_NAMESPACE_STD diff --git a/lib/libcxx/include/__fwd/memory_resource.h b/lib/libcxx/include/__fwd/memory_resource.h index ca9d377094..dc5a7ccb4a 100644 --- a/lib/libcxx/include/__fwd/memory_resource.h +++ b/lib/libcxx/include/__fwd/memory_resource.h @@ -21,7 +21,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD namespace pmr { template -class _LIBCPP_AVAILABILITY_PMR _LIBCPP_TEMPLATE_VIS polymorphic_allocator; +class _LIBCPP_AVAILABILITY_PMR polymorphic_allocator; } // namespace pmr _LIBCPP_END_NAMESPACE_STD diff --git a/lib/libcxx/include/__fwd/ostream.h b/lib/libcxx/include/__fwd/ostream.h index ff5a3612ef..9ceb02dc28 100644 --- a/lib/libcxx/include/__fwd/ostream.h +++ b/lib/libcxx/include/__fwd/ostream.h @@ -19,7 +19,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD template > -class _LIBCPP_TEMPLATE_VIS basic_ostream; +class basic_ostream; using ostream = basic_ostream; diff --git a/lib/libcxx/include/__fwd/pair.h b/lib/libcxx/include/__fwd/pair.h index b8ba2b7e92..cf07eabab6 100644 --- a/lib/libcxx/include/__fwd/pair.h +++ b/lib/libcxx/include/__fwd/pair.h @@ -20,7 +20,13 @@ _LIBCPP_BEGIN_NAMESPACE_STD template -struct _LIBCPP_TEMPLATE_VIS pair; +struct pair; + +template +inline const bool __is_pair_v = false; + +template +inline const bool __is_pair_v > = true; template _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 typename tuple_element<_Ip, pair<_T1, _T2> >::type& diff --git a/lib/libcxx/include/__fwd/queue.h b/lib/libcxx/include/__fwd/queue.h index 50d99ad9c2..d32730da13 100644 --- a/lib/libcxx/include/__fwd/queue.h +++ b/lib/libcxx/include/__fwd/queue.h @@ -21,10 +21,10 @@ _LIBCPP_BEGIN_NAMESPACE_STD template > -class _LIBCPP_TEMPLATE_VIS queue; +class queue; template , class _Compare = less > -class _LIBCPP_TEMPLATE_VIS priority_queue; +class priority_queue; _LIBCPP_END_NAMESPACE_STD diff --git a/lib/libcxx/include/__fwd/set.h b/lib/libcxx/include/__fwd/set.h new file mode 100644 index 0000000000..d5ef8d56b0 --- /dev/null +++ b/lib/libcxx/include/__fwd/set.h @@ -0,0 +1,30 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___FWD_SET_H +#define _LIBCPP___FWD_SET_H + +#include <__config> +#include <__fwd/functional.h> +#include <__fwd/memory.h> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +template , class _Allocator = allocator<_Key> > +class set; + +template , class _Allocator = allocator<_Key> > +class multiset; + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___FWD_SET_H diff --git a/lib/libcxx/include/__fwd/sstream.h b/lib/libcxx/include/__fwd/sstream.h index c176db6e5a..fe637d8624 100644 --- a/lib/libcxx/include/__fwd/sstream.h +++ b/lib/libcxx/include/__fwd/sstream.h @@ -20,14 +20,14 @@ _LIBCPP_BEGIN_NAMESPACE_STD template , class _Allocator = allocator<_CharT> > -class _LIBCPP_TEMPLATE_VIS basic_stringbuf; +class basic_stringbuf; template , class _Allocator = allocator<_CharT> > -class _LIBCPP_TEMPLATE_VIS basic_istringstream; +class basic_istringstream; template , class _Allocator = allocator<_CharT> > -class _LIBCPP_TEMPLATE_VIS basic_ostringstream; +class basic_ostringstream; template , class _Allocator = allocator<_CharT> > -class _LIBCPP_TEMPLATE_VIS basic_stringstream; +class basic_stringstream; using stringbuf = basic_stringbuf; using istringstream = basic_istringstream; diff --git a/lib/libcxx/include/__fwd/stack.h b/lib/libcxx/include/__fwd/stack.h index 7dab6c1a4f..922f03e940 100644 --- a/lib/libcxx/include/__fwd/stack.h +++ b/lib/libcxx/include/__fwd/stack.h @@ -19,7 +19,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD template > -class _LIBCPP_TEMPLATE_VIS stack; +class stack; _LIBCPP_END_NAMESPACE_STD diff --git a/lib/libcxx/include/__fwd/streambuf.h b/lib/libcxx/include/__fwd/streambuf.h index aee0ebb3ce..d3d9d466fd 100644 --- a/lib/libcxx/include/__fwd/streambuf.h +++ b/lib/libcxx/include/__fwd/streambuf.h @@ -19,7 +19,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD template > -class _LIBCPP_TEMPLATE_VIS basic_streambuf; +class basic_streambuf; using streambuf = basic_streambuf; diff --git a/lib/libcxx/include/__fwd/string.h b/lib/libcxx/include/__fwd/string.h index 89dec82d6f..254d0c874a 100644 --- a/lib/libcxx/include/__fwd/string.h +++ b/lib/libcxx/include/__fwd/string.h @@ -20,7 +20,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD template -struct _LIBCPP_TEMPLATE_VIS char_traits; +struct char_traits; template <> struct char_traits; @@ -40,7 +40,7 @@ struct char_traits; #endif template , class _Allocator = allocator<_CharT> > -class _LIBCPP_TEMPLATE_VIS basic_string; +class basic_string; using string = basic_string; diff --git a/lib/libcxx/include/__fwd/string_view.h b/lib/libcxx/include/__fwd/string_view.h index b848cb7f60..8da963d105 100644 --- a/lib/libcxx/include/__fwd/string_view.h +++ b/lib/libcxx/include/__fwd/string_view.h @@ -20,7 +20,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD template > -class _LIBCPP_TEMPLATE_VIS basic_string_view; +class basic_string_view; typedef basic_string_view string_view; #if _LIBCPP_HAS_CHAR8_T diff --git a/lib/libcxx/include/__fwd/subrange.h b/lib/libcxx/include/__fwd/subrange.h index 5b3a07e553..81db94ab73 100644 --- a/lib/libcxx/include/__fwd/subrange.h +++ b/lib/libcxx/include/__fwd/subrange.h @@ -28,7 +28,7 @@ enum class subrange_kind : bool { unsized, sized }; template _Sent, subrange_kind _Kind> requires(_Kind == subrange_kind::sized || !sized_sentinel_for<_Sent, _Iter>) -class _LIBCPP_TEMPLATE_VIS subrange; +class subrange; template requires((_Index == 0 && copyable<_Iter>) || _Index == 1) diff --git a/lib/libcxx/include/__fwd/tuple.h b/lib/libcxx/include/__fwd/tuple.h index 2ed32bc0df..fb922b29f3 100644 --- a/lib/libcxx/include/__fwd/tuple.h +++ b/lib/libcxx/include/__fwd/tuple.h @@ -19,15 +19,15 @@ _LIBCPP_BEGIN_NAMESPACE_STD template -struct _LIBCPP_TEMPLATE_VIS tuple_element; +struct tuple_element; #ifndef _LIBCPP_CXX03_LANG template -class _LIBCPP_TEMPLATE_VIS tuple; +class tuple; template -struct _LIBCPP_TEMPLATE_VIS tuple_size; +struct tuple_size; template _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 typename tuple_element<_Ip, tuple<_Tp...> >::type& diff --git a/lib/libcxx/include/__fwd/variant.h b/lib/libcxx/include/__fwd/variant.h index 71c792f46a..fef7071b32 100644 --- a/lib/libcxx/include/__fwd/variant.h +++ b/lib/libcxx/include/__fwd/variant.h @@ -21,16 +21,16 @@ _LIBCPP_BEGIN_NAMESPACE_STD #if _LIBCPP_STD_VER >= 17 template -class _LIBCPP_TEMPLATE_VIS variant; +class variant; template -struct _LIBCPP_TEMPLATE_VIS variant_size; +struct variant_size; template inline constexpr size_t variant_size_v = variant_size<_Tp>::value; template -struct _LIBCPP_TEMPLATE_VIS variant_alternative; +struct variant_alternative; template using variant_alternative_t = typename variant_alternative<_Ip, _Tp>::type; @@ -38,37 +38,28 @@ using variant_alternative_t = typename variant_alternative<_Ip, _Tp>::type; inline constexpr size_t variant_npos = static_cast(-1); template -_LIBCPP_HIDE_FROM_ABI -_LIBCPP_AVAILABILITY_THROW_BAD_VARIANT_ACCESS constexpr variant_alternative_t<_Ip, variant<_Types...>>& -get(variant<_Types...>&); +_LIBCPP_HIDE_FROM_ABI constexpr variant_alternative_t<_Ip, variant<_Types...>>& get(variant<_Types...>&); template -_LIBCPP_HIDE_FROM_ABI -_LIBCPP_AVAILABILITY_THROW_BAD_VARIANT_ACCESS constexpr variant_alternative_t<_Ip, variant<_Types...>>&& -get(variant<_Types...>&&); +_LIBCPP_HIDE_FROM_ABI constexpr variant_alternative_t<_Ip, variant<_Types...>>&& get(variant<_Types...>&&); template -_LIBCPP_HIDE_FROM_ABI -_LIBCPP_AVAILABILITY_THROW_BAD_VARIANT_ACCESS constexpr const variant_alternative_t<_Ip, variant<_Types...>>& -get(const variant<_Types...>&); +_LIBCPP_HIDE_FROM_ABI constexpr const variant_alternative_t<_Ip, variant<_Types...>>& get(const variant<_Types...>&); template -_LIBCPP_HIDE_FROM_ABI -_LIBCPP_AVAILABILITY_THROW_BAD_VARIANT_ACCESS constexpr const variant_alternative_t<_Ip, variant<_Types...>>&& -get(const variant<_Types...>&&); +_LIBCPP_HIDE_FROM_ABI constexpr const variant_alternative_t<_Ip, variant<_Types...>>&& get(const variant<_Types...>&&); template -_LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_THROW_BAD_VARIANT_ACCESS constexpr _Tp& get(variant<_Types...>&); +_LIBCPP_HIDE_FROM_ABI constexpr _Tp& get(variant<_Types...>&); template -_LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_THROW_BAD_VARIANT_ACCESS constexpr _Tp&& get(variant<_Types...>&&); +_LIBCPP_HIDE_FROM_ABI constexpr _Tp&& get(variant<_Types...>&&); template -_LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_THROW_BAD_VARIANT_ACCESS constexpr const _Tp& get(const variant<_Types...>&); +_LIBCPP_HIDE_FROM_ABI constexpr const _Tp& get(const variant<_Types...>&); template -_LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_THROW_BAD_VARIANT_ACCESS constexpr const _Tp&& -get(const variant<_Types...>&&); +_LIBCPP_HIDE_FROM_ABI constexpr const _Tp&& get(const variant<_Types...>&&); #endif // _LIBCPP_STD_VER >= 17 diff --git a/lib/libcxx/include/__fwd/vector.h b/lib/libcxx/include/__fwd/vector.h index 6980e40ec9..31084ec995 100644 --- a/lib/libcxx/include/__fwd/vector.h +++ b/lib/libcxx/include/__fwd/vector.h @@ -19,7 +19,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD template > -class _LIBCPP_TEMPLATE_VIS vector; +class vector; template class vector; diff --git a/lib/libcxx/include/__hash_table b/lib/libcxx/include/__hash_table index 9a82ec51da..78f2f3bfd2 100644 --- a/lib/libcxx/include/__hash_table +++ b/lib/libcxx/include/__hash_table @@ -29,6 +29,7 @@ #include <__memory/unique_ptr.h> #include <__new/launder.h> #include <__type_traits/can_extract_key.h> +#include <__type_traits/copy_cvref.h> #include <__type_traits/enable_if.h> #include <__type_traits/invoke.h> #include <__type_traits/is_const.h> @@ -108,9 +109,22 @@ struct __hash_node_base { _LIBCPP_HIDE_FROM_ABI explicit __hash_node_base(__next_pointer __next) _NOEXCEPT : __next_(__next) {} }; +template +struct __get_hash_node_value_type { + using type _LIBCPP_NODEBUG = _Tp; +}; + +template +struct __get_hash_node_value_type<__hash_value_type<_Key, _Tp> > { + using type _LIBCPP_NODEBUG = pair; +}; + +template +using __get_hash_node_value_type_t _LIBCPP_NODEBUG = typename __get_hash_node_value_type<_Tp>::type; + template struct __hash_node : public __hash_node_base< __rebind_pointer_t<_VoidPtr, __hash_node<_Tp, _VoidPtr> > > { - typedef _Tp __node_value_type; + using __node_value_type _LIBCPP_NODEBUG = __get_hash_node_value_type_t<_Tp>; using _Base _LIBCPP_NODEBUG = __hash_node_base<__rebind_pointer_t<_VoidPtr, __hash_node<_Tp, _VoidPtr> > >; using __next_pointer _LIBCPP_NODEBUG = typename _Base::__next_pointer; @@ -122,18 +136,20 @@ struct __hash_node : public __hash_node_base< __rebind_pointer_t<_VoidPtr, __has private: union { - _Tp __value_; + __node_value_type __value_; }; public: - _LIBCPP_HIDE_FROM_ABI _Tp& __get_value() { return __value_; } + _LIBCPP_HIDE_FROM_ABI __node_value_type& __get_value() { return __value_; } #else private: - _ALIGNAS_TYPE(_Tp) char __buffer_[sizeof(_Tp)]; + _ALIGNAS_TYPE(__node_value_type) char __buffer_[sizeof(__node_value_type)]; public: - _LIBCPP_HIDE_FROM_ABI _Tp& __get_value() { return *std::__launder(reinterpret_cast<_Tp*>(&__buffer_)); } + _LIBCPP_HIDE_FROM_ABI __node_value_type& __get_value() { + return *std::__launder(reinterpret_cast<__node_value_type*>(&__buffer_)); + } #endif _LIBCPP_HIDE_FROM_ABI explicit __hash_node(__next_pointer __next, size_t __hash) : _Base(__next), __hash_(__hash) {} @@ -147,24 +163,24 @@ inline _LIBCPP_HIDE_FROM_ABI size_t __constrain_hash(size_t __h, size_t __bc) { } inline _LIBCPP_HIDE_FROM_ABI size_t __next_hash_pow2(size_t __n) { - return __n < 2 ? __n : (size_t(1) << (numeric_limits::digits - __libcpp_clz(__n - 1))); + return __n < 2 ? __n : (size_t(1) << (numeric_limits::digits - std::__countl_zero(__n - 1))); } template class __hash_table; template -class _LIBCPP_TEMPLATE_VIS __hash_iterator; +class __hash_iterator; template -class _LIBCPP_TEMPLATE_VIS __hash_const_iterator; +class __hash_const_iterator; template -class _LIBCPP_TEMPLATE_VIS __hash_local_iterator; +class __hash_local_iterator; template -class _LIBCPP_TEMPLATE_VIS __hash_const_local_iterator; +class __hash_const_local_iterator; template -class _LIBCPP_TEMPLATE_VIS __hash_map_iterator; +class __hash_map_iterator; template -class _LIBCPP_TEMPLATE_VIS __hash_map_const_iterator; +class __hash_map_const_iterator; template struct __hash_key_value_types { @@ -191,18 +207,18 @@ struct __hash_key_value_types<__hash_value_type<_Key, _Tp> > { _LIBCPP_HIDE_FROM_ABI static key_type const& __get_key(__container_value_type const& __v) { return __v.first; } - template ::value, int> = 0> + template , __node_value_type>::value, int> = 0> _LIBCPP_HIDE_FROM_ABI static __container_value_type const& __get_value(_Up& __t) { return __t.__get_value(); } - template ::value, int> = 0> + template , __container_value_type>::value, int> = 0> _LIBCPP_HIDE_FROM_ABI static __container_value_type const& __get_value(_Up& __t) { return __t; } - _LIBCPP_HIDE_FROM_ABI static __container_value_type* __get_ptr(__node_value_type& __n) { - return std::addressof(__n.__get_value()); + _LIBCPP_HIDE_FROM_ABI static __container_value_type* __get_ptr(__container_value_type& __n) { + return std::addressof(__n); } _LIBCPP_HIDE_FROM_ABI static pair __move(__node_value_type& __v) { return __v.__move(); } }; @@ -242,7 +258,7 @@ public: typedef typename __node_base_type::__next_pointer __next_pointer; - typedef _Tp __node_value_type; + using __node_value_type _LIBCPP_NODEBUG = __get_hash_node_value_type_t<_Tp>; typedef __rebind_pointer_t<_VoidPtr, __node_value_type> __node_value_type_pointer; typedef __rebind_pointer_t<_VoidPtr, const __node_value_type> __const_node_value_type_pointer; @@ -273,7 +289,7 @@ struct __make_hash_node_types { }; template -class _LIBCPP_TEMPLATE_VIS __hash_iterator { +class __hash_iterator { typedef __hash_node_types<_NodePtr> _NodeTypes; typedef _NodePtr __node_pointer; typedef typename _NodeTypes::__next_pointer __next_pointer; @@ -327,17 +343,17 @@ private: template friend class __hash_table; template - friend class _LIBCPP_TEMPLATE_VIS __hash_const_iterator; + friend class __hash_const_iterator; template - friend class _LIBCPP_TEMPLATE_VIS __hash_map_iterator; + friend class __hash_map_iterator; template - friend class _LIBCPP_TEMPLATE_VIS unordered_map; + friend class unordered_map; template - friend class _LIBCPP_TEMPLATE_VIS unordered_multimap; + friend class unordered_multimap; }; template -class _LIBCPP_TEMPLATE_VIS __hash_const_iterator { +class __hash_const_iterator { static_assert(!is_const::element_type>::value, ""); typedef __hash_node_types<_NodePtr> _NodeTypes; typedef _NodePtr __node_pointer; @@ -395,15 +411,15 @@ private: template friend class __hash_table; template - friend class _LIBCPP_TEMPLATE_VIS __hash_map_const_iterator; + friend class __hash_map_const_iterator; template - friend class _LIBCPP_TEMPLATE_VIS unordered_map; + friend class unordered_map; template - friend class _LIBCPP_TEMPLATE_VIS unordered_multimap; + friend class unordered_multimap; }; template -class _LIBCPP_TEMPLATE_VIS __hash_local_iterator { +class __hash_local_iterator { typedef __hash_node_types<_NodePtr> _NodeTypes; typedef _NodePtr __node_pointer; typedef typename _NodeTypes::__next_pointer __next_pointer; @@ -468,13 +484,13 @@ private: template friend class __hash_table; template - friend class _LIBCPP_TEMPLATE_VIS __hash_const_local_iterator; + friend class __hash_const_local_iterator; template - friend class _LIBCPP_TEMPLATE_VIS __hash_map_iterator; + friend class __hash_map_iterator; }; template -class _LIBCPP_TEMPLATE_VIS __hash_const_local_iterator { +class __hash_const_local_iterator { typedef __hash_node_types<_ConstNodePtr> _NodeTypes; typedef _ConstNodePtr __node_pointer; typedef typename _NodeTypes::__next_pointer __next_pointer; @@ -553,7 +569,7 @@ private: template friend class __hash_table; template - friend class _LIBCPP_TEMPLATE_VIS __hash_map_const_iterator; + friend class __hash_map_const_iterator; }; template @@ -667,14 +683,14 @@ int __diagnose_unordered_container_requirements(void*); template class __hash_table { public: - typedef _Tp value_type; + using value_type = __get_hash_node_value_type_t<_Tp>; typedef _Hash hasher; typedef _Equal key_equal; typedef _Alloc allocator_type; private: typedef allocator_traits __alloc_traits; - typedef typename __make_hash_node_types::type _NodeTypes; + typedef typename __make_hash_node_types<_Tp, typename __alloc_traits::void_pointer>::type _NodeTypes; public: typedef typename _NodeTypes::__node_value_type __node_value_type; @@ -770,9 +786,10 @@ public: _LIBCPP_HIDE_FROM_ABI __hash_table& operator=(const __hash_table& __u); _LIBCPP_HIDE_FROM_ABI __hash_table& operator=(__hash_table&& __u) - _NOEXCEPT_(__node_traits::propagate_on_container_move_assignment::value&& - is_nothrow_move_assignable<__node_allocator>::value&& is_nothrow_move_assignable::value&& - is_nothrow_move_assignable::value); + _NOEXCEPT_(is_nothrow_move_assignable::value&& is_nothrow_move_assignable::value && + ((__node_traits::propagate_on_container_move_assignment::value && + is_nothrow_move_assignable<__node_allocator>::value) || + allocator_traits<__node_allocator>::is_always_equal::value)); template _LIBCPP_HIDE_FROM_ABI void __assign_unique(_InputIterator __first, _InputIterator __last); template @@ -835,27 +852,36 @@ public: template _LIBCPP_HIDE_FROM_ABI iterator __emplace_hint_multi(const_iterator __p, _Args&&... __args); - _LIBCPP_HIDE_FROM_ABI pair __insert_unique(__container_value_type&& __x) { - return __emplace_unique_key_args(_NodeTypes::__get_key(__x), std::move(__x)); + template ::value, int> = 0> + _LIBCPP_HIDE_FROM_ABI void __insert_unique_from_orphaned_node(value_type&& __value) { + using __key_type = typename _NodeTypes::key_type; + + __node_holder __h = __construct_node(const_cast<__key_type&&>(__value.first), std::move(__value.second)); + __node_insert_unique(__h.get()); + __h.release(); } - template ::value, int> = 0> - _LIBCPP_HIDE_FROM_ABI pair __insert_unique(_Pp&& __x) { - return __emplace_unique(std::forward<_Pp>(__x)); + template ::value, int> = 0> + _LIBCPP_HIDE_FROM_ABI void __insert_unique_from_orphaned_node(value_type&& __value) { + __node_holder __h = __construct_node(std::move(__value)); + __node_insert_unique(__h.get()); + __h.release(); } - template - _LIBCPP_HIDE_FROM_ABI iterator __insert_multi(_Pp&& __x) { - return __emplace_multi(std::forward<_Pp>(__x)); + template ::value, int> = 0> + _LIBCPP_HIDE_FROM_ABI void __insert_multi_from_orphaned_node(value_type&& __value) { + using __key_type = typename _NodeTypes::key_type; + + __node_holder __h = __construct_node(const_cast<__key_type&&>(__value.first), std::move(__value.second)); + __node_insert_multi(__h.get()); + __h.release(); } - template - _LIBCPP_HIDE_FROM_ABI iterator __insert_multi(const_iterator __p, _Pp&& __x) { - return __emplace_hint_multi(__p, std::forward<_Pp>(__x)); - } - - _LIBCPP_HIDE_FROM_ABI pair __insert_unique(const __container_value_type& __x) { - return __emplace_unique_key_args(_NodeTypes::__get_key(__x), __x); + template ::value, int> = 0> + _LIBCPP_HIDE_FROM_ABI void __insert_multi_from_orphaned_node(value_type&& __value) { + __node_holder __h = __construct_node(std::move(__value)); + __node_insert_multi(__h.get()); + __h.release(); } #if _LIBCPP_STD_VER >= 17 @@ -1019,10 +1045,25 @@ private: _LIBCPP_HIDE_FROM_ABI void __deallocate_node(__next_pointer __np) _NOEXCEPT; _LIBCPP_HIDE_FROM_ABI __next_pointer __detach() _NOEXCEPT; + template ::value, int> = 0> + _LIBCPP_HIDE_FROM_ABI void __assign_value(__get_hash_node_value_type_t<_Tp>& __lhs, _From&& __rhs) { + using __key_type = typename _NodeTypes::key_type; + + // This is technically UB, since the object was constructed as `const`. + // Clang doesn't optimize on this currently though. + const_cast<__key_type&>(__lhs.first) = const_cast<__copy_cvref_t<_From, __key_type>&&>(__rhs.first); + __lhs.second = std::forward<_From>(__rhs).second; + } + + template ::value, int> = 0> + _LIBCPP_HIDE_FROM_ABI void __assign_value(_Tp& __lhs, _From&& __rhs) { + __lhs = std::forward<_From>(__rhs); + } + template - friend class _LIBCPP_TEMPLATE_VIS unordered_map; + friend class unordered_map; template - friend class _LIBCPP_TEMPLATE_VIS unordered_multimap; + friend class unordered_multimap; }; template @@ -1215,8 +1256,8 @@ void __hash_table<_Tp, _Hash, _Equal, _Alloc>::__move_assign(__hash_table& __u, #endif // _LIBCPP_HAS_EXCEPTIONS const_iterator __i = __u.begin(); while (__cache != nullptr && __u.size() != 0) { - __cache->__upcast()->__get_value() = std::move(__u.remove(__i++)->__get_value()); - __next_pointer __next = __cache->__next_; + __assign_value(__cache->__upcast()->__get_value(), std::move(__u.remove(__i++)->__get_value())); + __next_pointer __next = __cache->__next_; __node_insert_multi(__cache->__upcast()); __cache = __next; } @@ -1229,19 +1270,17 @@ void __hash_table<_Tp, _Hash, _Equal, _Alloc>::__move_assign(__hash_table& __u, __deallocate_node(__cache); } const_iterator __i = __u.begin(); - while (__u.size() != 0) { - __node_holder __h = __construct_node(_NodeTypes::__move(__u.remove(__i++)->__get_value())); - __node_insert_multi(__h.get()); - __h.release(); - } + while (__u.size() != 0) + __insert_multi_from_orphaned_node(std::move(__u.remove(__i++)->__get_value())); } } template -inline __hash_table<_Tp, _Hash, _Equal, _Alloc>& -__hash_table<_Tp, _Hash, _Equal, _Alloc>::operator=(__hash_table&& __u) _NOEXCEPT_( - __node_traits::propagate_on_container_move_assignment::value&& is_nothrow_move_assignable<__node_allocator>::value&& - is_nothrow_move_assignable::value&& is_nothrow_move_assignable::value) { +inline __hash_table<_Tp, _Hash, _Equal, _Alloc>& __hash_table<_Tp, _Hash, _Equal, _Alloc>::operator=(__hash_table&& __u) + _NOEXCEPT_(is_nothrow_move_assignable::value&& is_nothrow_move_assignable::value && + ((__node_traits::propagate_on_container_move_assignment::value && + is_nothrow_move_assignable<__node_allocator>::value) || + allocator_traits<__node_allocator>::is_always_equal::value)) { __move_assign(__u, integral_constant()); return *this; } @@ -1260,8 +1299,8 @@ void __hash_table<_Tp, _Hash, _Equal, _Alloc>::__assign_unique(_InputIterator __ try { #endif // _LIBCPP_HAS_EXCEPTIONS for (; __cache != nullptr && __first != __last; ++__first) { - __cache->__upcast()->__get_value() = *__first; - __next_pointer __next = __cache->__next_; + __assign_value(__cache->__upcast()->__get_value(), *__first); + __next_pointer __next = __cache->__next_; __node_insert_unique(__cache->__upcast()); __cache = __next; } @@ -1274,7 +1313,7 @@ void __hash_table<_Tp, _Hash, _Equal, _Alloc>::__assign_unique(_InputIterator __ __deallocate_node(__cache); } for (; __first != __last; ++__first) - __insert_unique(*__first); + __emplace_unique(*__first); } template @@ -1292,7 +1331,7 @@ void __hash_table<_Tp, _Hash, _Equal, _Alloc>::__assign_multi(_InputIterator __f try { #endif // _LIBCPP_HAS_EXCEPTIONS for (; __cache != nullptr && __first != __last; ++__first) { - __cache->__upcast()->__get_value() = *__first; + __assign_value(__cache->__upcast()->__get_value(), *__first); __next_pointer __next = __cache->__next_; __node_insert_multi(__cache->__upcast()); __cache = __next; @@ -1306,7 +1345,7 @@ void __hash_table<_Tp, _Hash, _Equal, _Alloc>::__assign_multi(_InputIterator __f __deallocate_node(__cache); } for (; __first != __last; ++__first) - __insert_multi(_NodeTypes::__get_value(*__first)); + __emplace_multi(_NodeTypes::__get_value(*__first)); } template @@ -1769,9 +1808,9 @@ template template typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::iterator __hash_table<_Tp, _Hash, _Equal, _Alloc>::find(const _Key& __k) { - size_t __hash = hash_function()(__k); size_type __bc = bucket_count(); - if (__bc != 0) { + if (__bc != 0 && size() != 0) { + size_t __hash = hash_function()(__k); size_t __chash = std::__constrain_hash(__hash, __bc); __next_pointer __nd = __bucket_list_[__chash]; if (__nd != nullptr) { @@ -1790,9 +1829,9 @@ template template typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::const_iterator __hash_table<_Tp, _Hash, _Equal, _Alloc>::find(const _Key& __k) const { - size_t __hash = hash_function()(__k); size_type __bc = bucket_count(); - if (__bc != 0) { + if (__bc != 0 && size() != 0) { + size_t __hash = hash_function()(__k); size_t __chash = std::__constrain_hash(__hash, __bc); __next_pointer __nd = __bucket_list_[__chash]; if (__nd != nullptr) { diff --git a/lib/libcxx/include/__ios/fpos.h b/lib/libcxx/include/__ios/fpos.h index 1af1e23ee5..e5c21b4391 100644 --- a/lib/libcxx/include/__ios/fpos.h +++ b/lib/libcxx/include/__ios/fpos.h @@ -20,7 +20,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD template -class _LIBCPP_TEMPLATE_VIS fpos { +class fpos { private: _StateT __st_; streamoff __off_; diff --git a/lib/libcxx/include/__iterator/advance.h b/lib/libcxx/include/__iterator/advance.h index 57b1b845f1..c7d3c1f0e8 100644 --- a/lib/libcxx/include/__iterator/advance.h +++ b/lib/libcxx/include/__iterator/advance.h @@ -65,9 +65,8 @@ template < class _InputIter, _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX17 void advance(_InputIter& __i, _Distance __orig_n) { typedef typename iterator_traits<_InputIter>::difference_type _Difference; _Difference __n = static_cast<_Difference>(std::__convert_to_integral(__orig_n)); - // Calling `advance` with a negative value on a non-bidirectional iterator is a no-op in the current implementation. - _LIBCPP_ASSERT_PEDANTIC(__n >= 0 || __has_bidirectional_iterator_category<_InputIter>::value, - "Attempt to advance(it, n) with negative n on a non-bidirectional iterator"); + _LIBCPP_ASSERT_PEDANTIC(__has_bidirectional_iterator_category<_InputIter>::value || __n >= 0, + "std::advance: Can only pass a negative `n` with a bidirectional_iterator."); std::__advance(__i, __n, typename iterator_traits<_InputIter>::iterator_category()); } @@ -98,9 +97,8 @@ public: // Preconditions: If `I` does not model `bidirectional_iterator`, `n` is not negative. template _LIBCPP_HIDE_FROM_ABI constexpr void operator()(_Ip& __i, iter_difference_t<_Ip> __n) const { - // Calling `advance` with a negative value on a non-bidirectional iterator is a no-op in the current implementation. - _LIBCPP_ASSERT_PEDANTIC( - __n >= 0 || bidirectional_iterator<_Ip>, "If `n < 0`, then `bidirectional_iterator` must be true."); + _LIBCPP_ASSERT_PEDANTIC(bidirectional_iterator<_Ip> || __n >= 0, + "ranges::advance: Can only pass a negative `n` with a bidirectional_iterator."); // If `I` models `random_access_iterator`, equivalent to `i += n`. if constexpr (random_access_iterator<_Ip>) { @@ -149,9 +147,9 @@ public: template _Sp> _LIBCPP_HIDE_FROM_ABI constexpr iter_difference_t<_Ip> operator()(_Ip& __i, iter_difference_t<_Ip> __n, _Sp __bound_sentinel) const { - // Calling `advance` with a negative value on a non-bidirectional iterator is a no-op in the current implementation. - _LIBCPP_ASSERT_PEDANTIC((__n >= 0) || (bidirectional_iterator<_Ip> && same_as<_Ip, _Sp>), - "If `n < 0`, then `bidirectional_iterator && same_as` must be true."); + _LIBCPP_ASSERT_PEDANTIC( + (bidirectional_iterator<_Ip> && same_as<_Ip, _Sp>) || (__n >= 0), + "ranges::advance: Can only pass a negative `n` with a bidirectional_iterator coming from a common_range."); // If `S` and `I` model `sized_sentinel_for`: if constexpr (sized_sentinel_for<_Sp, _Ip>) { // If |n| >= |bound_sentinel - i|, equivalent to `ranges::advance(i, bound_sentinel)`. diff --git a/lib/libcxx/include/__iterator/aliasing_iterator.h b/lib/libcxx/include/__iterator/aliasing_iterator.h index e01127142a..528e95eb14 100644 --- a/lib/libcxx/include/__iterator/aliasing_iterator.h +++ b/lib/libcxx/include/__iterator/aliasing_iterator.h @@ -12,8 +12,10 @@ #include <__config> #include <__cstddef/ptrdiff_t.h> #include <__iterator/iterator_traits.h> +#include <__memory/addressof.h> #include <__memory/pointer_traits.h> -#include <__type_traits/is_trivial.h> +#include <__type_traits/is_trivially_constructible.h> +#include <__type_traits/is_trivially_copyable.h> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # pragma GCC system_header @@ -44,7 +46,8 @@ struct __aliasing_iterator_wrapper { using reference = value_type&; using pointer = value_type*; - static_assert(is_trivial::value); + static_assert(is_trivially_default_constructible::value); + static_assert(is_trivially_copyable::value); static_assert(sizeof(__base_value_type) == sizeof(value_type)); _LIBCPP_HIDE_FROM_ABI __iterator() = default; @@ -102,7 +105,7 @@ struct __aliasing_iterator_wrapper { _LIBCPP_HIDE_FROM_ABI _Alias operator*() const _NOEXCEPT { _Alias __val; - __builtin_memcpy(&__val, std::__to_address(__base_), sizeof(value_type)); + __builtin_memcpy(std::addressof(__val), std::__to_address(__base_), sizeof(value_type)); return __val; } diff --git a/lib/libcxx/include/__iterator/back_insert_iterator.h b/lib/libcxx/include/__iterator/back_insert_iterator.h index 9a59487533..3a11fae4cb 100644 --- a/lib/libcxx/include/__iterator/back_insert_iterator.h +++ b/lib/libcxx/include/__iterator/back_insert_iterator.h @@ -28,7 +28,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD _LIBCPP_SUPPRESS_DEPRECATED_PUSH template -class _LIBCPP_TEMPLATE_VIS back_insert_iterator +class back_insert_iterator #if _LIBCPP_STD_VER <= 14 || !defined(_LIBCPP_ABI_NO_ITERATOR_BASES) : public iterator #endif diff --git a/lib/libcxx/include/__iterator/common_iterator.h b/lib/libcxx/include/__iterator/common_iterator.h index 31fc8267e5..a59063d245 100644 --- a/lib/libcxx/include/__iterator/common_iterator.h +++ b/lib/libcxx/include/__iterator/common_iterator.h @@ -28,6 +28,7 @@ #include <__memory/addressof.h> #include <__type_traits/conditional.h> #include <__type_traits/is_pointer.h> +#include <__type_traits/is_referenceable.h> #include <__utility/declval.h> #include @@ -157,7 +158,7 @@ public: ++*this; return __tmp; } else if constexpr (requires(_Iter& __i) { - { *__i++ } -> __can_reference; + { *__i++ } -> __referenceable; } || !__can_use_postfix_proxy<_Iter>) { return std::__unchecked_get<_Iter>(__hold_)++; } else { @@ -272,13 +273,13 @@ concept __common_iter_has_ptr_op = requires(const common_iterator<_Iter, _Sent>& template struct __arrow_type_or_void { - using type = void; + using type _LIBCPP_NODEBUG = void; }; template requires __common_iter_has_ptr_op<_Iter, _Sent> struct __arrow_type_or_void<_Iter, _Sent> { - using type = decltype(std::declval&>().operator->()); + using type _LIBCPP_NODEBUG = decltype(std::declval&>().operator->()); }; template diff --git a/lib/libcxx/include/__iterator/concepts.h b/lib/libcxx/include/__iterator/concepts.h index 6e5ac1d3af..20a1ab4691 100644 --- a/lib/libcxx/include/__iterator/concepts.h +++ b/lib/libcxx/include/__iterator/concepts.h @@ -29,15 +29,19 @@ #include <__iterator/incrementable_traits.h> #include <__iterator/iter_move.h> #include <__iterator/iterator_traits.h> -#include <__iterator/readable_traits.h> #include <__memory/pointer_traits.h> #include <__type_traits/add_pointer.h> #include <__type_traits/common_reference.h> +#include <__type_traits/conditional.h> +#include <__type_traits/disjunction.h> +#include <__type_traits/enable_if.h> #include <__type_traits/integral_constant.h> #include <__type_traits/invoke.h> #include <__type_traits/is_pointer.h> #include <__type_traits/is_primary_template.h> #include <__type_traits/is_reference.h> +#include <__type_traits/is_referenceable.h> +#include <__type_traits/is_valid_expansion.h> #include <__type_traits/remove_cv.h> #include <__type_traits/remove_cvref.h> #include <__utility/forward.h> @@ -80,12 +84,13 @@ concept __specialization_of_projected = requires { template struct __indirect_value_t_impl { - using type = iter_value_t<_Tp>&; + using type _LIBCPP_NODEBUG = iter_value_t<_Tp>&; }; template <__specialization_of_projected _Tp> struct __indirect_value_t_impl<_Tp> { - using type = invoke_result_t<__projected_projection_t<_Tp>&, - typename __indirect_value_t_impl<__projected_iterator_t<_Tp>>::type>; + using type _LIBCPP_NODEBUG = + invoke_result_t<__projected_projection_t<_Tp>&, + typename __indirect_value_t_impl<__projected_iterator_t<_Tp>>::type>; }; template @@ -131,7 +136,7 @@ concept incrementable = regular<_Ip> && weakly_incrementable<_Ip> && requires(_I // [iterator.concept.iterator] template concept input_or_output_iterator = requires(_Ip __i) { - { *__i } -> __can_reference; + { *__i } -> __referenceable; } && weakly_incrementable<_Ip>; // [iterator.concept.sentinel] @@ -149,6 +154,42 @@ concept sized_sentinel_for = { __i - __s } -> same_as>; }; +template +struct __iter_traits_cache { + using type _LIBCPP_NODEBUG = + _If<__is_primary_template >::value, _Iter, iterator_traits<_Iter> >; +}; +template +using _ITER_TRAITS _LIBCPP_NODEBUG = typename __iter_traits_cache<_Iter>::type; + +struct __iter_concept_concept_test { + template + using _Apply _LIBCPP_NODEBUG = typename _ITER_TRAITS<_Iter>::iterator_concept; +}; +struct __iter_concept_category_test { + template + using _Apply _LIBCPP_NODEBUG = typename _ITER_TRAITS<_Iter>::iterator_category; +}; +struct __iter_concept_random_fallback { + template + using _Apply _LIBCPP_NODEBUG = + __enable_if_t<__is_primary_template >::value, random_access_iterator_tag>; +}; + +template +struct __test_iter_concept : _IsValidExpansion<_Tester::template _Apply, _Iter>, _Tester {}; + +template +struct __iter_concept_cache { + using type _LIBCPP_NODEBUG = + _Or<__test_iter_concept<_Iter, __iter_concept_concept_test>, + __test_iter_concept<_Iter, __iter_concept_category_test>, + __test_iter_concept<_Iter, __iter_concept_random_fallback> >; +}; + +template +using _ITER_CONCEPT _LIBCPP_NODEBUG = typename __iter_concept_cache<_Iter>::type::template _Apply<_Iter>; + // [iterator.concept.input] template concept input_iterator = input_or_output_iterator<_Ip> && indirectly_readable<_Ip> && requires { diff --git a/lib/libcxx/include/__iterator/front_insert_iterator.h b/lib/libcxx/include/__iterator/front_insert_iterator.h index 80819cd22a..d79c4d78b6 100644 --- a/lib/libcxx/include/__iterator/front_insert_iterator.h +++ b/lib/libcxx/include/__iterator/front_insert_iterator.h @@ -28,7 +28,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD _LIBCPP_SUPPRESS_DEPRECATED_PUSH template -class _LIBCPP_TEMPLATE_VIS front_insert_iterator +class front_insert_iterator #if _LIBCPP_STD_VER <= 14 || !defined(_LIBCPP_ABI_NO_ITERATOR_BASES) : public iterator #endif diff --git a/lib/libcxx/include/__iterator/insert_iterator.h b/lib/libcxx/include/__iterator/insert_iterator.h index e0ee0ce035..95768cb8e0 100644 --- a/lib/libcxx/include/__iterator/insert_iterator.h +++ b/lib/libcxx/include/__iterator/insert_iterator.h @@ -37,7 +37,7 @@ using __insert_iterator_iter_t _LIBCPP_NODEBUG = typename _Container::iterator; _LIBCPP_SUPPRESS_DEPRECATED_PUSH template -class _LIBCPP_TEMPLATE_VIS insert_iterator +class insert_iterator #if _LIBCPP_STD_VER <= 14 || !defined(_LIBCPP_ABI_NO_ITERATOR_BASES) : public iterator #endif diff --git a/lib/libcxx/include/__iterator/istream_iterator.h b/lib/libcxx/include/__iterator/istream_iterator.h index a6c74d0017..cdb8056cfe 100644 --- a/lib/libcxx/include/__iterator/istream_iterator.h +++ b/lib/libcxx/include/__iterator/istream_iterator.h @@ -27,7 +27,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD _LIBCPP_SUPPRESS_DEPRECATED_PUSH template , class _Distance = ptrdiff_t> -class _LIBCPP_TEMPLATE_VIS istream_iterator +class istream_iterator #if _LIBCPP_STD_VER <= 14 || !defined(_LIBCPP_ABI_NO_ITERATOR_BASES) : public iterator #endif @@ -58,6 +58,9 @@ public: __in_stream_ = nullptr; } + // LWG3600 Changed the wording of the copy constructor. In libc++ this constructor + // can still be trivial after this change. + _LIBCPP_HIDE_FROM_ABI const _Tp& operator*() const { return __value_; } _LIBCPP_HIDE_FROM_ABI const _Tp* operator->() const { return std::addressof((operator*())); } _LIBCPP_HIDE_FROM_ABI istream_iterator& operator++() { diff --git a/lib/libcxx/include/__iterator/istreambuf_iterator.h b/lib/libcxx/include/__iterator/istreambuf_iterator.h index 162873b955..b7b28cd1a0 100644 --- a/lib/libcxx/include/__iterator/istreambuf_iterator.h +++ b/lib/libcxx/include/__iterator/istreambuf_iterator.h @@ -27,7 +27,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD _LIBCPP_SUPPRESS_DEPRECATED_PUSH template -class _LIBCPP_TEMPLATE_VIS istreambuf_iterator +class istreambuf_iterator #if _LIBCPP_STD_VER <= 14 || !defined(_LIBCPP_ABI_NO_ITERATOR_BASES) : public iterator #endif diff --git a/lib/libcxx/include/__iterator/iter_move.h b/lib/libcxx/include/__iterator/iter_move.h index ba8aed3c0f..5cc1615259 100644 --- a/lib/libcxx/include/__iterator/iter_move.h +++ b/lib/libcxx/include/__iterator/iter_move.h @@ -14,6 +14,7 @@ #include <__config> #include <__iterator/iterator_traits.h> #include <__type_traits/is_reference.h> +#include <__type_traits/is_referenceable.h> #include <__type_traits/remove_cvref.h> #include <__utility/declval.h> #include <__utility/forward.h> @@ -90,7 +91,7 @@ inline constexpr auto iter_move = __iter_move::__fn{}; template <__dereferenceable _Tp> requires requires(_Tp& __t) { - { ranges::iter_move(__t) } -> __can_reference; + { ranges::iter_move(__t) } -> __referenceable; } using iter_rvalue_reference_t = decltype(ranges::iter_move(std::declval<_Tp&>())); diff --git a/lib/libcxx/include/__iterator/iterator.h b/lib/libcxx/include/__iterator/iterator.h index 1591655313..d7fcd8c4dd 100644 --- a/lib/libcxx/include/__iterator/iterator.h +++ b/lib/libcxx/include/__iterator/iterator.h @@ -20,7 +20,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD template -struct _LIBCPP_TEMPLATE_VIS _LIBCPP_DEPRECATED_IN_CXX17 iterator { +struct _LIBCPP_DEPRECATED_IN_CXX17 iterator { typedef _Tp value_type; typedef _Distance difference_type; typedef _Pointer pointer; diff --git a/lib/libcxx/include/__iterator/iterator_traits.h b/lib/libcxx/include/__iterator/iterator_traits.h index db68dd2c37..f727e8ff36 100644 --- a/lib/libcxx/include/__iterator/iterator_traits.h +++ b/lib/libcxx/include/__iterator/iterator_traits.h @@ -22,16 +22,18 @@ #include <__fwd/pair.h> #include <__iterator/incrementable_traits.h> #include <__iterator/readable_traits.h> +#include <__tuple/tuple_element.h> #include <__type_traits/common_reference.h> #include <__type_traits/conditional.h> +#include <__type_traits/detected_or.h> #include <__type_traits/disjunction.h> -#include <__type_traits/enable_if.h> #include <__type_traits/integral_constant.h> #include <__type_traits/is_convertible.h> #include <__type_traits/is_object.h> #include <__type_traits/is_primary_template.h> #include <__type_traits/is_reference.h> -#include <__type_traits/is_valid_expansion.h> +#include <__type_traits/is_referenceable.h> +#include <__type_traits/nat.h> #include <__type_traits/remove_const.h> #include <__type_traits/remove_cv.h> #include <__type_traits/remove_cvref.h> @@ -46,15 +48,9 @@ _LIBCPP_BEGIN_NAMESPACE_STD #if _LIBCPP_STD_VER >= 20 -template -using __with_reference _LIBCPP_NODEBUG = _Tp&; - -template -concept __can_reference = requires { typename __with_reference<_Tp>; }; - template concept __dereferenceable = requires(_Tp& __t) { - { *__t } -> __can_reference; // not required to be equality-preserving + { *__t } -> __referenceable; // not required to be equality-preserving }; // [iterator.traits] @@ -64,92 +60,17 @@ using iter_reference_t = decltype(*std::declval<_Tp&>()); #endif // _LIBCPP_STD_VER >= 20 template -struct _LIBCPP_TEMPLATE_VIS iterator_traits; +struct iterator_traits; -struct _LIBCPP_TEMPLATE_VIS input_iterator_tag {}; -struct _LIBCPP_TEMPLATE_VIS output_iterator_tag {}; -struct _LIBCPP_TEMPLATE_VIS forward_iterator_tag : public input_iterator_tag {}; -struct _LIBCPP_TEMPLATE_VIS bidirectional_iterator_tag : public forward_iterator_tag {}; -struct _LIBCPP_TEMPLATE_VIS random_access_iterator_tag : public bidirectional_iterator_tag {}; +struct input_iterator_tag {}; +struct output_iterator_tag {}; +struct forward_iterator_tag : public input_iterator_tag {}; +struct bidirectional_iterator_tag : public forward_iterator_tag {}; +struct random_access_iterator_tag : public bidirectional_iterator_tag {}; #if _LIBCPP_STD_VER >= 20 -struct _LIBCPP_TEMPLATE_VIS contiguous_iterator_tag : public random_access_iterator_tag {}; +struct contiguous_iterator_tag : public random_access_iterator_tag {}; #endif -template -struct __iter_traits_cache { - using type = _If< __is_primary_template >::value, _Iter, iterator_traits<_Iter> >; -}; -template -using _ITER_TRAITS _LIBCPP_NODEBUG = typename __iter_traits_cache<_Iter>::type; - -struct __iter_concept_concept_test { - template - using _Apply _LIBCPP_NODEBUG = typename _ITER_TRAITS<_Iter>::iterator_concept; -}; -struct __iter_concept_category_test { - template - using _Apply _LIBCPP_NODEBUG = typename _ITER_TRAITS<_Iter>::iterator_category; -}; -struct __iter_concept_random_fallback { - template - using _Apply _LIBCPP_NODEBUG = - __enable_if_t<__is_primary_template >::value, random_access_iterator_tag>; -}; - -template -struct __test_iter_concept : _IsValidExpansion<_Tester::template _Apply, _Iter>, _Tester {}; - -template -struct __iter_concept_cache { - using type = _Or< __test_iter_concept<_Iter, __iter_concept_concept_test>, - __test_iter_concept<_Iter, __iter_concept_category_test>, - __test_iter_concept<_Iter, __iter_concept_random_fallback> >; -}; - -template -using _ITER_CONCEPT _LIBCPP_NODEBUG = typename __iter_concept_cache<_Iter>::type::template _Apply<_Iter>; - -template -struct __has_iterator_typedefs { -private: - template - static false_type __test(...); - template - static true_type - __test(__void_t* = nullptr, - __void_t* = nullptr, - __void_t* = nullptr, - __void_t* = nullptr, - __void_t* = nullptr); - -public: - static const bool value = decltype(__test<_Tp>(nullptr, nullptr, nullptr, nullptr, nullptr))::value; -}; - -template -struct __has_iterator_category { -private: - template - static false_type __test(...); - template - static true_type __test(typename _Up::iterator_category* = nullptr); - -public: - static const bool value = decltype(__test<_Tp>(nullptr))::value; -}; - -template -struct __has_iterator_concept { -private: - template - static false_type __test(...); - template - static true_type __test(typename _Up::iterator_concept* = nullptr); - -public: - static const bool value = decltype(__test<_Tp>(nullptr))::value; -}; - #if _LIBCPP_STD_VER >= 20 // The `cpp17-*-iterator` exposition-only concepts have very similar names to the `Cpp17*Iterator` named requirements @@ -158,9 +79,9 @@ public: namespace __iterator_traits_detail { template concept __cpp17_iterator = requires(_Ip __i) { - { *__i } -> __can_reference; + { *__i } -> __referenceable; { ++__i } -> same_as<_Ip&>; - { *__i++ } -> __can_reference; + { *__i++ } -> __referenceable; } && copyable<_Ip>; template @@ -219,16 +140,6 @@ concept __specifies_members = requires { requires __has_member_iterator_category<_Ip>; }; -template -struct __iterator_traits_member_pointer_or_void { - using type = void; -}; - -template <__has_member_pointer _Tp> -struct __iterator_traits_member_pointer_or_void<_Tp> { - using type = typename _Tp::pointer; -}; - template concept __cpp17_iterator_missing_members = !__specifies_members<_Tp> && __iterator_traits_detail::__cpp17_iterator<_Tp>; @@ -239,14 +150,14 @@ concept __cpp17_input_iterator_missing_members = // Otherwise, `pointer` names `void`. template struct __iterator_traits_member_pointer_or_arrow_or_void { - using type = void; + using type _LIBCPP_NODEBUG = void; }; // [iterator.traits]/3.2.1 // If the qualified-id `I::pointer` is valid and denotes a type, `pointer` names that type. template <__has_member_pointer _Ip> struct __iterator_traits_member_pointer_or_arrow_or_void<_Ip> { - using type = typename _Ip::pointer; + using type _LIBCPP_NODEBUG = typename _Ip::pointer; }; // Otherwise, if `decltype(declval().operator->())` is well-formed, then `pointer` names that @@ -254,48 +165,48 @@ struct __iterator_traits_member_pointer_or_arrow_or_void<_Ip> { template requires requires(_Ip& __i) { __i.operator->(); } && (!__has_member_pointer<_Ip>) struct __iterator_traits_member_pointer_or_arrow_or_void<_Ip> { - using type = decltype(std::declval<_Ip&>().operator->()); + using type _LIBCPP_NODEBUG = decltype(std::declval<_Ip&>().operator->()); }; // Otherwise, `reference` names `iter-reference-t`. template struct __iterator_traits_member_reference { - using type = iter_reference_t<_Ip>; + using type _LIBCPP_NODEBUG = iter_reference_t<_Ip>; }; // [iterator.traits]/3.2.2 // If the qualified-id `I::reference` is valid and denotes a type, `reference` names that type. template <__has_member_reference _Ip> struct __iterator_traits_member_reference<_Ip> { - using type = typename _Ip::reference; + using type _LIBCPP_NODEBUG = typename _Ip::reference; }; // [iterator.traits]/3.2.3.4 // input_iterator_tag template struct __deduce_iterator_category { - using type = input_iterator_tag; + using type _LIBCPP_NODEBUG = input_iterator_tag; }; // [iterator.traits]/3.2.3.1 // `random_access_iterator_tag` if `I` satisfies `cpp17-random-access-iterator`, or otherwise template <__iterator_traits_detail::__cpp17_random_access_iterator _Ip> struct __deduce_iterator_category<_Ip> { - using type = random_access_iterator_tag; + using type _LIBCPP_NODEBUG = random_access_iterator_tag; }; // [iterator.traits]/3.2.3.2 // `bidirectional_iterator_tag` if `I` satisfies `cpp17-bidirectional-iterator`, or otherwise template <__iterator_traits_detail::__cpp17_bidirectional_iterator _Ip> struct __deduce_iterator_category<_Ip> { - using type = bidirectional_iterator_tag; + using type _LIBCPP_NODEBUG = bidirectional_iterator_tag; }; // [iterator.traits]/3.2.3.3 // `forward_iterator_tag` if `I` satisfies `cpp17-forward-iterator`, or otherwise template <__iterator_traits_detail::__cpp17_forward_iterator _Ip> struct __deduce_iterator_category<_Ip> { - using type = forward_iterator_tag; + using type _LIBCPP_NODEBUG = forward_iterator_tag; }; template @@ -306,13 +217,13 @@ struct __iterator_traits_iterator_category : __deduce_iterator_category<_Ip> {}; // that type. template <__has_member_iterator_category _Ip> struct __iterator_traits_iterator_category<_Ip> { - using type = typename _Ip::iterator_category; + using type _LIBCPP_NODEBUG = typename _Ip::iterator_category; }; // otherwise, it names void. template struct __iterator_traits_difference_type { - using type = void; + using type _LIBCPP_NODEBUG = void; }; // If the qualified-id `incrementable_traits::difference_type` is valid and denotes a type, then @@ -320,7 +231,7 @@ struct __iterator_traits_difference_type { template requires requires { typename incrementable_traits<_Ip>::difference_type; } struct __iterator_traits_difference_type<_Ip> { - using type = typename incrementable_traits<_Ip>::difference_type; + using type _LIBCPP_NODEBUG = typename incrementable_traits<_Ip>::difference_type; }; // [iterator.traits]/3.4 @@ -328,6 +239,9 @@ struct __iterator_traits_difference_type<_Ip> { template struct __iterator_traits {}; +template +using __pointer_member _LIBCPP_NODEBUG = typename _Tp::pointer; + // [iterator.traits]/3.1 // If `I` has valid ([temp.deduct]) member types `difference-type`, `value-type`, `reference`, and // `iterator-category`, then `iterator-traits` has the following publicly accessible members: @@ -336,7 +250,7 @@ struct __iterator_traits<_Ip> { using iterator_category = typename _Ip::iterator_category; using value_type = typename _Ip::value_type; using difference_type = typename _Ip::difference_type; - using pointer = typename __iterator_traits_member_pointer_or_void<_Ip>::type; + using pointer = __detected_or_t; using reference = typename _Ip::reference; }; @@ -391,13 +305,30 @@ struct __iterator_traits<_Iter, true> is_convertible::value || is_convertible::value > {}; +template +struct __has_iterator_typedefs { +private: + template + static false_type __test(...); + template + static true_type + __test(__void_t* = nullptr, + __void_t* = nullptr, + __void_t* = nullptr, + __void_t* = nullptr, + __void_t* = nullptr); + +public: + static const bool value = decltype(__test<_Tp>(nullptr, nullptr, nullptr, nullptr, nullptr))::value; +}; + // iterator_traits will only have the nested types if Iterator::iterator_category // exists. Else iterator_traits will be an empty class. This is a // conforming extension which allows some programs to compile and behave as // the client expects instead of failing at compile time. template -struct _LIBCPP_TEMPLATE_VIS iterator_traits : __iterator_traits<_Iter, __has_iterator_typedefs<_Iter>::value> { +struct iterator_traits : __iterator_traits<_Iter, __has_iterator_typedefs<_Iter>::value> { using __primary_template _LIBCPP_NODEBUG = iterator_traits; }; #endif // _LIBCPP_STD_VER >= 20 @@ -406,7 +337,7 @@ template #if _LIBCPP_STD_VER >= 20 requires is_object_v<_Tp> #endif -struct _LIBCPP_TEMPLATE_VIS iterator_traits<_Tp*> { +struct iterator_traits<_Tp*> { typedef ptrdiff_t difference_type; typedef __remove_cv_t<_Tp> value_type; typedef _Tp* pointer; @@ -417,18 +348,19 @@ struct _LIBCPP_TEMPLATE_VIS iterator_traits<_Tp*> { #endif }; -template >::value> -struct __has_iterator_category_convertible_to : is_convertible::iterator_category, _Up> { -}; +template +using __iterator_category _LIBCPP_NODEBUG = typename _Tp::iterator_category; + +template +using __iterator_concept _LIBCPP_NODEBUG = typename _Tp::iterator_concept; template -struct __has_iterator_category_convertible_to<_Tp, _Up, false> : false_type {}; - -template ::value> -struct __has_iterator_concept_convertible_to : is_convertible {}; +using __has_iterator_category_convertible_to _LIBCPP_NODEBUG = + is_convertible<__detected_or_t<__nat, __iterator_category, iterator_traits<_Tp> >, _Up>; template -struct __has_iterator_concept_convertible_to<_Tp, _Up, false> : false_type {}; +using __has_iterator_concept_convertible_to _LIBCPP_NODEBUG = + is_convertible<__detected_or_t<__nat, __iterator_concept, _Tp>, _Up>; template using __has_input_iterator_category _LIBCPP_NODEBUG = __has_iterator_category_convertible_to<_Tp, input_iterator_tag>; @@ -490,6 +422,18 @@ using __has_exactly_bidirectional_iterator_category _LIBCPP_NODEBUG = template using __iter_value_type _LIBCPP_NODEBUG = typename iterator_traits<_InputIterator>::value_type; +#if _LIBCPP_STD_VER >= 23 +template +using __iter_key_type _LIBCPP_NODEBUG = remove_const_t>>; + +template +using __iter_mapped_type _LIBCPP_NODEBUG = tuple_element_t<1, __iter_value_type<_InputIterator>>; + +template +using __iter_to_alloc_type _LIBCPP_NODEBUG = + pair>, + tuple_element_t<1, __iter_value_type<_InputIterator>>>; +#else template using __iter_key_type _LIBCPP_NODEBUG = __remove_const_t::value_type::first_type>; @@ -501,6 +445,7 @@ template using __iter_to_alloc_type _LIBCPP_NODEBUG = pair::value_type::first_type, typename iterator_traits<_InputIterator>::value_type::second_type>; +#endif // _LIBCPP_STD_VER >= 23 template using __iterator_category_type _LIBCPP_NODEBUG = typename iterator_traits<_Iter>::iterator_category; diff --git a/lib/libcxx/include/__iterator/move_iterator.h b/lib/libcxx/include/__iterator/move_iterator.h index a1c53e9bd2..2b64680a34 100644 --- a/lib/libcxx/include/__iterator/move_iterator.h +++ b/lib/libcxx/include/__iterator/move_iterator.h @@ -64,7 +64,7 @@ concept __move_iter_comparable = requires { #endif // _LIBCPP_STD_VER >= 20 template -class _LIBCPP_TEMPLATE_VIS move_iterator +class move_iterator #if _LIBCPP_STD_VER >= 20 : public __move_iter_category_base<_Iter> #endif diff --git a/lib/libcxx/include/__iterator/move_sentinel.h b/lib/libcxx/include/__iterator/move_sentinel.h index 4a2a09ef06..c77ca5f1a9 100644 --- a/lib/libcxx/include/__iterator/move_sentinel.h +++ b/lib/libcxx/include/__iterator/move_sentinel.h @@ -27,7 +27,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD #if _LIBCPP_STD_VER >= 20 template -class _LIBCPP_TEMPLATE_VIS move_sentinel { +class move_sentinel { public: _LIBCPP_HIDE_FROM_ABI move_sentinel() = default; diff --git a/lib/libcxx/include/__iterator/next.h b/lib/libcxx/include/__iterator/next.h index 1f68a5bec8..1143ab31ff 100644 --- a/lib/libcxx/include/__iterator/next.h +++ b/lib/libcxx/include/__iterator/next.h @@ -10,7 +10,6 @@ #ifndef _LIBCPP___ITERATOR_NEXT_H #define _LIBCPP___ITERATOR_NEXT_H -#include <__assert> #include <__config> #include <__iterator/advance.h> #include <__iterator/concepts.h> @@ -27,11 +26,6 @@ _LIBCPP_BEGIN_NAMESPACE_STD template ::value, int> = 0> [[__nodiscard__]] inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX17 _InputIter next(_InputIter __x, typename iterator_traits<_InputIter>::difference_type __n = 1) { - // Calling `advance` with a negative value on a non-bidirectional iterator is a no-op in the current implementation. - // Note that this check duplicates the similar check in `std::advance`. - _LIBCPP_ASSERT_PEDANTIC(__n >= 0 || __has_bidirectional_iterator_category<_InputIter>::value, - "Attempt to next(it, n) with negative n on a non-bidirectional iterator"); - std::advance(__x, __n); return __x; } diff --git a/lib/libcxx/include/__iterator/ostream_iterator.h b/lib/libcxx/include/__iterator/ostream_iterator.h index 93ecc03010..2b459f4628 100644 --- a/lib/libcxx/include/__iterator/ostream_iterator.h +++ b/lib/libcxx/include/__iterator/ostream_iterator.h @@ -26,7 +26,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD _LIBCPP_SUPPRESS_DEPRECATED_PUSH template > -class _LIBCPP_TEMPLATE_VIS ostream_iterator +class ostream_iterator #if _LIBCPP_STD_VER <= 14 || !defined(_LIBCPP_ABI_NO_ITERATOR_BASES) : public iterator #endif diff --git a/lib/libcxx/include/__iterator/ostreambuf_iterator.h b/lib/libcxx/include/__iterator/ostreambuf_iterator.h index f00449355e..7133331a7b 100644 --- a/lib/libcxx/include/__iterator/ostreambuf_iterator.h +++ b/lib/libcxx/include/__iterator/ostreambuf_iterator.h @@ -27,7 +27,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD _LIBCPP_SUPPRESS_DEPRECATED_PUSH template -class _LIBCPP_TEMPLATE_VIS ostreambuf_iterator +class ostreambuf_iterator #if _LIBCPP_STD_VER <= 14 || !defined(_LIBCPP_ABI_NO_ITERATOR_BASES) : public iterator #endif diff --git a/lib/libcxx/include/__iterator/prev.h b/lib/libcxx/include/__iterator/prev.h index bffd5527dc..97139e067c 100644 --- a/lib/libcxx/include/__iterator/prev.h +++ b/lib/libcxx/include/__iterator/prev.h @@ -10,7 +10,6 @@ #ifndef _LIBCPP___ITERATOR_PREV_H #define _LIBCPP___ITERATOR_PREV_H -#include <__assert> #include <__config> #include <__iterator/advance.h> #include <__iterator/concepts.h> @@ -31,10 +30,6 @@ _LIBCPP_BEGIN_NAMESPACE_STD template ::value, int> = 0> [[__nodiscard__]] inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX17 _InputIter prev(_InputIter __x, typename iterator_traits<_InputIter>::difference_type __n) { - // Calling `advance` with a negative value on a non-bidirectional iterator is a no-op in the current implementation. - // Note that this check duplicates the similar check in `std::advance`. - _LIBCPP_ASSERT_PEDANTIC(__n <= 0 || __has_bidirectional_iterator_category<_InputIter>::value, - "Attempt to prev(it, n) with a positive n on a non-bidirectional iterator"); std::advance(__x, -__n); return __x; } diff --git a/lib/libcxx/include/__iterator/product_iterator.h b/lib/libcxx/include/__iterator/product_iterator.h new file mode 100644 index 0000000000..1db673bafd --- /dev/null +++ b/lib/libcxx/include/__iterator/product_iterator.h @@ -0,0 +1,76 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___ITERATOR_PRODUCT_ITERATOR_H +#define _LIBCPP___ITERATOR_PRODUCT_ITERATOR_H + +// Product iterators are iterators that contain two or more underlying iterators. +// +// For example, std::flat_map stores its data into two separate containers, and its iterator +// is a proxy over two separate underlying iterators. The concept of product iterators +// allows algorithms to operate over these underlying iterators separately, opening the +// door to various optimizations. +// +// If __product_iterator_traits can be instantiated, the following functions and associated types must be provided: +// - static constexpr size_t Traits::__size +// The number of underlying iterators inside the product iterator. +// +// - template +// static decltype(auto) Traits::__get_iterator_element(It&& __it) +// Returns the _Nth iterator element of the given product iterator. +// +// - template +// static _Iterator __make_product_iterator(_Iters&&...); +// Creates a product iterator from the given underlying iterators. + +#include <__config> +#include <__cstddef/size_t.h> +#include <__type_traits/enable_if.h> +#include <__type_traits/integral_constant.h> +#include <__utility/declval.h> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +template +struct __product_iterator_traits; +/* exposition-only: +{ + static constexpr size_t __size = ...; + + template + static decltype(auto) __get_iterator_element(_Iter&&); + + template + static _Iterator __make_product_iterator(_Iters&&...); +}; +*/ + +template +struct __is_product_iterator : false_type {}; + +template +struct __is_product_iterator<_Tp, sizeof(__product_iterator_traits<_Tp>) * 0> : true_type {}; + +template +struct __is_product_iterator_of_size : false_type {}; + +template +struct __is_product_iterator_of_size<_Tp, _Size, __enable_if_t<__product_iterator_traits<_Tp>::__size == _Size> > + : true_type {}; + +template +using __product_iterator_element_t _LIBCPP_NODEBUG = + decltype(__product_iterator_traits<_Iterator>::template __get_iterator_element<_Nth>(std::declval<_Iterator>())); + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___ITERATOR_PRODUCT_ITERATOR_H diff --git a/lib/libcxx/include/__iterator/reverse_iterator.h b/lib/libcxx/include/__iterator/reverse_iterator.h index 5bd1f868d3..8935e5a8ff 100644 --- a/lib/libcxx/include/__iterator/reverse_iterator.h +++ b/lib/libcxx/include/__iterator/reverse_iterator.h @@ -48,7 +48,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD _LIBCPP_SUPPRESS_DEPRECATED_PUSH template -class _LIBCPP_TEMPLATE_VIS reverse_iterator +class reverse_iterator #if _LIBCPP_STD_VER <= 14 || !defined(_LIBCPP_ABI_NO_ITERATOR_BASES) : public iterator::iterator_category, typename iterator_traits<_Iter>::value_type, diff --git a/lib/libcxx/include/__iterator/segmented_iterator.h b/lib/libcxx/include/__iterator/segmented_iterator.h index 7a8e1addea..af27a7be41 100644 --- a/lib/libcxx/include/__iterator/segmented_iterator.h +++ b/lib/libcxx/include/__iterator/segmented_iterator.h @@ -42,6 +42,7 @@ #include <__config> #include <__cstddef/size_t.h> +#include <__iterator/iterator_traits.h> #include <__type_traits/integral_constant.h> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) @@ -74,6 +75,11 @@ struct __has_specialization<_Tp, sizeof(_Tp) * 0> : true_type {}; template using __is_segmented_iterator _LIBCPP_NODEBUG = __has_specialization<__segmented_iterator_traits<_Iterator> >; +template +struct __has_random_access_local_iterator + : __has_random_access_iterator_category< + typename __segmented_iterator_traits< _SegmentedIterator >::__local_iterator > {}; + _LIBCPP_END_NAMESPACE_STD #endif // _LIBCPP___SEGMENTED_ITERATOR_H diff --git a/lib/libcxx/include/__iterator/wrap_iter.h b/lib/libcxx/include/__iterator/wrap_iter.h index 966c4675b7..2b5bc489dd 100644 --- a/lib/libcxx/include/__iterator/wrap_iter.h +++ b/lib/libcxx/include/__iterator/wrap_iter.h @@ -112,9 +112,9 @@ private: template friend class basic_string_view; template - friend class _LIBCPP_TEMPLATE_VIS vector; + friend class vector; template - friend class _LIBCPP_TEMPLATE_VIS span; + friend class span; template friend struct array; }; @@ -236,7 +236,7 @@ struct __libcpp_is_contiguous_iterator<__wrap_iter<_It> > : true_type {}; #endif template -struct _LIBCPP_TEMPLATE_VIS pointer_traits<__wrap_iter<_It> > { +struct pointer_traits<__wrap_iter<_It> > { typedef __wrap_iter<_It> pointer; typedef typename pointer_traits<_It>::element_type element_type; typedef typename pointer_traits<_It>::difference_type difference_type; diff --git a/lib/libcxx/include/__locale b/lib/libcxx/include/__locale index dfe79d5e50..757a53951f 100644 --- a/lib/libcxx/include/__locale +++ b/lib/libcxx/include/__locale @@ -11,36 +11,43 @@ #define _LIBCPP___LOCALE #include <__config> -#include <__locale_dir/locale_base_api.h> -#include <__memory/shared_count.h> -#include <__mutex/once_flag.h> -#include <__type_traits/make_unsigned.h> -#include <__utility/no_destroy.h> -#include <__utility/private_constructor_tag.h> -#include -#include -#include -#include -#include + +#if _LIBCPP_HAS_LOCALIZATION + +# include <__locale_dir/locale_base_api.h> +# include <__memory/addressof.h> +# include <__memory/shared_count.h> +# include <__mutex/once_flag.h> +# include <__type_traits/make_unsigned.h> +# include <__utility/no_destroy.h> +# include <__utility/private_constructor_tag.h> +# include +# include +# include +# include +# include // Some platforms require more includes than others. Keep the includes on all plaforms for now. -#include -#include +# include +# include -#if _LIBCPP_HAS_WIDE_CHARACTERS -# include -#else -# include <__std_mbstate_t.h> -#endif +# if _LIBCPP_HAS_WIDE_CHARACTERS +# include +# else +# include <__std_mbstate_t.h> +# endif -#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) -# pragma GCC system_header -#endif +# if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +# endif _LIBCPP_BEGIN_NAMESPACE_STD class _LIBCPP_EXPORTED_FROM_ABI locale; +template +class collate; + template _LIBCPP_HIDE_FROM_ABI bool has_facet(const locale&) _NOEXCEPT; @@ -49,8 +56,10 @@ _LIBCPP_HIDE_FROM_ABI const _Facet& use_facet(const locale&); class _LIBCPP_EXPORTED_FROM_ABI locale { public: - // locale is essentially a shared_ptr that doesn't support weak_ptrs and never got a move constructor. + // locale is essentially a shared_ptr that doesn't support weak_ptrs and never got a move constructor, + // so it is trivially relocatable. Like shared_ptr, it is also replaceable. using __trivially_relocatable _LIBCPP_NODEBUG = locale; + using __replaceable _LIBCPP_NODEBUG = locale; // types: class _LIBCPP_EXPORTED_FROM_ABI facet; @@ -80,17 +89,25 @@ public: const locale& operator=(const locale&) _NOEXCEPT; template - _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS locale combine(const locale&) const; + _LIBCPP_HIDE_FROM_ABI locale combine(const locale& __other) const { + if (!std::has_facet<_Facet>(__other)) + __throw_runtime_error("locale::combine: locale missing facet"); + + return locale(*this, std::addressof(const_cast<_Facet&>(std::use_facet<_Facet>(__other)))); + } // locale operations: string name() const; bool operator==(const locale&) const; -#if _LIBCPP_STD_VER <= 17 +# if _LIBCPP_STD_VER <= 17 _LIBCPP_HIDE_FROM_ABI bool operator!=(const locale& __y) const { return !(*this == __y); } -#endif +# endif template - _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS bool - operator()(const basic_string<_CharT, _Traits, _Allocator>&, const basic_string<_CharT, _Traits, _Allocator>&) const; + _LIBCPP_HIDE_FROM_ABI bool operator()(const basic_string<_CharT, _Traits, _Allocator>& __x, + const basic_string<_CharT, _Traits, _Allocator>& __y) const { + return std::use_facet >(*this).compare( + __x.data(), __x.data() + __x.size(), __y.data(), __y.data() + __y.size()) < 0; + } // global locale objects: static locale global(const locale&); @@ -151,14 +168,6 @@ inline _LIBCPP_HIDE_FROM_ABI locale::locale(const locale& __other, _Facet* __f) __install_ctor(__other, __f, __f ? __f->id.__get() : 0); } -template -locale locale::combine(const locale& __other) const { - if (!std::has_facet<_Facet>(__other)) - __throw_runtime_error("locale::combine: locale missing facet"); - - return locale(*this, &const_cast<_Facet&>(std::use_facet<_Facet>(__other))); -} - template inline _LIBCPP_HIDE_FROM_ABI bool has_facet(const locale& __l) _NOEXCEPT { return __l.has_facet(_Facet::id); @@ -172,7 +181,7 @@ inline _LIBCPP_HIDE_FROM_ABI const _Facet& use_facet(const locale& __l) { // template class collate; template -class _LIBCPP_TEMPLATE_VIS collate : public locale::facet { +class collate : public locale::facet { public: typedef _CharT char_type; typedef basic_string string_type; @@ -237,14 +246,14 @@ long collate<_CharT>::do_hash(const char_type* __lo, const char_type* __hi) cons } extern template class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS collate; -#if _LIBCPP_HAS_WIDE_CHARACTERS +# if _LIBCPP_HAS_WIDE_CHARACTERS extern template class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS collate; -#endif +# endif // template class collate_byname; template -class _LIBCPP_TEMPLATE_VIS collate_byname; +class collate_byname; template <> class _LIBCPP_EXPORTED_FROM_ABI collate_byname : public collate { @@ -264,7 +273,7 @@ protected: string_type do_transform(const char_type* __lo, const char_type* __hi) const override; }; -#if _LIBCPP_HAS_WIDE_CHARACTERS +# if _LIBCPP_HAS_WIDE_CHARACTERS template <> class _LIBCPP_EXPORTED_FROM_ABI collate_byname : public collate { __locale::__locale_t __l_; @@ -283,20 +292,13 @@ protected: const char_type* __lo1, const char_type* __hi1, const char_type* __lo2, const char_type* __hi2) const override; string_type do_transform(const char_type* __lo, const char_type* __hi) const override; }; -#endif - -template -bool locale::operator()(const basic_string<_CharT, _Traits, _Allocator>& __x, - const basic_string<_CharT, _Traits, _Allocator>& __y) const { - return std::use_facet >(*this).compare( - __x.data(), __x.data() + __x.size(), __y.data(), __y.data() + __y.size()) < 0; -} +# endif // template class ctype class _LIBCPP_EXPORTED_FROM_ABI ctype_base { public: -#if defined(_LIBCPP_PROVIDES_DEFAULT_RUNE_TABLE) +# if defined(_LIBCPP_PROVIDES_DEFAULT_RUNE_TABLE) typedef unsigned long mask; static const mask space = 1 << 0; static const mask print = 1 << 1; @@ -308,14 +310,14 @@ public: static const mask punct = 1 << 7; static const mask xdigit = 1 << 8; static const mask blank = 1 << 9; -# if defined(__BIONIC__) +# if defined(__BIONIC__) // Historically this was a part of regex_traits rather than ctype_base. The // historical value of the constant is preserved for ABI compatibility. static const mask __regex_word = 0x8000; -# else +# else static const mask __regex_word = 1 << 10; -# endif // defined(__BIONIC__) -#elif defined(__GLIBC__) +# endif // defined(__BIONIC__) +# elif defined(__GLIBC__) typedef unsigned short mask; static const mask space = _ISspace; static const mask print = _ISprint; @@ -327,12 +329,12 @@ public: static const mask punct = _ISpunct; static const mask xdigit = _ISxdigit; static const mask blank = _ISblank; -# if defined(__mips__) || (BYTE_ORDER == BIG_ENDIAN) +# if defined(__mips__) || (BYTE_ORDER == BIG_ENDIAN) static const mask __regex_word = static_cast(_ISbit(15)); -# else +# else static const mask __regex_word = 0x80; -# endif -#elif defined(_LIBCPP_MSVCRT_LIKE) +# endif +# elif defined(_LIBCPP_MSVCRT_LIKE) typedef unsigned short mask; static const mask space = _SPACE; static const mask print = _BLANK | _PUNCT | _ALPHA | _DIGIT; @@ -345,16 +347,16 @@ public: static const mask xdigit = _HEX; static const mask blank = _BLANK; static const mask __regex_word = 0x4000; // 0x8000 and 0x0100 and 0x00ff are used -# define _LIBCPP_CTYPE_MASK_IS_COMPOSITE_PRINT -# define _LIBCPP_CTYPE_MASK_IS_COMPOSITE_ALPHA -#elif defined(__APPLE__) || defined(__FreeBSD__) || defined(__NetBSD__) -# ifdef __APPLE__ +# define _LIBCPP_CTYPE_MASK_IS_COMPOSITE_PRINT +# define _LIBCPP_CTYPE_MASK_IS_COMPOSITE_ALPHA +# elif defined(__APPLE__) || defined(__FreeBSD__) || defined(__NetBSD__) +# ifdef __APPLE__ typedef uint32_t mask; -# elif defined(__FreeBSD__) +# elif defined(__FreeBSD__) typedef unsigned long mask; -# elif defined(__NetBSD__) +# elif defined(__NetBSD__) typedef unsigned short mask; -# endif +# endif static const mask space = _CTYPE_S; static const mask print = _CTYPE_R; static const mask cntrl = _CTYPE_C; @@ -365,16 +367,16 @@ public: static const mask punct = _CTYPE_P; static const mask xdigit = _CTYPE_X; -# if defined(__NetBSD__) +# if defined(__NetBSD__) static const mask blank = _CTYPE_BL; // NetBSD defines classes up to 0x2000 // see sys/ctype_bits.h, _CTYPE_Q static const mask __regex_word = 0x8000; -# else +# else static const mask blank = _CTYPE_B; static const mask __regex_word = 0x80; -# endif -#elif defined(_AIX) +# endif +# elif defined(_AIX) typedef unsigned int mask; static const mask space = _ISSPACE; static const mask print = _ISPRINT; @@ -387,7 +389,7 @@ public: static const mask xdigit = _ISXDIGIT; static const mask blank = _ISBLANK; static const mask __regex_word = 0x8000; -#elif defined(_NEWLIB_VERSION) +# elif defined(_NEWLIB_VERSION) // Same type as Newlib's _ctype_ array in newlib/libc/include/ctype.h. typedef char mask; // In case char is signed, static_cast is needed to avoid warning on @@ -404,11 +406,11 @@ public: static const mask blank = static_cast(_B); // mask is already fully saturated, use a different type in regex_type_traits. static const unsigned short __regex_word = 0x100; -# define _LIBCPP_CTYPE_MASK_IS_COMPOSITE_PRINT -# define _LIBCPP_CTYPE_MASK_IS_COMPOSITE_ALPHA -# define _LIBCPP_CTYPE_MASK_IS_COMPOSITE_XDIGIT -#elif defined(__MVS__) -# if defined(__NATIVE_ASCII_F) +# define _LIBCPP_CTYPE_MASK_IS_COMPOSITE_PRINT +# define _LIBCPP_CTYPE_MASK_IS_COMPOSITE_ALPHA +# define _LIBCPP_CTYPE_MASK_IS_COMPOSITE_XDIGIT +# elif defined(__MVS__) +# if defined(__NATIVE_ASCII_F) typedef unsigned int mask; static const mask space = _ISSPACE_A; static const mask print = _ISPRINT_A; @@ -420,7 +422,7 @@ public: static const mask punct = _ISPUNCT_A; static const mask xdigit = _ISXDIGIT_A; static const mask blank = _ISBLANK_A; -# else +# else typedef unsigned short mask; static const mask space = __ISSPACE; static const mask print = __ISPRINT; @@ -432,11 +434,11 @@ public: static const mask punct = __ISPUNCT; static const mask xdigit = __ISXDIGIT; static const mask blank = __ISBLANK; -# endif +# endif static const mask __regex_word = 0x8000; -#else -# error unknown rune table for this platform -- do you mean to define _LIBCPP_PROVIDES_DEFAULT_RUNE_TABLE? -#endif +# else +# error unknown rune table for this platform -- do you mean to define _LIBCPP_PROVIDES_DEFAULT_RUNE_TABLE? +# endif static const mask alnum = alpha | digit; static const mask graph = alnum | punct; @@ -448,9 +450,9 @@ public: }; template -class _LIBCPP_TEMPLATE_VIS ctype; +class ctype; -#if _LIBCPP_HAS_WIDE_CHARACTERS +# if _LIBCPP_HAS_WIDE_CHARACTERS template <> class _LIBCPP_EXPORTED_FROM_ABI ctype : public locale::facet, public ctype_base { public: @@ -515,7 +517,7 @@ protected: virtual const char_type* do_narrow(const char_type* __low, const char_type* __high, char __dfault, char* __dest) const; }; -#endif // _LIBCPP_HAS_WIDE_CHARACTERS +# endif // _LIBCPP_HAS_WIDE_CHARACTERS inline _LIBCPP_HIDE_FROM_ABI bool __libcpp_isascii(int __c) { return (__c & ~0x7F) == 0; } @@ -580,25 +582,13 @@ public: static locale::id id; -#ifdef _CACHED_RUNES +# ifdef _CACHED_RUNES static const size_t table_size = _CACHED_RUNES; -#else +# else static const size_t table_size = 256; // FIXME: Don't hardcode this. -#endif +# endif _LIBCPP_HIDE_FROM_ABI const mask* table() const _NOEXCEPT { return __tab_; } static const mask* classic_table() _NOEXCEPT; -#if defined(__GLIBC__) || defined(__EMSCRIPTEN__) - static const int* __classic_upper_table() _NOEXCEPT; - static const int* __classic_lower_table() _NOEXCEPT; -#endif -#if defined(__NetBSD__) - static const short* __classic_upper_table() _NOEXCEPT; - static const short* __classic_lower_table() _NOEXCEPT; -#endif -#if defined(__MVS__) - static const unsigned short* __classic_upper_table() _NOEXCEPT; - static const unsigned short* __classic_lower_table() _NOEXCEPT; -#endif protected: ~ctype() override; @@ -615,7 +605,7 @@ protected: // template class ctype_byname; template -class _LIBCPP_TEMPLATE_VIS ctype_byname; +class ctype_byname; template <> class _LIBCPP_EXPORTED_FROM_ABI ctype_byname : public ctype { @@ -633,7 +623,7 @@ protected: const char_type* do_tolower(char_type* __low, const char_type* __high) const override; }; -#if _LIBCPP_HAS_WIDE_CHARACTERS +# if _LIBCPP_HAS_WIDE_CHARACTERS template <> class _LIBCPP_EXPORTED_FROM_ABI ctype_byname : public ctype { __locale::__locale_t __l_; @@ -658,7 +648,7 @@ protected: const char_type* do_narrow(const char_type* __low, const char_type* __high, char __dfault, char* __dest) const override; }; -#endif // _LIBCPP_HAS_WIDE_CHARACTERS +# endif // _LIBCPP_HAS_WIDE_CHARACTERS template inline _LIBCPP_HIDE_FROM_ABI bool isspace(_CharT __c, const locale& __loc) { @@ -741,7 +731,7 @@ public: // template class codecvt; template -class _LIBCPP_TEMPLATE_VIS codecvt; +class codecvt; // template <> class codecvt @@ -824,7 +814,7 @@ protected: // template <> class codecvt -#if _LIBCPP_HAS_WIDE_CHARACTERS +# if _LIBCPP_HAS_WIDE_CHARACTERS template <> class _LIBCPP_EXPORTED_FROM_ABI codecvt : public locale::facet, public codecvt_base { __locale::__locale_t __l_; @@ -903,7 +893,7 @@ protected: virtual int do_length(state_type&, const extern_type* __frm, const extern_type* __end, size_t __mx) const; virtual int do_max_length() const _NOEXCEPT; }; -#endif // _LIBCPP_HAS_WIDE_CHARACTERS +# endif // _LIBCPP_HAS_WIDE_CHARACTERS // template <> class codecvt // deprecated in C++20 @@ -985,7 +975,7 @@ protected: virtual int do_max_length() const _NOEXCEPT; }; -#if _LIBCPP_HAS_CHAR8_T +# if _LIBCPP_HAS_CHAR8_T // template <> class codecvt // C++20 @@ -1066,7 +1056,7 @@ protected: virtual int do_max_length() const _NOEXCEPT; }; -#endif +# endif // template <> class codecvt // deprecated in C++20 @@ -1148,7 +1138,7 @@ protected: virtual int do_max_length() const _NOEXCEPT; }; -#if _LIBCPP_HAS_CHAR8_T +# if _LIBCPP_HAS_CHAR8_T // template <> class codecvt // C++20 @@ -1229,12 +1219,12 @@ protected: virtual int do_max_length() const _NOEXCEPT; }; -#endif +# endif // template class codecvt_byname template -class _LIBCPP_TEMPLATE_VIS codecvt_byname : public codecvt<_InternT, _ExternT, _StateT> { +class codecvt_byname : public codecvt<_InternT, _ExternT, _StateT> { public: _LIBCPP_HIDE_FROM_ABI explicit codecvt_byname(const char* __nm, size_t __refs = 0) : codecvt<_InternT, _ExternT, _StateT>(__nm, __refs) {} @@ -1251,17 +1241,17 @@ codecvt_byname<_InternT, _ExternT, _StateT>::~codecvt_byname() {} _LIBCPP_SUPPRESS_DEPRECATED_POP extern template class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS codecvt_byname; -#if _LIBCPP_HAS_WIDE_CHARACTERS +# if _LIBCPP_HAS_WIDE_CHARACTERS extern template class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS codecvt_byname; -#endif +# endif extern template class _LIBCPP_DEPRECATED_IN_CXX20 _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS codecvt_byname; // deprecated in C++20 extern template class _LIBCPP_DEPRECATED_IN_CXX20 _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS codecvt_byname; // deprecated in C++20 -#if _LIBCPP_HAS_CHAR8_T +# if _LIBCPP_HAS_CHAR8_T extern template class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS codecvt_byname; // C++20 extern template class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS codecvt_byname; // C++20 -#endif +# endif template struct __narrow_to_utf8 { @@ -1298,7 +1288,7 @@ struct _LIBCPP_EXPORTED_FROM_ABI __narrow_to_utf8<16> : public codecvt : public codecvt : public codecvt __sz ? __nb + __sz : __ne, __nn, __buf, __buf + __sz, __bn); if (__r == codecvt_base::error || __nn == __nb) - __throw_runtime_error("locale not supported"); + std::__throw_runtime_error("locale not supported"); for (const char16_t* __p = __buf; __p < __bn; ++__p, ++__s) *__s = *__p; __nb = __nn; @@ -1398,7 +1388,7 @@ struct _LIBCPP_EXPORTED_FROM_ABI __widen_from_utf8<32> : public codecvt __sz ? __nb + __sz : __ne, __nn, __buf, __buf + __sz, __bn); if (__r == codecvt_base::error || __nn == __nb) - __throw_runtime_error("locale not supported"); + std::__throw_runtime_error("locale not supported"); for (const char32_t* __p = __buf; __p < __bn; ++__p, ++__s) *__s = *__p; __nb = __nn; @@ -1410,7 +1400,7 @@ struct _LIBCPP_EXPORTED_FROM_ABI __widen_from_utf8<32> : public codecvt class numpunct template -class _LIBCPP_TEMPLATE_VIS numpunct; +class numpunct; template <> class _LIBCPP_EXPORTED_FROM_ABI numpunct : public locale::facet { @@ -1441,7 +1431,7 @@ protected: string __grouping_; }; -#if _LIBCPP_HAS_WIDE_CHARACTERS +# if _LIBCPP_HAS_WIDE_CHARACTERS template <> class _LIBCPP_EXPORTED_FROM_ABI numpunct : public locale::facet { public: @@ -1470,12 +1460,12 @@ protected: char_type __thousands_sep_; string __grouping_; }; -#endif // _LIBCPP_HAS_WIDE_CHARACTERS +# endif // _LIBCPP_HAS_WIDE_CHARACTERS // template class numpunct_byname template -class _LIBCPP_TEMPLATE_VIS numpunct_byname; +class numpunct_byname; template <> class _LIBCPP_EXPORTED_FROM_ABI numpunct_byname : public numpunct { @@ -1493,7 +1483,7 @@ private: void __init(const char*); }; -#if _LIBCPP_HAS_WIDE_CHARACTERS +# if _LIBCPP_HAS_WIDE_CHARACTERS template <> class _LIBCPP_EXPORTED_FROM_ABI numpunct_byname : public numpunct { public: @@ -1509,8 +1499,10 @@ protected: private: void __init(const char*); }; -#endif // _LIBCPP_HAS_WIDE_CHARACTERS +# endif // _LIBCPP_HAS_WIDE_CHARACTERS _LIBCPP_END_NAMESPACE_STD +#endif // _LIBCPP_HAS_LOCALIZATION + #endif // _LIBCPP___LOCALE diff --git a/lib/libcxx/include/__locale_dir/check_grouping.h b/lib/libcxx/include/__locale_dir/check_grouping.h new file mode 100644 index 0000000000..93e9e404bb --- /dev/null +++ b/lib/libcxx/include/__locale_dir/check_grouping.h @@ -0,0 +1,31 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___LOCALE_DIR_CHECK_GROUPING_H +#define _LIBCPP___LOCALE_DIR_CHECK_GROUPING_H + +#include <__config> +#include <__fwd/string.h> +#include + +#if _LIBCPP_HAS_LOCALIZATION + +# if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +# endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +_LIBCPP_EXPORTED_FROM_ABI void +__check_grouping(const string& __grouping, unsigned* __g, unsigned* __g_end, ios_base::iostate& __err); + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP_HAS_LOCALIZATION + +#endif // _LIBCPP___LOCALE_DIR_CHECK_GROUPING_H diff --git a/lib/libcxx/include/__locale_dir/get_c_locale.h b/lib/libcxx/include/__locale_dir/get_c_locale.h new file mode 100644 index 0000000000..e8bac9a870 --- /dev/null +++ b/lib/libcxx/include/__locale_dir/get_c_locale.h @@ -0,0 +1,40 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___LOCALE_DIR_GET_C_LOCALE_H +#define _LIBCPP___LOCALE_DIR_GET_C_LOCALE_H + +#include <__config> +#include <__locale_dir/locale_base_api.h> + +#if _LIBCPP_HAS_LOCALIZATION + +# if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +# endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +// FIXME: This should really be part of the locale base API + +# if defined(__APPLE__) || defined(__FreeBSD__) +# define _LIBCPP_GET_C_LOCALE 0 +# elif defined(__NetBSD__) +# define _LIBCPP_GET_C_LOCALE LC_C_LOCALE +# else +# define _LIBCPP_GET_C_LOCALE __cloc() +// Get the C locale object +_LIBCPP_EXPORTED_FROM_ABI __locale::__locale_t __cloc(); +# define __cloc_defined +# endif + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP_HAS_LOCALIZATION + +#endif // _LIBCPP___LOCALE_DIR_GET_C_LOCALE_H diff --git a/lib/libcxx/include/__locale_dir/locale_base_api.h b/lib/libcxx/include/__locale_dir/locale_base_api.h index 538b194ec3..5e6c69e95e 100644 --- a/lib/libcxx/include/__locale_dir/locale_base_api.h +++ b/lib/libcxx/include/__locale_dir/locale_base_api.h @@ -64,8 +64,6 @@ // Character manipulation functions // -------------------------------- // namespace __locale { -// int __islower(int, __locale_t); -// int __isupper(int, __locale_t); // int __isdigit(int, __locale_t); // required by the headers // int __isxdigit(int, __locale_t); // required by the headers // int __toupper(int, __locale_t); @@ -111,59 +109,64 @@ // int __sscanf(const char*, __locale_t, const char*, ...); // required by the headers // } -#if defined(__APPLE__) -# include <__locale_dir/support/apple.h> -#elif defined(__FreeBSD__) -# include <__locale_dir/support/freebsd.h> -#elif defined(__NetBSD__) -# include <__locale_dir/support/netbsd.h> -#elif defined(_LIBCPP_MSVCRT_LIKE) -# include <__locale_dir/support/windows.h> -#elif defined(__Fuchsia__) -# include <__locale_dir/support/fuchsia.h> -#else +#if _LIBCPP_HAS_LOCALIZATION + +# if defined(__APPLE__) +# include <__locale_dir/support/apple.h> +# elif defined(__FreeBSD__) +# include <__locale_dir/support/freebsd.h> +/* zig patch: https://github.com/llvm/llvm-project/pull/143055 */ +# elif defined(__NetBSD__) +# include <__locale_dir/support/netbsd.h> +# elif defined(_LIBCPP_MSVCRT_LIKE) +# include <__locale_dir/support/windows.h> +# elif defined(__Fuchsia__) +# include <__locale_dir/support/fuchsia.h> +# elif defined(__linux__) +# include <__locale_dir/support/linux.h> +# else // TODO: This is a temporary definition to bridge between the old way we defined the locale base API // (by providing global non-reserved names) and the new API. As we move individual platforms // towards the new way of defining the locale base API, this should disappear since each platform // will define those directly. -# if defined(_AIX) || defined(__MVS__) -# include <__locale_dir/locale_base_api/ibm.h> -# elif defined(__ANDROID__) -# include <__locale_dir/locale_base_api/android.h> -# elif defined(__OpenBSD__) -# include <__locale_dir/locale_base_api/openbsd.h> -# elif defined(__wasi__) || _LIBCPP_HAS_MUSL_LIBC -# include <__locale_dir/locale_base_api/musl.h> -# endif +# if defined(_AIX) || defined(__MVS__) +# include <__locale_dir/locale_base_api/ibm.h> +# elif defined(__ANDROID__) +# include <__locale_dir/locale_base_api/android.h> +# elif defined(__OpenBSD__) +# include <__locale_dir/locale_base_api/openbsd.h> +# elif defined(__wasi__) || _LIBCPP_HAS_MUSL_LIBC +# include <__locale_dir/locale_base_api/musl.h> +# endif -# include <__locale_dir/locale_base_api/bsd_locale_fallbacks.h> +# include <__locale_dir/locale_base_api/bsd_locale_fallbacks.h> -# include <__cstddef/size_t.h> -# include <__utility/forward.h> -# include -# include -# include -# if _LIBCPP_HAS_WIDE_CHARACTERS -# include -# endif +# include <__cstddef/size_t.h> +# include <__utility/forward.h> +# include +# include +# include +# if _LIBCPP_HAS_WIDE_CHARACTERS +# include +# endif _LIBCPP_BEGIN_NAMESPACE_STD namespace __locale { // // Locale management // -# define _LIBCPP_COLLATE_MASK LC_COLLATE_MASK -# define _LIBCPP_CTYPE_MASK LC_CTYPE_MASK -# define _LIBCPP_MONETARY_MASK LC_MONETARY_MASK -# define _LIBCPP_NUMERIC_MASK LC_NUMERIC_MASK -# define _LIBCPP_TIME_MASK LC_TIME_MASK -# define _LIBCPP_MESSAGES_MASK LC_MESSAGES_MASK -# define _LIBCPP_ALL_MASK LC_ALL_MASK -# define _LIBCPP_LC_ALL LC_ALL +# define _LIBCPP_COLLATE_MASK LC_COLLATE_MASK +# define _LIBCPP_CTYPE_MASK LC_CTYPE_MASK +# define _LIBCPP_MONETARY_MASK LC_MONETARY_MASK +# define _LIBCPP_NUMERIC_MASK LC_NUMERIC_MASK +# define _LIBCPP_TIME_MASK LC_TIME_MASK +# define _LIBCPP_MESSAGES_MASK LC_MESSAGES_MASK +# define _LIBCPP_ALL_MASK LC_ALL_MASK +# define _LIBCPP_LC_ALL LC_ALL using __locale_t _LIBCPP_NODEBUG = locale_t; -# if defined(_LIBCPP_BUILDING_LIBRARY) +# if defined(_LIBCPP_BUILDING_LIBRARY) using __lconv_t _LIBCPP_NODEBUG = lconv; inline _LIBCPP_HIDE_FROM_ABI __locale_t __newlocale(int __category_mask, const char* __name, __locale_t __loc) { @@ -177,7 +180,7 @@ inline _LIBCPP_HIDE_FROM_ABI char* __setlocale(int __category, char const* __loc inline _LIBCPP_HIDE_FROM_ABI void __freelocale(__locale_t __loc) { freelocale(__loc); } inline _LIBCPP_HIDE_FROM_ABI __lconv_t* __localeconv(__locale_t& __loc) { return __libcpp_localeconv_l(__loc); } -# endif // _LIBCPP_BUILDING_LIBRARY +# endif // _LIBCPP_BUILDING_LIBRARY // // Strtonum functions @@ -206,15 +209,10 @@ __strtoull(const char* __nptr, char** __endptr, int __base, __locale_t __loc) { // // Character manipulation functions // -# if defined(_LIBCPP_BUILDING_LIBRARY) -inline _LIBCPP_HIDE_FROM_ABI int __islower(int __ch, __locale_t __loc) { return islower_l(__ch, __loc); } -inline _LIBCPP_HIDE_FROM_ABI int __isupper(int __ch, __locale_t __loc) { return isupper_l(__ch, __loc); } -# endif - inline _LIBCPP_HIDE_FROM_ABI int __isdigit(int __ch, __locale_t __loc) { return isdigit_l(__ch, __loc); } inline _LIBCPP_HIDE_FROM_ABI int __isxdigit(int __ch, __locale_t __loc) { return isxdigit_l(__ch, __loc); } -# if defined(_LIBCPP_BUILDING_LIBRARY) +# if defined(_LIBCPP_BUILDING_LIBRARY) inline _LIBCPP_HIDE_FROM_ABI int __strcoll(const char* __s1, const char* __s2, __locale_t __loc) { return strcoll_l(__s1, __s2, __loc); } @@ -224,7 +222,7 @@ inline _LIBCPP_HIDE_FROM_ABI size_t __strxfrm(char* __dest, const char* __src, s inline _LIBCPP_HIDE_FROM_ABI int __toupper(int __ch, __locale_t __loc) { return toupper_l(__ch, __loc); } inline _LIBCPP_HIDE_FROM_ABI int __tolower(int __ch, __locale_t __loc) { return tolower_l(__ch, __loc); } -# if _LIBCPP_HAS_WIDE_CHARACTERS +# if _LIBCPP_HAS_WIDE_CHARACTERS inline _LIBCPP_HIDE_FROM_ABI int __wcscoll(const wchar_t* __s1, const wchar_t* __s2, __locale_t __loc) { return wcscoll_l(__s1, __s2, __loc); } @@ -246,7 +244,7 @@ inline _LIBCPP_HIDE_FROM_ABI int __iswpunct(wint_t __ch, __locale_t __loc) { ret inline _LIBCPP_HIDE_FROM_ABI int __iswxdigit(wint_t __ch, __locale_t __loc) { return iswxdigit_l(__ch, __loc); } inline _LIBCPP_HIDE_FROM_ABI wint_t __towupper(wint_t __ch, __locale_t __loc) { return towupper_l(__ch, __loc); } inline _LIBCPP_HIDE_FROM_ABI wint_t __towlower(wint_t __ch, __locale_t __loc) { return towlower_l(__ch, __loc); } -# endif +# endif inline _LIBCPP_HIDE_FROM_ABI size_t __strftime(char* __s, size_t __max, const char* __format, const tm* __tm, __locale_t __loc) { @@ -259,7 +257,7 @@ __strftime(char* __s, size_t __max, const char* __format, const tm* __tm, __loca inline _LIBCPP_HIDE_FROM_ABI decltype(__libcpp_mb_cur_max_l(__locale_t())) __mb_len_max(__locale_t __loc) { return __libcpp_mb_cur_max_l(__loc); } -# if _LIBCPP_HAS_WIDE_CHARACTERS +# if _LIBCPP_HAS_WIDE_CHARACTERS inline _LIBCPP_HIDE_FROM_ABI wint_t __btowc(int __ch, __locale_t __loc) { return __libcpp_btowc_l(__ch, __loc); } inline _LIBCPP_HIDE_FROM_ABI int __wctob(wint_t __ch, __locale_t __loc) { return __libcpp_wctob_l(__ch, __loc); } inline _LIBCPP_HIDE_FROM_ABI size_t @@ -287,17 +285,17 @@ inline _LIBCPP_HIDE_FROM_ABI size_t __mbsrtowcs(wchar_t* __dest, const char** __src, size_t __len, mbstate_t* __ps, __locale_t __loc) { return __libcpp_mbsrtowcs_l(__dest, __src, __len, __ps, __loc); } -# endif // _LIBCPP_HAS_WIDE_CHARACTERS -# endif // _LIBCPP_BUILDING_LIBRARY +# endif // _LIBCPP_HAS_WIDE_CHARACTERS +# endif // _LIBCPP_BUILDING_LIBRARY _LIBCPP_DIAGNOSTIC_PUSH _LIBCPP_CLANG_DIAGNOSTIC_IGNORED("-Wgcc-compat") _LIBCPP_GCC_DIAGNOSTIC_IGNORED("-Wformat-nonliteral") // GCC doesn't support [[gnu::format]] on variadic templates -# ifdef _LIBCPP_COMPILER_CLANG_BASED -# define _LIBCPP_VARIADIC_ATTRIBUTE_FORMAT(...) _LIBCPP_ATTRIBUTE_FORMAT(__VA_ARGS__) -# else -# define _LIBCPP_VARIADIC_ATTRIBUTE_FORMAT(...) /* nothing */ -# endif +# ifdef _LIBCPP_COMPILER_CLANG_BASED +# define _LIBCPP_VARIADIC_ATTRIBUTE_FORMAT(...) _LIBCPP_ATTRIBUTE_FORMAT(__VA_ARGS__) +# else +# define _LIBCPP_VARIADIC_ATTRIBUTE_FORMAT(...) /* nothing */ +# endif template _LIBCPP_HIDE_FROM_ABI _LIBCPP_VARIADIC_ATTRIBUTE_FORMAT(__printf__, 4, 5) int __snprintf( @@ -315,11 +313,13 @@ _LIBCPP_HIDE_FROM_ABI _LIBCPP_VARIADIC_ATTRIBUTE_FORMAT(__scanf__, 3, 4) int __s return std::__libcpp_sscanf_l(__s, __loc, __format, std::forward<_Args>(__args)...); } _LIBCPP_DIAGNOSTIC_POP -# undef _LIBCPP_VARIADIC_ATTRIBUTE_FORMAT +# undef _LIBCPP_VARIADIC_ATTRIBUTE_FORMAT } // namespace __locale _LIBCPP_END_NAMESPACE_STD -#endif // Compatibility definition of locale base APIs +# endif // Compatibility definition of locale base APIs + +#endif // _LIBCPP_HAS_LOCALIZATION #endif // _LIBCPP___LOCALE_DIR_LOCALE_BASE_API_H diff --git a/lib/libcxx/include/__locale_dir/messages.h b/lib/libcxx/include/__locale_dir/messages.h new file mode 100644 index 0000000000..c04bf04025 --- /dev/null +++ b/lib/libcxx/include/__locale_dir/messages.h @@ -0,0 +1,143 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___LOCALE_DIR_MESSAGES_H +#define _LIBCPP___LOCALE_DIR_MESSAGES_H + +#include <__config> +#include <__iterator/back_insert_iterator.h> +#include <__locale> +#include + +#if _LIBCPP_HAS_LOCALIZATION + +# if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +# endif + +# if defined(__unix__) || (defined(__APPLE__) && defined(__MACH__)) +// Most unix variants have catopen. These are the specific ones that don't. +# if !defined(__BIONIC__) && !defined(_NEWLIB_VERSION) && !defined(__EMSCRIPTEN__) +# define _LIBCPP_HAS_CATOPEN 1 +# include +# else +# define _LIBCPP_HAS_CATOPEN 0 +# endif +# else +# define _LIBCPP_HAS_CATOPEN 0 +# endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +class _LIBCPP_EXPORTED_FROM_ABI messages_base { +public: + typedef intptr_t catalog; + + _LIBCPP_HIDE_FROM_ABI messages_base() {} +}; + +template +class messages : public locale::facet, public messages_base { +public: + typedef _CharT char_type; + typedef basic_string<_CharT> string_type; + + _LIBCPP_HIDE_FROM_ABI explicit messages(size_t __refs = 0) : locale::facet(__refs) {} + + _LIBCPP_HIDE_FROM_ABI catalog open(const basic_string& __nm, const locale& __loc) const { + return do_open(__nm, __loc); + } + + _LIBCPP_HIDE_FROM_ABI string_type get(catalog __c, int __set, int __msgid, const string_type& __dflt) const { + return do_get(__c, __set, __msgid, __dflt); + } + + _LIBCPP_HIDE_FROM_ABI void close(catalog __c) const { do_close(__c); } + + static locale::id id; + +protected: + _LIBCPP_HIDE_FROM_ABI_VIRTUAL ~messages() override {} + + virtual catalog do_open(const basic_string&, const locale&) const; + virtual string_type do_get(catalog, int __set, int __msgid, const string_type& __dflt) const; + virtual void do_close(catalog) const; +}; + +template +locale::id messages<_CharT>::id; + +template +typename messages<_CharT>::catalog messages<_CharT>::do_open(const basic_string& __nm, const locale&) const { +# if _LIBCPP_HAS_CATOPEN + return (catalog)catopen(__nm.c_str(), NL_CAT_LOCALE); +# else // !_LIBCPP_HAS_CATOPEN + (void)__nm; + return -1; +# endif // _LIBCPP_HAS_CATOPEN +} + +template +typename messages<_CharT>::string_type +messages<_CharT>::do_get(catalog __c, int __set, int __msgid, const string_type& __dflt) const { +# if _LIBCPP_HAS_CATOPEN + string __ndflt; + __narrow_to_utf8()( + std::back_inserter(__ndflt), __dflt.c_str(), __dflt.c_str() + __dflt.size()); + nl_catd __cat = (nl_catd)__c; + static_assert(sizeof(catalog) >= sizeof(nl_catd), "Unexpected nl_catd type"); + char* __n = catgets(__cat, __set, __msgid, __ndflt.c_str()); + string_type __w; + __widen_from_utf8()(std::back_inserter(__w), __n, __n + std::strlen(__n)); + return __w; +# else // !_LIBCPP_HAS_CATOPEN + (void)__c; + (void)__set; + (void)__msgid; + return __dflt; +# endif // _LIBCPP_HAS_CATOPEN +} + +template +void messages<_CharT>::do_close(catalog __c) const { +# if _LIBCPP_HAS_CATOPEN + catclose((nl_catd)__c); +# else // !_LIBCPP_HAS_CATOPEN + (void)__c; +# endif // _LIBCPP_HAS_CATOPEN +} + +extern template class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS messages; +# if _LIBCPP_HAS_WIDE_CHARACTERS +extern template class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS messages; +# endif + +template +class messages_byname : public messages<_CharT> { +public: + typedef messages_base::catalog catalog; + typedef basic_string<_CharT> string_type; + + _LIBCPP_HIDE_FROM_ABI explicit messages_byname(const char*, size_t __refs = 0) : messages<_CharT>(__refs) {} + + _LIBCPP_HIDE_FROM_ABI explicit messages_byname(const string&, size_t __refs = 0) : messages<_CharT>(__refs) {} + +protected: + _LIBCPP_HIDE_FROM_ABI_VIRTUAL ~messages_byname() override {} +}; + +extern template class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS messages_byname; +# if _LIBCPP_HAS_WIDE_CHARACTERS +extern template class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS messages_byname; +# endif + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP_HAS_LOCALIZATION + +#endif // _LIBCPP___LOCALE_DIR_MESSAGES_H diff --git a/lib/libcxx/include/__locale_dir/money.h b/lib/libcxx/include/__locale_dir/money.h new file mode 100644 index 0000000000..c129666550 --- /dev/null +++ b/lib/libcxx/include/__locale_dir/money.h @@ -0,0 +1,873 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___LOCALE_DIR_MONEY_H +#define _LIBCPP___LOCALE_DIR_MONEY_H + +#include <__algorithm/copy.h> +#include <__algorithm/equal.h> +#include <__algorithm/find.h> +#include <__algorithm/reverse.h> +#include <__config> +#include <__locale> +#include <__locale_dir/check_grouping.h> +#include <__locale_dir/get_c_locale.h> +#include <__locale_dir/pad_and_output.h> +#include <__memory/unique_ptr.h> +#include +#include + +#if _LIBCPP_HAS_LOCALIZATION + +# if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +# endif + +_LIBCPP_PUSH_MACROS +# include <__undef_macros> + +_LIBCPP_BEGIN_NAMESPACE_STD + +// money_base + +class _LIBCPP_EXPORTED_FROM_ABI money_base { +public: + enum part { none, space, symbol, sign, value }; + struct pattern { + char field[4]; + }; + + _LIBCPP_HIDE_FROM_ABI money_base() {} +}; + +// moneypunct + +template +class moneypunct : public locale::facet, public money_base { +public: + typedef _CharT char_type; + typedef basic_string string_type; + + _LIBCPP_HIDE_FROM_ABI explicit moneypunct(size_t __refs = 0) : locale::facet(__refs) {} + + _LIBCPP_HIDE_FROM_ABI char_type decimal_point() const { return do_decimal_point(); } + _LIBCPP_HIDE_FROM_ABI char_type thousands_sep() const { return do_thousands_sep(); } + _LIBCPP_HIDE_FROM_ABI string grouping() const { return do_grouping(); } + _LIBCPP_HIDE_FROM_ABI string_type curr_symbol() const { return do_curr_symbol(); } + _LIBCPP_HIDE_FROM_ABI string_type positive_sign() const { return do_positive_sign(); } + _LIBCPP_HIDE_FROM_ABI string_type negative_sign() const { return do_negative_sign(); } + _LIBCPP_HIDE_FROM_ABI int frac_digits() const { return do_frac_digits(); } + _LIBCPP_HIDE_FROM_ABI pattern pos_format() const { return do_pos_format(); } + _LIBCPP_HIDE_FROM_ABI pattern neg_format() const { return do_neg_format(); } + + static locale::id id; + static const bool intl = _International; + +protected: + _LIBCPP_HIDE_FROM_ABI_VIRTUAL ~moneypunct() override {} + + virtual char_type do_decimal_point() const { return numeric_limits::max(); } + virtual char_type do_thousands_sep() const { return numeric_limits::max(); } + virtual string do_grouping() const { return string(); } + virtual string_type do_curr_symbol() const { return string_type(); } + virtual string_type do_positive_sign() const { return string_type(); } + virtual string_type do_negative_sign() const { return string_type(1, '-'); } + virtual int do_frac_digits() const { return 0; } + virtual pattern do_pos_format() const { + pattern __p = {{symbol, sign, none, value}}; + return __p; + } + virtual pattern do_neg_format() const { + pattern __p = {{symbol, sign, none, value}}; + return __p; + } +}; + +template +locale::id moneypunct<_CharT, _International>::id; + +template +const bool moneypunct<_CharT, _International>::intl; + +extern template class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS moneypunct; +extern template class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS moneypunct; +# if _LIBCPP_HAS_WIDE_CHARACTERS +extern template class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS moneypunct; +extern template class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS moneypunct; +# endif + +// moneypunct_byname + +template +class moneypunct_byname : public moneypunct<_CharT, _International> { +public: + typedef money_base::pattern pattern; + typedef _CharT char_type; + typedef basic_string string_type; + + _LIBCPP_HIDE_FROM_ABI explicit moneypunct_byname(const char* __nm, size_t __refs = 0) + : moneypunct<_CharT, _International>(__refs) { + init(__nm); + } + + _LIBCPP_HIDE_FROM_ABI explicit moneypunct_byname(const string& __nm, size_t __refs = 0) + : moneypunct<_CharT, _International>(__refs) { + init(__nm.c_str()); + } + +protected: + _LIBCPP_HIDE_FROM_ABI_VIRTUAL ~moneypunct_byname() override {} + + char_type do_decimal_point() const override { return __decimal_point_; } + char_type do_thousands_sep() const override { return __thousands_sep_; } + string do_grouping() const override { return __grouping_; } + string_type do_curr_symbol() const override { return __curr_symbol_; } + string_type do_positive_sign() const override { return __positive_sign_; } + string_type do_negative_sign() const override { return __negative_sign_; } + int do_frac_digits() const override { return __frac_digits_; } + pattern do_pos_format() const override { return __pos_format_; } + pattern do_neg_format() const override { return __neg_format_; } + +private: + char_type __decimal_point_; + char_type __thousands_sep_; + string __grouping_; + string_type __curr_symbol_; + string_type __positive_sign_; + string_type __negative_sign_; + int __frac_digits_; + pattern __pos_format_; + pattern __neg_format_; + + void init(const char*); +}; + +template <> +_LIBCPP_EXPORTED_FROM_ABI void moneypunct_byname::init(const char*); +template <> +_LIBCPP_EXPORTED_FROM_ABI void moneypunct_byname::init(const char*); +extern template class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS moneypunct_byname; +extern template class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS moneypunct_byname; + +# if _LIBCPP_HAS_WIDE_CHARACTERS +template <> +_LIBCPP_EXPORTED_FROM_ABI void moneypunct_byname::init(const char*); +template <> +_LIBCPP_EXPORTED_FROM_ABI void moneypunct_byname::init(const char*); +extern template class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS moneypunct_byname; +extern template class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS moneypunct_byname; +# endif + +// money_get + +template +class __money_get { +protected: + typedef _CharT char_type; + typedef basic_string string_type; + + _LIBCPP_HIDE_FROM_ABI __money_get() {} + + static void __gather_info( + bool __intl, + const locale& __loc, + money_base::pattern& __pat, + char_type& __dp, + char_type& __ts, + string& __grp, + string_type& __sym, + string_type& __psn, + string_type& __nsn, + int& __fd); +}; + +template +void __money_get<_CharT>::__gather_info( + bool __intl, + const locale& __loc, + money_base::pattern& __pat, + char_type& __dp, + char_type& __ts, + string& __grp, + string_type& __sym, + string_type& __psn, + string_type& __nsn, + int& __fd) { + if (__intl) { + const moneypunct& __mp = std::use_facet >(__loc); + __pat = __mp.neg_format(); + __nsn = __mp.negative_sign(); + __psn = __mp.positive_sign(); + __dp = __mp.decimal_point(); + __ts = __mp.thousands_sep(); + __grp = __mp.grouping(); + __sym = __mp.curr_symbol(); + __fd = __mp.frac_digits(); + } else { + const moneypunct& __mp = std::use_facet >(__loc); + __pat = __mp.neg_format(); + __nsn = __mp.negative_sign(); + __psn = __mp.positive_sign(); + __dp = __mp.decimal_point(); + __ts = __mp.thousands_sep(); + __grp = __mp.grouping(); + __sym = __mp.curr_symbol(); + __fd = __mp.frac_digits(); + } +} + +extern template class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS __money_get; +# if _LIBCPP_HAS_WIDE_CHARACTERS +extern template class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS __money_get; +# endif + +template > +class money_get : public locale::facet, private __money_get<_CharT> { +public: + typedef _CharT char_type; + typedef _InputIterator iter_type; + typedef basic_string string_type; + + _LIBCPP_HIDE_FROM_ABI explicit money_get(size_t __refs = 0) : locale::facet(__refs) {} + + _LIBCPP_HIDE_FROM_ABI iter_type + get(iter_type __b, iter_type __e, bool __intl, ios_base& __iob, ios_base::iostate& __err, long double& __v) const { + return do_get(__b, __e, __intl, __iob, __err, __v); + } + + _LIBCPP_HIDE_FROM_ABI iter_type + get(iter_type __b, iter_type __e, bool __intl, ios_base& __iob, ios_base::iostate& __err, string_type& __v) const { + return do_get(__b, __e, __intl, __iob, __err, __v); + } + + static locale::id id; + +protected: + _LIBCPP_HIDE_FROM_ABI_VIRTUAL ~money_get() override {} + + virtual iter_type + do_get(iter_type __b, iter_type __e, bool __intl, ios_base& __iob, ios_base::iostate& __err, long double& __v) const; + virtual iter_type + do_get(iter_type __b, iter_type __e, bool __intl, ios_base& __iob, ios_base::iostate& __err, string_type& __v) const; + +private: + static bool __do_get( + iter_type& __b, + iter_type __e, + bool __intl, + const locale& __loc, + ios_base::fmtflags __flags, + ios_base::iostate& __err, + bool& __neg, + const ctype& __ct, + unique_ptr& __wb, + char_type*& __wn, + char_type* __we); +}; + +template +locale::id money_get<_CharT, _InputIterator>::id; + +_LIBCPP_EXPORTED_FROM_ABI void __do_nothing(void*); + +template +_LIBCPP_HIDE_FROM_ABI void __double_or_nothing(unique_ptr<_Tp, void (*)(void*)>& __b, _Tp*& __n, _Tp*& __e) { + bool __owns = __b.get_deleter() != __do_nothing; + size_t __cur_cap = static_cast(__e - __b.get()) * sizeof(_Tp); + size_t __new_cap = __cur_cap < numeric_limits::max() / 2 ? 2 * __cur_cap : numeric_limits::max(); + if (__new_cap == 0) + __new_cap = sizeof(_Tp); + size_t __n_off = static_cast(__n - __b.get()); + _Tp* __t = (_Tp*)std::realloc(__owns ? __b.get() : 0, __new_cap); + if (__t == 0) + std::__throw_bad_alloc(); + if (__owns) + __b.release(); + else + std::memcpy(__t, __b.get(), __cur_cap); + __b = unique_ptr<_Tp, void (*)(void*)>(__t, free); + __new_cap /= sizeof(_Tp); + __n = __b.get() + __n_off; + __e = __b.get() + __new_cap; +} + +// true == success +template +bool money_get<_CharT, _InputIterator>::__do_get( + iter_type& __b, + iter_type __e, + bool __intl, + const locale& __loc, + ios_base::fmtflags __flags, + ios_base::iostate& __err, + bool& __neg, + const ctype& __ct, + unique_ptr& __wb, + char_type*& __wn, + char_type* __we) { + if (__b == __e) { + __err |= ios_base::failbit; + return false; + } + const unsigned __bz = 100; + unsigned __gbuf[__bz]; + unique_ptr __gb(__gbuf, __do_nothing); + unsigned* __gn = __gb.get(); + unsigned* __ge = __gn + __bz; + money_base::pattern __pat; + char_type __dp; + char_type __ts; + string __grp; + string_type __sym; + string_type __psn; + string_type __nsn; + // Capture the spaces read into money_base::{space,none} so they + // can be compared to initial spaces in __sym. + string_type __spaces; + int __fd; + __money_get<_CharT>::__gather_info(__intl, __loc, __pat, __dp, __ts, __grp, __sym, __psn, __nsn, __fd); + const string_type* __trailing_sign = 0; + __wn = __wb.get(); + for (unsigned __p = 0; __p < 4 && __b != __e; ++__p) { + switch (__pat.field[__p]) { + case money_base::space: + if (__p != 3) { + if (__ct.is(ctype_base::space, *__b)) + __spaces.push_back(*__b++); + else { + __err |= ios_base::failbit; + return false; + } + } + [[__fallthrough__]]; + case money_base::none: + if (__p != 3) { + while (__b != __e && __ct.is(ctype_base::space, *__b)) + __spaces.push_back(*__b++); + } + break; + case money_base::sign: + if (__psn.size() > 0 && *__b == __psn[0]) { + ++__b; + __neg = false; + if (__psn.size() > 1) + __trailing_sign = std::addressof(__psn); + break; + } + if (__nsn.size() > 0 && *__b == __nsn[0]) { + ++__b; + __neg = true; + if (__nsn.size() > 1) + __trailing_sign = std::addressof(__nsn); + break; + } + if (__psn.size() > 0 && __nsn.size() > 0) { // sign is required + __err |= ios_base::failbit; + return false; + } + if (__psn.size() == 0 && __nsn.size() == 0) + // locale has no way of specifying a sign. Use the initial value of __neg as a default + break; + __neg = (__nsn.size() == 0); + break; + case money_base::symbol: { + bool __more_needed = + __trailing_sign || (__p < 2) || (__p == 2 && __pat.field[3] != static_cast(money_base::none)); + bool __sb = (__flags & ios_base::showbase) != 0; + if (__sb || __more_needed) { + typename string_type::const_iterator __sym_space_end = __sym.begin(); + if (__p > 0 && (__pat.field[__p - 1] == money_base::none || __pat.field[__p - 1] == money_base::space)) { + // Match spaces we've already read against spaces at + // the beginning of __sym. + while (__sym_space_end != __sym.end() && __ct.is(ctype_base::space, *__sym_space_end)) + ++__sym_space_end; + const size_t __num_spaces = __sym_space_end - __sym.begin(); + if (__num_spaces > __spaces.size() || + !std::equal(__spaces.end() - __num_spaces, __spaces.end(), __sym.begin())) { + // No match. Put __sym_space_end back at the + // beginning of __sym, which will prevent a + // match in the next loop. + __sym_space_end = __sym.begin(); + } + } + typename string_type::const_iterator __sym_curr_char = __sym_space_end; + while (__sym_curr_char != __sym.end() && __b != __e && *__b == *__sym_curr_char) { + ++__b; + ++__sym_curr_char; + } + if (__sb && __sym_curr_char != __sym.end()) { + __err |= ios_base::failbit; + return false; + } + } + } break; + case money_base::value: { + unsigned __ng = 0; + for (; __b != __e; ++__b) { + char_type __c = *__b; + if (__ct.is(ctype_base::digit, __c)) { + if (__wn == __we) + std::__double_or_nothing(__wb, __wn, __we); + *__wn++ = __c; + ++__ng; + } else if (__grp.size() > 0 && __ng > 0 && __c == __ts) { + if (__gn == __ge) + std::__double_or_nothing(__gb, __gn, __ge); + *__gn++ = __ng; + __ng = 0; + } else + break; + } + if (__gb.get() != __gn && __ng > 0) { + if (__gn == __ge) + std::__double_or_nothing(__gb, __gn, __ge); + *__gn++ = __ng; + } + if (__fd > 0) { + if (__b == __e || *__b != __dp) { + __err |= ios_base::failbit; + return false; + } + for (++__b; __fd > 0; --__fd, ++__b) { + if (__b == __e || !__ct.is(ctype_base::digit, *__b)) { + __err |= ios_base::failbit; + return false; + } + if (__wn == __we) + std::__double_or_nothing(__wb, __wn, __we); + *__wn++ = *__b; + } + } + if (__wn == __wb.get()) { + __err |= ios_base::failbit; + return false; + } + } break; + } + } + if (__trailing_sign) { + for (unsigned __i = 1; __i < __trailing_sign->size(); ++__i, ++__b) { + if (__b == __e || *__b != (*__trailing_sign)[__i]) { + __err |= ios_base::failbit; + return false; + } + } + } + if (__gb.get() != __gn) { + ios_base::iostate __et = ios_base::goodbit; + __check_grouping(__grp, __gb.get(), __gn, __et); + if (__et) { + __err |= ios_base::failbit; + return false; + } + } + return true; +} + +template +_InputIterator money_get<_CharT, _InputIterator>::do_get( + iter_type __b, iter_type __e, bool __intl, ios_base& __iob, ios_base::iostate& __err, long double& __v) const { + const int __bz = 100; + char_type __wbuf[__bz]; + unique_ptr __wb(__wbuf, __do_nothing); + char_type* __wn; + char_type* __we = __wbuf + __bz; + locale __loc = __iob.getloc(); + const ctype& __ct = std::use_facet >(__loc); + bool __neg = false; + if (__do_get(__b, __e, __intl, __loc, __iob.flags(), __err, __neg, __ct, __wb, __wn, __we)) { + const char __src[] = "0123456789"; + char_type __atoms[sizeof(__src) - 1]; + __ct.widen(__src, __src + (sizeof(__src) - 1), __atoms); + char __nbuf[__bz]; + char* __nc = __nbuf; + const char* __nc_in = __nc; + unique_ptr __h(nullptr, free); + if (__wn - __wb.get() > __bz - 2) { + __h.reset((char*)malloc(static_cast(__wn - __wb.get() + 2))); + if (__h.get() == nullptr) + std::__throw_bad_alloc(); + __nc = __h.get(); + __nc_in = __nc; + } + if (__neg) + *__nc++ = '-'; + for (const char_type* __w = __wb.get(); __w < __wn; ++__w, ++__nc) + *__nc = __src[std::find(__atoms, std::end(__atoms), *__w) - __atoms]; + *__nc = char(); + if (sscanf(__nc_in, "%Lf", &__v) != 1) + std::__throw_runtime_error("money_get error"); + } + if (__b == __e) + __err |= ios_base::eofbit; + return __b; +} + +template +_InputIterator money_get<_CharT, _InputIterator>::do_get( + iter_type __b, iter_type __e, bool __intl, ios_base& __iob, ios_base::iostate& __err, string_type& __v) const { + const int __bz = 100; + char_type __wbuf[__bz]; + unique_ptr __wb(__wbuf, __do_nothing); + char_type* __wn; + char_type* __we = __wbuf + __bz; + locale __loc = __iob.getloc(); + const ctype& __ct = std::use_facet >(__loc); + bool __neg = false; + if (__do_get(__b, __e, __intl, __loc, __iob.flags(), __err, __neg, __ct, __wb, __wn, __we)) { + __v.clear(); + if (__neg) + __v.push_back(__ct.widen('-')); + char_type __z = __ct.widen('0'); + char_type* __w; + for (__w = __wb.get(); __w < __wn - 1; ++__w) + if (*__w != __z) + break; + __v.append(__w, __wn); + } + if (__b == __e) + __err |= ios_base::eofbit; + return __b; +} + +extern template class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS money_get; +# if _LIBCPP_HAS_WIDE_CHARACTERS +extern template class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS money_get; +# endif + +// money_put + +template +class __money_put { +protected: + typedef _CharT char_type; + typedef basic_string string_type; + + _LIBCPP_HIDE_FROM_ABI __money_put() {} + + static void __gather_info( + bool __intl, + bool __neg, + const locale& __loc, + money_base::pattern& __pat, + char_type& __dp, + char_type& __ts, + string& __grp, + string_type& __sym, + string_type& __sn, + int& __fd); + static void __format( + char_type* __mb, + char_type*& __mi, + char_type*& __me, + ios_base::fmtflags __flags, + const char_type* __db, + const char_type* __de, + const ctype& __ct, + bool __neg, + const money_base::pattern& __pat, + char_type __dp, + char_type __ts, + const string& __grp, + const string_type& __sym, + const string_type& __sn, + int __fd); +}; + +template +void __money_put<_CharT>::__gather_info( + bool __intl, + bool __neg, + const locale& __loc, + money_base::pattern& __pat, + char_type& __dp, + char_type& __ts, + string& __grp, + string_type& __sym, + string_type& __sn, + int& __fd) { + if (__intl) { + const moneypunct& __mp = std::use_facet >(__loc); + if (__neg) { + __pat = __mp.neg_format(); + __sn = __mp.negative_sign(); + } else { + __pat = __mp.pos_format(); + __sn = __mp.positive_sign(); + } + __dp = __mp.decimal_point(); + __ts = __mp.thousands_sep(); + __grp = __mp.grouping(); + __sym = __mp.curr_symbol(); + __fd = __mp.frac_digits(); + } else { + const moneypunct& __mp = std::use_facet >(__loc); + if (__neg) { + __pat = __mp.neg_format(); + __sn = __mp.negative_sign(); + } else { + __pat = __mp.pos_format(); + __sn = __mp.positive_sign(); + } + __dp = __mp.decimal_point(); + __ts = __mp.thousands_sep(); + __grp = __mp.grouping(); + __sym = __mp.curr_symbol(); + __fd = __mp.frac_digits(); + } +} + +template +void __money_put<_CharT>::__format( + char_type* __mb, + char_type*& __mi, + char_type*& __me, + ios_base::fmtflags __flags, + const char_type* __db, + const char_type* __de, + const ctype& __ct, + bool __neg, + const money_base::pattern& __pat, + char_type __dp, + char_type __ts, + const string& __grp, + const string_type& __sym, + const string_type& __sn, + int __fd) { + __me = __mb; + for (char __p : __pat.field) { + switch (__p) { + case money_base::none: + __mi = __me; + break; + case money_base::space: + __mi = __me; + *__me++ = __ct.widen(' '); + break; + case money_base::sign: + if (!__sn.empty()) + *__me++ = __sn[0]; + break; + case money_base::symbol: + if (!__sym.empty() && (__flags & ios_base::showbase)) + __me = std::copy(__sym.begin(), __sym.end(), __me); + break; + case money_base::value: { + // remember start of value so we can reverse it + char_type* __t = __me; + // find beginning of digits + if (__neg) + ++__db; + // find end of digits + const char_type* __d; + for (__d = __db; __d < __de; ++__d) + if (!__ct.is(ctype_base::digit, *__d)) + break; + // print fractional part + if (__fd > 0) { + int __f; + for (__f = __fd; __d > __db && __f > 0; --__f) + *__me++ = *--__d; + char_type __z = __f > 0 ? __ct.widen('0') : char_type(); + for (; __f > 0; --__f) + *__me++ = __z; + *__me++ = __dp; + } + // print units part + if (__d == __db) { + *__me++ = __ct.widen('0'); + } else { + unsigned __ng = 0; + unsigned __ig = 0; + unsigned __gl = __grp.empty() ? numeric_limits::max() : static_cast(__grp[__ig]); + while (__d != __db) { + if (__ng == __gl) { + *__me++ = __ts; + __ng = 0; + if (++__ig < __grp.size()) + __gl = __grp[__ig] == numeric_limits::max() + ? numeric_limits::max() + : static_cast(__grp[__ig]); + } + *__me++ = *--__d; + ++__ng; + } + } + // reverse it + std::reverse(__t, __me); + } break; + } + } + // print rest of sign, if any + if (__sn.size() > 1) + __me = std::copy(__sn.begin() + 1, __sn.end(), __me); + // set alignment + if ((__flags & ios_base::adjustfield) == ios_base::left) + __mi = __me; + else if ((__flags & ios_base::adjustfield) != ios_base::internal) + __mi = __mb; +} + +extern template class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS __money_put; +# if _LIBCPP_HAS_WIDE_CHARACTERS +extern template class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS __money_put; +# endif + +template > +class money_put : public locale::facet, private __money_put<_CharT> { +public: + typedef _CharT char_type; + typedef _OutputIterator iter_type; + typedef basic_string string_type; + + _LIBCPP_HIDE_FROM_ABI explicit money_put(size_t __refs = 0) : locale::facet(__refs) {} + + _LIBCPP_HIDE_FROM_ABI iter_type + put(iter_type __s, bool __intl, ios_base& __iob, char_type __fl, long double __units) const { + return do_put(__s, __intl, __iob, __fl, __units); + } + + _LIBCPP_HIDE_FROM_ABI iter_type + put(iter_type __s, bool __intl, ios_base& __iob, char_type __fl, const string_type& __digits) const { + return do_put(__s, __intl, __iob, __fl, __digits); + } + + static locale::id id; + +protected: + _LIBCPP_HIDE_FROM_ABI_VIRTUAL ~money_put() override {} + + virtual iter_type do_put(iter_type __s, bool __intl, ios_base& __iob, char_type __fl, long double __units) const; + virtual iter_type + do_put(iter_type __s, bool __intl, ios_base& __iob, char_type __fl, const string_type& __digits) const; +}; + +template +locale::id money_put<_CharT, _OutputIterator>::id; + +template +_OutputIterator money_put<_CharT, _OutputIterator>::do_put( + iter_type __s, bool __intl, ios_base& __iob, char_type __fl, long double __units) const { + // convert to char + const size_t __bs = 100; + char __buf[__bs]; + char* __bb = __buf; + char_type __digits[__bs]; + char_type* __db = __digits; + int __n = snprintf(__bb, __bs, "%.0Lf", __units); + unique_ptr __hn(nullptr, free); + unique_ptr __hd(0, free); + // secure memory for digit storage + if (static_cast(__n) > __bs - 1) { + __n = __locale::__asprintf(&__bb, _LIBCPP_GET_C_LOCALE, "%.0Lf", __units); + if (__n == -1) + std::__throw_bad_alloc(); + __hn.reset(__bb); + __hd.reset((char_type*)malloc(static_cast(__n) * sizeof(char_type))); + if (__hd == nullptr) + std::__throw_bad_alloc(); + __db = __hd.get(); + } + // gather info + locale __loc = __iob.getloc(); + const ctype& __ct = std::use_facet >(__loc); + __ct.widen(__bb, __bb + __n, __db); + bool __neg = __n > 0 && __bb[0] == '-'; + money_base::pattern __pat; + char_type __dp; + char_type __ts; + string __grp; + string_type __sym; + string_type __sn; + int __fd; + this->__gather_info(__intl, __neg, __loc, __pat, __dp, __ts, __grp, __sym, __sn, __fd); + // secure memory for formatting + char_type __mbuf[__bs]; + char_type* __mb = __mbuf; + unique_ptr __hw(0, free); + size_t __exn = __n > __fd ? (static_cast(__n) - static_cast(__fd)) * 2 + __sn.size() + __sym.size() + + static_cast(__fd) + 1 + : __sn.size() + __sym.size() + static_cast(__fd) + 2; + if (__exn > __bs) { + __hw.reset((char_type*)malloc(__exn * sizeof(char_type))); + __mb = __hw.get(); + if (__mb == 0) + std::__throw_bad_alloc(); + } + // format + char_type* __mi; + char_type* __me; + this->__format( + __mb, __mi, __me, __iob.flags(), __db, __db + __n, __ct, __neg, __pat, __dp, __ts, __grp, __sym, __sn, __fd); + return std::__pad_and_output(__s, __mb, __mi, __me, __iob, __fl); +} + +template +_OutputIterator money_put<_CharT, _OutputIterator>::do_put( + iter_type __s, bool __intl, ios_base& __iob, char_type __fl, const string_type& __digits) const { + // gather info + locale __loc = __iob.getloc(); + const ctype& __ct = std::use_facet >(__loc); + bool __neg = __digits.size() > 0 && __digits[0] == __ct.widen('-'); + money_base::pattern __pat; + char_type __dp; + char_type __ts; + string __grp; + string_type __sym; + string_type __sn; + int __fd; + this->__gather_info(__intl, __neg, __loc, __pat, __dp, __ts, __grp, __sym, __sn, __fd); + // secure memory for formatting + char_type __mbuf[100]; + char_type* __mb = __mbuf; + unique_ptr __h(0, free); + size_t __exn = + static_cast(__digits.size()) > __fd + ? (__digits.size() - static_cast(__fd)) * 2 + __sn.size() + __sym.size() + static_cast(__fd) + + 1 + : __sn.size() + __sym.size() + static_cast(__fd) + 2; + if (__exn > 100) { + __h.reset((char_type*)malloc(__exn * sizeof(char_type))); + __mb = __h.get(); + if (__mb == 0) + std::__throw_bad_alloc(); + } + // format + char_type* __mi; + char_type* __me; + this->__format( + __mb, + __mi, + __me, + __iob.flags(), + __digits.data(), + __digits.data() + __digits.size(), + __ct, + __neg, + __pat, + __dp, + __ts, + __grp, + __sym, + __sn, + __fd); + return std::__pad_and_output(__s, __mb, __mi, __me, __iob, __fl); +} + +extern template class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS money_put; +# if _LIBCPP_HAS_WIDE_CHARACTERS +extern template class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS money_put; +# endif + +_LIBCPP_END_NAMESPACE_STD + +_LIBCPP_POP_MACROS + +#endif // _LIBCPP_HAS_LOCALIZATION + +#endif // _LIBCPP___LOCALE_DIR_MONEY_H diff --git a/lib/libcxx/include/__locale_dir/num.h b/lib/libcxx/include/__locale_dir/num.h new file mode 100644 index 0000000000..7ca8ffe348 --- /dev/null +++ b/lib/libcxx/include/__locale_dir/num.h @@ -0,0 +1,1072 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___LOCALE_DIR_NUM_H +#define _LIBCPP___LOCALE_DIR_NUM_H + +#include <__algorithm/find.h> +#include <__algorithm/reverse.h> +#include <__charconv/to_chars_integral.h> +#include <__charconv/traits.h> +#include <__config> +#include <__iterator/istreambuf_iterator.h> +#include <__iterator/ostreambuf_iterator.h> +#include <__locale_dir/check_grouping.h> +#include <__locale_dir/get_c_locale.h> +#include <__locale_dir/pad_and_output.h> +#include <__locale_dir/scan_keyword.h> +#include <__memory/unique_ptr.h> +#include <__system_error/errc.h> +#include +#include +#include + +#if _LIBCPP_HAS_LOCALIZATION + +# if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +# endif + +// TODO: Properly qualify calls now that the locale base API defines functions instead of macros +// NOLINTBEGIN(libcpp-robust-against-adl) + +_LIBCPP_PUSH_MACROS +# include <__undef_macros> + +_LIBCPP_BEGIN_NAMESPACE_STD + +struct _LIBCPP_EXPORTED_FROM_ABI __num_get_base { + static const int __num_get_buf_sz = 40; + + static int __get_base(ios_base&); + static const char __src[33]; // "0123456789abcdefABCDEFxX+-pPiInN" + // count of leading characters in __src used for parsing integers ("012..X+-") + static const size_t __int_chr_cnt = 26; + // count of leading characters in __src used for parsing floating-point values ("012..-pP") + static const size_t __fp_chr_cnt = 28; +}; + +template +struct __num_get : protected __num_get_base { + static string __stage2_float_prep(ios_base& __iob, _CharT* __atoms, _CharT& __decimal_point, _CharT& __thousands_sep); + + static int __stage2_float_loop( + _CharT __ct, + bool& __in_units, + char& __exp, + char* __a, + char*& __a_end, + _CharT __decimal_point, + _CharT __thousands_sep, + const string& __grouping, + unsigned* __g, + unsigned*& __g_end, + unsigned& __dc, + _CharT* __atoms); + + [[__deprecated__("This exists only for ABI compatibility")]] static string + __stage2_int_prep(ios_base& __iob, _CharT* __atoms, _CharT& __thousands_sep); + static int __stage2_int_loop( + _CharT __ct, + int __base, + char* __a, + char*& __a_end, + unsigned& __dc, + _CharT __thousands_sep, + const string& __grouping, + unsigned* __g, + unsigned*& __g_end, + _CharT* __atoms); + + _LIBCPP_HIDE_FROM_ABI static string __stage2_int_prep(ios_base& __iob, _CharT& __thousands_sep) { + locale __loc = __iob.getloc(); + const numpunct<_CharT>& __np = use_facet >(__loc); + __thousands_sep = __np.thousands_sep(); + return __np.grouping(); + } + + _LIBCPP_HIDE_FROM_ABI const _CharT* __do_widen(ios_base& __iob, _CharT* __atoms) const { + return __do_widen_p(__iob, __atoms); + } + +private: + template + _LIBCPP_HIDE_FROM_ABI const _Tp* __do_widen_p(ios_base& __iob, _Tp* __atoms) const { + locale __loc = __iob.getloc(); + use_facet >(__loc).widen(__src, __src + __int_chr_cnt, __atoms); + return __atoms; + } + + _LIBCPP_HIDE_FROM_ABI const char* __do_widen_p(ios_base& __iob, char* __atoms) const { + (void)__iob; + (void)__atoms; + return __src; + } +}; + +template +string __num_get<_CharT>::__stage2_float_prep( + ios_base& __iob, _CharT* __atoms, _CharT& __decimal_point, _CharT& __thousands_sep) { + locale __loc = __iob.getloc(); + std::use_facet >(__loc).widen(__src, __src + __fp_chr_cnt, __atoms); + const numpunct<_CharT>& __np = std::use_facet >(__loc); + __decimal_point = __np.decimal_point(); + __thousands_sep = __np.thousands_sep(); + return __np.grouping(); +} + +template +int __num_get<_CharT>::__stage2_int_loop( + _CharT __ct, + int __base, + char* __a, + char*& __a_end, + unsigned& __dc, + _CharT __thousands_sep, + const string& __grouping, + unsigned* __g, + unsigned*& __g_end, + _CharT* __atoms) { + if (__a_end == __a && (__ct == __atoms[24] || __ct == __atoms[25])) { + *__a_end++ = __ct == __atoms[24] ? '+' : '-'; + __dc = 0; + return 0; + } + if (__grouping.size() != 0 && __ct == __thousands_sep) { + if (__g_end - __g < __num_get_buf_sz) { + *__g_end++ = __dc; + __dc = 0; + } + return 0; + } + ptrdiff_t __f = std::find(__atoms, __atoms + __int_chr_cnt, __ct) - __atoms; + if (__f >= 24) + return -1; + switch (__base) { + case 8: + case 10: + if (__f >= __base) + return -1; + break; + case 16: + if (__f < 22) + break; + if (__a_end != __a && __a_end - __a <= 2 && __a_end[-1] == '0') { + __dc = 0; + *__a_end++ = __src[__f]; + return 0; + } + return -1; + } + *__a_end++ = __src[__f]; + ++__dc; + return 0; +} + +template +int __num_get<_CharT>::__stage2_float_loop( + _CharT __ct, + bool& __in_units, + char& __exp, + char* __a, + char*& __a_end, + _CharT __decimal_point, + _CharT __thousands_sep, + const string& __grouping, + unsigned* __g, + unsigned*& __g_end, + unsigned& __dc, + _CharT* __atoms) { + if (__ct == __decimal_point) { + if (!__in_units) + return -1; + __in_units = false; + *__a_end++ = '.'; + if (__grouping.size() != 0 && __g_end - __g < __num_get_buf_sz) + *__g_end++ = __dc; + return 0; + } + if (__ct == __thousands_sep && __grouping.size() != 0) { + if (!__in_units) + return -1; + if (__g_end - __g < __num_get_buf_sz) { + *__g_end++ = __dc; + __dc = 0; + } + return 0; + } + ptrdiff_t __f = std::find(__atoms, __atoms + __num_get_base::__fp_chr_cnt, __ct) - __atoms; + if (__f >= static_cast(__num_get_base::__fp_chr_cnt)) + return -1; + char __x = __src[__f]; + if (__x == '-' || __x == '+') { + if (__a_end == __a || (std::toupper(__a_end[-1]) == std::toupper(__exp))) { + *__a_end++ = __x; + return 0; + } + return -1; + } + if (__x == 'x' || __x == 'X') + __exp = 'P'; + else if (std::toupper(__x) == __exp) { + __exp = std::tolower(__exp); + if (__in_units) { + __in_units = false; + if (__grouping.size() != 0 && __g_end - __g < __num_get_buf_sz) + *__g_end++ = __dc; + } + } + *__a_end++ = __x; + if (__f >= 22) + return 0; + ++__dc; + return 0; +} + +extern template struct _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS __num_get; +# if _LIBCPP_HAS_WIDE_CHARACTERS +extern template struct _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS __num_get; +# endif + +template +_LIBCPP_HIDE_FROM_ABI _Tp __do_strtod(const char* __a, char** __p2); + +template <> +inline _LIBCPP_HIDE_FROM_ABI float __do_strtod(const char* __a, char** __p2) { + return __locale::__strtof(__a, __p2, _LIBCPP_GET_C_LOCALE); +} + +template <> +inline _LIBCPP_HIDE_FROM_ABI double __do_strtod(const char* __a, char** __p2) { + return __locale::__strtod(__a, __p2, _LIBCPP_GET_C_LOCALE); +} + +template <> +inline _LIBCPP_HIDE_FROM_ABI long double __do_strtod(const char* __a, char** __p2) { + return __locale::__strtold(__a, __p2, _LIBCPP_GET_C_LOCALE); +} + +template +_LIBCPP_HIDE_FROM_ABI _Tp __num_get_float(const char* __a, const char* __a_end, ios_base::iostate& __err) { + if (__a != __a_end) { + __libcpp_remove_reference_t __save_errno = errno; + errno = 0; + char* __p2; + _Tp __ld = std::__do_strtod<_Tp>(__a, &__p2); + __libcpp_remove_reference_t __current_errno = errno; + if (__current_errno == 0) + errno = __save_errno; + if (__p2 != __a_end) { + __err = ios_base::failbit; + return 0; + } else if (__current_errno == ERANGE) + __err = ios_base::failbit; + return __ld; + } + __err = ios_base::failbit; + return 0; +} + +template +_LIBCPP_HIDE_FROM_ABI _Tp +__num_get_signed_integral(const char* __a, const char* __a_end, ios_base::iostate& __err, int __base) { + if (__a != __a_end) { + __libcpp_remove_reference_t __save_errno = errno; + errno = 0; + char* __p2; + long long __ll = __locale::__strtoll(__a, &__p2, __base, _LIBCPP_GET_C_LOCALE); + __libcpp_remove_reference_t __current_errno = errno; + if (__current_errno == 0) + errno = __save_errno; + if (__p2 != __a_end) { + __err = ios_base::failbit; + return 0; + } else if (__current_errno == ERANGE || __ll < numeric_limits<_Tp>::min() || numeric_limits<_Tp>::max() < __ll) { + __err = ios_base::failbit; + if (__ll > 0) + return numeric_limits<_Tp>::max(); + else + return numeric_limits<_Tp>::min(); + } + return static_cast<_Tp>(__ll); + } + __err = ios_base::failbit; + return 0; +} + +template +_LIBCPP_HIDE_FROM_ABI _Tp +__num_get_unsigned_integral(const char* __a, const char* __a_end, ios_base::iostate& __err, int __base) { + if (__a != __a_end) { + const bool __negate = *__a == '-'; + if (__negate && ++__a == __a_end) { + __err = ios_base::failbit; + return 0; + } + __libcpp_remove_reference_t __save_errno = errno; + errno = 0; + char* __p2; + unsigned long long __ll = __locale::__strtoull(__a, &__p2, __base, _LIBCPP_GET_C_LOCALE); + __libcpp_remove_reference_t __current_errno = errno; + if (__current_errno == 0) + errno = __save_errno; + if (__p2 != __a_end) { + __err = ios_base::failbit; + return 0; + } else if (__current_errno == ERANGE || numeric_limits<_Tp>::max() < __ll) { + __err = ios_base::failbit; + return numeric_limits<_Tp>::max(); + } + _Tp __res = static_cast<_Tp>(__ll); + if (__negate) + __res = -__res; + return __res; + } + __err = ios_base::failbit; + return 0; +} + +template > +class num_get : public locale::facet, private __num_get<_CharT> { +public: + typedef _CharT char_type; + typedef _InputIterator iter_type; + + _LIBCPP_HIDE_FROM_ABI explicit num_get(size_t __refs = 0) : locale::facet(__refs) {} + + _LIBCPP_HIDE_FROM_ABI iter_type + get(iter_type __b, iter_type __e, ios_base& __iob, ios_base::iostate& __err, bool& __v) const { + return do_get(__b, __e, __iob, __err, __v); + } + + _LIBCPP_HIDE_FROM_ABI iter_type + get(iter_type __b, iter_type __e, ios_base& __iob, ios_base::iostate& __err, long& __v) const { + return do_get(__b, __e, __iob, __err, __v); + } + + _LIBCPP_HIDE_FROM_ABI iter_type + get(iter_type __b, iter_type __e, ios_base& __iob, ios_base::iostate& __err, long long& __v) const { + return do_get(__b, __e, __iob, __err, __v); + } + + _LIBCPP_HIDE_FROM_ABI iter_type + get(iter_type __b, iter_type __e, ios_base& __iob, ios_base::iostate& __err, unsigned short& __v) const { + return do_get(__b, __e, __iob, __err, __v); + } + + _LIBCPP_HIDE_FROM_ABI iter_type + get(iter_type __b, iter_type __e, ios_base& __iob, ios_base::iostate& __err, unsigned int& __v) const { + return do_get(__b, __e, __iob, __err, __v); + } + + _LIBCPP_HIDE_FROM_ABI iter_type + get(iter_type __b, iter_type __e, ios_base& __iob, ios_base::iostate& __err, unsigned long& __v) const { + return do_get(__b, __e, __iob, __err, __v); + } + + _LIBCPP_HIDE_FROM_ABI iter_type + get(iter_type __b, iter_type __e, ios_base& __iob, ios_base::iostate& __err, unsigned long long& __v) const { + return do_get(__b, __e, __iob, __err, __v); + } + + _LIBCPP_HIDE_FROM_ABI iter_type + get(iter_type __b, iter_type __e, ios_base& __iob, ios_base::iostate& __err, float& __v) const { + return do_get(__b, __e, __iob, __err, __v); + } + + _LIBCPP_HIDE_FROM_ABI iter_type + get(iter_type __b, iter_type __e, ios_base& __iob, ios_base::iostate& __err, double& __v) const { + return do_get(__b, __e, __iob, __err, __v); + } + + _LIBCPP_HIDE_FROM_ABI iter_type + get(iter_type __b, iter_type __e, ios_base& __iob, ios_base::iostate& __err, long double& __v) const { + return do_get(__b, __e, __iob, __err, __v); + } + + _LIBCPP_HIDE_FROM_ABI iter_type + get(iter_type __b, iter_type __e, ios_base& __iob, ios_base::iostate& __err, void*& __v) const { + return do_get(__b, __e, __iob, __err, __v); + } + + static locale::id id; + +protected: + _LIBCPP_HIDE_FROM_ABI_VIRTUAL ~num_get() override {} + + template + _LIBCPP_HIDE_FROM_ABI iter_type + __do_get_floating_point(iter_type __b, iter_type __e, ios_base& __iob, ios_base::iostate& __err, _Fp& __v) const { + // Stage 1, nothing to do + // Stage 2 + char_type __atoms[__num_get_base::__fp_chr_cnt]; + char_type __decimal_point; + char_type __thousands_sep; + string __grouping = this->__stage2_float_prep(__iob, __atoms, __decimal_point, __thousands_sep); + string __buf; + __buf.resize(__buf.capacity()); + char* __a = &__buf[0]; + char* __a_end = __a; + unsigned __g[__num_get_base::__num_get_buf_sz]; + unsigned* __g_end = __g; + unsigned __dc = 0; + bool __in_units = true; + char __exp = 'E'; + bool __is_leading_parsed = false; + for (; __b != __e; ++__b) { + if (__a_end == __a + __buf.size()) { + size_t __tmp = __buf.size(); + __buf.resize(2 * __buf.size()); + __buf.resize(__buf.capacity()); + __a = &__buf[0]; + __a_end = __a + __tmp; + } + if (this->__stage2_float_loop( + *__b, + __in_units, + __exp, + __a, + __a_end, + __decimal_point, + __thousands_sep, + __grouping, + __g, + __g_end, + __dc, + __atoms)) + break; + + // the leading character excluding the sign must be a decimal digit + if (!__is_leading_parsed) { + if (__a_end - __a >= 1 && __a[0] != '-' && __a[0] != '+') { + if (('0' <= __a[0] && __a[0] <= '9') || __a[0] == '.') + __is_leading_parsed = true; + else + break; + } else if (__a_end - __a >= 2 && (__a[0] == '-' || __a[0] == '+')) { + if (('0' <= __a[1] && __a[1] <= '9') || __a[1] == '.') + __is_leading_parsed = true; + else + break; + } + } + } + if (__grouping.size() != 0 && __in_units && __g_end - __g < __num_get_base::__num_get_buf_sz) + *__g_end++ = __dc; + // Stage 3 + __v = std::__num_get_float<_Fp>(__a, __a_end, __err); + // Digit grouping checked + __check_grouping(__grouping, __g, __g_end, __err); + // EOF checked + if (__b == __e) + __err |= ios_base::eofbit; + return __b; + } + + template + _LIBCPP_HIDE_FROM_ABI iter_type + __do_get_signed(iter_type __b, iter_type __e, ios_base& __iob, ios_base::iostate& __err, _Signed& __v) const { + // Stage 1 + int __base = this->__get_base(__iob); + // Stage 2 + char_type __thousands_sep; + const int __atoms_size = __num_get_base::__int_chr_cnt; + char_type __atoms1[__atoms_size]; + const char_type* __atoms = this->__do_widen(__iob, __atoms1); + string __grouping = this->__stage2_int_prep(__iob, __thousands_sep); + string __buf; + __buf.resize(__buf.capacity()); + char* __a = &__buf[0]; + char* __a_end = __a; + unsigned __g[__num_get_base::__num_get_buf_sz]; + unsigned* __g_end = __g; + unsigned __dc = 0; + for (; __b != __e; ++__b) { + if (__a_end == __a + __buf.size()) { + size_t __tmp = __buf.size(); + __buf.resize(2 * __buf.size()); + __buf.resize(__buf.capacity()); + __a = &__buf[0]; + __a_end = __a + __tmp; + } + if (this->__stage2_int_loop( + *__b, + __base, + __a, + __a_end, + __dc, + __thousands_sep, + __grouping, + __g, + __g_end, + const_cast(__atoms))) + break; + } + if (__grouping.size() != 0 && __g_end - __g < __num_get_base::__num_get_buf_sz) + *__g_end++ = __dc; + // Stage 3 + __v = std::__num_get_signed_integral<_Signed>(__a, __a_end, __err, __base); + // Digit grouping checked + __check_grouping(__grouping, __g, __g_end, __err); + // EOF checked + if (__b == __e) + __err |= ios_base::eofbit; + return __b; + } + + template + _LIBCPP_HIDE_FROM_ABI iter_type + __do_get_unsigned(iter_type __b, iter_type __e, ios_base& __iob, ios_base::iostate& __err, _Unsigned& __v) const { + // Stage 1 + int __base = this->__get_base(__iob); + // Stage 2 + char_type __thousands_sep; + const int __atoms_size = __num_get_base::__int_chr_cnt; + char_type __atoms1[__atoms_size]; + const char_type* __atoms = this->__do_widen(__iob, __atoms1); + string __grouping = this->__stage2_int_prep(__iob, __thousands_sep); + string __buf; + __buf.resize(__buf.capacity()); + char* __a = &__buf[0]; + char* __a_end = __a; + unsigned __g[__num_get_base::__num_get_buf_sz]; + unsigned* __g_end = __g; + unsigned __dc = 0; + for (; __b != __e; ++__b) { + if (__a_end == __a + __buf.size()) { + size_t __tmp = __buf.size(); + __buf.resize(2 * __buf.size()); + __buf.resize(__buf.capacity()); + __a = &__buf[0]; + __a_end = __a + __tmp; + } + if (this->__stage2_int_loop( + *__b, + __base, + __a, + __a_end, + __dc, + __thousands_sep, + __grouping, + __g, + __g_end, + const_cast(__atoms))) + break; + } + if (__grouping.size() != 0 && __g_end - __g < __num_get_base::__num_get_buf_sz) + *__g_end++ = __dc; + // Stage 3 + __v = std::__num_get_unsigned_integral<_Unsigned>(__a, __a_end, __err, __base); + // Digit grouping checked + __check_grouping(__grouping, __g, __g_end, __err); + // EOF checked + if (__b == __e) + __err |= ios_base::eofbit; + return __b; + } + + virtual iter_type do_get(iter_type __b, iter_type __e, ios_base& __iob, ios_base::iostate& __err, bool& __v) const; + + virtual iter_type do_get(iter_type __b, iter_type __e, ios_base& __iob, ios_base::iostate& __err, long& __v) const { + return this->__do_get_signed(__b, __e, __iob, __err, __v); + } + + virtual iter_type + do_get(iter_type __b, iter_type __e, ios_base& __iob, ios_base::iostate& __err, long long& __v) const { + return this->__do_get_signed(__b, __e, __iob, __err, __v); + } + + virtual iter_type + do_get(iter_type __b, iter_type __e, ios_base& __iob, ios_base::iostate& __err, unsigned short& __v) const { + return this->__do_get_unsigned(__b, __e, __iob, __err, __v); + } + + virtual iter_type + do_get(iter_type __b, iter_type __e, ios_base& __iob, ios_base::iostate& __err, unsigned int& __v) const { + return this->__do_get_unsigned(__b, __e, __iob, __err, __v); + } + + virtual iter_type + do_get(iter_type __b, iter_type __e, ios_base& __iob, ios_base::iostate& __err, unsigned long& __v) const { + return this->__do_get_unsigned(__b, __e, __iob, __err, __v); + } + + virtual iter_type + do_get(iter_type __b, iter_type __e, ios_base& __iob, ios_base::iostate& __err, unsigned long long& __v) const { + return this->__do_get_unsigned(__b, __e, __iob, __err, __v); + } + + virtual iter_type do_get(iter_type __b, iter_type __e, ios_base& __iob, ios_base::iostate& __err, float& __v) const { + return this->__do_get_floating_point(__b, __e, __iob, __err, __v); + } + + virtual iter_type do_get(iter_type __b, iter_type __e, ios_base& __iob, ios_base::iostate& __err, double& __v) const { + return this->__do_get_floating_point(__b, __e, __iob, __err, __v); + } + + virtual iter_type + do_get(iter_type __b, iter_type __e, ios_base& __iob, ios_base::iostate& __err, long double& __v) const { + return this->__do_get_floating_point(__b, __e, __iob, __err, __v); + } + + virtual iter_type do_get(iter_type __b, iter_type __e, ios_base& __iob, ios_base::iostate& __err, void*& __v) const; +}; + +template +locale::id num_get<_CharT, _InputIterator>::id; + +template +_InputIterator num_get<_CharT, _InputIterator>::do_get( + iter_type __b, iter_type __e, ios_base& __iob, ios_base::iostate& __err, bool& __v) const { + if ((__iob.flags() & ios_base::boolalpha) == 0) { + long __lv = -1; + __b = do_get(__b, __e, __iob, __err, __lv); + switch (__lv) { + case 0: + __v = false; + break; + case 1: + __v = true; + break; + default: + __v = true; + __err = ios_base::failbit; + break; + } + return __b; + } + const ctype<_CharT>& __ct = std::use_facet >(__iob.getloc()); + const numpunct<_CharT>& __np = std::use_facet >(__iob.getloc()); + typedef typename numpunct<_CharT>::string_type string_type; + const string_type __names[2] = {__np.truename(), __np.falsename()}; + const string_type* __i = std::__scan_keyword(__b, __e, __names, __names + 2, __ct, __err); + __v = __i == __names; + return __b; +} + +template +_InputIterator num_get<_CharT, _InputIterator>::do_get( + iter_type __b, iter_type __e, ios_base& __iob, ios_base::iostate& __err, void*& __v) const { + // Stage 1 + int __base = 16; + // Stage 2 + char_type __atoms[__num_get_base::__int_chr_cnt]; + char_type __thousands_sep = char_type(); + string __grouping; + std::use_facet >(__iob.getloc()) + .widen(__num_get_base::__src, __num_get_base::__src + __num_get_base::__int_chr_cnt, __atoms); + string __buf; + __buf.resize(__buf.capacity()); + char* __a = &__buf[0]; + char* __a_end = __a; + unsigned __g[__num_get_base::__num_get_buf_sz]; + unsigned* __g_end = __g; + unsigned __dc = 0; + for (; __b != __e; ++__b) { + if (__a_end == __a + __buf.size()) { + size_t __tmp = __buf.size(); + __buf.resize(2 * __buf.size()); + __buf.resize(__buf.capacity()); + __a = &__buf[0]; + __a_end = __a + __tmp; + } + if (this->__stage2_int_loop(*__b, __base, __a, __a_end, __dc, __thousands_sep, __grouping, __g, __g_end, __atoms)) + break; + } + // Stage 3 + __buf.resize(__a_end - __a); + if (__locale::__sscanf(__buf.c_str(), _LIBCPP_GET_C_LOCALE, "%p", &__v) != 1) + __err = ios_base::failbit; + // EOF checked + if (__b == __e) + __err |= ios_base::eofbit; + return __b; +} + +extern template class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS num_get; +# if _LIBCPP_HAS_WIDE_CHARACTERS +extern template class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS num_get; +# endif + +struct _LIBCPP_EXPORTED_FROM_ABI __num_put_base { +protected: + static void __format_int(char* __fmt, const char* __len, bool __signd, ios_base::fmtflags __flags); + static bool __format_float(char* __fmt, const char* __len, ios_base::fmtflags __flags); + static char* __identify_padding(char* __nb, char* __ne, const ios_base& __iob); +}; + +template +struct __num_put : protected __num_put_base { + static void __widen_and_group_int( + char* __nb, char* __np, char* __ne, _CharT* __ob, _CharT*& __op, _CharT*& __oe, const locale& __loc); + static void __widen_and_group_float( + char* __nb, char* __np, char* __ne, _CharT* __ob, _CharT*& __op, _CharT*& __oe, const locale& __loc); +}; + +template +void __num_put<_CharT>::__widen_and_group_int( + char* __nb, char* __np, char* __ne, _CharT* __ob, _CharT*& __op, _CharT*& __oe, const locale& __loc) { + const ctype<_CharT>& __ct = std::use_facet >(__loc); + const numpunct<_CharT>& __npt = std::use_facet >(__loc); + string __grouping = __npt.grouping(); + if (__grouping.empty()) { + __ct.widen(__nb, __ne, __ob); + __oe = __ob + (__ne - __nb); + } else { + __oe = __ob; + char* __nf = __nb; + if (*__nf == '-' || *__nf == '+') + *__oe++ = __ct.widen(*__nf++); + if (__ne - __nf >= 2 && __nf[0] == '0' && (__nf[1] == 'x' || __nf[1] == 'X')) { + *__oe++ = __ct.widen(*__nf++); + *__oe++ = __ct.widen(*__nf++); + } + std::reverse(__nf, __ne); + _CharT __thousands_sep = __npt.thousands_sep(); + unsigned __dc = 0; + unsigned __dg = 0; + for (char* __p = __nf; __p < __ne; ++__p) { + if (static_cast(__grouping[__dg]) > 0 && __dc == static_cast(__grouping[__dg])) { + *__oe++ = __thousands_sep; + __dc = 0; + if (__dg < __grouping.size() - 1) + ++__dg; + } + *__oe++ = __ct.widen(*__p); + ++__dc; + } + std::reverse(__ob + (__nf - __nb), __oe); + } + if (__np == __ne) + __op = __oe; + else + __op = __ob + (__np - __nb); +} + +template +void __num_put<_CharT>::__widen_and_group_float( + char* __nb, char* __np, char* __ne, _CharT* __ob, _CharT*& __op, _CharT*& __oe, const locale& __loc) { + const ctype<_CharT>& __ct = std::use_facet >(__loc); + const numpunct<_CharT>& __npt = std::use_facet >(__loc); + string __grouping = __npt.grouping(); + __oe = __ob; + char* __nf = __nb; + if (*__nf == '-' || *__nf == '+') + *__oe++ = __ct.widen(*__nf++); + char* __ns; + if (__ne - __nf >= 2 && __nf[0] == '0' && (__nf[1] == 'x' || __nf[1] == 'X')) { + *__oe++ = __ct.widen(*__nf++); + *__oe++ = __ct.widen(*__nf++); + for (__ns = __nf; __ns < __ne; ++__ns) + if (!__locale::__isxdigit(*__ns, _LIBCPP_GET_C_LOCALE)) + break; + } else { + for (__ns = __nf; __ns < __ne; ++__ns) + if (!__locale::__isdigit(*__ns, _LIBCPP_GET_C_LOCALE)) + break; + } + if (__grouping.empty()) { + __ct.widen(__nf, __ns, __oe); + __oe += __ns - __nf; + } else { + std::reverse(__nf, __ns); + _CharT __thousands_sep = __npt.thousands_sep(); + unsigned __dc = 0; + unsigned __dg = 0; + for (char* __p = __nf; __p < __ns; ++__p) { + if (__grouping[__dg] > 0 && __dc == static_cast(__grouping[__dg])) { + *__oe++ = __thousands_sep; + __dc = 0; + if (__dg < __grouping.size() - 1) + ++__dg; + } + *__oe++ = __ct.widen(*__p); + ++__dc; + } + std::reverse(__ob + (__nf - __nb), __oe); + } + for (__nf = __ns; __nf < __ne; ++__nf) { + if (*__nf == '.') { + *__oe++ = __npt.decimal_point(); + ++__nf; + break; + } else + *__oe++ = __ct.widen(*__nf); + } + __ct.widen(__nf, __ne, __oe); + __oe += __ne - __nf; + if (__np == __ne) + __op = __oe; + else + __op = __ob + (__np - __nb); +} + +extern template struct _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS __num_put; +# if _LIBCPP_HAS_WIDE_CHARACTERS +extern template struct _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS __num_put; +# endif + +template > +class num_put : public locale::facet, private __num_put<_CharT> { +public: + typedef _CharT char_type; + typedef _OutputIterator iter_type; + + _LIBCPP_HIDE_FROM_ABI explicit num_put(size_t __refs = 0) : locale::facet(__refs) {} + + _LIBCPP_HIDE_FROM_ABI iter_type put(iter_type __s, ios_base& __iob, char_type __fl, bool __v) const { + return do_put(__s, __iob, __fl, __v); + } + + _LIBCPP_HIDE_FROM_ABI iter_type put(iter_type __s, ios_base& __iob, char_type __fl, long __v) const { + return do_put(__s, __iob, __fl, __v); + } + + _LIBCPP_HIDE_FROM_ABI iter_type put(iter_type __s, ios_base& __iob, char_type __fl, long long __v) const { + return do_put(__s, __iob, __fl, __v); + } + + _LIBCPP_HIDE_FROM_ABI iter_type put(iter_type __s, ios_base& __iob, char_type __fl, unsigned long __v) const { + return do_put(__s, __iob, __fl, __v); + } + + _LIBCPP_HIDE_FROM_ABI iter_type put(iter_type __s, ios_base& __iob, char_type __fl, unsigned long long __v) const { + return do_put(__s, __iob, __fl, __v); + } + + _LIBCPP_HIDE_FROM_ABI iter_type put(iter_type __s, ios_base& __iob, char_type __fl, double __v) const { + return do_put(__s, __iob, __fl, __v); + } + + _LIBCPP_HIDE_FROM_ABI iter_type put(iter_type __s, ios_base& __iob, char_type __fl, long double __v) const { + return do_put(__s, __iob, __fl, __v); + } + + _LIBCPP_HIDE_FROM_ABI iter_type put(iter_type __s, ios_base& __iob, char_type __fl, const void* __v) const { + return do_put(__s, __iob, __fl, __v); + } + + static locale::id id; + +protected: + _LIBCPP_HIDE_FROM_ABI_VIRTUAL ~num_put() override {} + + virtual iter_type do_put(iter_type __s, ios_base& __iob, char_type __fl, bool __v) const; + virtual iter_type do_put(iter_type __s, ios_base& __iob, char_type __fl, long __v) const; + virtual iter_type do_put(iter_type __s, ios_base& __iob, char_type __fl, long long __v) const; + virtual iter_type do_put(iter_type __s, ios_base& __iob, char_type __fl, unsigned long) const; + virtual iter_type do_put(iter_type __s, ios_base& __iob, char_type __fl, unsigned long long) const; + virtual iter_type do_put(iter_type __s, ios_base& __iob, char_type __fl, double __v) const; + virtual iter_type do_put(iter_type __s, ios_base& __iob, char_type __fl, long double __v) const; + virtual iter_type do_put(iter_type __s, ios_base& __iob, char_type __fl, const void* __v) const; + + template + _LIBCPP_HIDE_FROM_ABI inline _OutputIterator + __do_put_integral(iter_type __s, ios_base& __iob, char_type __fl, _Integral __v) const; + + template + _LIBCPP_HIDE_FROM_ABI inline _OutputIterator + __do_put_floating_point(iter_type __s, ios_base& __iob, char_type __fl, _Float __v, char const* __len) const; +}; + +template +locale::id num_put<_CharT, _OutputIterator>::id; + +template +_OutputIterator +num_put<_CharT, _OutputIterator>::do_put(iter_type __s, ios_base& __iob, char_type __fl, bool __v) const { + if ((__iob.flags() & ios_base::boolalpha) == 0) + return do_put(__s, __iob, __fl, (unsigned long)__v); + const numpunct& __np = std::use_facet >(__iob.getloc()); + typedef typename numpunct::string_type string_type; + string_type __nm = __v ? __np.truename() : __np.falsename(); + for (typename string_type::iterator __i = __nm.begin(); __i != __nm.end(); ++__i, ++__s) + *__s = *__i; + return __s; +} + +template +template +_LIBCPP_HIDE_FROM_ABI inline _OutputIterator num_put<_CharT, _OutputIterator>::__do_put_integral( + iter_type __s, ios_base& __iob, char_type __fl, _Integral __v) const { + // Stage 1 - Get number in narrow char + + // Worst case is octal, with showbase enabled. Note that octal is always + // printed as an unsigned value. + using _Unsigned = typename make_unsigned<_Integral>::type; + _LIBCPP_CONSTEXPR const unsigned __buffer_size = + (numeric_limits<_Unsigned>::digits / 3) // 1 char per 3 bits + + ((numeric_limits<_Unsigned>::digits % 3) != 0) // round up + + 2; // base prefix + terminating null character + + char __char_buffer[__buffer_size]; + char* __buffer_ptr = __char_buffer; + + auto __flags = __iob.flags(); + + auto __basefield = (__flags & ios_base::basefield); + + // Extract base + int __base = 10; + if (__basefield == ios_base::oct) + __base = 8; + else if (__basefield == ios_base::hex) + __base = 16; + + // Print '-' and make the argument unsigned + auto __uval = std::__to_unsigned_like(__v); + if (__basefield != ios_base::oct && __basefield != ios_base::hex && __v < 0) { + *__buffer_ptr++ = '-'; + __uval = std::__complement(__uval); + } + + // Maybe add '+' prefix + if (std::is_signed<_Integral>::value && (__flags & ios_base::showpos) && __basefield != ios_base::oct && + __basefield != ios_base::hex && __v >= 0) + *__buffer_ptr++ = '+'; + + // Add base prefix + if (__v != 0 && __flags & ios_base::showbase) { + if (__basefield == ios_base::oct) { + *__buffer_ptr++ = '0'; + } else if (__basefield == ios_base::hex) { + *__buffer_ptr++ = '0'; + *__buffer_ptr++ = (__flags & ios_base::uppercase ? 'X' : 'x'); + } + } + + auto __res = std::__to_chars_integral(__buffer_ptr, __char_buffer + __buffer_size, __uval, __base); + _LIBCPP_ASSERT_INTERNAL(__res.__ec == std::errc(0), "to_chars: invalid maximum buffer size computed?"); + + // Make letters uppercase + if (__flags & ios_base::hex && __flags & ios_base::uppercase) { + for (; __buffer_ptr != __res.__ptr; ++__buffer_ptr) + *__buffer_ptr = std::__hex_to_upper(*__buffer_ptr); + } + + char* __np = this->__identify_padding(__char_buffer, __res.__ptr, __iob); + // Stage 2 - Widen __nar while adding thousands separators + char_type __o[2 * (__buffer_size - 1) - 1]; + char_type* __op; // pad here + char_type* __oe; // end of output + this->__widen_and_group_int(__char_buffer, __np, __res.__ptr, __o, __op, __oe, __iob.getloc()); + // [__o, __oe) contains thousands_sep'd wide number + // Stage 3 & 4 + return std::__pad_and_output(__s, __o, __op, __oe, __iob, __fl); +} + +template +_OutputIterator +num_put<_CharT, _OutputIterator>::do_put(iter_type __s, ios_base& __iob, char_type __fl, long __v) const { + return this->__do_put_integral(__s, __iob, __fl, __v); +} + +template +_OutputIterator +num_put<_CharT, _OutputIterator>::do_put(iter_type __s, ios_base& __iob, char_type __fl, long long __v) const { + return this->__do_put_integral(__s, __iob, __fl, __v); +} + +template +_OutputIterator +num_put<_CharT, _OutputIterator>::do_put(iter_type __s, ios_base& __iob, char_type __fl, unsigned long __v) const { + return this->__do_put_integral(__s, __iob, __fl, __v); +} + +template +_OutputIterator +num_put<_CharT, _OutputIterator>::do_put(iter_type __s, ios_base& __iob, char_type __fl, unsigned long long __v) const { + return this->__do_put_integral(__s, __iob, __fl, __v); +} + +template +template +_LIBCPP_HIDE_FROM_ABI inline _OutputIterator num_put<_CharT, _OutputIterator>::__do_put_floating_point( + iter_type __s, ios_base& __iob, char_type __fl, _Float __v, char const* __len) const { + // Stage 1 - Get number in narrow char + char __fmt[8] = {'%', 0}; + bool __specify_precision = this->__format_float(__fmt + 1, __len, __iob.flags()); + const unsigned __nbuf = 30; + char __nar[__nbuf]; + char* __nb = __nar; + int __nc; + _LIBCPP_DIAGNOSTIC_PUSH + _LIBCPP_CLANG_DIAGNOSTIC_IGNORED("-Wformat-nonliteral") + _LIBCPP_GCC_DIAGNOSTIC_IGNORED("-Wformat-nonliteral") + if (__specify_precision) + __nc = __locale::__snprintf(__nb, __nbuf, _LIBCPP_GET_C_LOCALE, __fmt, (int)__iob.precision(), __v); + else + __nc = __locale::__snprintf(__nb, __nbuf, _LIBCPP_GET_C_LOCALE, __fmt, __v); + unique_ptr __nbh(nullptr, free); + if (__nc > static_cast(__nbuf - 1)) { + if (__specify_precision) + __nc = __locale::__asprintf(&__nb, _LIBCPP_GET_C_LOCALE, __fmt, (int)__iob.precision(), __v); + else + __nc = __locale::__asprintf(&__nb, _LIBCPP_GET_C_LOCALE, __fmt, __v); + if (__nc == -1) + std::__throw_bad_alloc(); + __nbh.reset(__nb); + } + _LIBCPP_DIAGNOSTIC_POP + char* __ne = __nb + __nc; + char* __np = this->__identify_padding(__nb, __ne, __iob); + // Stage 2 - Widen __nar while adding thousands separators + char_type __o[2 * (__nbuf - 1) - 1]; + char_type* __ob = __o; + unique_ptr __obh(0, free); + if (__nb != __nar) { + __ob = (char_type*)malloc(2 * static_cast(__nc) * sizeof(char_type)); + if (__ob == 0) + std::__throw_bad_alloc(); + __obh.reset(__ob); + } + char_type* __op; // pad here + char_type* __oe; // end of output + this->__widen_and_group_float(__nb, __np, __ne, __ob, __op, __oe, __iob.getloc()); + // [__o, __oe) contains thousands_sep'd wide number + // Stage 3 & 4 + __s = std::__pad_and_output(__s, __ob, __op, __oe, __iob, __fl); + return __s; +} + +template +_OutputIterator +num_put<_CharT, _OutputIterator>::do_put(iter_type __s, ios_base& __iob, char_type __fl, double __v) const { + return this->__do_put_floating_point(__s, __iob, __fl, __v, ""); +} + +template +_OutputIterator +num_put<_CharT, _OutputIterator>::do_put(iter_type __s, ios_base& __iob, char_type __fl, long double __v) const { + return this->__do_put_floating_point(__s, __iob, __fl, __v, "L"); +} + +template +_OutputIterator +num_put<_CharT, _OutputIterator>::do_put(iter_type __s, ios_base& __iob, char_type __fl, const void* __v) const { + auto __flags = __iob.flags(); + __iob.flags((__flags & ~ios_base::basefield & ~ios_base::uppercase) | ios_base::hex | ios_base::showbase); + auto __res = __do_put_integral(__s, __iob, __fl, reinterpret_cast(__v)); + __iob.flags(__flags); + return __res; +} + +extern template class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS num_put; +# if _LIBCPP_HAS_WIDE_CHARACTERS +extern template class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS num_put; +# endif + +_LIBCPP_END_NAMESPACE_STD + +_LIBCPP_POP_MACROS + +// NOLINTEND(libcpp-robust-against-adl) + +#endif // _LIBCPP_HAS_LOCALIZATION + +#endif // _LIBCPP___LOCALE_DIR_NUM_H diff --git a/lib/libcxx/include/__locale_dir/scan_keyword.h b/lib/libcxx/include/__locale_dir/scan_keyword.h new file mode 100644 index 0000000000..78dd0a46a8 --- /dev/null +++ b/lib/libcxx/include/__locale_dir/scan_keyword.h @@ -0,0 +1,143 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___LOCALE_DIR_SCAN_KEYWORD_H +#define _LIBCPP___LOCALE_DIR_SCAN_KEYWORD_H + +#include <__config> +#include <__memory/unique_ptr.h> +#include + +#if _LIBCPP_HAS_LOCALIZATION + +# if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +# endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +// __scan_keyword +// Scans [__b, __e) until a match is found in the basic_strings range +// [__kb, __ke) or until it can be shown that there is no match in [__kb, __ke). +// __b will be incremented (visibly), consuming CharT until a match is found +// or proved to not exist. A keyword may be "", in which will match anything. +// If one keyword is a prefix of another, and the next CharT in the input +// might match another keyword, the algorithm will attempt to find the longest +// matching keyword. If the longer matching keyword ends up not matching, then +// no keyword match is found. If no keyword match is found, __ke is returned +// and failbit is set in __err. +// Else an iterator pointing to the matching keyword is found. If more than +// one keyword matches, an iterator to the first matching keyword is returned. +// If on exit __b == __e, eofbit is set in __err. If __case_sensitive is false, +// __ct is used to force to lower case before comparing characters. +// Examples: +// Keywords: "a", "abb" +// If the input is "a", the first keyword matches and eofbit is set. +// If the input is "abc", no match is found and "ab" are consumed. +template +_LIBCPP_HIDE_FROM_ABI _ForwardIterator __scan_keyword( + _InputIterator& __b, + _InputIterator __e, + _ForwardIterator __kb, + _ForwardIterator __ke, + const _Ctype& __ct, + ios_base::iostate& __err, + bool __case_sensitive = true) { + typedef typename iterator_traits<_InputIterator>::value_type _CharT; + size_t __nkw = static_cast(std::distance(__kb, __ke)); + const unsigned char __doesnt_match = '\0'; + const unsigned char __might_match = '\1'; + const unsigned char __does_match = '\2'; + unsigned char __statbuf[100]; + unsigned char* __status = __statbuf; + unique_ptr __stat_hold(nullptr, free); + if (__nkw > sizeof(__statbuf)) { + __status = (unsigned char*)malloc(__nkw); + if (__status == nullptr) + std::__throw_bad_alloc(); + __stat_hold.reset(__status); + } + size_t __n_might_match = __nkw; // At this point, any keyword might match + size_t __n_does_match = 0; // but none of them definitely do + // Initialize all statuses to __might_match, except for "" keywords are __does_match + unsigned char* __st = __status; + for (_ForwardIterator __ky = __kb; __ky != __ke; ++__ky, (void)++__st) { + if (!__ky->empty()) + *__st = __might_match; + else { + *__st = __does_match; + --__n_might_match; + ++__n_does_match; + } + } + // While there might be a match, test keywords against the next CharT + for (size_t __indx = 0; __b != __e && __n_might_match > 0; ++__indx) { + // Peek at the next CharT but don't consume it + _CharT __c = *__b; + if (!__case_sensitive) + __c = __ct.toupper(__c); + bool __consume = false; + // For each keyword which might match, see if the __indx character is __c + // If a match if found, consume __c + // If a match is found, and that is the last character in the keyword, + // then that keyword matches. + // If the keyword doesn't match this character, then change the keyword + // to doesn't match + __st = __status; + for (_ForwardIterator __ky = __kb; __ky != __ke; ++__ky, (void)++__st) { + if (*__st == __might_match) { + _CharT __kc = (*__ky)[__indx]; + if (!__case_sensitive) + __kc = __ct.toupper(__kc); + if (__c == __kc) { + __consume = true; + if (__ky->size() == __indx + 1) { + *__st = __does_match; + --__n_might_match; + ++__n_does_match; + } + } else { + *__st = __doesnt_match; + --__n_might_match; + } + } + } + // consume if we matched a character + if (__consume) { + ++__b; + // If we consumed a character and there might be a matched keyword that + // was marked matched on a previous iteration, then such keywords + // which are now marked as not matching. + if (__n_might_match + __n_does_match > 1) { + __st = __status; + for (_ForwardIterator __ky = __kb; __ky != __ke; ++__ky, (void)++__st) { + if (*__st == __does_match && __ky->size() != __indx + 1) { + *__st = __doesnt_match; + --__n_does_match; + } + } + } + } + } + // We've exited the loop because we hit eof and/or we have no more "might matches". + if (__b == __e) + __err |= ios_base::eofbit; + // Return the first matching result + for (__st = __status; __kb != __ke; ++__kb, (void)++__st) + if (*__st == __does_match) + break; + if (__kb == __ke) + __err |= ios_base::failbit; + return __kb; +} + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP_HAS_LOCALIZATION + +#endif // _LIBCPP___LOCALE_DIR_SCAN_KEYWORD_H diff --git a/lib/libcxx/include/__locale_dir/support/apple.h b/lib/libcxx/include/__locale_dir/support/apple.h index 5216ed2ba7..62eb79c30d 100644 --- a/lib/libcxx/include/__locale_dir/support/apple.h +++ b/lib/libcxx/include/__locale_dir/support/apple.h @@ -15,8 +15,6 @@ # pragma GCC system_header #endif -#include - #include <__locale_dir/support/bsd_like.h> #endif // _LIBCPP___LOCALE_DIR_SUPPORT_APPLE_H diff --git a/lib/libcxx/include/__locale_dir/support/bsd_like.h b/lib/libcxx/include/__locale_dir/support/bsd_like.h index 51b37e5861..2b03e18920 100644 --- a/lib/libcxx/include/__locale_dir/support/bsd_like.h +++ b/lib/libcxx/include/__locale_dir/support/bsd_like.h @@ -24,6 +24,11 @@ # include #endif +/* zig patch: https://github.com/llvm/llvm-project/pull/143055 */ +#if __has_include() +# include +#endif + #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # pragma GCC system_header #endif @@ -43,9 +48,9 @@ namespace __locale { #define _LIBCPP_ALL_MASK LC_ALL_MASK #define _LIBCPP_LC_ALL LC_ALL -using __locale_t = ::locale_t; +using __locale_t _LIBCPP_NODEBUG = ::locale_t; #if defined(_LIBCPP_BUILDING_LIBRARY) -using __lconv_t = std::lconv; +using __lconv_t _LIBCPP_NODEBUG = std::lconv; inline _LIBCPP_HIDE_FROM_ABI __locale_t __newlocale(int __category_mask, const char* __locale, __locale_t __base) { return ::newlocale(__category_mask, __locale, __base); @@ -87,12 +92,6 @@ __strtoull(const char* __nptr, char** __endptr, int __base, __locale_t __loc) { // // Character manipulation functions // -#if defined(_LIBCPP_BUILDING_LIBRARY) -inline _LIBCPP_HIDE_FROM_ABI int __islower(int __c, __locale_t __loc) { return ::islower_l(__c, __loc); } - -inline _LIBCPP_HIDE_FROM_ABI int __isupper(int __c, __locale_t __loc) { return ::isupper_l(__c, __loc); } -#endif - inline _LIBCPP_HIDE_FROM_ABI int __isdigit(int __c, __locale_t __loc) { return ::isdigit_l(__c, __loc); } inline _LIBCPP_HIDE_FROM_ABI int __isxdigit(int __c, __locale_t __loc) { return ::isxdigit_l(__c, __loc); } diff --git a/lib/libcxx/include/__locale_dir/support/freebsd.h b/lib/libcxx/include/__locale_dir/support/freebsd.h index 5e24cbd29b..5c6e21e387 100644 --- a/lib/libcxx/include/__locale_dir/support/freebsd.h +++ b/lib/libcxx/include/__locale_dir/support/freebsd.h @@ -15,8 +15,6 @@ # pragma GCC system_header #endif -#include - #include <__locale_dir/support/bsd_like.h> #endif // _LIBCPP___LOCALE_DIR_SUPPORT_FREEBSD_H diff --git a/lib/libcxx/include/__locale_dir/support/fuchsia.h b/lib/libcxx/include/__locale_dir/support/fuchsia.h index fb9de74ab7..4b9e63facb 100644 --- a/lib/libcxx/include/__locale_dir/support/fuchsia.h +++ b/lib/libcxx/include/__locale_dir/support/fuchsia.h @@ -49,10 +49,10 @@ struct __locale_guard { #define _LIBCPP_ALL_MASK LC_ALL_MASK #define _LIBCPP_LC_ALL LC_ALL -using __locale_t = locale_t; +using __locale_t _LIBCPP_NODEBUG = locale_t; #if defined(_LIBCPP_BUILDING_LIBRARY) -using __lconv_t = std::lconv; +using __lconv_t _LIBCPP_NODEBUG = std::lconv; inline _LIBCPP_HIDE_FROM_ABI __locale_t __newlocale(int __category_mask, const char* __name, __locale_t __loc) { return ::newlocale(__category_mask, __name, __loc); diff --git a/lib/libcxx/include/__locale_dir/support/linux.h b/lib/libcxx/include/__locale_dir/support/linux.h new file mode 100644 index 0000000000..23bcf44c31 --- /dev/null +++ b/lib/libcxx/include/__locale_dir/support/linux.h @@ -0,0 +1,281 @@ +//===-----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___LOCALE_DIR_SUPPORT_LINUX_H +#define _LIBCPP___LOCALE_DIR_SUPPORT_LINUX_H + +#include <__config> +#include <__cstddef/size_t.h> +#include <__std_mbstate_t.h> +#include <__utility/forward.h> +#include // std::lconv +#include +#include +#include +#include +#include +#include +#if _LIBCPP_HAS_WIDE_CHARACTERS +# include +# include +#endif + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD +namespace __locale { + +struct __locale_guard { + _LIBCPP_HIDE_FROM_ABI __locale_guard(locale_t& __loc) : __old_loc_(::uselocale(__loc)) {} + + _LIBCPP_HIDE_FROM_ABI ~__locale_guard() { + if (__old_loc_) + ::uselocale(__old_loc_); + } + + locale_t __old_loc_; + + __locale_guard(__locale_guard const&) = delete; + __locale_guard& operator=(__locale_guard const&) = delete; +}; + +// +// Locale management +// +#define _LIBCPP_COLLATE_MASK LC_COLLATE_MASK +#define _LIBCPP_CTYPE_MASK LC_CTYPE_MASK +#define _LIBCPP_MONETARY_MASK LC_MONETARY_MASK +#define _LIBCPP_NUMERIC_MASK LC_NUMERIC_MASK +#define _LIBCPP_TIME_MASK LC_TIME_MASK +#define _LIBCPP_MESSAGES_MASK LC_MESSAGES_MASK +#define _LIBCPP_ALL_MASK LC_ALL_MASK +#define _LIBCPP_LC_ALL LC_ALL + +using __locale_t _LIBCPP_NODEBUG = ::locale_t; + +#if defined(_LIBCPP_BUILDING_LIBRARY) +using __lconv_t _LIBCPP_NODEBUG = std::lconv; + +inline _LIBCPP_HIDE_FROM_ABI __locale_t __newlocale(int __category_mask, const char* __locale, __locale_t __base) { + return ::newlocale(__category_mask, __locale, __base); +} + +inline _LIBCPP_HIDE_FROM_ABI void __freelocale(__locale_t __loc) { ::freelocale(__loc); } + +inline _LIBCPP_HIDE_FROM_ABI char* __setlocale(int __category, char const* __locale) { + return ::setlocale(__category, __locale); +} + +inline _LIBCPP_HIDE_FROM_ABI __lconv_t* __localeconv(__locale_t& __loc) { + __locale_guard __current(__loc); + return std::localeconv(); +} +#endif // _LIBCPP_BUILDING_LIBRARY + +// +// Strtonum functions +// +inline _LIBCPP_HIDE_FROM_ABI float __strtof(const char* __nptr, char** __endptr, __locale_t __loc) { + return ::strtof_l(__nptr, __endptr, __loc); +} + +inline _LIBCPP_HIDE_FROM_ABI double __strtod(const char* __nptr, char** __endptr, __locale_t __loc) { + return ::strtod_l(__nptr, __endptr, __loc); +} + +inline _LIBCPP_HIDE_FROM_ABI long double __strtold(const char* __nptr, char** __endptr, __locale_t __loc) { + return ::strtold_l(__nptr, __endptr, __loc); +} + +inline _LIBCPP_HIDE_FROM_ABI long long __strtoll(const char* __nptr, char** __endptr, int __base, __locale_t __loc) { +#if !_LIBCPP_HAS_MUSL_LIBC + return ::strtoll_l(__nptr, __endptr, __base, __loc); +#else + (void)__loc; + return ::strtoll(__nptr, __endptr, __base); +#endif +} + +inline _LIBCPP_HIDE_FROM_ABI unsigned long long +__strtoull(const char* __nptr, char** __endptr, int __base, __locale_t __loc) { +#if !_LIBCPP_HAS_MUSL_LIBC + return ::strtoull_l(__nptr, __endptr, __base, __loc); +#else + (void)__loc; + return ::strtoull(__nptr, __endptr, __base); +#endif +} + +// +// Character manipulation functions +// +inline _LIBCPP_HIDE_FROM_ABI int __isdigit(int __c, __locale_t __loc) { return isdigit_l(__c, __loc); } + +inline _LIBCPP_HIDE_FROM_ABI int __isxdigit(int __c, __locale_t __loc) { return isxdigit_l(__c, __loc); } + +#if defined(_LIBCPP_BUILDING_LIBRARY) +inline _LIBCPP_HIDE_FROM_ABI int __toupper(int __c, __locale_t __loc) { return toupper_l(__c, __loc); } + +inline _LIBCPP_HIDE_FROM_ABI int __tolower(int __c, __locale_t __loc) { return tolower_l(__c, __loc); } + +inline _LIBCPP_HIDE_FROM_ABI int __strcoll(const char* __s1, const char* __s2, __locale_t __loc) { + return strcoll_l(__s1, __s2, __loc); +} + +inline _LIBCPP_HIDE_FROM_ABI size_t __strxfrm(char* __dest, const char* __src, size_t __n, __locale_t __loc) { + return strxfrm_l(__dest, __src, __n, __loc); +} + +# if _LIBCPP_HAS_WIDE_CHARACTERS +inline _LIBCPP_HIDE_FROM_ABI int __iswctype(wint_t __c, wctype_t __type, __locale_t __loc) { + return iswctype_l(__c, __type, __loc); +} + +inline _LIBCPP_HIDE_FROM_ABI int __iswspace(wint_t __c, __locale_t __loc) { return iswspace_l(__c, __loc); } + +inline _LIBCPP_HIDE_FROM_ABI int __iswprint(wint_t __c, __locale_t __loc) { return iswprint_l(__c, __loc); } + +inline _LIBCPP_HIDE_FROM_ABI int __iswcntrl(wint_t __c, __locale_t __loc) { return iswcntrl_l(__c, __loc); } + +inline _LIBCPP_HIDE_FROM_ABI int __iswupper(wint_t __c, __locale_t __loc) { return iswupper_l(__c, __loc); } + +inline _LIBCPP_HIDE_FROM_ABI int __iswlower(wint_t __c, __locale_t __loc) { return iswlower_l(__c, __loc); } + +inline _LIBCPP_HIDE_FROM_ABI int __iswalpha(wint_t __c, __locale_t __loc) { return iswalpha_l(__c, __loc); } + +inline _LIBCPP_HIDE_FROM_ABI int __iswblank(wint_t __c, __locale_t __loc) { return iswblank_l(__c, __loc); } + +inline _LIBCPP_HIDE_FROM_ABI int __iswdigit(wint_t __c, __locale_t __loc) { return iswdigit_l(__c, __loc); } + +inline _LIBCPP_HIDE_FROM_ABI int __iswpunct(wint_t __c, __locale_t __loc) { return iswpunct_l(__c, __loc); } + +inline _LIBCPP_HIDE_FROM_ABI int __iswxdigit(wint_t __c, __locale_t __loc) { return iswxdigit_l(__c, __loc); } + +inline _LIBCPP_HIDE_FROM_ABI wint_t __towupper(wint_t __c, __locale_t __loc) { return towupper_l(__c, __loc); } + +inline _LIBCPP_HIDE_FROM_ABI wint_t __towlower(wint_t __c, __locale_t __loc) { return towlower_l(__c, __loc); } + +inline _LIBCPP_HIDE_FROM_ABI int __wcscoll(const wchar_t* __ws1, const wchar_t* __ws2, __locale_t __loc) { + return wcscoll_l(__ws1, __ws2, __loc); +} + +inline _LIBCPP_HIDE_FROM_ABI size_t __wcsxfrm(wchar_t* __dest, const wchar_t* __src, size_t __n, __locale_t __loc) { + return wcsxfrm_l(__dest, __src, __n, __loc); +} +# endif // _LIBCPP_HAS_WIDE_CHARACTERS + +inline _LIBCPP_HIDE_FROM_ABI size_t +__strftime(char* __s, size_t __max, const char* __format, const struct tm* __tm, __locale_t __loc) { + return strftime_l(__s, __max, __format, __tm, __loc); +} + +// +// Other functions +// +inline _LIBCPP_HIDE_FROM_ABI decltype(MB_CUR_MAX) __mb_len_max(__locale_t __loc) { + __locale_guard __current(__loc); + return MB_CUR_MAX; +} + +# if _LIBCPP_HAS_WIDE_CHARACTERS +inline _LIBCPP_HIDE_FROM_ABI wint_t __btowc(int __c, __locale_t __loc) { + __locale_guard __current(__loc); + return std::btowc(__c); +} + +inline _LIBCPP_HIDE_FROM_ABI int __wctob(wint_t __c, __locale_t __loc) { + __locale_guard __current(__loc); + return std::wctob(__c); +} + +inline _LIBCPP_HIDE_FROM_ABI size_t +__wcsnrtombs(char* __dest, const wchar_t** __src, size_t __nwc, size_t __len, mbstate_t* __ps, __locale_t __loc) { + __locale_guard __current(__loc); + return ::wcsnrtombs(__dest, __src, __nwc, __len, __ps); // non-standard +} + +inline _LIBCPP_HIDE_FROM_ABI size_t __wcrtomb(char* __s, wchar_t __wc, mbstate_t* __ps, __locale_t __loc) { + __locale_guard __current(__loc); + return std::wcrtomb(__s, __wc, __ps); +} + +inline _LIBCPP_HIDE_FROM_ABI size_t +__mbsnrtowcs(wchar_t* __dest, const char** __src, size_t __nms, size_t __len, mbstate_t* __ps, __locale_t __loc) { + __locale_guard __current(__loc); + return ::mbsnrtowcs(__dest, __src, __nms, __len, __ps); // non-standard +} + +inline _LIBCPP_HIDE_FROM_ABI size_t +__mbrtowc(wchar_t* __pwc, const char* __s, size_t __n, mbstate_t* __ps, __locale_t __loc) { + __locale_guard __current(__loc); + return std::mbrtowc(__pwc, __s, __n, __ps); +} + +inline _LIBCPP_HIDE_FROM_ABI int __mbtowc(wchar_t* __pwc, const char* __pmb, size_t __max, __locale_t __loc) { + __locale_guard __current(__loc); + return std::mbtowc(__pwc, __pmb, __max); +} + +inline _LIBCPP_HIDE_FROM_ABI size_t __mbrlen(const char* __s, size_t __n, mbstate_t* __ps, __locale_t __loc) { + __locale_guard __current(__loc); + return std::mbrlen(__s, __n, __ps); +} + +inline _LIBCPP_HIDE_FROM_ABI size_t +__mbsrtowcs(wchar_t* __dest, const char** __src, size_t __len, mbstate_t* __ps, __locale_t __loc) { + __locale_guard __current(__loc); + return std::mbsrtowcs(__dest, __src, __len, __ps); +} +# endif // _LIBCPP_HAS_WIDE_CHARACTERS +#endif // _LIBCPP_BUILDING_LIBRARY + +#ifndef _LIBCPP_COMPILER_GCC // GCC complains that this can't be always_inline due to C-style varargs +_LIBCPP_HIDE_FROM_ABI +#endif +inline _LIBCPP_ATTRIBUTE_FORMAT(__printf__, 4, 5) int __snprintf( + char* __s, size_t __n, __locale_t __loc, const char* __format, ...) { + va_list __va; + va_start(__va, __format); + __locale_guard __current(__loc); + int __res = std::vsnprintf(__s, __n, __format, __va); + va_end(__va); + return __res; +} + +#ifndef _LIBCPP_COMPILER_GCC // GCC complains that this can't be always_inline due to C-style varargs +_LIBCPP_HIDE_FROM_ABI +#endif +inline _LIBCPP_ATTRIBUTE_FORMAT(__printf__, 3, 4) int __asprintf( + char** __s, __locale_t __loc, const char* __format, ...) { + va_list __va; + va_start(__va, __format); + __locale_guard __current(__loc); + int __res = ::vasprintf(__s, __format, __va); // non-standard + va_end(__va); + return __res; +} + +#ifndef _LIBCPP_COMPILER_GCC // GCC complains that this can't be always_inline due to C-style varargs +_LIBCPP_HIDE_FROM_ABI +#endif +inline _LIBCPP_ATTRIBUTE_FORMAT(__scanf__, 3, 4) int __sscanf( + const char* __s, __locale_t __loc, const char* __format, ...) { + va_list __va; + va_start(__va, __format); + __locale_guard __current(__loc); + int __res = std::vsscanf(__s, __format, __va); + va_end(__va); + return __res; +} + +} // namespace __locale +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___LOCALE_DIR_SUPPORT_LINUX_H diff --git a/lib/libcxx/include/__locale_dir/support/netbsd.h b/lib/libcxx/include/__locale_dir/support/netbsd.h index 190857f6f8..b1e67ade55 100644 --- a/lib/libcxx/include/__locale_dir/support/netbsd.h +++ b/lib/libcxx/include/__locale_dir/support/netbsd.h @@ -6,6 +6,8 @@ // //===----------------------------------------------------------------------===// +/* zig patch: https://github.com/llvm/llvm-project/pull/143055 */ + #ifndef _LIBCPP___LOCALE_DIR_SUPPORT_NETBSD_H #define _LIBCPP___LOCALE_DIR_SUPPORT_NETBSD_H diff --git a/lib/libcxx/include/__locale_dir/support/no_locale/characters.h b/lib/libcxx/include/__locale_dir/support/no_locale/characters.h index 4fb48ed9ce..1281b8bd13 100644 --- a/lib/libcxx/include/__locale_dir/support/no_locale/characters.h +++ b/lib/libcxx/include/__locale_dir/support/no_locale/characters.h @@ -29,12 +29,6 @@ namespace __locale { // // Character manipulation functions // -#if defined(_LIBCPP_BUILDING_LIBRARY) -inline _LIBCPP_HIDE_FROM_ABI int __islower(int __c, __locale_t) { return std::islower(__c); } - -inline _LIBCPP_HIDE_FROM_ABI int __isupper(int __c, __locale_t) { return std::isupper(__c); } -#endif - inline _LIBCPP_HIDE_FROM_ABI int __isdigit(int __c, __locale_t) { return std::isdigit(__c); } inline _LIBCPP_HIDE_FROM_ABI int __isxdigit(int __c, __locale_t) { return std::isxdigit(__c); } diff --git a/lib/libcxx/include/__locale_dir/support/windows.h b/lib/libcxx/include/__locale_dir/support/windows.h index 56d34c6f0e..0df8709f11 100644 --- a/lib/libcxx/include/__locale_dir/support/windows.h +++ b/lib/libcxx/include/__locale_dir/support/windows.h @@ -29,7 +29,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD namespace __locale { -using __lconv_t = std::lconv; +using __lconv_t _LIBCPP_NODEBUG = std::lconv; class __lconv_storage { public: @@ -197,12 +197,6 @@ __strtoull(const char* __nptr, char** __endptr, int __base, __locale_t __loc) { // // Character manipulation functions // -#if defined(_LIBCPP_BUILDING_LIBRARY) -inline _LIBCPP_HIDE_FROM_ABI int __islower(int __c, __locale_t __loc) { return _islower_l(__c, __loc); } - -inline _LIBCPP_HIDE_FROM_ABI int __isupper(int __c, __locale_t __loc) { return _isupper_l(__c, __loc); } -#endif - inline _LIBCPP_HIDE_FROM_ABI int __isdigit(int __c, __locale_t __loc) { return _isdigit_l(__c, __loc); } inline _LIBCPP_HIDE_FROM_ABI int __isxdigit(int __c, __locale_t __loc) { return _isxdigit_l(__c, __loc); } @@ -317,7 +311,7 @@ struct __locale_guard { if (std::strcmp(__l.__get_locale(), __lc) != 0) { __locale_all = _strdup(__lc); if (__locale_all == nullptr) - __throw_bad_alloc(); + std::__throw_bad_alloc(); __locale::__setlocale(LC_ALL, __l.__get_locale()); } } diff --git a/lib/libcxx/include/__locale_dir/time.h b/lib/libcxx/include/__locale_dir/time.h new file mode 100644 index 0000000000..5f60d5f36b --- /dev/null +++ b/lib/libcxx/include/__locale_dir/time.h @@ -0,0 +1,766 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___LOCALE_DIR_TIME_H +#define _LIBCPP___LOCALE_DIR_TIME_H + +#include <__algorithm/copy.h> +#include <__config> +#include <__locale_dir/get_c_locale.h> +#include <__locale_dir/scan_keyword.h> +#include + +#if _LIBCPP_HAS_LOCALIZATION + +# if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +# endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +template +_LIBCPP_HIDE_FROM_ABI int __get_up_to_n_digits( + _InputIterator& __b, _InputIterator __e, ios_base::iostate& __err, const ctype<_CharT>& __ct, int __n) { + // Precondition: __n >= 1 + if (__b == __e) { + __err |= ios_base::eofbit | ios_base::failbit; + return 0; + } + // get first digit + _CharT __c = *__b; + if (!__ct.is(ctype_base::digit, __c)) { + __err |= ios_base::failbit; + return 0; + } + int __r = __ct.narrow(__c, 0) - '0'; + for (++__b, (void)--__n; __b != __e && __n > 0; ++__b, (void)--__n) { + // get next digit + __c = *__b; + if (!__ct.is(ctype_base::digit, __c)) + return __r; + __r = __r * 10 + __ct.narrow(__c, 0) - '0'; + } + if (__b == __e) + __err |= ios_base::eofbit; + return __r; +} + +class _LIBCPP_EXPORTED_FROM_ABI time_base { +public: + enum dateorder { no_order, dmy, mdy, ymd, ydm }; +}; + +template +class __time_get_c_storage { +protected: + typedef basic_string<_CharT> string_type; + + virtual const string_type* __weeks() const; + virtual const string_type* __months() const; + virtual const string_type* __am_pm() const; + virtual const string_type& __c() const; + virtual const string_type& __r() const; + virtual const string_type& __x() const; + virtual const string_type& __X() const; + + _LIBCPP_HIDE_FROM_ABI ~__time_get_c_storage() {} +}; + +template <> +_LIBCPP_EXPORTED_FROM_ABI const string* __time_get_c_storage::__weeks() const; +template <> +_LIBCPP_EXPORTED_FROM_ABI const string* __time_get_c_storage::__months() const; +template <> +_LIBCPP_EXPORTED_FROM_ABI const string* __time_get_c_storage::__am_pm() const; +template <> +_LIBCPP_EXPORTED_FROM_ABI const string& __time_get_c_storage::__c() const; +template <> +_LIBCPP_EXPORTED_FROM_ABI const string& __time_get_c_storage::__r() const; +template <> +_LIBCPP_EXPORTED_FROM_ABI const string& __time_get_c_storage::__x() const; +template <> +_LIBCPP_EXPORTED_FROM_ABI const string& __time_get_c_storage::__X() const; + +# if _LIBCPP_HAS_WIDE_CHARACTERS +template <> +_LIBCPP_EXPORTED_FROM_ABI const wstring* __time_get_c_storage::__weeks() const; +template <> +_LIBCPP_EXPORTED_FROM_ABI const wstring* __time_get_c_storage::__months() const; +template <> +_LIBCPP_EXPORTED_FROM_ABI const wstring* __time_get_c_storage::__am_pm() const; +template <> +_LIBCPP_EXPORTED_FROM_ABI const wstring& __time_get_c_storage::__c() const; +template <> +_LIBCPP_EXPORTED_FROM_ABI const wstring& __time_get_c_storage::__r() const; +template <> +_LIBCPP_EXPORTED_FROM_ABI const wstring& __time_get_c_storage::__x() const; +template <> +_LIBCPP_EXPORTED_FROM_ABI const wstring& __time_get_c_storage::__X() const; +# endif + +template > +class time_get : public locale::facet, public time_base, private __time_get_c_storage<_CharT> { +public: + typedef _CharT char_type; + typedef _InputIterator iter_type; + typedef time_base::dateorder dateorder; + typedef basic_string string_type; + + _LIBCPP_HIDE_FROM_ABI explicit time_get(size_t __refs = 0) : locale::facet(__refs) {} + + _LIBCPP_HIDE_FROM_ABI dateorder date_order() const { return this->do_date_order(); } + + _LIBCPP_HIDE_FROM_ABI iter_type + get_time(iter_type __b, iter_type __e, ios_base& __iob, ios_base::iostate& __err, tm* __tm) const { + return do_get_time(__b, __e, __iob, __err, __tm); + } + + _LIBCPP_HIDE_FROM_ABI iter_type + get_date(iter_type __b, iter_type __e, ios_base& __iob, ios_base::iostate& __err, tm* __tm) const { + return do_get_date(__b, __e, __iob, __err, __tm); + } + + _LIBCPP_HIDE_FROM_ABI iter_type + get_weekday(iter_type __b, iter_type __e, ios_base& __iob, ios_base::iostate& __err, tm* __tm) const { + return do_get_weekday(__b, __e, __iob, __err, __tm); + } + + _LIBCPP_HIDE_FROM_ABI iter_type + get_monthname(iter_type __b, iter_type __e, ios_base& __iob, ios_base::iostate& __err, tm* __tm) const { + return do_get_monthname(__b, __e, __iob, __err, __tm); + } + + _LIBCPP_HIDE_FROM_ABI iter_type + get_year(iter_type __b, iter_type __e, ios_base& __iob, ios_base::iostate& __err, tm* __tm) const { + return do_get_year(__b, __e, __iob, __err, __tm); + } + + _LIBCPP_HIDE_FROM_ABI iter_type + get(iter_type __b, iter_type __e, ios_base& __iob, ios_base::iostate& __err, tm* __tm, char __fmt, char __mod = 0) + const { + return do_get(__b, __e, __iob, __err, __tm, __fmt, __mod); + } + + iter_type + get(iter_type __b, + iter_type __e, + ios_base& __iob, + ios_base::iostate& __err, + tm* __tm, + const char_type* __fmtb, + const char_type* __fmte) const; + + static locale::id id; + +protected: + _LIBCPP_HIDE_FROM_ABI_VIRTUAL ~time_get() override {} + + virtual dateorder do_date_order() const; + virtual iter_type + do_get_time(iter_type __b, iter_type __e, ios_base& __iob, ios_base::iostate& __err, tm* __tm) const; + virtual iter_type + do_get_date(iter_type __b, iter_type __e, ios_base& __iob, ios_base::iostate& __err, tm* __tm) const; + virtual iter_type + do_get_weekday(iter_type __b, iter_type __e, ios_base& __iob, ios_base::iostate& __err, tm* __tm) const; + virtual iter_type + do_get_monthname(iter_type __b, iter_type __e, ios_base& __iob, ios_base::iostate& __err, tm* __tm) const; + virtual iter_type + do_get_year(iter_type __b, iter_type __e, ios_base& __iob, ios_base::iostate& __err, tm* __tm) const; + virtual iter_type do_get( + iter_type __b, iter_type __e, ios_base& __iob, ios_base::iostate& __err, tm* __tm, char __fmt, char __mod) const; + +private: + void __get_white_space(iter_type& __b, iter_type __e, ios_base::iostate& __err, const ctype& __ct) const; + void __get_percent(iter_type& __b, iter_type __e, ios_base::iostate& __err, const ctype& __ct) const; + + void __get_weekdayname( + int& __m, iter_type& __b, iter_type __e, ios_base::iostate& __err, const ctype& __ct) const; + void __get_monthname( + int& __m, iter_type& __b, iter_type __e, ios_base::iostate& __err, const ctype& __ct) const; + void __get_day(int& __d, iter_type& __b, iter_type __e, ios_base::iostate& __err, const ctype& __ct) const; + void + __get_month(int& __m, iter_type& __b, iter_type __e, ios_base::iostate& __err, const ctype& __ct) const; + void + __get_year(int& __y, iter_type& __b, iter_type __e, ios_base::iostate& __err, const ctype& __ct) const; + void + __get_year4(int& __y, iter_type& __b, iter_type __e, ios_base::iostate& __err, const ctype& __ct) const; + void + __get_hour(int& __d, iter_type& __b, iter_type __e, ios_base::iostate& __err, const ctype& __ct) const; + void + __get_12_hour(int& __h, iter_type& __b, iter_type __e, ios_base::iostate& __err, const ctype& __ct) const; + void + __get_am_pm(int& __h, iter_type& __b, iter_type __e, ios_base::iostate& __err, const ctype& __ct) const; + void + __get_minute(int& __m, iter_type& __b, iter_type __e, ios_base::iostate& __err, const ctype& __ct) const; + void + __get_second(int& __s, iter_type& __b, iter_type __e, ios_base::iostate& __err, const ctype& __ct) const; + void + __get_weekday(int& __w, iter_type& __b, iter_type __e, ios_base::iostate& __err, const ctype& __ct) const; + void __get_day_year_num( + int& __w, iter_type& __b, iter_type __e, ios_base::iostate& __err, const ctype& __ct) const; +}; + +template +locale::id time_get<_CharT, _InputIterator>::id; + +// time_get primitives + +template +void time_get<_CharT, _InputIterator>::__get_weekdayname( + int& __w, iter_type& __b, iter_type __e, ios_base::iostate& __err, const ctype& __ct) const { + // Note: ignoring case comes from the POSIX strptime spec + const string_type* __wk = this->__weeks(); + ptrdiff_t __i = std::__scan_keyword(__b, __e, __wk, __wk + 14, __ct, __err, false) - __wk; + if (__i < 14) + __w = __i % 7; +} + +template +void time_get<_CharT, _InputIterator>::__get_monthname( + int& __m, iter_type& __b, iter_type __e, ios_base::iostate& __err, const ctype& __ct) const { + // Note: ignoring case comes from the POSIX strptime spec + const string_type* __month = this->__months(); + ptrdiff_t __i = std::__scan_keyword(__b, __e, __month, __month + 24, __ct, __err, false) - __month; + if (__i < 24) + __m = __i % 12; +} + +template +void time_get<_CharT, _InputIterator>::__get_day( + int& __d, iter_type& __b, iter_type __e, ios_base::iostate& __err, const ctype& __ct) const { + int __t = std::__get_up_to_n_digits(__b, __e, __err, __ct, 2); + if (!(__err & ios_base::failbit) && 1 <= __t && __t <= 31) + __d = __t; + else + __err |= ios_base::failbit; +} + +template +void time_get<_CharT, _InputIterator>::__get_month( + int& __m, iter_type& __b, iter_type __e, ios_base::iostate& __err, const ctype& __ct) const { + int __t = std::__get_up_to_n_digits(__b, __e, __err, __ct, 2) - 1; + if (!(__err & ios_base::failbit) && 0 <= __t && __t <= 11) + __m = __t; + else + __err |= ios_base::failbit; +} + +template +void time_get<_CharT, _InputIterator>::__get_year( + int& __y, iter_type& __b, iter_type __e, ios_base::iostate& __err, const ctype& __ct) const { + int __t = std::__get_up_to_n_digits(__b, __e, __err, __ct, 4); + if (!(__err & ios_base::failbit)) { + if (__t < 69) + __t += 2000; + else if (69 <= __t && __t <= 99) + __t += 1900; + __y = __t - 1900; + } +} + +template +void time_get<_CharT, _InputIterator>::__get_year4( + int& __y, iter_type& __b, iter_type __e, ios_base::iostate& __err, const ctype& __ct) const { + int __t = std::__get_up_to_n_digits(__b, __e, __err, __ct, 4); + if (!(__err & ios_base::failbit)) + __y = __t - 1900; +} + +template +void time_get<_CharT, _InputIterator>::__get_hour( + int& __h, iter_type& __b, iter_type __e, ios_base::iostate& __err, const ctype& __ct) const { + int __t = std::__get_up_to_n_digits(__b, __e, __err, __ct, 2); + if (!(__err & ios_base::failbit) && __t <= 23) + __h = __t; + else + __err |= ios_base::failbit; +} + +template +void time_get<_CharT, _InputIterator>::__get_12_hour( + int& __h, iter_type& __b, iter_type __e, ios_base::iostate& __err, const ctype& __ct) const { + int __t = std::__get_up_to_n_digits(__b, __e, __err, __ct, 2); + if (!(__err & ios_base::failbit) && 1 <= __t && __t <= 12) + __h = __t; + else + __err |= ios_base::failbit; +} + +template +void time_get<_CharT, _InputIterator>::__get_minute( + int& __m, iter_type& __b, iter_type __e, ios_base::iostate& __err, const ctype& __ct) const { + int __t = std::__get_up_to_n_digits(__b, __e, __err, __ct, 2); + if (!(__err & ios_base::failbit) && __t <= 59) + __m = __t; + else + __err |= ios_base::failbit; +} + +template +void time_get<_CharT, _InputIterator>::__get_second( + int& __s, iter_type& __b, iter_type __e, ios_base::iostate& __err, const ctype& __ct) const { + int __t = std::__get_up_to_n_digits(__b, __e, __err, __ct, 2); + if (!(__err & ios_base::failbit) && __t <= 60) + __s = __t; + else + __err |= ios_base::failbit; +} + +template +void time_get<_CharT, _InputIterator>::__get_weekday( + int& __w, iter_type& __b, iter_type __e, ios_base::iostate& __err, const ctype& __ct) const { + int __t = std::__get_up_to_n_digits(__b, __e, __err, __ct, 1); + if (!(__err & ios_base::failbit) && __t <= 6) + __w = __t; + else + __err |= ios_base::failbit; +} + +template +void time_get<_CharT, _InputIterator>::__get_day_year_num( + int& __d, iter_type& __b, iter_type __e, ios_base::iostate& __err, const ctype& __ct) const { + int __t = std::__get_up_to_n_digits(__b, __e, __err, __ct, 3); + if (!(__err & ios_base::failbit) && __t <= 365) + __d = __t; + else + __err |= ios_base::failbit; +} + +template +void time_get<_CharT, _InputIterator>::__get_white_space( + iter_type& __b, iter_type __e, ios_base::iostate& __err, const ctype& __ct) const { + for (; __b != __e && __ct.is(ctype_base::space, *__b); ++__b) + ; + if (__b == __e) + __err |= ios_base::eofbit; +} + +template +void time_get<_CharT, _InputIterator>::__get_am_pm( + int& __h, iter_type& __b, iter_type __e, ios_base::iostate& __err, const ctype& __ct) const { + const string_type* __ap = this->__am_pm(); + if (__ap[0].size() + __ap[1].size() == 0) { + __err |= ios_base::failbit; + return; + } + ptrdiff_t __i = std::__scan_keyword(__b, __e, __ap, __ap + 2, __ct, __err, false) - __ap; + if (__i == 0 && __h == 12) + __h = 0; + else if (__i == 1 && __h < 12) + __h += 12; +} + +template +void time_get<_CharT, _InputIterator>::__get_percent( + iter_type& __b, iter_type __e, ios_base::iostate& __err, const ctype& __ct) const { + if (__b == __e) { + __err |= ios_base::eofbit | ios_base::failbit; + return; + } + if (__ct.narrow(*__b, 0) != '%') + __err |= ios_base::failbit; + else if (++__b == __e) + __err |= ios_base::eofbit; +} + +// time_get end primitives + +template +_InputIterator time_get<_CharT, _InputIterator>::get( + iter_type __b, + iter_type __e, + ios_base& __iob, + ios_base::iostate& __err, + tm* __tm, + const char_type* __fmtb, + const char_type* __fmte) const { + const ctype& __ct = std::use_facet >(__iob.getloc()); + __err = ios_base::goodbit; + while (__fmtb != __fmte && __err == ios_base::goodbit) { + if (__b == __e) { + __err = ios_base::failbit; + break; + } + if (__ct.narrow(*__fmtb, 0) == '%') { + if (++__fmtb == __fmte) { + __err = ios_base::failbit; + break; + } + char __cmd = __ct.narrow(*__fmtb, 0); + char __opt = '\0'; + if (__cmd == 'E' || __cmd == '0') { + if (++__fmtb == __fmte) { + __err = ios_base::failbit; + break; + } + __opt = __cmd; + __cmd = __ct.narrow(*__fmtb, 0); + } + __b = do_get(__b, __e, __iob, __err, __tm, __cmd, __opt); + ++__fmtb; + } else if (__ct.is(ctype_base::space, *__fmtb)) { + for (++__fmtb; __fmtb != __fmte && __ct.is(ctype_base::space, *__fmtb); ++__fmtb) + ; + for (; __b != __e && __ct.is(ctype_base::space, *__b); ++__b) + ; + } else if (__ct.toupper(*__b) == __ct.toupper(*__fmtb)) { + ++__b; + ++__fmtb; + } else + __err = ios_base::failbit; + } + if (__b == __e) + __err |= ios_base::eofbit; + return __b; +} + +template +typename time_get<_CharT, _InputIterator>::dateorder time_get<_CharT, _InputIterator>::do_date_order() const { + return mdy; +} + +template +_InputIterator time_get<_CharT, _InputIterator>::do_get_time( + iter_type __b, iter_type __e, ios_base& __iob, ios_base::iostate& __err, tm* __tm) const { + const char_type __fmt[] = {'%', 'H', ':', '%', 'M', ':', '%', 'S'}; + return get(__b, __e, __iob, __err, __tm, __fmt, __fmt + sizeof(__fmt) / sizeof(__fmt[0])); +} + +template +_InputIterator time_get<_CharT, _InputIterator>::do_get_date( + iter_type __b, iter_type __e, ios_base& __iob, ios_base::iostate& __err, tm* __tm) const { + const string_type& __fmt = this->__x(); + return get(__b, __e, __iob, __err, __tm, __fmt.data(), __fmt.data() + __fmt.size()); +} + +template +_InputIterator time_get<_CharT, _InputIterator>::do_get_weekday( + iter_type __b, iter_type __e, ios_base& __iob, ios_base::iostate& __err, tm* __tm) const { + const ctype& __ct = std::use_facet >(__iob.getloc()); + __get_weekdayname(__tm->tm_wday, __b, __e, __err, __ct); + return __b; +} + +template +_InputIterator time_get<_CharT, _InputIterator>::do_get_monthname( + iter_type __b, iter_type __e, ios_base& __iob, ios_base::iostate& __err, tm* __tm) const { + const ctype& __ct = std::use_facet >(__iob.getloc()); + __get_monthname(__tm->tm_mon, __b, __e, __err, __ct); + return __b; +} + +template +_InputIterator time_get<_CharT, _InputIterator>::do_get_year( + iter_type __b, iter_type __e, ios_base& __iob, ios_base::iostate& __err, tm* __tm) const { + const ctype& __ct = std::use_facet >(__iob.getloc()); + __get_year(__tm->tm_year, __b, __e, __err, __ct); + return __b; +} + +template +_InputIterator time_get<_CharT, _InputIterator>::do_get( + iter_type __b, iter_type __e, ios_base& __iob, ios_base::iostate& __err, tm* __tm, char __fmt, char) const { + __err = ios_base::goodbit; + const ctype& __ct = std::use_facet >(__iob.getloc()); + switch (__fmt) { + case 'a': + case 'A': + __get_weekdayname(__tm->tm_wday, __b, __e, __err, __ct); + break; + case 'b': + case 'B': + case 'h': + __get_monthname(__tm->tm_mon, __b, __e, __err, __ct); + break; + case 'c': { + const string_type& __fm = this->__c(); + __b = get(__b, __e, __iob, __err, __tm, __fm.data(), __fm.data() + __fm.size()); + } break; + case 'd': + case 'e': + __get_day(__tm->tm_mday, __b, __e, __err, __ct); + break; + case 'D': { + const char_type __fm[] = {'%', 'm', '/', '%', 'd', '/', '%', 'y'}; + __b = get(__b, __e, __iob, __err, __tm, __fm, __fm + sizeof(__fm) / sizeof(__fm[0])); + } break; + case 'F': { + const char_type __fm[] = {'%', 'Y', '-', '%', 'm', '-', '%', 'd'}; + __b = get(__b, __e, __iob, __err, __tm, __fm, __fm + sizeof(__fm) / sizeof(__fm[0])); + } break; + case 'H': + __get_hour(__tm->tm_hour, __b, __e, __err, __ct); + break; + case 'I': + __get_12_hour(__tm->tm_hour, __b, __e, __err, __ct); + break; + case 'j': + __get_day_year_num(__tm->tm_yday, __b, __e, __err, __ct); + break; + case 'm': + __get_month(__tm->tm_mon, __b, __e, __err, __ct); + break; + case 'M': + __get_minute(__tm->tm_min, __b, __e, __err, __ct); + break; + case 'n': + case 't': + __get_white_space(__b, __e, __err, __ct); + break; + case 'p': + __get_am_pm(__tm->tm_hour, __b, __e, __err, __ct); + break; + case 'r': { + const char_type __fm[] = {'%', 'I', ':', '%', 'M', ':', '%', 'S', ' ', '%', 'p'}; + __b = get(__b, __e, __iob, __err, __tm, __fm, __fm + sizeof(__fm) / sizeof(__fm[0])); + } break; + case 'R': { + const char_type __fm[] = {'%', 'H', ':', '%', 'M'}; + __b = get(__b, __e, __iob, __err, __tm, __fm, __fm + sizeof(__fm) / sizeof(__fm[0])); + } break; + case 'S': + __get_second(__tm->tm_sec, __b, __e, __err, __ct); + break; + case 'T': { + const char_type __fm[] = {'%', 'H', ':', '%', 'M', ':', '%', 'S'}; + __b = get(__b, __e, __iob, __err, __tm, __fm, __fm + sizeof(__fm) / sizeof(__fm[0])); + } break; + case 'w': + __get_weekday(__tm->tm_wday, __b, __e, __err, __ct); + break; + case 'x': + return do_get_date(__b, __e, __iob, __err, __tm); + case 'X': { + const string_type& __fm = this->__X(); + __b = get(__b, __e, __iob, __err, __tm, __fm.data(), __fm.data() + __fm.size()); + } break; + case 'y': + __get_year(__tm->tm_year, __b, __e, __err, __ct); + break; + case 'Y': + __get_year4(__tm->tm_year, __b, __e, __err, __ct); + break; + case '%': + __get_percent(__b, __e, __err, __ct); + break; + default: + __err |= ios_base::failbit; + } + return __b; +} + +extern template class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS time_get; +# if _LIBCPP_HAS_WIDE_CHARACTERS +extern template class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS time_get; +# endif + +class _LIBCPP_EXPORTED_FROM_ABI __time_get { +protected: + __locale::__locale_t __loc_; + + __time_get(const char* __nm); + __time_get(const string& __nm); + ~__time_get(); +}; + +template +class __time_get_storage : public __time_get { +protected: + typedef basic_string<_CharT> string_type; + + string_type __weeks_[14]; + string_type __months_[24]; + string_type __am_pm_[2]; + string_type __c_; + string_type __r_; + string_type __x_; + string_type __X_; + + explicit __time_get_storage(const char* __nm); + explicit __time_get_storage(const string& __nm); + + _LIBCPP_HIDE_FROM_ABI ~__time_get_storage() {} + + time_base::dateorder __do_date_order() const; + +private: + void init(const ctype<_CharT>&); + string_type __analyze(char __fmt, const ctype<_CharT>&); +}; + +# define _LIBCPP_TIME_GET_STORAGE_EXPLICIT_INSTANTIATION(_CharT) \ + template <> \ + _LIBCPP_EXPORTED_FROM_ABI time_base::dateorder __time_get_storage<_CharT>::__do_date_order() const; \ + template <> \ + _LIBCPP_EXPORTED_FROM_ABI __time_get_storage<_CharT>::__time_get_storage(const char*); \ + template <> \ + _LIBCPP_EXPORTED_FROM_ABI __time_get_storage<_CharT>::__time_get_storage(const string&); \ + template <> \ + _LIBCPP_EXPORTED_FROM_ABI void __time_get_storage<_CharT>::init(const ctype<_CharT>&); \ + template <> \ + _LIBCPP_EXPORTED_FROM_ABI __time_get_storage<_CharT>::string_type __time_get_storage<_CharT>::__analyze( \ + char, const ctype<_CharT>&); \ + extern template _LIBCPP_EXPORTED_FROM_ABI time_base::dateorder __time_get_storage<_CharT>::__do_date_order() \ + const; \ + extern template _LIBCPP_EXPORTED_FROM_ABI __time_get_storage<_CharT>::__time_get_storage(const char*); \ + extern template _LIBCPP_EXPORTED_FROM_ABI __time_get_storage<_CharT>::__time_get_storage(const string&); \ + extern template _LIBCPP_EXPORTED_FROM_ABI void __time_get_storage<_CharT>::init(const ctype<_CharT>&); \ + extern template _LIBCPP_EXPORTED_FROM_ABI __time_get_storage<_CharT>::string_type \ + __time_get_storage<_CharT>::__analyze(char, const ctype<_CharT>&); + +_LIBCPP_TIME_GET_STORAGE_EXPLICIT_INSTANTIATION(char) +# if _LIBCPP_HAS_WIDE_CHARACTERS +_LIBCPP_TIME_GET_STORAGE_EXPLICIT_INSTANTIATION(wchar_t) +# endif +# undef _LIBCPP_TIME_GET_STORAGE_EXPLICIT_INSTANTIATION + +template > +class time_get_byname : public time_get<_CharT, _InputIterator>, private __time_get_storage<_CharT> { +public: + typedef time_base::dateorder dateorder; + typedef _InputIterator iter_type; + typedef _CharT char_type; + typedef basic_string string_type; + + _LIBCPP_HIDE_FROM_ABI explicit time_get_byname(const char* __nm, size_t __refs = 0) + : time_get<_CharT, _InputIterator>(__refs), __time_get_storage<_CharT>(__nm) {} + _LIBCPP_HIDE_FROM_ABI explicit time_get_byname(const string& __nm, size_t __refs = 0) + : time_get<_CharT, _InputIterator>(__refs), __time_get_storage<_CharT>(__nm) {} + +protected: + _LIBCPP_HIDE_FROM_ABI_VIRTUAL ~time_get_byname() override {} + + _LIBCPP_HIDE_FROM_ABI_VIRTUAL dateorder do_date_order() const override { return this->__do_date_order(); } + +private: + _LIBCPP_HIDE_FROM_ABI_VIRTUAL const string_type* __weeks() const override { return this->__weeks_; } + _LIBCPP_HIDE_FROM_ABI_VIRTUAL const string_type* __months() const override { return this->__months_; } + _LIBCPP_HIDE_FROM_ABI_VIRTUAL const string_type* __am_pm() const override { return this->__am_pm_; } + _LIBCPP_HIDE_FROM_ABI_VIRTUAL const string_type& __c() const override { return this->__c_; } + _LIBCPP_HIDE_FROM_ABI_VIRTUAL const string_type& __r() const override { return this->__r_; } + _LIBCPP_HIDE_FROM_ABI_VIRTUAL const string_type& __x() const override { return this->__x_; } + _LIBCPP_HIDE_FROM_ABI_VIRTUAL const string_type& __X() const override { return this->__X_; } +}; + +extern template class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS time_get_byname; +# if _LIBCPP_HAS_WIDE_CHARACTERS +extern template class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS time_get_byname; +# endif + +class _LIBCPP_EXPORTED_FROM_ABI __time_put { + __locale::__locale_t __loc_; + +protected: + _LIBCPP_HIDE_FROM_ABI __time_put() : __loc_(_LIBCPP_GET_C_LOCALE) {} + __time_put(const char* __nm); + __time_put(const string& __nm); + ~__time_put(); + void __do_put(char* __nb, char*& __ne, const tm* __tm, char __fmt, char __mod) const; +# if _LIBCPP_HAS_WIDE_CHARACTERS + void __do_put(wchar_t* __wb, wchar_t*& __we, const tm* __tm, char __fmt, char __mod) const; +# endif +}; + +template > +class time_put : public locale::facet, private __time_put { +public: + typedef _CharT char_type; + typedef _OutputIterator iter_type; + + _LIBCPP_HIDE_FROM_ABI explicit time_put(size_t __refs = 0) : locale::facet(__refs) {} + + iter_type + put(iter_type __s, ios_base& __iob, char_type __fl, const tm* __tm, const char_type* __pb, const char_type* __pe) + const; + + _LIBCPP_HIDE_FROM_ABI iter_type + put(iter_type __s, ios_base& __iob, char_type __fl, const tm* __tm, char __fmt, char __mod = 0) const { + return do_put(__s, __iob, __fl, __tm, __fmt, __mod); + } + + static locale::id id; + +protected: + _LIBCPP_HIDE_FROM_ABI_VIRTUAL ~time_put() override {} + virtual iter_type do_put(iter_type __s, ios_base&, char_type, const tm* __tm, char __fmt, char __mod) const; + + _LIBCPP_HIDE_FROM_ABI explicit time_put(const char* __nm, size_t __refs) : locale::facet(__refs), __time_put(__nm) {} + _LIBCPP_HIDE_FROM_ABI explicit time_put(const string& __nm, size_t __refs) + : locale::facet(__refs), __time_put(__nm) {} +}; + +template +locale::id time_put<_CharT, _OutputIterator>::id; + +template +_OutputIterator time_put<_CharT, _OutputIterator>::put( + iter_type __s, ios_base& __iob, char_type __fl, const tm* __tm, const char_type* __pb, const char_type* __pe) + const { + const ctype& __ct = std::use_facet >(__iob.getloc()); + for (; __pb != __pe; ++__pb) { + if (__ct.narrow(*__pb, 0) == '%') { + if (++__pb == __pe) { + *__s++ = __pb[-1]; + break; + } + char __mod = 0; + char __fmt = __ct.narrow(*__pb, 0); + if (__fmt == 'E' || __fmt == 'O') { + if (++__pb == __pe) { + *__s++ = __pb[-2]; + *__s++ = __pb[-1]; + break; + } + __mod = __fmt; + __fmt = __ct.narrow(*__pb, 0); + } + __s = do_put(__s, __iob, __fl, __tm, __fmt, __mod); + } else + *__s++ = *__pb; + } + return __s; +} + +template +_OutputIterator time_put<_CharT, _OutputIterator>::do_put( + iter_type __s, ios_base&, char_type, const tm* __tm, char __fmt, char __mod) const { + char_type __nar[100]; + char_type* __nb = __nar; + char_type* __ne = __nb + 100; + __do_put(__nb, __ne, __tm, __fmt, __mod); + return std::copy(__nb, __ne, __s); +} + +extern template class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS time_put; +# if _LIBCPP_HAS_WIDE_CHARACTERS +extern template class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS time_put; +# endif + +template > +class time_put_byname : public time_put<_CharT, _OutputIterator> { +public: + _LIBCPP_HIDE_FROM_ABI explicit time_put_byname(const char* __nm, size_t __refs = 0) + : time_put<_CharT, _OutputIterator>(__nm, __refs) {} + + _LIBCPP_HIDE_FROM_ABI explicit time_put_byname(const string& __nm, size_t __refs = 0) + : time_put<_CharT, _OutputIterator>(__nm, __refs) {} + +protected: + _LIBCPP_HIDE_FROM_ABI_VIRTUAL ~time_put_byname() override {} +}; + +extern template class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS time_put_byname; +# if _LIBCPP_HAS_WIDE_CHARACTERS +extern template class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS time_put_byname; +# endif + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP_HAS_LOCALIZATION + +#endif // _LIBCPP___LOCALE_DIR_TIME_H diff --git a/lib/libcxx/include/__locale_dir/wbuffer_convert.h b/lib/libcxx/include/__locale_dir/wbuffer_convert.h new file mode 100644 index 0000000000..a6818aadf5 --- /dev/null +++ b/lib/libcxx/include/__locale_dir/wbuffer_convert.h @@ -0,0 +1,430 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___LOCALE_DIR_WBUFFER_CONVERT_H +#define _LIBCPP___LOCALE_DIR_WBUFFER_CONVERT_H + +#include <__algorithm/reverse.h> +#include <__config> +#include <__string/char_traits.h> +#include +#include + +#if _LIBCPP_HAS_LOCALIZATION + +# if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +# endif + +# if _LIBCPP_STD_VER < 26 || defined(_LIBCPP_ENABLE_CXX26_REMOVED_WSTRING_CONVERT) + +_LIBCPP_PUSH_MACROS +# include <__undef_macros> + +_LIBCPP_BEGIN_NAMESPACE_STD + +template > +class _LIBCPP_DEPRECATED_IN_CXX17 wbuffer_convert : public basic_streambuf<_Elem, _Tr> { +public: + // types: + typedef _Elem char_type; + typedef _Tr traits_type; + typedef typename traits_type::int_type int_type; + typedef typename traits_type::pos_type pos_type; + typedef typename traits_type::off_type off_type; + typedef typename _Codecvt::state_type state_type; + +private: + char* __extbuf_; + const char* __extbufnext_; + const char* __extbufend_; + char __extbuf_min_[8]; + size_t __ebs_; + char_type* __intbuf_; + size_t __ibs_; + streambuf* __bufptr_; + _Codecvt* __cv_; + state_type __st_; + ios_base::openmode __cm_; + bool __owns_eb_; + bool __owns_ib_; + bool __always_noconv_; + +public: +# ifndef _LIBCPP_CXX03_LANG + _LIBCPP_HIDE_FROM_ABI wbuffer_convert() : wbuffer_convert(nullptr) {} + explicit _LIBCPP_HIDE_FROM_ABI + wbuffer_convert(streambuf* __bytebuf, _Codecvt* __pcvt = new _Codecvt, state_type __state = state_type()); +# else + _LIBCPP_EXPLICIT_SINCE_CXX14 _LIBCPP_HIDE_FROM_ABI + wbuffer_convert(streambuf* __bytebuf = nullptr, _Codecvt* __pcvt = new _Codecvt, state_type __state = state_type()); +# endif + + _LIBCPP_HIDE_FROM_ABI ~wbuffer_convert(); + + _LIBCPP_HIDE_FROM_ABI streambuf* rdbuf() const { return __bufptr_; } + _LIBCPP_HIDE_FROM_ABI streambuf* rdbuf(streambuf* __bytebuf) { + streambuf* __r = __bufptr_; + __bufptr_ = __bytebuf; + return __r; + } + + wbuffer_convert(const wbuffer_convert&) = delete; + wbuffer_convert& operator=(const wbuffer_convert&) = delete; + + _LIBCPP_HIDE_FROM_ABI state_type state() const { return __st_; } + +protected: + _LIBCPP_HIDE_FROM_ABI_VIRTUAL virtual int_type underflow(); + _LIBCPP_HIDE_FROM_ABI_VIRTUAL virtual int_type pbackfail(int_type __c = traits_type::eof()); + _LIBCPP_HIDE_FROM_ABI_VIRTUAL virtual int_type overflow(int_type __c = traits_type::eof()); + _LIBCPP_HIDE_FROM_ABI_VIRTUAL virtual basic_streambuf* setbuf(char_type* __s, streamsize __n); + _LIBCPP_HIDE_FROM_ABI_VIRTUAL virtual pos_type + seekoff(off_type __off, ios_base::seekdir __way, ios_base::openmode __wch = ios_base::in | ios_base::out); + _LIBCPP_HIDE_FROM_ABI_VIRTUAL virtual pos_type + seekpos(pos_type __sp, ios_base::openmode __wch = ios_base::in | ios_base::out); + _LIBCPP_HIDE_FROM_ABI_VIRTUAL virtual int sync(); + +private: + _LIBCPP_HIDE_FROM_ABI_VIRTUAL bool __read_mode(); + _LIBCPP_HIDE_FROM_ABI_VIRTUAL void __write_mode(); + _LIBCPP_HIDE_FROM_ABI_VIRTUAL wbuffer_convert* __close(); +}; + +_LIBCPP_SUPPRESS_DEPRECATED_PUSH +template +wbuffer_convert<_Codecvt, _Elem, _Tr>::wbuffer_convert(streambuf* __bytebuf, _Codecvt* __pcvt, state_type __state) + : __extbuf_(nullptr), + __extbufnext_(nullptr), + __extbufend_(nullptr), + __ebs_(0), + __intbuf_(0), + __ibs_(0), + __bufptr_(__bytebuf), + __cv_(__pcvt), + __st_(__state), + __cm_(0), + __owns_eb_(false), + __owns_ib_(false), + __always_noconv_(__cv_ ? __cv_->always_noconv() : false) { + setbuf(0, 4096); +} + +template +wbuffer_convert<_Codecvt, _Elem, _Tr>::~wbuffer_convert() { + __close(); + delete __cv_; + if (__owns_eb_) + delete[] __extbuf_; + if (__owns_ib_) + delete[] __intbuf_; +} + +template +typename wbuffer_convert<_Codecvt, _Elem, _Tr>::int_type wbuffer_convert<_Codecvt, _Elem, _Tr>::underflow() { + _LIBCPP_SUPPRESS_DEPRECATED_POP + if (__cv_ == 0 || __bufptr_ == nullptr) + return traits_type::eof(); + bool __initial = __read_mode(); + char_type __1buf; + if (this->gptr() == 0) + this->setg(std::addressof(__1buf), std::addressof(__1buf) + 1, std::addressof(__1buf) + 1); + const size_t __unget_sz = __initial ? 0 : std::min((this->egptr() - this->eback()) / 2, 4); + int_type __c = traits_type::eof(); + if (this->gptr() == this->egptr()) { + std::memmove(this->eback(), this->egptr() - __unget_sz, __unget_sz * sizeof(char_type)); + if (__always_noconv_) { + streamsize __nmemb = static_cast(this->egptr() - this->eback() - __unget_sz); + __nmemb = __bufptr_->sgetn((char*)this->eback() + __unget_sz, __nmemb); + if (__nmemb != 0) { + this->setg(this->eback(), this->eback() + __unget_sz, this->eback() + __unget_sz + __nmemb); + __c = *this->gptr(); + } + } else { + if (__extbufend_ != __extbufnext_) { + _LIBCPP_ASSERT_NON_NULL(__extbufnext_ != nullptr, "underflow moving from nullptr"); + _LIBCPP_ASSERT_NON_NULL(__extbuf_ != nullptr, "underflow moving into nullptr"); + std::memmove(__extbuf_, __extbufnext_, __extbufend_ - __extbufnext_); + } + __extbufnext_ = __extbuf_ + (__extbufend_ - __extbufnext_); + __extbufend_ = __extbuf_ + (__extbuf_ == __extbuf_min_ ? sizeof(__extbuf_min_) : __ebs_); + streamsize __nmemb = std::min(static_cast(this->egptr() - this->eback() - __unget_sz), + static_cast(__extbufend_ - __extbufnext_)); + codecvt_base::result __r; + // FIXME: Do we ever need to restore the state here? + // state_type __svs = __st_; + streamsize __nr = __bufptr_->sgetn(const_cast(__extbufnext_), __nmemb); + if (__nr != 0) { + __extbufend_ = __extbufnext_ + __nr; + char_type* __inext; + __r = __cv_->in( + __st_, __extbuf_, __extbufend_, __extbufnext_, this->eback() + __unget_sz, this->egptr(), __inext); + if (__r == codecvt_base::noconv) { + this->setg((char_type*)__extbuf_, (char_type*)__extbuf_, (char_type*)const_cast(__extbufend_)); + __c = *this->gptr(); + } else if (__inext != this->eback() + __unget_sz) { + this->setg(this->eback(), this->eback() + __unget_sz, __inext); + __c = *this->gptr(); + } + } + } + } else + __c = *this->gptr(); + if (this->eback() == std::addressof(__1buf)) + this->setg(0, 0, 0); + return __c; +} + +_LIBCPP_SUPPRESS_DEPRECATED_PUSH +template +typename wbuffer_convert<_Codecvt, _Elem, _Tr>::int_type +wbuffer_convert<_Codecvt, _Elem, _Tr>::pbackfail(int_type __c) { + _LIBCPP_SUPPRESS_DEPRECATED_POP + if (__cv_ != 0 && __bufptr_ && this->eback() < this->gptr()) { + if (traits_type::eq_int_type(__c, traits_type::eof())) { + this->gbump(-1); + return traits_type::not_eof(__c); + } + if (traits_type::eq(traits_type::to_char_type(__c), this->gptr()[-1])) { + this->gbump(-1); + *this->gptr() = traits_type::to_char_type(__c); + return __c; + } + } + return traits_type::eof(); +} + +_LIBCPP_SUPPRESS_DEPRECATED_PUSH +template +typename wbuffer_convert<_Codecvt, _Elem, _Tr>::int_type wbuffer_convert<_Codecvt, _Elem, _Tr>::overflow(int_type __c) { + _LIBCPP_SUPPRESS_DEPRECATED_POP + if (__cv_ == 0 || !__bufptr_) + return traits_type::eof(); + __write_mode(); + char_type __1buf; + char_type* __pb_save = this->pbase(); + char_type* __epb_save = this->epptr(); + if (!traits_type::eq_int_type(__c, traits_type::eof())) { + if (this->pptr() == 0) + this->setp(std::addressof(__1buf), std::addressof(__1buf) + 1); + *this->pptr() = traits_type::to_char_type(__c); + this->pbump(1); + } + if (this->pptr() != this->pbase()) { + if (__always_noconv_) { + streamsize __nmemb = static_cast(this->pptr() - this->pbase()); + if (__bufptr_->sputn((const char*)this->pbase(), __nmemb) != __nmemb) + return traits_type::eof(); + } else { + char* __extbe = __extbuf_; + codecvt_base::result __r; + do { + const char_type* __e; + __r = __cv_->out(__st_, this->pbase(), this->pptr(), __e, __extbuf_, __extbuf_ + __ebs_, __extbe); + if (__e == this->pbase()) + return traits_type::eof(); + if (__r == codecvt_base::noconv) { + streamsize __nmemb = static_cast(this->pptr() - this->pbase()); + if (__bufptr_->sputn((const char*)this->pbase(), __nmemb) != __nmemb) + return traits_type::eof(); + } else if (__r == codecvt_base::ok || __r == codecvt_base::partial) { + streamsize __nmemb = static_cast(__extbe - __extbuf_); + if (__bufptr_->sputn(__extbuf_, __nmemb) != __nmemb) + return traits_type::eof(); + if (__r == codecvt_base::partial) { + this->setp(const_cast(__e), this->pptr()); + this->__pbump(this->epptr() - this->pbase()); + } + } else + return traits_type::eof(); + } while (__r == codecvt_base::partial); + } + this->setp(__pb_save, __epb_save); + } + return traits_type::not_eof(__c); +} + +_LIBCPP_SUPPRESS_DEPRECATED_PUSH +template +basic_streambuf<_Elem, _Tr>* wbuffer_convert<_Codecvt, _Elem, _Tr>::setbuf(char_type* __s, streamsize __n) { + _LIBCPP_SUPPRESS_DEPRECATED_POP + this->setg(0, 0, 0); + this->setp(0, 0); + if (__owns_eb_) + delete[] __extbuf_; + if (__owns_ib_) + delete[] __intbuf_; + __ebs_ = __n; + if (__ebs_ > sizeof(__extbuf_min_)) { + if (__always_noconv_ && __s) { + __extbuf_ = (char*)__s; + __owns_eb_ = false; + } else { + __extbuf_ = new char[__ebs_]; + __owns_eb_ = true; + } + } else { + __extbuf_ = __extbuf_min_; + __ebs_ = sizeof(__extbuf_min_); + __owns_eb_ = false; + } + if (!__always_noconv_) { + __ibs_ = max(__n, sizeof(__extbuf_min_)); + if (__s && __ibs_ >= sizeof(__extbuf_min_)) { + __intbuf_ = __s; + __owns_ib_ = false; + } else { + __intbuf_ = new char_type[__ibs_]; + __owns_ib_ = true; + } + } else { + __ibs_ = 0; + __intbuf_ = 0; + __owns_ib_ = false; + } + return this; +} + +_LIBCPP_SUPPRESS_DEPRECATED_PUSH +template +typename wbuffer_convert<_Codecvt, _Elem, _Tr>::pos_type +wbuffer_convert<_Codecvt, _Elem, _Tr>::seekoff(off_type __off, ios_base::seekdir __way, ios_base::openmode __om) { + int __width = __cv_->encoding(); + if (__cv_ == 0 || !__bufptr_ || (__width <= 0 && __off != 0) || sync()) + return pos_type(off_type(-1)); + // __width > 0 || __off == 0, now check __way + if (__way != ios_base::beg && __way != ios_base::cur && __way != ios_base::end) + return pos_type(off_type(-1)); + pos_type __r = __bufptr_->pubseekoff(__width * __off, __way, __om); + __r.state(__st_); + return __r; +} + +template +typename wbuffer_convert<_Codecvt, _Elem, _Tr>::pos_type +wbuffer_convert<_Codecvt, _Elem, _Tr>::seekpos(pos_type __sp, ios_base::openmode __wch) { + if (__cv_ == 0 || !__bufptr_ || sync()) + return pos_type(off_type(-1)); + if (__bufptr_->pubseekpos(__sp, __wch) == pos_type(off_type(-1))) + return pos_type(off_type(-1)); + return __sp; +} + +template +int wbuffer_convert<_Codecvt, _Elem, _Tr>::sync() { + _LIBCPP_SUPPRESS_DEPRECATED_POP + if (__cv_ == 0 || !__bufptr_) + return 0; + if (__cm_ & ios_base::out) { + if (this->pptr() != this->pbase()) + if (overflow() == traits_type::eof()) + return -1; + codecvt_base::result __r; + do { + char* __extbe; + __r = __cv_->unshift(__st_, __extbuf_, __extbuf_ + __ebs_, __extbe); + streamsize __nmemb = static_cast(__extbe - __extbuf_); + if (__bufptr_->sputn(__extbuf_, __nmemb) != __nmemb) + return -1; + } while (__r == codecvt_base::partial); + if (__r == codecvt_base::error) + return -1; + if (__bufptr_->pubsync()) + return -1; + } else if (__cm_ & ios_base::in) { + off_type __c; + if (__always_noconv_) + __c = this->egptr() - this->gptr(); + else { + int __width = __cv_->encoding(); + __c = __extbufend_ - __extbufnext_; + if (__width > 0) + __c += __width * (this->egptr() - this->gptr()); + else { + if (this->gptr() != this->egptr()) { + std::reverse(this->gptr(), this->egptr()); + codecvt_base::result __r; + const char_type* __e = this->gptr(); + char* __extbe; + do { + __r = __cv_->out(__st_, __e, this->egptr(), __e, __extbuf_, __extbuf_ + __ebs_, __extbe); + switch (__r) { + case codecvt_base::noconv: + __c += this->egptr() - this->gptr(); + break; + case codecvt_base::ok: + case codecvt_base::partial: + __c += __extbe - __extbuf_; + break; + default: + return -1; + } + } while (__r == codecvt_base::partial); + } + } + } + if (__bufptr_->pubseekoff(-__c, ios_base::cur, __cm_) == pos_type(off_type(-1))) + return -1; + this->setg(0, 0, 0); + __cm_ = 0; + } + return 0; +} + +_LIBCPP_SUPPRESS_DEPRECATED_PUSH +template +bool wbuffer_convert<_Codecvt, _Elem, _Tr>::__read_mode() { + if (!(__cm_ & ios_base::in)) { + this->setp(0, 0); + if (__always_noconv_) + this->setg((char_type*)__extbuf_, (char_type*)__extbuf_ + __ebs_, (char_type*)__extbuf_ + __ebs_); + else + this->setg(__intbuf_, __intbuf_ + __ibs_, __intbuf_ + __ibs_); + __cm_ = ios_base::in; + return true; + } + return false; +} + +template +void wbuffer_convert<_Codecvt, _Elem, _Tr>::__write_mode() { + if (!(__cm_ & ios_base::out)) { + this->setg(0, 0, 0); + if (__ebs_ > sizeof(__extbuf_min_)) { + if (__always_noconv_) + this->setp((char_type*)__extbuf_, (char_type*)__extbuf_ + (__ebs_ - 1)); + else + this->setp(__intbuf_, __intbuf_ + (__ibs_ - 1)); + } else + this->setp(0, 0); + __cm_ = ios_base::out; + } +} + +template +wbuffer_convert<_Codecvt, _Elem, _Tr>* wbuffer_convert<_Codecvt, _Elem, _Tr>::__close() { + wbuffer_convert* __rt = nullptr; + if (__cv_ != nullptr && __bufptr_ != nullptr) { + __rt = this; + if ((__cm_ & ios_base::out) && sync()) + __rt = nullptr; + } + return __rt; +} + +_LIBCPP_SUPPRESS_DEPRECATED_POP + +_LIBCPP_END_NAMESPACE_STD + +_LIBCPP_POP_MACROS + +# endif // _LIBCPP_STD_VER < 26 || defined(_LIBCPP_ENABLE_CXX26_REMOVED_WSTRING_CONVERT) + +#endif // _LIBCPP_HAS_LOCALIZATION + +#endif // _LIBCPP___LOCALE_DIR_WBUFFER_CONVERT_H diff --git a/lib/libcxx/include/__locale_dir/wstring_convert.h b/lib/libcxx/include/__locale_dir/wstring_convert.h new file mode 100644 index 0000000000..42a56eb857 --- /dev/null +++ b/lib/libcxx/include/__locale_dir/wstring_convert.h @@ -0,0 +1,254 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___LOCALE_DIR_WSTRING_CONVERT_H +#define _LIBCPP___LOCALE_DIR_WSTRING_CONVERT_H + +#include <__config> +#include <__locale> +#include <__memory/allocator.h> +#include + +#if _LIBCPP_HAS_LOCALIZATION + +# if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +# endif + +# if _LIBCPP_STD_VER < 26 || defined(_LIBCPP_ENABLE_CXX26_REMOVED_WSTRING_CONVERT) + +_LIBCPP_PUSH_MACROS +# include <__undef_macros> + +_LIBCPP_BEGIN_NAMESPACE_STD + +template , + class _ByteAlloc = allocator > +class _LIBCPP_DEPRECATED_IN_CXX17 wstring_convert { +public: + typedef basic_string, _ByteAlloc> byte_string; + typedef basic_string<_Elem, char_traits<_Elem>, _WideAlloc> wide_string; + typedef typename _Codecvt::state_type state_type; + typedef typename wide_string::traits_type::int_type int_type; + +private: + byte_string __byte_err_string_; + wide_string __wide_err_string_; + _Codecvt* __cvtptr_; + state_type __cvtstate_; + size_t __cvtcount_; + +public: +# ifndef _LIBCPP_CXX03_LANG + _LIBCPP_HIDE_FROM_ABI wstring_convert() : wstring_convert(new _Codecvt) {} + _LIBCPP_HIDE_FROM_ABI explicit wstring_convert(_Codecvt* __pcvt); +# else + _LIBCPP_HIDE_FROM_ABI _LIBCPP_EXPLICIT_SINCE_CXX14 wstring_convert(_Codecvt* __pcvt = new _Codecvt); +# endif + + _LIBCPP_HIDE_FROM_ABI wstring_convert(_Codecvt* __pcvt, state_type __state); + _LIBCPP_EXPLICIT_SINCE_CXX14 _LIBCPP_HIDE_FROM_ABI + wstring_convert(const byte_string& __byte_err, const wide_string& __wide_err = wide_string()); +# ifndef _LIBCPP_CXX03_LANG + _LIBCPP_HIDE_FROM_ABI wstring_convert(wstring_convert&& __wc); +# endif + _LIBCPP_HIDE_FROM_ABI ~wstring_convert(); + + wstring_convert(const wstring_convert& __wc) = delete; + wstring_convert& operator=(const wstring_convert& __wc) = delete; + + _LIBCPP_HIDE_FROM_ABI wide_string from_bytes(char __byte) { return from_bytes(&__byte, &__byte + 1); } + _LIBCPP_HIDE_FROM_ABI wide_string from_bytes(const char* __ptr) { + return from_bytes(__ptr, __ptr + char_traits::length(__ptr)); + } + _LIBCPP_HIDE_FROM_ABI wide_string from_bytes(const byte_string& __str) { + return from_bytes(__str.data(), __str.data() + __str.size()); + } + _LIBCPP_HIDE_FROM_ABI wide_string from_bytes(const char* __first, const char* __last); + + _LIBCPP_HIDE_FROM_ABI byte_string to_bytes(_Elem __wchar) { + return to_bytes(std::addressof(__wchar), std::addressof(__wchar) + 1); + } + _LIBCPP_HIDE_FROM_ABI byte_string to_bytes(const _Elem* __wptr) { + return to_bytes(__wptr, __wptr + char_traits<_Elem>::length(__wptr)); + } + _LIBCPP_HIDE_FROM_ABI byte_string to_bytes(const wide_string& __wstr) { + return to_bytes(__wstr.data(), __wstr.data() + __wstr.size()); + } + _LIBCPP_HIDE_FROM_ABI byte_string to_bytes(const _Elem* __first, const _Elem* __last); + + _LIBCPP_HIDE_FROM_ABI size_t converted() const _NOEXCEPT { return __cvtcount_; } + _LIBCPP_HIDE_FROM_ABI state_type state() const { return __cvtstate_; } +}; + +_LIBCPP_SUPPRESS_DEPRECATED_PUSH +template +inline wstring_convert<_Codecvt, _Elem, _WideAlloc, _ByteAlloc>::wstring_convert(_Codecvt* __pcvt) + : __cvtptr_(__pcvt), __cvtstate_(), __cvtcount_(0) {} +_LIBCPP_SUPPRESS_DEPRECATED_POP + +template +inline wstring_convert<_Codecvt, _Elem, _WideAlloc, _ByteAlloc>::wstring_convert(_Codecvt* __pcvt, state_type __state) + : __cvtptr_(__pcvt), __cvtstate_(__state), __cvtcount_(0) {} + +template +wstring_convert<_Codecvt, _Elem, _WideAlloc, _ByteAlloc>::wstring_convert( + const byte_string& __byte_err, const wide_string& __wide_err) + : __byte_err_string_(__byte_err), __wide_err_string_(__wide_err), __cvtstate_(), __cvtcount_(0) { + __cvtptr_ = new _Codecvt; +} + +# ifndef _LIBCPP_CXX03_LANG + +template +inline wstring_convert<_Codecvt, _Elem, _WideAlloc, _ByteAlloc>::wstring_convert(wstring_convert&& __wc) + : __byte_err_string_(std::move(__wc.__byte_err_string_)), + __wide_err_string_(std::move(__wc.__wide_err_string_)), + __cvtptr_(__wc.__cvtptr_), + __cvtstate_(__wc.__cvtstate_), + __cvtcount_(__wc.__cvtcount_) { + __wc.__cvtptr_ = nullptr; +} + +# endif // _LIBCPP_CXX03_LANG + +_LIBCPP_SUPPRESS_DEPRECATED_PUSH +template +wstring_convert<_Codecvt, _Elem, _WideAlloc, _ByteAlloc>::~wstring_convert() { + delete __cvtptr_; +} + +template +typename wstring_convert<_Codecvt, _Elem, _WideAlloc, _ByteAlloc>::wide_string +wstring_convert<_Codecvt, _Elem, _WideAlloc, _ByteAlloc>::from_bytes(const char* __frm, const char* __frm_end) { + _LIBCPP_SUPPRESS_DEPRECATED_POP + __cvtcount_ = 0; + if (__cvtptr_ != nullptr) { + wide_string __ws(2 * (__frm_end - __frm), _Elem()); + if (__frm != __frm_end) + __ws.resize(__ws.capacity()); + codecvt_base::result __r = codecvt_base::ok; + state_type __st = __cvtstate_; + if (__frm != __frm_end) { + _Elem* __to = std::addressof(__ws[0]); + _Elem* __to_end = __to + __ws.size(); + const char* __frm_nxt; + do { + _Elem* __to_nxt; + __r = __cvtptr_->in(__st, __frm, __frm_end, __frm_nxt, __to, __to_end, __to_nxt); + __cvtcount_ += __frm_nxt - __frm; + if (__frm_nxt == __frm) { + __r = codecvt_base::error; + } else if (__r == codecvt_base::noconv) { + __ws.resize(__to - std::addressof(__ws[0])); + // This only gets executed if _Elem is char + __ws.append((const _Elem*)__frm, (const _Elem*)__frm_end); + __frm = __frm_nxt; + __r = codecvt_base::ok; + } else if (__r == codecvt_base::ok) { + __ws.resize(__to_nxt - std::addressof(__ws[0])); + __frm = __frm_nxt; + } else if (__r == codecvt_base::partial) { + ptrdiff_t __s = __to_nxt - std::addressof(__ws[0]); + __ws.resize(2 * __s); + __to = std::addressof(__ws[0]) + __s; + __to_end = std::addressof(__ws[0]) + __ws.size(); + __frm = __frm_nxt; + } + } while (__r == codecvt_base::partial && __frm_nxt < __frm_end); + } + if (__r == codecvt_base::ok) + return __ws; + } + + if (__wide_err_string_.empty()) + std::__throw_range_error("wstring_convert: from_bytes error"); + + return __wide_err_string_; +} + +template +typename wstring_convert<_Codecvt, _Elem, _WideAlloc, _ByteAlloc>::byte_string +wstring_convert<_Codecvt, _Elem, _WideAlloc, _ByteAlloc>::to_bytes(const _Elem* __frm, const _Elem* __frm_end) { + __cvtcount_ = 0; + if (__cvtptr_ != nullptr) { + byte_string __bs(2 * (__frm_end - __frm), char()); + if (__frm != __frm_end) + __bs.resize(__bs.capacity()); + codecvt_base::result __r = codecvt_base::ok; + state_type __st = __cvtstate_; + if (__frm != __frm_end) { + char* __to = std::addressof(__bs[0]); + char* __to_end = __to + __bs.size(); + const _Elem* __frm_nxt; + do { + char* __to_nxt; + __r = __cvtptr_->out(__st, __frm, __frm_end, __frm_nxt, __to, __to_end, __to_nxt); + __cvtcount_ += __frm_nxt - __frm; + if (__frm_nxt == __frm) { + __r = codecvt_base::error; + } else if (__r == codecvt_base::noconv) { + __bs.resize(__to - std::addressof(__bs[0])); + // This only gets executed if _Elem is char + __bs.append((const char*)__frm, (const char*)__frm_end); + __frm = __frm_nxt; + __r = codecvt_base::ok; + } else if (__r == codecvt_base::ok) { + __bs.resize(__to_nxt - std::addressof(__bs[0])); + __frm = __frm_nxt; + } else if (__r == codecvt_base::partial) { + ptrdiff_t __s = __to_nxt - std::addressof(__bs[0]); + __bs.resize(2 * __s); + __to = std::addressof(__bs[0]) + __s; + __to_end = std::addressof(__bs[0]) + __bs.size(); + __frm = __frm_nxt; + } + } while (__r == codecvt_base::partial && __frm_nxt < __frm_end); + } + if (__r == codecvt_base::ok) { + size_t __s = __bs.size(); + __bs.resize(__bs.capacity()); + char* __to = std::addressof(__bs[0]) + __s; + char* __to_end = __to + __bs.size(); + do { + char* __to_nxt; + __r = __cvtptr_->unshift(__st, __to, __to_end, __to_nxt); + if (__r == codecvt_base::noconv) { + __bs.resize(__to - std::addressof(__bs[0])); + __r = codecvt_base::ok; + } else if (__r == codecvt_base::ok) { + __bs.resize(__to_nxt - std::addressof(__bs[0])); + } else if (__r == codecvt_base::partial) { + ptrdiff_t __sp = __to_nxt - std::addressof(__bs[0]); + __bs.resize(2 * __sp); + __to = std::addressof(__bs[0]) + __sp; + __to_end = std::addressof(__bs[0]) + __bs.size(); + } + } while (__r == codecvt_base::partial); + if (__r == codecvt_base::ok) + return __bs; + } + } + + if (__byte_err_string_.empty()) + std::__throw_range_error("wstring_convert: to_bytes error"); + + return __byte_err_string_; +} + +_LIBCPP_END_NAMESPACE_STD + +_LIBCPP_POP_MACROS + +# endif // _LIBCPP_STD_VER < 26 || defined(_LIBCPP_ENABLE_CXX26_REMOVED_WSTRING_CONVERT) + +#endif // _LIBCPP_HAS_LOCALIZATION + +#endif // _LIBCPP___LOCALE_DIR_WSTRING_CONVERT_H diff --git a/lib/libcxx/include/__log_hardening_failure b/lib/libcxx/include/__log_hardening_failure new file mode 100644 index 0000000000..d1805306f6 --- /dev/null +++ b/lib/libcxx/include/__log_hardening_failure @@ -0,0 +1,42 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___LOG_HARDENING_FAILURE +#define _LIBCPP___LOG_HARDENING_FAILURE + +#include <__config> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +// Hardening logging is not available in the C++03 mode; moreover, it is currently only available in the experimental +// library. +#if _LIBCPP_HAS_EXPERIMENTAL_HARDENING_OBSERVE_SEMANTIC && !defined(_LIBCPP_CXX03_LANG) + +_LIBCPP_BEGIN_NAMESPACE_STD + +// This function should never be called directly from the code -- it should only be called through the +// `_LIBCPP_LOG_HARDENING_FAILURE` macro. +[[__gnu__::__cold__]] _LIBCPP_EXPORTED_FROM_ABI void __log_hardening_failure(const char* __message) noexcept; + +// _LIBCPP_LOG_HARDENING_FAILURE(message) +// +// This macro is used to log an error without terminating the program (as is the case for hardening failures if the +// `observe` assertion semantic is used). + +# if !defined(_LIBCPP_LOG_HARDENING_FAILURE) +# define _LIBCPP_LOG_HARDENING_FAILURE(__message) ::std::__log_hardening_failure(__message) +# endif // !defined(_LIBCPP_LOG_HARDENING_FAILURE) + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP_HAS_EXPERIMENTAL_HARDENING_OBSERVE_SEMANTIC && !defined(_LIBCPP_CXX03_LANG) + +#endif // _LIBCPP___LOG_HARDENING_FAILURE diff --git a/lib/libcxx/include/__math/abs.h b/lib/libcxx/include/__math/abs.h index fc3bf3a2c7..b780159f11 100644 --- a/lib/libcxx/include/__math/abs.h +++ b/lib/libcxx/include/__math/abs.h @@ -39,6 +39,30 @@ template ::value, int> = 0> return __builtin_fabs((double)__x); } +// abs + +[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI inline float abs(float __x) _NOEXCEPT { return __builtin_fabsf(__x); } +[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI inline double abs(double __x) _NOEXCEPT { return __builtin_fabs(__x); } + +[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI inline long double abs(long double __x) _NOEXCEPT { + return __builtin_fabsl(__x); +} + +template +[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI inline int abs(int __x) _NOEXCEPT { + return __builtin_abs(__x); +} + +template +[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI inline long abs(long __x) _NOEXCEPT { + return __builtin_labs(__x); +} + +template +[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI inline long long abs(long long __x) _NOEXCEPT { + return __builtin_llabs(__x); +} + } // namespace __math _LIBCPP_END_NAMESPACE_STD diff --git a/lib/libcxx/include/__math/copysign.h b/lib/libcxx/include/__math/copysign.h index c3ca6a3b03..4c297cb089 100644 --- a/lib/libcxx/include/__math/copysign.h +++ b/lib/libcxx/include/__math/copysign.h @@ -33,7 +33,7 @@ namespace __math { } template ::value && is_arithmetic<_A2>::value, int> = 0> -[[__nodiscard__]] inline _LIBCPP_HIDE_FROM_ABI typename __promote<_A1, _A2>::type copysign(_A1 __x, _A2 __y) _NOEXCEPT { +[[__nodiscard__]] inline _LIBCPP_HIDE_FROM_ABI __promote_t<_A1, _A2> copysign(_A1 __x, _A2 __y) _NOEXCEPT { return ::__builtin_copysign(__x, __y); } diff --git a/lib/libcxx/include/__math/exponential_functions.h b/lib/libcxx/include/__math/exponential_functions.h index 109c334997..09930b7819 100644 --- a/lib/libcxx/include/__math/exponential_functions.h +++ b/lib/libcxx/include/__math/exponential_functions.h @@ -158,8 +158,8 @@ inline _LIBCPP_HIDE_FROM_ABI long double pow(long double __x, long double __y) _ } template ::value && is_arithmetic<_A2>::value, int> = 0> -inline _LIBCPP_HIDE_FROM_ABI typename __promote<_A1, _A2>::type pow(_A1 __x, _A2 __y) _NOEXCEPT { - using __result_type = typename __promote<_A1, _A2>::type; +inline _LIBCPP_HIDE_FROM_ABI __promote_t<_A1, _A2> pow(_A1 __x, _A2 __y) _NOEXCEPT { + using __result_type = __promote_t<_A1, _A2>; static_assert(!(_IsSame<_A1, __result_type>::value && _IsSame<_A2, __result_type>::value), ""); return __math::pow((__result_type)__x, (__result_type)__y); } diff --git a/lib/libcxx/include/__math/fdim.h b/lib/libcxx/include/__math/fdim.h index dc1b4ecc07..a1081c7bde 100644 --- a/lib/libcxx/include/__math/fdim.h +++ b/lib/libcxx/include/__math/fdim.h @@ -35,8 +35,8 @@ inline _LIBCPP_HIDE_FROM_ABI long double fdim(long double __x, long double __y) } template ::value && is_arithmetic<_A2>::value, int> = 0> -inline _LIBCPP_HIDE_FROM_ABI typename __promote<_A1, _A2>::type fdim(_A1 __x, _A2 __y) _NOEXCEPT { - using __result_type = typename __promote<_A1, _A2>::type; +inline _LIBCPP_HIDE_FROM_ABI __promote_t<_A1, _A2> fdim(_A1 __x, _A2 __y) _NOEXCEPT { + using __result_type = __promote_t<_A1, _A2>; static_assert(!(_IsSame<_A1, __result_type>::value && _IsSame<_A2, __result_type>::value), ""); return __math::fdim((__result_type)__x, (__result_type)__y); } diff --git a/lib/libcxx/include/__math/fma.h b/lib/libcxx/include/__math/fma.h index 6ba7a5a2d2..b972d85b89 100644 --- a/lib/libcxx/include/__math/fma.h +++ b/lib/libcxx/include/__math/fma.h @@ -40,8 +40,8 @@ template ::value && is_arithmetic<_A2>::value && is_arithmetic<_A3>::value, int> = 0> -inline _LIBCPP_HIDE_FROM_ABI typename __promote<_A1, _A2, _A3>::type fma(_A1 __x, _A2 __y, _A3 __z) _NOEXCEPT { - using __result_type = typename __promote<_A1, _A2, _A3>::type; +inline _LIBCPP_HIDE_FROM_ABI __promote_t<_A1, _A2, _A3> fma(_A1 __x, _A2 __y, _A3 __z) _NOEXCEPT { + using __result_type = __promote_t<_A1, _A2, _A3>; static_assert( !(_IsSame<_A1, __result_type>::value && _IsSame<_A2, __result_type>::value && _IsSame<_A3, __result_type>::value), ""); diff --git a/lib/libcxx/include/__math/hypot.h b/lib/libcxx/include/__math/hypot.h index b2bf8e11c8..8e8c35b4a4 100644 --- a/lib/libcxx/include/__math/hypot.h +++ b/lib/libcxx/include/__math/hypot.h @@ -43,8 +43,8 @@ inline _LIBCPP_HIDE_FROM_ABI long double hypot(long double __x, long double __y) } template ::value && is_arithmetic<_A2>::value, int> = 0> -inline _LIBCPP_HIDE_FROM_ABI typename __promote<_A1, _A2>::type hypot(_A1 __x, _A2 __y) _NOEXCEPT { - using __result_type = typename __promote<_A1, _A2>::type; +inline _LIBCPP_HIDE_FROM_ABI __promote_t<_A1, _A2> hypot(_A1 __x, _A2 __y) _NOEXCEPT { + using __result_type = __promote_t<_A1, _A2>; static_assert(!(_IsSame<_A1, __result_type>::value && _IsSame<_A2, __result_type>::value), ""); return __math::hypot((__result_type)__x, (__result_type)__y); } @@ -91,8 +91,8 @@ template && is_arithmetic_v<_A2> && is_arithmetic_v<_A3>, int> = 0 > -_LIBCPP_HIDE_FROM_ABI typename __promote<_A1, _A2, _A3>::type hypot(_A1 __x, _A2 __y, _A3 __z) _NOEXCEPT { - using __result_type = typename __promote<_A1, _A2, _A3>::type; +_LIBCPP_HIDE_FROM_ABI __promote_t<_A1, _A2, _A3> hypot(_A1 __x, _A2 __y, _A3 __z) _NOEXCEPT { + using __result_type = __promote_t<_A1, _A2, _A3>; static_assert(!( std::is_same_v<_A1, __result_type> && std::is_same_v<_A2, __result_type> && std::is_same_v<_A3, __result_type>)); return __math::__hypot( diff --git a/lib/libcxx/include/__math/inverse_trigonometric_functions.h b/lib/libcxx/include/__math/inverse_trigonometric_functions.h index cd98b46a6a..409500278e 100644 --- a/lib/libcxx/include/__math/inverse_trigonometric_functions.h +++ b/lib/libcxx/include/__math/inverse_trigonometric_functions.h @@ -86,8 +86,8 @@ inline _LIBCPP_HIDE_FROM_ABI long double atan2(long double __y, long double __x) } template ::value && is_arithmetic<_A2>::value, int> = 0> -inline _LIBCPP_HIDE_FROM_ABI typename __promote<_A1, _A2>::type atan2(_A1 __y, _A2 __x) _NOEXCEPT { - using __result_type = typename __promote<_A1, _A2>::type; +inline _LIBCPP_HIDE_FROM_ABI __promote_t<_A1, _A2> atan2(_A1 __y, _A2 __x) _NOEXCEPT { + using __result_type = __promote_t<_A1, _A2>; static_assert(!(_IsSame<_A1, __result_type>::value && _IsSame<_A2, __result_type>::value), ""); return __math::atan2((__result_type)__y, (__result_type)__x); } diff --git a/lib/libcxx/include/__math/min_max.h b/lib/libcxx/include/__math/min_max.h index db900c849e..1ddbb557d1 100644 --- a/lib/libcxx/include/__math/min_max.h +++ b/lib/libcxx/include/__math/min_max.h @@ -39,8 +39,8 @@ template } template ::value && is_arithmetic<_A2>::value, int> = 0> -[[__nodiscard__]] inline _LIBCPP_HIDE_FROM_ABI typename __promote<_A1, _A2>::type fmax(_A1 __x, _A2 __y) _NOEXCEPT { - using __result_type = typename __promote<_A1, _A2>::type; +[[__nodiscard__]] inline _LIBCPP_HIDE_FROM_ABI __promote_t<_A1, _A2> fmax(_A1 __x, _A2 __y) _NOEXCEPT { + using __result_type = __promote_t<_A1, _A2>; static_assert(!(_IsSame<_A1, __result_type>::value && _IsSame<_A2, __result_type>::value), ""); return __math::fmax((__result_type)__x, (__result_type)__y); } @@ -61,8 +61,8 @@ template } template ::value && is_arithmetic<_A2>::value, int> = 0> -[[__nodiscard__]] inline _LIBCPP_HIDE_FROM_ABI typename __promote<_A1, _A2>::type fmin(_A1 __x, _A2 __y) _NOEXCEPT { - using __result_type = typename __promote<_A1, _A2>::type; +[[__nodiscard__]] inline _LIBCPP_HIDE_FROM_ABI __promote_t<_A1, _A2> fmin(_A1 __x, _A2 __y) _NOEXCEPT { + using __result_type = __promote_t<_A1, _A2>; static_assert(!(_IsSame<_A1, __result_type>::value && _IsSame<_A2, __result_type>::value), ""); return __math::fmin((__result_type)__x, (__result_type)__y); } diff --git a/lib/libcxx/include/__math/modulo.h b/lib/libcxx/include/__math/modulo.h index c8ea506f37..71405abb6b 100644 --- a/lib/libcxx/include/__math/modulo.h +++ b/lib/libcxx/include/__math/modulo.h @@ -37,8 +37,8 @@ inline _LIBCPP_HIDE_FROM_ABI long double fmod(long double __x, long double __y) } template ::value && is_arithmetic<_A2>::value, int> = 0> -inline _LIBCPP_HIDE_FROM_ABI typename __promote<_A1, _A2>::type fmod(_A1 __x, _A2 __y) _NOEXCEPT { - using __result_type = typename __promote<_A1, _A2>::type; +inline _LIBCPP_HIDE_FROM_ABI __promote_t<_A1, _A2> fmod(_A1 __x, _A2 __y) _NOEXCEPT { + using __result_type = __promote_t<_A1, _A2>; static_assert(!(_IsSame<_A1, __result_type>::value && _IsSame<_A2, __result_type>::value), ""); return __math::fmod((__result_type)__x, (__result_type)__y); } diff --git a/lib/libcxx/include/__math/remainder.h b/lib/libcxx/include/__math/remainder.h index 0adb7f3af5..39fb76af6b 100644 --- a/lib/libcxx/include/__math/remainder.h +++ b/lib/libcxx/include/__math/remainder.h @@ -37,8 +37,8 @@ inline _LIBCPP_HIDE_FROM_ABI long double remainder(long double __x, long double } template ::value && is_arithmetic<_A2>::value, int> = 0> -inline _LIBCPP_HIDE_FROM_ABI typename __promote<_A1, _A2>::type remainder(_A1 __x, _A2 __y) _NOEXCEPT { - using __result_type = typename __promote<_A1, _A2>::type; +inline _LIBCPP_HIDE_FROM_ABI __promote_t<_A1, _A2> remainder(_A1 __x, _A2 __y) _NOEXCEPT { + using __result_type = __promote_t<_A1, _A2>; static_assert(!(_IsSame<_A1, __result_type>::value && _IsSame<_A2, __result_type>::value), ""); return __math::remainder((__result_type)__x, (__result_type)__y); } @@ -59,8 +59,8 @@ inline _LIBCPP_HIDE_FROM_ABI long double remquo(long double __x, long double __y } template ::value && is_arithmetic<_A2>::value, int> = 0> -inline _LIBCPP_HIDE_FROM_ABI typename __promote<_A1, _A2>::type remquo(_A1 __x, _A2 __y, int* __z) _NOEXCEPT { - using __result_type = typename __promote<_A1, _A2>::type; +inline _LIBCPP_HIDE_FROM_ABI __promote_t<_A1, _A2> remquo(_A1 __x, _A2 __y, int* __z) _NOEXCEPT { + using __result_type = __promote_t<_A1, _A2>; static_assert(!(_IsSame<_A1, __result_type>::value && _IsSame<_A2, __result_type>::value), ""); return __math::remquo((__result_type)__x, (__result_type)__y, __z); } diff --git a/lib/libcxx/include/__math/rounding_functions.h b/lib/libcxx/include/__math/rounding_functions.h index 474f585a62..aadeb395fa 100644 --- a/lib/libcxx/include/__math/rounding_functions.h +++ b/lib/libcxx/include/__math/rounding_functions.h @@ -158,8 +158,8 @@ inline _LIBCPP_HIDE_FROM_ABI long double nextafter(long double __x, long double } template ::value && is_arithmetic<_A2>::value, int> = 0> -inline _LIBCPP_HIDE_FROM_ABI typename __promote<_A1, _A2>::type nextafter(_A1 __x, _A2 __y) _NOEXCEPT { - using __result_type = typename __promote<_A1, _A2>::type; +inline _LIBCPP_HIDE_FROM_ABI __promote_t<_A1, _A2> nextafter(_A1 __x, _A2 __y) _NOEXCEPT { + using __result_type = __promote_t<_A1, _A2>; static_assert(!(_IsSame<_A1, __result_type>::value && _IsSame<_A2, __result_type>::value), ""); return __math::nextafter((__result_type)__x, (__result_type)__y); } diff --git a/lib/libcxx/include/__math/traits.h b/lib/libcxx/include/__math/traits.h index 0c96f766a7..4a6e58c6da 100644 --- a/lib/libcxx/include/__math/traits.h +++ b/lib/libcxx/include/__math/traits.h @@ -13,7 +13,6 @@ #include <__type_traits/enable_if.h> #include <__type_traits/is_arithmetic.h> #include <__type_traits/is_integral.h> -#include <__type_traits/is_signed.h> #include <__type_traits/promote.h> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) @@ -51,16 +50,11 @@ template return __builtin_signbit(__x); } -template ::value && is_signed<_A1>::value, int> = 0> +template ::value, int> = 0> [[__nodiscard__]] inline _LIBCPP_SIGNBIT_CONSTEXPR _LIBCPP_HIDE_FROM_ABI bool signbit(_A1 __x) _NOEXCEPT { return __x < 0; } -template ::value && !is_signed<_A1>::value, int> = 0> -[[__nodiscard__]] inline _LIBCPP_SIGNBIT_CONSTEXPR _LIBCPP_HIDE_FROM_ABI bool signbit(_A1) _NOEXCEPT { - return false; -} - // isfinite template ::value, int> = 0> @@ -151,7 +145,7 @@ template ::value, int> = 0> template ::value && is_arithmetic<_A2>::value, int> = 0> [[__nodiscard__]] inline _LIBCPP_HIDE_FROM_ABI bool isgreater(_A1 __x, _A2 __y) _NOEXCEPT { - using type = typename __promote<_A1, _A2>::type; + using type = __promote_t<_A1, _A2>; return __builtin_isgreater((type)__x, (type)__y); } @@ -159,7 +153,7 @@ template ::value && is_ar template ::value && is_arithmetic<_A2>::value, int> = 0> [[__nodiscard__]] inline _LIBCPP_HIDE_FROM_ABI bool isgreaterequal(_A1 __x, _A2 __y) _NOEXCEPT { - using type = typename __promote<_A1, _A2>::type; + using type = __promote_t<_A1, _A2>; return __builtin_isgreaterequal((type)__x, (type)__y); } @@ -167,7 +161,7 @@ template ::value && is_ar template ::value && is_arithmetic<_A2>::value, int> = 0> [[__nodiscard__]] inline _LIBCPP_HIDE_FROM_ABI bool isless(_A1 __x, _A2 __y) _NOEXCEPT { - using type = typename __promote<_A1, _A2>::type; + using type = __promote_t<_A1, _A2>; return __builtin_isless((type)__x, (type)__y); } @@ -175,7 +169,7 @@ template ::value && is_ar template ::value && is_arithmetic<_A2>::value, int> = 0> [[__nodiscard__]] inline _LIBCPP_HIDE_FROM_ABI bool islessequal(_A1 __x, _A2 __y) _NOEXCEPT { - using type = typename __promote<_A1, _A2>::type; + using type = __promote_t<_A1, _A2>; return __builtin_islessequal((type)__x, (type)__y); } @@ -183,7 +177,7 @@ template ::value && is_ar template ::value && is_arithmetic<_A2>::value, int> = 0> [[__nodiscard__]] inline _LIBCPP_HIDE_FROM_ABI bool islessgreater(_A1 __x, _A2 __y) _NOEXCEPT { - using type = typename __promote<_A1, _A2>::type; + using type = __promote_t<_A1, _A2>; return __builtin_islessgreater((type)__x, (type)__y); } @@ -191,7 +185,7 @@ template ::value && is_ar template ::value && is_arithmetic<_A2>::value, int> = 0> [[__nodiscard__]] inline _LIBCPP_HIDE_FROM_ABI bool isunordered(_A1 __x, _A2 __y) _NOEXCEPT { - using type = typename __promote<_A1, _A2>::type; + using type = __promote_t<_A1, _A2>; return __builtin_isunordered((type)__x, (type)__y); } diff --git a/lib/libcxx/include/__mbstate_t.h b/lib/libcxx/include/__mbstate_t.h index e013384454..c23ea7113c 100644 --- a/lib/libcxx/include/__mbstate_t.h +++ b/lib/libcxx/include/__mbstate_t.h @@ -43,12 +43,12 @@ # include // works on most Unixes #elif __has_include() # include // works on Darwin -#elif _LIBCPP_HAS_WIDE_CHARACTERS && __has_include_next() -# include_next // fall back to the C standard provider of mbstate_t +#elif __has_include_next() +# include_next // use the C standard provider of mbstate_t if present #elif __has_include_next() -# include_next // is also required to make mbstate_t visible +# include_next // Try in absence of for mbstate_t #else -# error "We don't know how to get the definition of mbstate_t without on your platform." +# error "We don't know how to get the definition of mbstate_t on your platform." #endif #endif // _LIBCPP___MBSTATE_T_H diff --git a/lib/libcxx/include/__mdspan/aligned_accessor.h b/lib/libcxx/include/__mdspan/aligned_accessor.h new file mode 100644 index 0000000000..2b8d4c52d8 --- /dev/null +++ b/lib/libcxx/include/__mdspan/aligned_accessor.h @@ -0,0 +1,87 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +// Kokkos v. 4.0 +// Copyright (2022) National Technology & Engineering +// Solutions of Sandia, LLC (NTESS). +// +// Under the terms of Contract DE-NA0003525 with NTESS, +// the U.S. Government retains certain rights in this software. +// +//===---------------------------------------------------------------------===// + +#ifndef _LIBCPP___MDSPAN_ALIGNED_ACCESSOR_H +#define _LIBCPP___MDSPAN_ALIGNED_ACCESSOR_H + +#include <__config> +#include <__cstddef/size_t.h> +#include <__mdspan/default_accessor.h> +#include <__memory/assume_aligned.h> +#include <__type_traits/is_abstract.h> +#include <__type_traits/is_array.h> +#include <__type_traits/is_convertible.h> +#include <__type_traits/remove_const.h> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_PUSH_MACROS +#include <__undef_macros> + +_LIBCPP_BEGIN_NAMESPACE_STD + +#if _LIBCPP_STD_VER >= 26 + +template +struct aligned_accessor { + static_assert(_ByteAlignment != 0 && (_ByteAlignment & (_ByteAlignment - 1)) == 0, + "aligned_accessor: byte alignment must be a power of two"); + static_assert(_ByteAlignment >= alignof(_ElementType), "aligned_accessor: insufficient byte alignment"); + static_assert(!is_array_v<_ElementType>, "aligned_accessor: template argument may not be an array type"); + static_assert(!is_abstract_v<_ElementType>, "aligned_accessor: template argument may not be an abstract class"); + + using offset_policy = default_accessor<_ElementType>; + using element_type = _ElementType; + using reference = _ElementType&; + using data_handle_type = _ElementType*; + + static constexpr size_t byte_alignment = _ByteAlignment; + + _LIBCPP_HIDE_FROM_ABI constexpr aligned_accessor() noexcept = default; + + template + requires(is_convertible_v<_OtherElementType (*)[], element_type (*)[]> && _OtherByteAlignment >= byte_alignment) + _LIBCPP_HIDE_FROM_ABI constexpr aligned_accessor(aligned_accessor<_OtherElementType, _OtherByteAlignment>) noexcept {} + + template + requires(is_convertible_v<_OtherElementType (*)[], element_type (*)[]>) + _LIBCPP_HIDE_FROM_ABI explicit constexpr aligned_accessor(default_accessor<_OtherElementType>) noexcept {} + + template + requires(is_convertible_v) + _LIBCPP_HIDE_FROM_ABI constexpr operator default_accessor<_OtherElementType>() const noexcept { + return {}; + } + + _LIBCPP_HIDE_FROM_ABI constexpr reference access(data_handle_type __p, size_t __i) const noexcept { + return std::assume_aligned(__p)[__i]; + } + + _LIBCPP_HIDE_FROM_ABI constexpr typename offset_policy::data_handle_type + offset(data_handle_type __p, size_t __i) const noexcept { + return std::assume_aligned(__p) + __i; + } +}; + +#endif // _LIBCPP_STD_VER >= 26 + +_LIBCPP_END_NAMESPACE_STD + +_LIBCPP_POP_MACROS + +#endif // _LIBCPP___MDSPAN_ALIGNED_ACCESSOR_H diff --git a/lib/libcxx/include/__mdspan/extents.h b/lib/libcxx/include/__mdspan/extents.h index 65a697769b..99b54badf8 100644 --- a/lib/libcxx/include/__mdspan/extents.h +++ b/lib/libcxx/include/__mdspan/extents.h @@ -21,11 +21,10 @@ #include <__config> #include <__concepts/arithmetic.h> -#include <__cstddef/byte.h> #include <__type_traits/common_type.h> +#include <__type_traits/integer_traits.h> #include <__type_traits/is_convertible.h> #include <__type_traits/is_nothrow_constructible.h> -#include <__type_traits/is_same.h> #include <__type_traits/make_unsigned.h> #include <__utility/integer_sequence.h> #include <__utility/unreachable.h> @@ -283,7 +282,8 @@ public: using size_type = make_unsigned_t; using rank_type = size_t; - static_assert(__libcpp_integer, "extents::index_type must be a signed or unsigned integer type"); + static_assert(__signed_or_unsigned_integer, + "extents::index_type must be a signed or unsigned integer type"); static_assert(((__mdspan_detail::__is_representable_as(_Extents) || (_Extents == dynamic_extent)) && ...), "extents ctor: arguments must be representable as index_type and nonnegative"); @@ -440,13 +440,13 @@ struct __make_dextents; template struct __make_dextents< _IndexType, _Rank, extents<_IndexType, _ExtentsPack...>> { - using type = + using type _LIBCPP_NODEBUG = typename __make_dextents< _IndexType, _Rank - 1, extents<_IndexType, dynamic_extent, _ExtentsPack...>>::type; }; template struct __make_dextents< _IndexType, 0, extents<_IndexType, _ExtentsPack...>> { - using type = extents<_IndexType, _ExtentsPack...>; + using type _LIBCPP_NODEBUG = extents<_IndexType, _ExtentsPack...>; }; } // namespace __mdspan_detail diff --git a/lib/libcxx/include/__mdspan/layout_left.h b/lib/libcxx/include/__mdspan/layout_left.h index 288b3dd803..2f515afb6c 100644 --- a/lib/libcxx/include/__mdspan/layout_left.h +++ b/lib/libcxx/include/__mdspan/layout_left.h @@ -21,6 +21,7 @@ #include <__config> #include <__fwd/mdspan.h> #include <__mdspan/extents.h> +#include <__memory/addressof.h> #include <__type_traits/common_type.h> #include <__type_traits/is_constructible.h> #include <__type_traits/is_convertible.h> @@ -58,7 +59,7 @@ private: index_type __prod = __ext.extent(0); for (rank_type __r = 1; __r < extents_type::rank(); __r++) { - bool __overflowed = __builtin_mul_overflow(__prod, __ext.extent(__r), &__prod); + bool __overflowed = __builtin_mul_overflow(__prod, __ext.extent(__r), std::addressof(__prod)); if (__overflowed) return false; } diff --git a/lib/libcxx/include/__mdspan/layout_right.h b/lib/libcxx/include/__mdspan/layout_right.h index 72922d1049..ccfbd23e28 100644 --- a/lib/libcxx/include/__mdspan/layout_right.h +++ b/lib/libcxx/include/__mdspan/layout_right.h @@ -22,6 +22,7 @@ #include <__cstddef/size_t.h> #include <__fwd/mdspan.h> #include <__mdspan/extents.h> +#include <__memory/addressof.h> #include <__type_traits/common_type.h> #include <__type_traits/is_constructible.h> #include <__type_traits/is_convertible.h> @@ -58,7 +59,7 @@ private: index_type __prod = __ext.extent(0); for (rank_type __r = 1; __r < extents_type::rank(); __r++) { - bool __overflowed = __builtin_mul_overflow(__prod, __ext.extent(__r), &__prod); + bool __overflowed = __builtin_mul_overflow(__prod, __ext.extent(__r), std::addressof(__prod)); if (__overflowed) return false; } diff --git a/lib/libcxx/include/__mdspan/layout_stride.h b/lib/libcxx/include/__mdspan/layout_stride.h index bb93de9775..9d77d71bc3 100644 --- a/lib/libcxx/include/__mdspan/layout_stride.h +++ b/lib/libcxx/include/__mdspan/layout_stride.h @@ -22,6 +22,7 @@ #include <__config> #include <__fwd/mdspan.h> #include <__mdspan/extents.h> +#include <__memory/addressof.h> #include <__type_traits/common_type.h> #include <__type_traits/is_constructible.h> #include <__type_traits/is_convertible.h> @@ -86,7 +87,7 @@ private: index_type __prod = __ext.extent(0); for (rank_type __r = 1; __r < __rank_; __r++) { - bool __overflowed = __builtin_mul_overflow(__prod, __ext.extent(__r), &__prod); + bool __overflowed = __builtin_mul_overflow(__prod, __ext.extent(__r), std::addressof(__prod)); if (__overflowed) return false; } @@ -109,11 +110,12 @@ private: } if (__ext.extent(__r) == static_cast(0)) return true; - index_type __prod = (__ext.extent(__r) - 1); - bool __overflowed_mul = __builtin_mul_overflow(__prod, static_cast(__strides[__r]), &__prod); + index_type __prod = (__ext.extent(__r) - 1); + bool __overflowed_mul = + __builtin_mul_overflow(__prod, static_cast(__strides[__r]), std::addressof(__prod)); if (__overflowed_mul) return false; - bool __overflowed_add = __builtin_add_overflow(__size, __prod, &__size); + bool __overflowed_add = __builtin_add_overflow(__size, __prod, std::addressof(__size)); if (__overflowed_add) return false; } diff --git a/lib/libcxx/include/__mdspan/mdspan.h b/lib/libcxx/include/__mdspan/mdspan.h index 3f9b35b185..c0f2767819 100644 --- a/lib/libcxx/include/__mdspan/mdspan.h +++ b/lib/libcxx/include/__mdspan/mdspan.h @@ -20,8 +20,10 @@ #include <__assert> #include <__config> #include <__fwd/mdspan.h> +#include <__mdspan/aligned_accessor.h> #include <__mdspan/default_accessor.h> #include <__mdspan/extents.h> +#include <__memory/addressof.h> #include <__type_traits/extent.h> #include <__type_traits/is_abstract.h> #include <__type_traits/is_array.h> @@ -215,7 +217,7 @@ public: _LIBCPP_ASSERT_UNCATEGORIZED( false == ([&](index_sequence<_Idxs...>) { size_type __prod = 1; - return (__builtin_mul_overflow(__prod, extent(_Idxs), &__prod) || ... || false); + return (__builtin_mul_overflow(__prod, extent(_Idxs), std::addressof(__prod)) || ... || false); }(make_index_sequence())), "mdspan: size() is not representable as size_type"); return [&](index_sequence<_Idxs...>) { @@ -266,13 +268,13 @@ private: # if _LIBCPP_STD_VER >= 26 template requires((is_convertible_v<_OtherIndexTypes, size_t> && ...) && (sizeof...(_OtherIndexTypes) > 0)) -explicit mdspan(_ElementType*, - _OtherIndexTypes...) -> mdspan<_ElementType, extents...>>; +explicit mdspan(_ElementType*, _OtherIndexTypes...) + -> mdspan<_ElementType, extents...>>; # else template requires((is_convertible_v<_OtherIndexTypes, size_t> && ...) && (sizeof...(_OtherIndexTypes) > 0)) -explicit mdspan(_ElementType*, - _OtherIndexTypes...) -> mdspan<_ElementType, dextents>; +explicit mdspan(_ElementType*, _OtherIndexTypes...) + -> mdspan<_ElementType, dextents>; # endif template diff --git a/lib/libcxx/include/__memory/addressof.h b/lib/libcxx/include/__memory/addressof.h index 98b08958a6..667071dfc6 100644 --- a/lib/libcxx/include/__memory/addressof.h +++ b/lib/libcxx/include/__memory/addressof.h @@ -23,7 +23,7 @@ inline _LIBCPP_CONSTEXPR_SINCE_CXX17 _LIBCPP_NO_CFI _LIBCPP_HIDE_FROM_ABI _Tp* a return __builtin_addressof(__x); } -#if _LIBCPP_HAS_OBJC_ARC +#if __has_feature(objc_arc) // Objective-C++ Automatic Reference Counting uses qualified pointers // that require special addressof() signatures. template @@ -31,7 +31,7 @@ inline _LIBCPP_HIDE_FROM_ABI __strong _Tp* addressof(__strong _Tp& __x) _NOEXCEP return &__x; } -# if _LIBCPP_HAS_OBJC_ARC_WEAK +# if __has_feature(objc_arc_weak) template inline _LIBCPP_HIDE_FROM_ABI __weak _Tp* addressof(__weak _Tp& __x) _NOEXCEPT { return &__x; diff --git a/lib/libcxx/include/__memory/allocation_guard.h b/lib/libcxx/include/__memory/allocation_guard.h index 66edcd92ed..016e1a3a42 100644 --- a/lib/libcxx/include/__memory/allocation_guard.h +++ b/lib/libcxx/include/__memory/allocation_guard.h @@ -49,24 +49,26 @@ struct __allocation_guard { using _Size _LIBCPP_NODEBUG = typename allocator_traits<_Alloc>::size_type; template // we perform the allocator conversion inside the constructor - _LIBCPP_HIDE_FROM_ABI explicit __allocation_guard(_AllocT __alloc, _Size __n) + _LIBCPP_CONSTEXPR_SINCE_CXX26 _LIBCPP_HIDE_FROM_ABI explicit __allocation_guard(_AllocT __alloc, _Size __n) : __alloc_(std::move(__alloc)), __n_(__n), __ptr_(allocator_traits<_Alloc>::allocate(__alloc_, __n_)) // initialization order is important {} - _LIBCPP_HIDE_FROM_ABI ~__allocation_guard() _NOEXCEPT { __destroy(); } + _LIBCPP_CONSTEXPR_SINCE_CXX26 _LIBCPP_HIDE_FROM_ABI ~__allocation_guard() _NOEXCEPT { __destroy(); } - _LIBCPP_HIDE_FROM_ABI __allocation_guard(const __allocation_guard&) = delete; - _LIBCPP_HIDE_FROM_ABI __allocation_guard(__allocation_guard&& __other) _NOEXCEPT + __allocation_guard(const __allocation_guard&) = delete; + __allocation_guard& operator=(const __allocation_guard& __other) = delete; + + _LIBCPP_CONSTEXPR_SINCE_CXX26 _LIBCPP_HIDE_FROM_ABI __allocation_guard(__allocation_guard&& __other) _NOEXCEPT : __alloc_(std::move(__other.__alloc_)), __n_(__other.__n_), __ptr_(__other.__ptr_) { __other.__ptr_ = nullptr; } - _LIBCPP_HIDE_FROM_ABI __allocation_guard& operator=(const __allocation_guard& __other) = delete; - _LIBCPP_HIDE_FROM_ABI __allocation_guard& operator=(__allocation_guard&& __other) _NOEXCEPT { + _LIBCPP_CONSTEXPR_SINCE_CXX26 _LIBCPP_HIDE_FROM_ABI __allocation_guard& + operator=(__allocation_guard&& __other) _NOEXCEPT { if (std::addressof(__other) != this) { __destroy(); @@ -79,17 +81,17 @@ struct __allocation_guard { return *this; } - _LIBCPP_HIDE_FROM_ABI _Pointer + _LIBCPP_CONSTEXPR_SINCE_CXX26 _LIBCPP_HIDE_FROM_ABI _Pointer __release_ptr() _NOEXCEPT { // not called __release() because it's a keyword in objective-c++ _Pointer __tmp = __ptr_; __ptr_ = nullptr; return __tmp; } - _LIBCPP_HIDE_FROM_ABI _Pointer __get() const _NOEXCEPT { return __ptr_; } + _LIBCPP_CONSTEXPR_SINCE_CXX26 _LIBCPP_HIDE_FROM_ABI _Pointer __get() const _NOEXCEPT { return __ptr_; } private: - _LIBCPP_HIDE_FROM_ABI void __destroy() _NOEXCEPT { + _LIBCPP_CONSTEXPR_SINCE_CXX26 _LIBCPP_HIDE_FROM_ABI void __destroy() _NOEXCEPT { if (__ptr_ != nullptr) { allocator_traits<_Alloc>::deallocate(__alloc_, __ptr_, __n_); } diff --git a/lib/libcxx/include/__memory/allocator.h b/lib/libcxx/include/__memory/allocator.h index 191a59e661..52f4122a9b 100644 --- a/lib/libcxx/include/__memory/allocator.h +++ b/lib/libcxx/include/__memory/allocator.h @@ -38,7 +38,7 @@ class allocator; // These specializations shouldn't be marked _LIBCPP_DEPRECATED_IN_CXX17. // Specializing allocator is deprecated, but not using it. template <> -class _LIBCPP_TEMPLATE_VIS allocator { +class allocator { public: _LIBCPP_DEPRECATED_IN_CXX17 typedef void* pointer; _LIBCPP_DEPRECATED_IN_CXX17 typedef const void* const_pointer; @@ -77,7 +77,7 @@ struct __non_trivial_if { // allocator trivial in C++20. template -class _LIBCPP_TEMPLATE_VIS allocator : private __non_trivial_if::value, allocator<_Tp> > { +class allocator : private __non_trivial_if::value, allocator<_Tp> > { static_assert(!is_const<_Tp>::value, "std::allocator does not support const types"); static_assert(!is_volatile<_Tp>::value, "std::allocator does not support volatile types"); @@ -98,7 +98,7 @@ public: [[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _Tp* allocate(size_t __n) { static_assert(sizeof(_Tp) >= 0, "cannot allocate memory for an incomplete type"); if (__n > allocator_traits::max_size(*this)) - __throw_bad_array_new_length(); + std::__throw_bad_array_new_length(); if (__libcpp_is_constant_evaluated()) { return static_cast<_Tp*>(::operator new(__n * sizeof(_Tp))); } else { diff --git a/lib/libcxx/include/__memory/allocator_arg_t.h b/lib/libcxx/include/__memory/allocator_arg_t.h index 72a0a9c399..31a73fc455 100644 --- a/lib/libcxx/include/__memory/allocator_arg_t.h +++ b/lib/libcxx/include/__memory/allocator_arg_t.h @@ -23,7 +23,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD -struct _LIBCPP_TEMPLATE_VIS allocator_arg_t { +struct allocator_arg_t { explicit allocator_arg_t() = default; }; diff --git a/lib/libcxx/include/__memory/allocator_traits.h b/lib/libcxx/include/__memory/allocator_traits.h index 2d9ab847e9..46c247f704 100644 --- a/lib/libcxx/include/__memory/allocator_traits.h +++ b/lib/libcxx/include/__memory/allocator_traits.h @@ -36,12 +36,7 @@ _LIBCPP_PUSH_MACROS _LIBCPP_BEGIN_NAMESPACE_STD -#define _LIBCPP_ALLOCATOR_TRAITS_HAS_XXX(NAME, PROPERTY) \ - template \ - struct NAME : false_type {}; \ - template \ - struct NAME<_Tp, __void_t > : true_type {} - +_LIBCPP_SUPPRESS_DEPRECATED_PUSH // __pointer template using __pointer_member _LIBCPP_NODEBUG = typename _Tp::pointer; @@ -49,50 +44,45 @@ using __pointer_member _LIBCPP_NODEBUG = typename _Tp::pointer; template using __pointer _LIBCPP_NODEBUG = __detected_or_t<_Tp*, __pointer_member, __libcpp_remove_reference_t<_Alloc> >; -// __const_pointer -_LIBCPP_ALLOCATOR_TRAITS_HAS_XXX(__has_const_pointer, const_pointer); -template ::value> -struct __const_pointer { - using type _LIBCPP_NODEBUG = typename _Alloc::const_pointer; -}; -template -struct __const_pointer<_Tp, _Ptr, _Alloc, false> { +// This trait returns _Alias<_Alloc> if that's well-formed, and _Ptr rebound to _Tp otherwise +template class _Alias, class _Ptr, class _Tp, class = void> +struct __rebind_or_alias_pointer { #ifdef _LIBCPP_CXX03_LANG - using type _LIBCPP_NODEBUG = typename pointer_traits<_Ptr>::template rebind::other; + using type _LIBCPP_NODEBUG = typename pointer_traits<_Ptr>::template rebind<_Tp>::other; #else - using type _LIBCPP_NODEBUG = typename pointer_traits<_Ptr>::template rebind; + using type _LIBCPP_NODEBUG = typename pointer_traits<_Ptr>::template rebind<_Tp>; #endif }; +template class _Alias> +struct __rebind_or_alias_pointer<_Alloc, _Alias, _Ptr, _Tp, __void_t<_Alias<_Alloc> > > { + using type _LIBCPP_NODEBUG = _Alias<_Alloc>; +}; + +// __const_pointer +template +using __const_pointer_member _LIBCPP_NODEBUG = typename _Alloc::const_pointer; + +template +using __const_pointer_t _LIBCPP_NODEBUG = + typename __rebind_or_alias_pointer<_Alloc, __const_pointer_member, _Ptr, const _Tp>::type; +_LIBCPP_SUPPRESS_DEPRECATED_POP + // __void_pointer -_LIBCPP_ALLOCATOR_TRAITS_HAS_XXX(__has_void_pointer, void_pointer); -template ::value> -struct __void_pointer { - using type _LIBCPP_NODEBUG = typename _Alloc::void_pointer; -}; +template +using __void_pointer_member _LIBCPP_NODEBUG = typename _Alloc::void_pointer; + template -struct __void_pointer<_Ptr, _Alloc, false> { -#ifdef _LIBCPP_CXX03_LANG - using type _LIBCPP_NODEBUG = typename pointer_traits<_Ptr>::template rebind::other; -#else - using type _LIBCPP_NODEBUG = typename pointer_traits<_Ptr>::template rebind; -#endif -}; +using __void_pointer_t _LIBCPP_NODEBUG = + typename __rebind_or_alias_pointer<_Alloc, __void_pointer_member, _Ptr, void>::type; // __const_void_pointer -_LIBCPP_ALLOCATOR_TRAITS_HAS_XXX(__has_const_void_pointer, const_void_pointer); -template ::value> -struct __const_void_pointer { - using type _LIBCPP_NODEBUG = typename _Alloc::const_void_pointer; -}; +template +using __const_void_pointer_member _LIBCPP_NODEBUG = typename _Alloc::const_void_pointer; + template -struct __const_void_pointer<_Ptr, _Alloc, false> { -#ifdef _LIBCPP_CXX03_LANG - using type _LIBCPP_NODEBUG = typename pointer_traits<_Ptr>::template rebind::other; -#else - using type _LIBCPP_NODEBUG = typename pointer_traits<_Ptr>::template rebind; -#endif -}; +using __const_void_pointer_t _LIBCPP_NODEBUG = + typename __rebind_or_alias_pointer<_Alloc, __const_void_pointer_member, _Ptr, const void>::type; // __size_type template @@ -102,13 +92,13 @@ template using __size_type _LIBCPP_NODEBUG = __detected_or_t<__make_unsigned_t<_DiffType>, __size_type_member, _Alloc>; // __alloc_traits_difference_type -_LIBCPP_ALLOCATOR_TRAITS_HAS_XXX(__has_alloc_traits_difference_type, difference_type); -template ::value> +template struct __alloc_traits_difference_type { using type _LIBCPP_NODEBUG = typename pointer_traits<_Ptr>::difference_type; }; + template -struct __alloc_traits_difference_type<_Alloc, _Ptr, true> { +struct __alloc_traits_difference_type<_Alloc, _Ptr, __void_t > { using type _LIBCPP_NODEBUG = typename _Alloc::difference_type; }; @@ -138,6 +128,7 @@ template using __propagate_on_container_swap _LIBCPP_NODEBUG = __detected_or_t; +_LIBCPP_SUPPRESS_DEPRECATED_PUSH // __is_always_equal template using __is_always_equal_member _LIBCPP_NODEBUG = typename _Tp::is_always_equal; @@ -147,15 +138,14 @@ using __is_always_equal _LIBCPP_NODEBUG = __detected_or_t::type, __is_always_equal_member, _Alloc>; // __allocator_traits_rebind -_LIBCPP_SUPPRESS_DEPRECATED_PUSH template -struct __has_rebind_other : false_type {}; +inline const bool __has_rebind_other_v = false; template -struct __has_rebind_other<_Tp, _Up, __void_t::other> > : true_type {}; +inline const bool __has_rebind_other_v<_Tp, _Up, __void_t::other> > = true; -template ::value> +template > struct __allocator_traits_rebind { - static_assert(__has_rebind_other<_Tp, _Up>::value, "This allocator has to implement rebind"); + static_assert(__has_rebind_other_v<_Tp, _Up>, "This allocator has to implement rebind"); using type _LIBCPP_NODEBUG = typename _Tp::template rebind<_Up>::other; }; template